Changed the type of the result of the ! (NOT) operator to char;
[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) && !(sym->isitmp))
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 /*-----------------------------------------------------------------*/
1612 /* opIsGptr: returns non-zero if the passed operand is       */
1613 /* a generic pointer type.             */
1614 /*-----------------------------------------------------------------*/
1615 static int
1616 opIsGptr (operand * op)
1617 {
1618   sym_link *type = operandType (op);
1619
1620   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1621     {
1622       return 1;
1623     }
1624   return 0;
1625 }
1626
1627 /*-----------------------------------------------------------------*/
1628 /* getDataSize - get the operand data size                         */
1629 /*-----------------------------------------------------------------*/
1630 static int
1631 getDataSize (operand * op)
1632 {
1633   int size;
1634   size = AOP_SIZE (op);
1635   if (size == GPTRSIZE)
1636     {
1637       sym_link *type = operandType (op);
1638       if (IS_GENPTR (type))
1639         {
1640           /* generic pointer; arithmetic operations
1641            * should ignore the high byte (pointer type).
1642            */
1643           size--;
1644         }
1645     }
1646   return size;
1647 }
1648
1649 /*-----------------------------------------------------------------*/
1650 /* outAcc - output Acc                                             */
1651 /*-----------------------------------------------------------------*/
1652 static void
1653 outAcc (operand * result)
1654 {
1655   int size, offset;
1656   size = getDataSize (result);
1657   if (size)
1658     {
1659       aopPut (AOP (result), "a", 0);
1660       size--;
1661       offset = 1;
1662       /* unsigned or positive */
1663       while (size--)
1664         {
1665           aopPut (AOP (result), zero, offset++);
1666         }
1667     }
1668 }
1669
1670 /*-----------------------------------------------------------------*/
1671 /* outBitC - output a bit C                                        */
1672 /*-----------------------------------------------------------------*/
1673 static void
1674 outBitC (operand * result)
1675 {
1676   /* if the result is bit */
1677   if (AOP_TYPE (result) == AOP_CRY)
1678     {
1679       aopPut (AOP (result), "c", 0);
1680     }
1681   else
1682     {
1683       emitcode ("clr", "a");
1684       emitcode ("rlc", "a");
1685       outAcc (result);
1686     }
1687 }
1688
1689 /*-----------------------------------------------------------------*/
1690 /* toBoolean - emit code for orl a,operator(sizeop)                */
1691 /*-----------------------------------------------------------------*/
1692 static void
1693 toBoolean (operand * oper)
1694 {
1695   int   size = AOP_SIZE (oper) - 1;
1696   int   offset = 1;
1697   bool usedB = FALSE;
1698
1699   /* The generic part of a generic pointer should
1700    * not participate in it's truth value.
1701    *
1702    * i.e. 0x10000000 is zero.
1703    */
1704   if (opIsGptr (oper))
1705     {
1706       D (emitcode (";", "toBoolean: generic ptr special case."););
1707       size--;
1708     }
1709
1710   _startLazyDPSEvaluation ();
1711   if (AOP_NEEDSACC (oper) && size)
1712     {
1713       usedB = TRUE;
1714       if (_G.bInUse)
1715       {
1716           emitcode ("push", "b");
1717       }
1718       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1719     }
1720   else
1721     {
1722       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1723     }
1724     
1725   while (size--)
1726     {
1727       if (usedB)
1728         {
1729           emitcode ("orl", "b,%s",
1730                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1731         }
1732       else
1733         {
1734           emitcode ("orl", "a,%s",
1735                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1736         }
1737     }
1738   _endLazyDPSEvaluation ();
1739
1740   if (usedB)
1741     {
1742       emitcode ("mov", "a,b");
1743       if (_G.bInUse)
1744       {
1745           emitcode ("pop", "b");
1746       }
1747         
1748     }
1749 }
1750
1751
1752 /*-----------------------------------------------------------------*/
1753 /* genNot - generate code for ! operation                          */
1754 /*-----------------------------------------------------------------*/
1755 static void
1756 genNot (iCode * ic)
1757 {
1758   symbol *tlbl;
1759
1760   D (emitcode (";", "genNot "););
1761
1762   /* assign asmOps to operand & result */
1763   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1764   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1765
1766   /* if in bit space then a special case */
1767   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1768     {
1769       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1770       emitcode ("cpl", "c");
1771       outBitC (IC_RESULT (ic));
1772       goto release;
1773     }
1774
1775   toBoolean (IC_LEFT (ic));
1776
1777   tlbl = newiTempLabel (NULL);
1778   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1779   emitcode ("", "!tlabeldef", tlbl->key + 100);
1780   outBitC (IC_RESULT (ic));
1781
1782 release:
1783   /* release the aops */
1784   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1785   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1786 }
1787
1788
1789 /*-----------------------------------------------------------------*/
1790 /* genCpl - generate code for complement                           */
1791 /*-----------------------------------------------------------------*/
1792 static void
1793 genCpl (iCode * ic)
1794 {
1795   int offset = 0;
1796   int size;
1797   symbol *tlbl;
1798
1799   D (emitcode (";", "genCpl "););
1800
1801
1802   /* assign asmOps to operand & result */
1803   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1804   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1805
1806   /* special case if in bit space */
1807   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1808     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1809       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1810       emitcode ("cpl", "c");
1811       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1812       goto release;
1813     }
1814     tlbl=newiTempLabel(NULL);
1815     emitcode ("cjne", "%s,#0x01,%05d$", 
1816               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1817     emitcode ("", "%05d$:", tlbl->key+100);
1818     outBitC (IC_RESULT(ic));
1819     goto release;
1820   }
1821
1822   size = AOP_SIZE (IC_RESULT (ic));
1823   _startLazyDPSEvaluation ();
1824   while (size--)
1825     {
1826       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1827       emitcode ("cpl", "a");
1828       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1829     }
1830   _endLazyDPSEvaluation ();
1831
1832
1833 release:
1834   /* release the aops */
1835   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1836   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1837 }
1838
1839 /*-----------------------------------------------------------------*/
1840 /* genUminusFloat - unary minus for floating points                */
1841 /*-----------------------------------------------------------------*/
1842 static void
1843 genUminusFloat (operand * op, operand * result)
1844 {
1845   int size, offset = 0;
1846     
1847   D(emitcode (";", "genUminusFloat"););
1848   
1849   /* for this we just copy and then flip the bit */
1850     
1851   _startLazyDPSEvaluation ();
1852   size = AOP_SIZE (op) - 1;
1853
1854   while (size--)
1855   {
1856       aopPut (AOP (result),
1857               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1858               offset);
1859       offset++;
1860     }
1861   
1862   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1863
1864   emitcode ("cpl", "acc.7");
1865   aopPut (AOP (result), "a", offset);    
1866   _endLazyDPSEvaluation ();
1867 }
1868
1869 /*-----------------------------------------------------------------*/
1870 /* genUminus - unary minus code generation                         */
1871 /*-----------------------------------------------------------------*/
1872 static void
1873 genUminus (iCode * ic)
1874 {
1875   int offset, size;
1876   sym_link *optype;
1877
1878   D (emitcode (";", "genUminus "););
1879
1880   /* assign asmops */
1881   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1882   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1883
1884   /* if both in bit space then special
1885      case */
1886   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1887       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1888     {
1889
1890       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1891       emitcode ("cpl", "c");
1892       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1893       goto release;
1894     }
1895
1896   optype = operandType (IC_LEFT (ic));
1897
1898   /* if float then do float stuff */
1899   if (IS_FLOAT (optype))
1900     {
1901       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1902       goto release;
1903     }
1904
1905   /* otherwise subtract from zero */
1906   size = AOP_SIZE (IC_LEFT (ic));
1907   offset = 0;
1908   _startLazyDPSEvaluation ();
1909   while (size--)
1910     {
1911       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1912       if (!strcmp (l, "a"))
1913         {
1914           if (offset == 0)
1915             SETC;
1916           emitcode ("cpl", "a");
1917           emitcode ("addc", "a,#0");
1918         }
1919       else
1920         {
1921           if (offset == 0)
1922             CLRC;
1923           emitcode ("clr", "a");
1924           emitcode ("subb", "a,%s", l);
1925         }
1926       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1927     }
1928   _endLazyDPSEvaluation ();
1929
1930   /* if any remaining bytes in the result */
1931   /* we just need to propagate the sign   */
1932   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1933     {
1934       emitcode ("rlc", "a");
1935       emitcode ("subb", "a,acc");
1936       while (size--)
1937         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1938     }
1939
1940 release:
1941   /* release the aops */
1942   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1943   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1944 }
1945
1946 /*-----------------------------------------------------------------*/
1947 /* savermask - saves registers in the mask                         */
1948 /*-----------------------------------------------------------------*/
1949 static void savermask(bitVect *rs_mask)
1950 {
1951     int i;
1952     if (options.useXstack) {
1953         if (bitVectBitValue (rs_mask, R0_IDX))
1954             emitcode ("mov", "b,r0");
1955         emitcode ("mov", "r0,%s", spname);
1956         for (i = 0; i < ds390_nRegs; i++) {
1957             if (bitVectBitValue (rs_mask, i)) {
1958                 if (i == R0_IDX)
1959                     emitcode ("mov", "a,b");
1960                 else
1961                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1962                 emitcode ("movx", "@r0,a");
1963                 emitcode ("inc", "r0");
1964             }
1965         }
1966         emitcode ("mov", "%s,r0", spname);
1967         if (bitVectBitValue (rs_mask, R0_IDX))
1968             emitcode ("mov", "r0,b");
1969     } else {
1970         for (i = 0; i < ds390_nRegs; i++) {
1971             if (bitVectBitValue (rs_mask, i))
1972                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1973         }
1974     }
1975 }
1976
1977 /*-----------------------------------------------------------------*/
1978 /* saveRegisters - will look for a call and save the registers     */
1979 /*-----------------------------------------------------------------*/
1980 static void
1981 saveRegisters (iCode * lic)
1982 {
1983   iCode *ic;
1984   bitVect *rsave;
1985
1986   /* look for call */
1987   for (ic = lic; ic; ic = ic->next)
1988     if (ic->op == CALL || ic->op == PCALL)
1989       break;
1990
1991   if (!ic)
1992     {
1993       fprintf (stderr, "found parameter push with no function call\n");
1994       return;
1995     }
1996
1997   /* if the registers have been saved already then
1998      do nothing */
1999   if (ic->regsSaved 
2000       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2001     return ;
2002
2003   /* special case if DPTR alive across a function call then must save it 
2004      even though callee saves */
2005   if (IS_SYMOP(IC_LEFT(ic)) &&
2006       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2007       int i;
2008       rsave = newBitVect(ic->rMask->size);
2009       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2010           if (bitVectBitValue(ic->rMask,i))
2011               rsave = bitVectSetBit(rsave,i);
2012       }
2013       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2014   } else {
2015     /* safe the registers in use at this time but skip the
2016        ones for the result */
2017     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2018                            ds390_rUmaskForOp (IC_RESULT(ic)));
2019   }
2020   ic->regsSaved = 1;
2021   savermask(rsave);
2022 }
2023
2024 /*-----------------------------------------------------------------*/
2025 /* usavermask - restore registers with mask                        */
2026 /*-----------------------------------------------------------------*/
2027 static void unsavermask(bitVect *rs_mask)
2028 {
2029     int i;
2030     if (options.useXstack) {
2031         emitcode ("mov", "r0,%s", spname);
2032         for (i = ds390_nRegs; i >= 0; i--) {
2033             if (bitVectBitValue (rs_mask, i)) {
2034                 emitcode ("dec", "r0");
2035                 emitcode ("movx", "a,@r0");
2036                 if (i == R0_IDX)
2037                     emitcode ("mov", "b,a");
2038                 else
2039                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2040             }       
2041         }
2042         emitcode ("mov", "%s,r0", spname);
2043         if (bitVectBitValue (rs_mask, R0_IDX))
2044             emitcode ("mov", "r0,b");
2045     } else {
2046         for (i = ds390_nRegs; i >= 0; i--) {
2047             if (bitVectBitValue (rs_mask, i))
2048                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2049         }
2050     }
2051 }
2052
2053 /*-----------------------------------------------------------------*/
2054 /* unsaveRegisters - pop the pushed registers                      */
2055 /*-----------------------------------------------------------------*/
2056 static void
2057 unsaveRegisters (iCode * ic)
2058 {
2059   bitVect *rsave;
2060
2061   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2062       int i;
2063       rsave = newBitVect(ic->rMask->size);
2064       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2065           if (bitVectBitValue(ic->rMask,i))
2066               rsave = bitVectSetBit(rsave,i);
2067       }
2068       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2069   } else {
2070     /* restore the registers in use at this time but skip the
2071        ones for the result */
2072     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2073                            ds390_rUmaskForOp (IC_RESULT(ic)));
2074   }
2075   unsavermask(rsave);
2076 }
2077
2078
2079 /*-----------------------------------------------------------------*/
2080 /* pushSide -                */
2081 /*-----------------------------------------------------------------*/
2082 static void
2083 pushSide (operand * oper, int size)
2084 {
2085   int offset = 0;
2086   _startLazyDPSEvaluation ();
2087   while (size--)
2088     {
2089       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2090       if (AOP_TYPE (oper) != AOP_REG &&
2091           AOP_TYPE (oper) != AOP_DIR &&
2092           strcmp (l, "a"))
2093         {
2094           emitcode ("mov", "a,%s", l);
2095           emitcode ("push", "acc");
2096         }
2097       else
2098         emitcode ("push", "%s", l);
2099     }
2100   _endLazyDPSEvaluation ();
2101 }
2102
2103 /*-----------------------------------------------------------------*/
2104 /* assignResultValue -               */
2105 /*-----------------------------------------------------------------*/
2106 static void
2107 assignResultValue (operand * oper)
2108 {
2109   int offset = 0;
2110   int size = AOP_SIZE (oper);
2111   bool pushedAcc = FALSE;
2112
2113   if (size == fReturnSizeDS390)
2114   {
2115       /* I don't think this case can ever happen... */
2116       /* ACC is the last part of this. If writing the result
2117        * uses AC, we must preserve it.
2118        */
2119       if (AOP_NEEDSACC(oper))
2120       {
2121           emitcode(";", "assignResultValue special case for ACC.");
2122           emitcode("push", "acc");
2123           pushedAcc = TRUE;
2124           size--;
2125       }
2126   }
2127     
2128     
2129   _startLazyDPSEvaluation ();
2130   while (size--)
2131     {
2132       aopPut (AOP (oper), fReturn[offset], offset);
2133       offset++;
2134     }
2135   _endLazyDPSEvaluation ();
2136     
2137   if (pushedAcc)
2138     {
2139         emitcode("pop", "acc");
2140         aopPut(AOP(oper), "a", offset);
2141     }
2142 }
2143
2144
2145 /*-----------------------------------------------------------------*/
2146 /* genXpush - pushes onto the external stack                       */
2147 /*-----------------------------------------------------------------*/
2148 static void
2149 genXpush (iCode * ic)
2150 {
2151   asmop *aop = newAsmop (0);
2152   regs *r;
2153   int size, offset = 0;
2154
2155   D (emitcode (";", "genXpush ");
2156     );
2157
2158   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2159   r = getFreePtr (ic, &aop, FALSE);
2160
2161
2162   emitcode ("mov", "%s,_spx", r->name);
2163
2164   size = AOP_SIZE (IC_LEFT (ic));
2165   _startLazyDPSEvaluation ();
2166   while (size--)
2167     {
2168
2169       MOVA (aopGet (AOP (IC_LEFT (ic)),
2170                         offset++, FALSE, FALSE, NULL));
2171       emitcode ("movx", "@%s,a", r->name);
2172       emitcode ("inc", "%s", r->name);
2173
2174     }
2175   _endLazyDPSEvaluation ();
2176
2177
2178   emitcode ("mov", "_spx,%s", r->name);
2179
2180   freeAsmop (NULL, aop, ic, TRUE);
2181   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2182 }
2183
2184 /*-----------------------------------------------------------------*/
2185 /* genIpush - generate code for pushing this gets a little complex  */
2186 /*-----------------------------------------------------------------*/
2187 static void
2188 genIpush (iCode * ic)
2189 {
2190   int size, offset = 0;
2191   char *l;
2192
2193   D (emitcode (";", "genIpush ");
2194     );
2195
2196   /* if this is not a parm push : ie. it is spill push
2197      and spill push is always done on the local stack */
2198   if (!ic->parmPush)
2199     {
2200
2201       /* and the item is spilt then do nothing */
2202       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2203         return;
2204
2205       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2206       size = AOP_SIZE (IC_LEFT (ic));
2207       /* push it on the stack */
2208       _startLazyDPSEvaluation ();
2209       while (size--)
2210         {
2211           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2212           if (*l == '#')
2213             {
2214               MOVA (l);
2215               l = "acc";
2216             }
2217           emitcode ("push", "%s", l);
2218         }
2219       _endLazyDPSEvaluation ();
2220       return;
2221     }
2222
2223   /* this is a paramter push: in this case we call
2224      the routine to find the call and save those
2225      registers that need to be saved */
2226   saveRegisters (ic);
2227
2228   /* if use external stack then call the external
2229      stack pushing routine */
2230   if (options.useXstack)
2231     {
2232       genXpush (ic);
2233       return;
2234     }
2235
2236   /* then do the push */
2237   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2238
2239   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2240   size = AOP_SIZE (IC_LEFT (ic));
2241
2242   _startLazyDPSEvaluation ();
2243   while (size--)
2244     {
2245       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2246       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2247           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2248           strcmp (l, "acc"))
2249         {
2250           emitcode ("mov", "a,%s", l);
2251           emitcode ("push", "acc");
2252         }
2253       else
2254         {
2255             emitcode ("push", "%s", l);
2256         }
2257     }
2258   _endLazyDPSEvaluation ();
2259
2260   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2261 }
2262
2263 /*-----------------------------------------------------------------*/
2264 /* genIpop - recover the registers: can happen only for spilling   */
2265 /*-----------------------------------------------------------------*/
2266 static void
2267 genIpop (iCode * ic)
2268 {
2269   int size, offset;
2270
2271   D (emitcode (";", "genIpop ");
2272     );
2273
2274
2275   /* if the temp was not pushed then */
2276   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2277     return;
2278
2279   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2280   size = AOP_SIZE (IC_LEFT (ic));
2281   offset = (size - 1);
2282   _startLazyDPSEvaluation ();
2283   while (size--)
2284     {
2285       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2286                                      FALSE, TRUE, NULL));
2287     }
2288   _endLazyDPSEvaluation ();
2289
2290   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2291 }
2292
2293 /*-----------------------------------------------------------------*/
2294 /* unsaveRBank - restores the resgister bank from stack            */
2295 /*-----------------------------------------------------------------*/
2296 static void
2297 unsaveRBank (int bank, iCode * ic, bool popPsw)
2298 {
2299   int i;
2300   asmop *aop = NULL;
2301   regs *r = NULL;
2302
2303   if (options.useXstack)
2304   {
2305       if (!ic)
2306       {
2307           /* Assume r0 is available for use. */
2308           r = ds390_regWithIdx (R0_IDX);;          
2309       } 
2310       else
2311       {
2312           aop = newAsmop (0);
2313           r = getFreePtr (ic, &aop, FALSE);
2314       }
2315       emitcode ("mov", "%s,_spx", r->name);      
2316   }
2317   
2318   if (popPsw)
2319     {
2320       if (options.useXstack)
2321       {
2322           emitcode ("movx", "a,@%s", r->name);
2323           emitcode ("mov", "psw,a");
2324           emitcode ("dec", "%s", r->name);
2325         }
2326       else
2327       {
2328         emitcode ("pop", "psw");
2329       }
2330     }
2331
2332   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2333     {
2334       if (options.useXstack)
2335         {
2336           emitcode ("movx", "a,@%s", r->name);
2337           emitcode ("mov", "(%s+%d),a",
2338                     regs390[i].base, 8 * bank + regs390[i].offset);
2339           emitcode ("dec", "%s", r->name);
2340
2341         }
2342       else
2343         emitcode ("pop", "(%s+%d)",
2344                   regs390[i].base, 8 * bank + regs390[i].offset);
2345     }
2346
2347   if (options.useXstack)
2348     {
2349       emitcode ("mov", "_spx,%s", r->name);
2350     }
2351     
2352   if (aop)
2353   {
2354       freeAsmop (NULL, aop, ic, TRUE);  
2355   }    
2356 }
2357
2358 /*-----------------------------------------------------------------*/
2359 /* saveRBank - saves an entire register bank on the stack          */
2360 /*-----------------------------------------------------------------*/
2361 static void
2362 saveRBank (int bank, iCode * ic, bool pushPsw)
2363 {
2364   int i;
2365   asmop *aop = NULL;
2366   regs *r = NULL;
2367
2368   if (options.useXstack)
2369     {
2370         if (!ic)
2371         {
2372           /* Assume r0 is available for use. */
2373                   r = ds390_regWithIdx (R0_IDX);;
2374         }
2375         else
2376         {
2377           aop = newAsmop (0);
2378           r = getFreePtr (ic, &aop, FALSE);
2379         }
2380         emitcode ("mov", "%s,_spx", r->name);    
2381     }
2382
2383   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2384     {
2385       if (options.useXstack)
2386         {
2387           emitcode ("inc", "%s", r->name);
2388           emitcode ("mov", "a,(%s+%d)",
2389                     regs390[i].base, 8 * bank + regs390[i].offset);
2390           emitcode ("movx", "@%s,a", r->name);
2391         }
2392       else
2393         emitcode ("push", "(%s+%d)",
2394                   regs390[i].base, 8 * bank + regs390[i].offset);
2395     }
2396
2397   if (pushPsw)
2398     {
2399       if (options.useXstack)
2400         {
2401           emitcode ("mov", "a,psw");
2402           emitcode ("movx", "@%s,a", r->name);
2403           emitcode ("inc", "%s", r->name);
2404           emitcode ("mov", "_spx,%s", r->name);
2405         }
2406       else
2407       {
2408         emitcode ("push", "psw");
2409       }
2410
2411       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2412     }
2413   
2414   if (aop)
2415   {
2416        freeAsmop (NULL, aop, ic, TRUE);
2417   }    
2418     
2419   if (ic)
2420   {  
2421       ic->bankSaved = 1;
2422   }
2423 }
2424
2425 /*-----------------------------------------------------------------*/
2426 /* genSend - gen code for SEND                                     */
2427 /*-----------------------------------------------------------------*/
2428 static void genSend(set *sendSet)
2429 {
2430     iCode *sic;
2431     int sendCount = 0 ;
2432     static int rb1_count = 0;
2433
2434     for (sic = setFirstItem (sendSet); sic;
2435          sic = setNextItem (sendSet)) {     
2436         int size, offset = 0;
2437         
2438         size=getSize(operandType(IC_LEFT(sic)));
2439         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2440         if (sendCount == 0) { /* first parameter */
2441             // we know that dpl(hxb) is the result, so
2442             rb1_count = 0 ;
2443             _startLazyDPSEvaluation ();
2444             if (size>1) {
2445                 aopOp (IC_LEFT (sic), sic, FALSE, 
2446                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2447             } else {
2448                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2449             }
2450             while (size--) {
2451                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2452                                   FALSE, FALSE, NULL);
2453                 if (strcmp (l, fReturn[offset])) {
2454                     emitcode ("mov", "%s,%s",
2455                               fReturn[offset],
2456                               l);
2457                 }
2458                 offset++;
2459             }
2460             _endLazyDPSEvaluation ();
2461             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2462             rb1_count =0;
2463         } else { /* if more parameter in registers */
2464             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2465             while (size--) {
2466                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2467                                                                 FALSE, FALSE, NULL));
2468             }
2469             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2470         }
2471         sendCount++;
2472     }
2473 }
2474
2475 static void
2476 adjustEsp(const char *reg)
2477 {
2478     emitcode ("anl","%s,#3", reg);
2479     if (TARGET_IS_DS400)
2480     {
2481         emitcode ("orl","%s,#!constbyte",
2482                   reg,
2483                   (options.stack_loc >> 8) & 0xff);
2484     }
2485 }
2486
2487 /*-----------------------------------------------------------------*/
2488 /* genCall - generates a call statement                            */
2489 /*-----------------------------------------------------------------*/
2490 static void
2491 genCall (iCode * ic)
2492 {
2493   sym_link *dtype;
2494   bool restoreBank = FALSE;
2495   bool swapBanks = FALSE;
2496
2497   D (emitcode (";", "genCall "););
2498
2499   /* if we are calling a not _naked function that is not using
2500      the same register bank then we need to save the
2501      destination registers on the stack */
2502   dtype = operandType (IC_LEFT (ic));
2503   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2504       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2505       IFFUNC_ISISR (currFunc->type))
2506   {
2507       if (!ic->bankSaved) 
2508       {
2509            /* This is unexpected; the bank should have been saved in
2510             * genFunction.
2511             */
2512            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2513            restoreBank = TRUE;
2514       }
2515       swapBanks = TRUE;
2516   }
2517   
2518     /* if caller saves & we have not saved then */
2519     if (!ic->regsSaved)
2520       saveRegisters (ic);
2521   
2522   /* if send set is not empty the assign */
2523   /* We've saved all the registers we care about;
2524   * therefore, we may clobber any register not used
2525   * in the calling convention (i.e. anything not in
2526   * fReturn.
2527   */
2528   if (_G.sendSet)
2529     {
2530         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2531             genSend(reverseSet(_G.sendSet));
2532         } else {
2533             genSend(_G.sendSet);
2534         }
2535       _G.sendSet = NULL;
2536     }  
2537     
2538   if (swapBanks)
2539   {
2540         emitcode ("mov", "psw,#!constbyte", 
2541            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2542   }
2543
2544   /* make the call */
2545   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2546                             OP_SYMBOL (IC_LEFT (ic))->rname :
2547                             OP_SYMBOL (IC_LEFT (ic))->name));
2548
2549   if (swapBanks)
2550   {
2551        emitcode ("mov", "psw,#!constbyte", 
2552           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2553   }
2554
2555   /* if we need assign a result value */
2556   if ((IS_ITEMP (IC_RESULT (ic)) &&
2557        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2558         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2559         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2560       IS_TRUE_SYMOP (IC_RESULT (ic)))
2561     {
2562       if (isOperandInFarSpace (IC_RESULT (ic))
2563           && getSize (operandType (IC_RESULT (ic))) <= 2)
2564         {
2565           int size = getSize (operandType (IC_RESULT (ic)));
2566
2567           /* Special case for 1 or 2 byte return in far space. */
2568           MOVA (fReturn[0]);
2569           if (size > 1)
2570             {
2571               emitcode ("mov", "b,%s", fReturn[1]);
2572             }
2573
2574           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2575           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2576
2577           if (size > 1)
2578             {
2579               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2580             }
2581           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2582         }
2583       else
2584         {
2585           _G.accInUse++;
2586           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2587           _G.accInUse--;
2588
2589           assignResultValue (IC_RESULT (ic));
2590
2591           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2592         }
2593     }
2594
2595   /* adjust the stack for parameters if
2596      required */
2597   if (ic->parmBytes) {
2598       int i;
2599       if (options.stack10bit) {
2600           if (ic->parmBytes <= 10) {
2601               emitcode(";","stack adjustment for parms");
2602               for (i=0; i < ic->parmBytes ; i++) {
2603                   emitcode("pop","acc");
2604               }
2605           } else {            
2606               PROTECT_SP;
2607               emitcode ("clr","c");
2608               emitcode ("mov","a,sp");
2609               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2610               emitcode ("mov","sp,a");
2611               emitcode ("mov","a,esp");
2612               adjustEsp("a");
2613               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2614               emitcode ("mov","esp,a");   
2615               UNPROTECT_SP;
2616           }
2617       } else {
2618           if (ic->parmBytes > 3) {
2619               emitcode ("mov", "a,%s", spname);
2620               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2621               emitcode ("mov", "%s,a", spname);
2622           } else
2623               for (i = 0; i < ic->parmBytes; i++)
2624                   emitcode ("dec", "%s", spname);
2625       }
2626   }
2627
2628   /* if we hade saved some registers then unsave them */
2629   if (ic->regsSaved)
2630     unsaveRegisters (ic);
2631
2632   /* if register bank was saved then pop them */
2633   if (restoreBank)
2634     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2635 }
2636
2637 /*-----------------------------------------------------------------*/
2638 /* genPcall - generates a call by pointer statement                */
2639 /*-----------------------------------------------------------------*/
2640 static void
2641 genPcall (iCode * ic)
2642 {
2643   sym_link *dtype;
2644   symbol *rlbl = newiTempLabel (NULL);
2645   bool restoreBank=FALSE;
2646
2647   D (emitcode (";", "genPcall ");
2648     );
2649
2650
2651   /* if caller saves & we have not saved then */
2652   if (!ic->regsSaved)
2653     saveRegisters (ic);
2654
2655   /* if we are calling a function that is not using
2656      the same register bank then we need to save the
2657      destination registers on the stack */
2658   dtype = operandType (IC_LEFT (ic));
2659   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2660       IFFUNC_ISISR (currFunc->type) &&
2661       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2662     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2663     restoreBank=TRUE;
2664   }
2665
2666   /* push the return address on to the stack */
2667   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2668   emitcode ("push", "acc");
2669   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2670   emitcode ("push", "acc");
2671
2672   if (options.model == MODEL_FLAT24)
2673     {
2674       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2675       emitcode ("push", "acc");
2676     }
2677
2678   /* now push the calling address */
2679   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2680
2681   pushSide (IC_LEFT (ic), FPTRSIZE);
2682
2683   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2684
2685   /* if send set is not empty the assign */
2686   if (_G.sendSet)
2687     {
2688         genSend(reverseSet(_G.sendSet));
2689         _G.sendSet = NULL;
2690     }
2691
2692   emitcode ("ret", "");
2693   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2694
2695
2696   /* if we need assign a result value */
2697   if ((IS_ITEMP (IC_RESULT (ic)) &&
2698        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2699         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2700       IS_TRUE_SYMOP (IC_RESULT (ic)))
2701     {
2702
2703       _G.accInUse++;
2704       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2705       _G.accInUse--;
2706
2707       assignResultValue (IC_RESULT (ic));
2708
2709       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2710     }
2711
2712   /* adjust the stack for parameters if
2713      required */
2714   if (ic->parmBytes)
2715     {
2716       int i;
2717       if (options.stack10bit) {
2718           if (ic->parmBytes <= 10) {
2719               emitcode(";","stack adjustment for parms");
2720               for (i=0; i < ic->parmBytes ; i++) {
2721                   emitcode("pop","acc");
2722               }
2723           } else {            
2724               PROTECT_SP;
2725               emitcode ("clr","c");
2726               emitcode ("mov","a,sp");
2727               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2728               emitcode ("mov","sp,a");
2729               emitcode ("mov","a,esp");
2730               adjustEsp("a");
2731               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2732               emitcode ("mov","esp,a");   
2733               UNPROTECT_SP;
2734           }
2735       } else {
2736           if (ic->parmBytes > 3) {
2737               emitcode ("mov", "a,%s", spname);
2738               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2739               emitcode ("mov", "%s,a", spname);
2740           }
2741           else
2742               for (i = 0; i < ic->parmBytes; i++)
2743                   emitcode ("dec", "%s", spname);
2744           
2745       }
2746     }
2747   /* if register bank was saved then unsave them */
2748   if (restoreBank)
2749     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2750   
2751   /* if we hade saved some registers then
2752      unsave them */
2753   if (ic->regsSaved)
2754     unsaveRegisters (ic);
2755
2756 }
2757
2758 /*-----------------------------------------------------------------*/
2759 /* resultRemat - result  is rematerializable                       */
2760 /*-----------------------------------------------------------------*/
2761 static int
2762 resultRemat (iCode * ic)
2763 {
2764   if (SKIP_IC (ic) || ic->op == IFX)
2765     return 0;
2766
2767   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2768     {
2769       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2770       if (sym->remat && !POINTER_SET (ic))
2771         return 1;
2772     }
2773
2774   return 0;
2775 }
2776
2777 #if defined(__BORLANDC__) || defined(_MSC_VER)
2778 #define STRCASECMP stricmp
2779 #else
2780 #define STRCASECMP strcasecmp
2781 #endif
2782
2783 /*-----------------------------------------------------------------*/
2784 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2785 /*-----------------------------------------------------------------*/
2786 static int
2787 regsCmp(void *p1, void *p2)
2788 {
2789   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2790 }
2791
2792 static bool
2793 inExcludeList (char *s)
2794 {
2795   const char *p = setFirstItem(options.excludeRegsSet);
2796
2797   if (p == NULL || STRCASECMP(p, "none") == 0)
2798     return FALSE;
2799
2800
2801   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2802 }
2803
2804 /*-----------------------------------------------------------------*/
2805 /* genFunction - generated code for function entry                 */
2806 /*-----------------------------------------------------------------*/
2807 static void
2808 genFunction (iCode * ic)
2809 {
2810   symbol *sym;
2811   sym_link *ftype;
2812   bool   switchedPSW = FALSE;
2813
2814   D (emitcode (";", "genFunction "););
2815
2816   _G.nRegsSaved = 0;
2817   /* create the function header */
2818   emitcode (";", "-----------------------------------------");
2819   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2820   emitcode (";", "-----------------------------------------");
2821
2822   emitcode ("", "%s:", sym->rname);
2823   ftype = operandType (IC_LEFT (ic));
2824
2825   if (IFFUNC_ISNAKED(ftype))
2826   {
2827       emitcode(";", "naked function: no prologue.");
2828       return;
2829   }
2830   
2831   if (options.stack_probe) 
2832       emitcode ("lcall","__stack_probe");
2833   /* if critical function then turn interrupts off */
2834   if (IFFUNC_ISCRITICAL (ftype))
2835     emitcode ("clr", "ea");
2836
2837   /* here we need to generate the equates for the
2838      register bank if required */
2839   if (FUNC_REGBANK (ftype) != rbank)
2840     {
2841       int i;
2842
2843       rbank = FUNC_REGBANK (ftype);
2844       for (i = 0; i < ds390_nRegs; i++)
2845         {
2846           if (regs390[i].print) {
2847               if (strcmp (regs390[i].base, "0") == 0)
2848                   emitcode ("", "%s !equ !constbyte",
2849                             regs390[i].dname,
2850                             8 * rbank + regs390[i].offset);
2851               else
2852                   emitcode ("", "%s !equ %s + !constbyte",
2853                             regs390[i].dname,
2854                             regs390[i].base,
2855                             8 * rbank + regs390[i].offset);
2856           }
2857         }
2858     }
2859
2860   /* if this is an interrupt service routine then
2861      save acc, b, dpl, dph  */
2862   if (IFFUNC_ISISR (sym->type))
2863       { /* is ISR */
2864       if (!inExcludeList ("acc"))
2865         emitcode ("push", "acc");
2866       if (!inExcludeList ("b"))
2867         emitcode ("push", "b");
2868       if (!inExcludeList ("dpl"))
2869         emitcode ("push", "dpl");
2870       if (!inExcludeList ("dph"))
2871         emitcode ("push", "dph");
2872       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2873         {
2874           emitcode ("push", "dpx");
2875           /* Make sure we're using standard DPTR */
2876           emitcode ("push", "dps");
2877           emitcode ("mov", "dps,#0");
2878           if (options.stack10bit)
2879             {
2880               /* This ISR could conceivably use DPTR2. Better save it. */
2881               emitcode ("push", "dpl1");
2882               emitcode ("push", "dph1");
2883               emitcode ("push", "dpx1");
2884               emitcode ("push",  DP2_RESULT_REG);
2885             }
2886         }
2887       /* if this isr has no bank i.e. is going to
2888          run with bank 0 , then we need to save more
2889          registers :-) */
2890       if (!FUNC_REGBANK (sym->type))
2891         {
2892             int i;
2893
2894           /* if this function does not call any other
2895              function then we can be economical and
2896              save only those registers that are used */
2897           if (!IFFUNC_HASFCALL(sym->type))
2898             {
2899
2900               /* if any registers used */
2901               if (sym->regsUsed)
2902                 {
2903                   /* save the registers used */
2904                   for (i = 0; i < sym->regsUsed->size; i++)
2905                     {
2906                       if (bitVectBitValue (sym->regsUsed, i) ||
2907                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2908                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2909                     }
2910                 }
2911
2912             }
2913           else
2914             {
2915               /* this function has  a function call cannot
2916                  determines register usage so we will have to push the
2917                  entire bank */
2918               saveRBank (0, ic, FALSE);
2919               if (options.parms_in_bank1) {
2920                   for (i=0; i < 8 ; i++ ) {
2921                       emitcode ("push","%s",rb1regs[i]);
2922                   }
2923               }
2924             }
2925         }
2926         else
2927         {
2928             /* This ISR uses a non-zero bank.
2929              *
2930              * We assume that the bank is available for our
2931              * exclusive use.
2932              *
2933              * However, if this ISR calls a function which uses some
2934              * other bank, we must save that bank entirely.
2935              */
2936             unsigned long banksToSave = 0;
2937             
2938             if (IFFUNC_HASFCALL(sym->type))
2939             {
2940
2941 #define MAX_REGISTER_BANKS 4
2942
2943                 iCode *i;
2944                 int ix;
2945
2946                 for (i = ic; i; i = i->next)
2947                 {
2948                     if (i->op == ENDFUNCTION)
2949                     {
2950                         /* we got to the end OK. */
2951                         break;
2952                     }
2953                     
2954                     if (i->op == CALL)
2955                     {
2956                         sym_link *dtype;
2957                         
2958                         dtype = operandType (IC_LEFT(i));
2959                         if (dtype 
2960                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2961                         {
2962                              /* Mark this bank for saving. */
2963                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2964                              {
2965                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2966                              }
2967                              else
2968                              {
2969                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2970                              }
2971                              
2972                              /* And note that we don't need to do it in 
2973                               * genCall.
2974                               */
2975                              i->bankSaved = 1;
2976                         }
2977                     }
2978                     if (i->op == PCALL)
2979                     {
2980                         /* This is a mess; we have no idea what
2981                          * register bank the called function might
2982                          * use.
2983                          *
2984                          * The only thing I can think of to do is
2985                          * throw a warning and hope.
2986                          */
2987                         werror(W_FUNCPTR_IN_USING_ISR);   
2988                     }
2989                 }
2990
2991                 if (banksToSave && options.useXstack)
2992                 {
2993                     /* Since we aren't passing it an ic, 
2994                      * saveRBank will assume r0 is available to abuse.
2995                      *
2996                      * So switch to our (trashable) bank now, so
2997                      * the caller's R0 isn't trashed.
2998                      */
2999                     emitcode ("push", "psw");
3000                     emitcode ("mov", "psw,#!constbyte", 
3001                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3002                     switchedPSW = TRUE;
3003                 }
3004                 
3005                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3006                 {
3007                      if (banksToSave & (1 << ix))
3008                      {
3009                          saveRBank(ix, NULL, FALSE);
3010                      }
3011                 }
3012             }
3013             // TODO: this needs a closer look
3014             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3015         }
3016     }
3017   else
3018     {
3019       /* if callee-save to be used for this function
3020          then save the registers being used in this function */
3021       if (IFFUNC_CALLEESAVES(sym->type))
3022         {
3023           int i;
3024
3025           /* if any registers used */
3026           if (sym->regsUsed)
3027             {
3028               /* save the registers used */
3029               for (i = 0; i < sym->regsUsed->size; i++)
3030                 {
3031                   if (bitVectBitValue (sym->regsUsed, i) ||
3032                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3033                     {
3034                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3035                       _G.nRegsSaved++;
3036                     }
3037                 }
3038             }
3039         }
3040     }
3041
3042   /* set the register bank to the desired value */
3043   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3044    && !switchedPSW)
3045     {
3046       emitcode ("push", "psw");
3047       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3048     }
3049
3050   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3051        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3052       if (options.stack10bit) {
3053           emitcode ("push","_bpx");
3054           emitcode ("push","_bpx+1");
3055           emitcode ("mov","_bpx,%s",spname);
3056           emitcode ("mov","_bpx+1,esp");
3057           adjustEsp("_bpx+1");
3058       } else {
3059           if (options.useXstack) {
3060               emitcode ("mov", "r0,%s", spname);
3061               emitcode ("mov", "a,_bp");
3062               emitcode ("movx", "@r0,a");
3063               emitcode ("inc", "%s", spname);
3064           } else {
3065               /* set up the stack */
3066               emitcode ("push", "_bp"); /* save the callers stack  */
3067           }
3068           emitcode ("mov", "_bp,%s", spname);
3069       }
3070   }
3071
3072   /* adjust the stack for the function */
3073   if (sym->stack) {
3074       int i = sym->stack;
3075       if (options.stack10bit) {
3076           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3077           assert (sym->recvSize <= 4);
3078           if (sym->stack <= 8) {
3079               while (i--) emitcode ("push","acc");
3080           } else {
3081               PROTECT_SP;
3082               emitcode ("mov","a,sp");
3083               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3084               emitcode ("mov","sp,a");
3085               emitcode ("mov","a,esp");
3086               adjustEsp("a");
3087               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3088               emitcode ("mov","esp,a");
3089               UNPROTECT_SP;
3090           }
3091       } else {
3092           if (i > 256)
3093               werror (W_STACK_OVERFLOW, sym->name);
3094           
3095           if (i > 3 && sym->recvSize < 4) {
3096               
3097               emitcode ("mov", "a,sp");
3098               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3099               emitcode ("mov", "sp,a");
3100               
3101           } else
3102               while (i--)
3103                   emitcode ("inc", "sp");
3104       }
3105   }
3106
3107   if (sym->xstack)
3108     {
3109
3110       emitcode ("mov", "a,_spx");
3111       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3112       emitcode ("mov", "_spx,a");
3113     }
3114
3115 }
3116
3117 /*-----------------------------------------------------------------*/
3118 /* genEndFunction - generates epilogue for functions               */
3119 /*-----------------------------------------------------------------*/
3120 static void
3121 genEndFunction (iCode * ic)
3122 {
3123   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3124
3125   D (emitcode (";", "genEndFunction "););
3126
3127   if (IFFUNC_ISNAKED(sym->type))
3128   {
3129       emitcode(";", "naked function: no epilogue.");
3130       return;
3131   }
3132
3133   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3134        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3135
3136       if (options.stack10bit) {
3137           PROTECT_SP;     
3138           emitcode ("mov", "sp,_bpx", spname);
3139           emitcode ("mov", "esp,_bpx+1", spname);
3140           UNPROTECT_SP;
3141       } else {
3142           emitcode ("mov", "%s,_bp", spname);
3143       }
3144   }
3145
3146   /* if use external stack but some variables were
3147      added to the local stack then decrement the
3148      local stack */
3149   if (options.useXstack && sym->stack) {
3150       emitcode ("mov", "a,sp");
3151       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3152       emitcode ("mov", "sp,a");
3153   }
3154
3155
3156   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3157        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3158
3159       if (options.useXstack) {
3160           emitcode ("mov", "r0,%s", spname);
3161           emitcode ("movx", "a,@r0");
3162           emitcode ("mov", "_bp,a");
3163           emitcode ("dec", "%s", spname);
3164       } else {
3165           if (options.stack10bit) {
3166               emitcode ("pop", "_bpx+1");
3167               emitcode ("pop", "_bpx");
3168           } else {
3169               emitcode ("pop", "_bp");
3170           }
3171       }
3172   }
3173
3174   /* restore the register bank  */
3175   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3176   {
3177     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3178      || !options.useXstack)
3179     {
3180         /* Special case of ISR using non-zero bank with useXstack
3181          * is handled below.
3182          */
3183         emitcode ("pop", "psw");
3184     }
3185   } 
3186
3187   if (IFFUNC_ISISR (sym->type))
3188       { /* is ISR */  
3189
3190       /* now we need to restore the registers */
3191       /* if this isr has no bank i.e. is going to
3192          run with bank 0 , then we need to save more
3193          registers :-) */
3194       if (!FUNC_REGBANK (sym->type))
3195         {
3196             int i;
3197           /* if this function does not call any other
3198              function then we can be economical and
3199              save only those registers that are used */
3200           if (!IFFUNC_HASFCALL(sym->type))
3201             {
3202
3203               /* if any registers used */
3204               if (sym->regsUsed)
3205                 {
3206                   /* save the registers used */
3207                   for (i = sym->regsUsed->size; i >= 0; i--)
3208                     {
3209                       if (bitVectBitValue (sym->regsUsed, i) ||
3210                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3211                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3212                     }
3213                 }
3214
3215             }
3216           else
3217             {
3218               /* this function has  a function call cannot
3219                  determines register usage so we will have to pop the
3220                  entire bank */
3221               if (options.parms_in_bank1) {
3222                   for (i = 7 ; i >= 0 ; i-- ) {
3223                       emitcode ("pop","%s",rb1regs[i]);
3224                   }
3225               }
3226               unsaveRBank (0, ic, FALSE);
3227             }
3228         }
3229         else
3230         {
3231             /* This ISR uses a non-zero bank.
3232              *
3233              * Restore any register banks saved by genFunction
3234              * in reverse order.
3235              */
3236             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3237             int ix;
3238           
3239             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3240             {
3241                 if (savedBanks & (1 << ix))
3242                 {
3243                     unsaveRBank(ix, NULL, FALSE);
3244                 }
3245             }
3246             
3247             if (options.useXstack)
3248             {
3249                 /* Restore bank AFTER calling unsaveRBank,
3250                  * since it can trash r0.
3251                  */
3252                 emitcode ("pop", "psw");
3253             }
3254         }
3255
3256       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3257         {
3258           if (options.stack10bit)
3259             {
3260               emitcode ("pop", DP2_RESULT_REG);
3261               emitcode ("pop", "dpx1");
3262               emitcode ("pop", "dph1");
3263               emitcode ("pop", "dpl1");
3264             }
3265           emitcode ("pop", "dps");
3266           emitcode ("pop", "dpx");
3267         }
3268       if (!inExcludeList ("dph"))
3269         emitcode ("pop", "dph");
3270       if (!inExcludeList ("dpl"))
3271         emitcode ("pop", "dpl");
3272       if (!inExcludeList ("b"))
3273         emitcode ("pop", "b");
3274       if (!inExcludeList ("acc"))
3275         emitcode ("pop", "acc");
3276
3277       if (IFFUNC_ISCRITICAL (sym->type))
3278         emitcode ("setb", "ea");
3279
3280       /* if debug then send end of function */
3281       if (options.debug && currFunc) {
3282           _G.debugLine = 1;
3283           emitcode ("", "C$%s$%d$%d$%d ==.",
3284                     FileBaseName (ic->filename), currFunc->lastLine,
3285                     ic->level, ic->block);
3286           if (IS_STATIC (currFunc->etype))
3287             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3288           else
3289             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3290           _G.debugLine = 0;
3291         }
3292
3293       emitcode ("reti", "");
3294     }
3295   else
3296     {
3297       if (IFFUNC_ISCRITICAL (sym->type))
3298         emitcode ("setb", "ea");
3299
3300       if (IFFUNC_CALLEESAVES(sym->type))
3301         {
3302           int i;
3303
3304           /* if any registers used */
3305           if (sym->regsUsed)
3306             {
3307               /* save the registers used */
3308               for (i = sym->regsUsed->size; i >= 0; i--)
3309                 {
3310                   if (bitVectBitValue (sym->regsUsed, i) ||
3311                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3312                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3313                 }
3314             }
3315
3316         }
3317
3318       /* if debug then send end of function */
3319       if (options.debug && currFunc)
3320         {
3321           _G.debugLine = 1;
3322           emitcode ("", "C$%s$%d$%d$%d ==.",
3323                     FileBaseName (ic->filename), currFunc->lastLine,
3324                     ic->level, ic->block);
3325           if (IS_STATIC (currFunc->etype))
3326             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3327           else
3328             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3329           _G.debugLine = 0;
3330         }
3331
3332       emitcode ("ret", "");
3333     }
3334
3335 }
3336
3337 /*-----------------------------------------------------------------*/
3338 /* genJavaNativeRet - generate code for return JavaNative          */
3339 /*-----------------------------------------------------------------*/
3340 static void genJavaNativeRet(iCode *ic)
3341 {
3342     int i, size;
3343
3344     aopOp (IC_LEFT (ic), ic, FALSE, 
3345            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3346     size = AOP_SIZE (IC_LEFT (ic));
3347
3348     assert (size <= 4);
3349
3350     /* it is assigned to GPR0-R3 then push them */
3351     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3352         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3353         for (i = 0 ; i < size ; i++ ) {
3354             emitcode ("push","%s",
3355                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3356         }
3357         for (i = (size-1) ; i >= 0 ; i--) {
3358             emitcode ("pop","a%s",javaRet[i]);
3359         }
3360     } else {
3361         for (i = 0 ; i < size ; i++) 
3362             emitcode ("mov","%s,%s",javaRet[i],
3363                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3364     }
3365     for (i = size ; i < 4 ; i++ )
3366             emitcode ("mov","%s,#0",javaRet[i]);
3367     return;
3368 }
3369
3370 /*-----------------------------------------------------------------*/
3371 /* genRet - generate code for return statement                     */
3372 /*-----------------------------------------------------------------*/
3373 static void
3374 genRet (iCode * ic)
3375 {
3376   int size, offset = 0, pushed = 0;
3377
3378   D (emitcode (";", "genRet "););
3379
3380   /* if we have no return value then
3381      just generate the "ret" */
3382   if (!IC_LEFT (ic))
3383     goto jumpret;
3384
3385   /* if this is a JavaNative function then return 
3386      value in different register */
3387   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3388       genJavaNativeRet(ic);
3389       goto jumpret;
3390   }
3391   /* we have something to return then
3392      move the return value into place */
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   _startLazyDPSEvaluation ();
3398   while (size--)
3399     {
3400       char *l;
3401       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3402         {
3403           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3404                       FALSE, TRUE, NULL);
3405           emitcode ("push", "%s", l);
3406           pushed++;
3407         }
3408       else
3409         {
3410           /* Since A is the last element of fReturn,
3411            * is is OK to clobber it in the aopGet.
3412            */
3413           l = aopGet (AOP (IC_LEFT (ic)), offset,
3414                       FALSE, FALSE, NULL);
3415           if (strcmp (fReturn[offset], l))
3416             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3417         }
3418     }
3419   _endLazyDPSEvaluation ();
3420
3421   if (pushed)
3422     {
3423       while (pushed)
3424         {
3425           pushed--;
3426           if (strcmp (fReturn[pushed], "a"))
3427             emitcode ("pop", fReturn[pushed]);
3428           else
3429             emitcode ("pop", "acc");
3430         }
3431     }
3432   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3433
3434 jumpret:
3435   /* generate a jump to the return label
3436      if the next is not the return statement */
3437   if (!(ic->next && ic->next->op == LABEL &&
3438         IC_LABEL (ic->next) == returnLabel))
3439
3440     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3441
3442 }
3443
3444 /*-----------------------------------------------------------------*/
3445 /* genLabel - generates a label                                    */
3446 /*-----------------------------------------------------------------*/
3447 static void
3448 genLabel (iCode * ic)
3449 {
3450   /* special case never generate */
3451   if (IC_LABEL (ic) == entryLabel)
3452     return;
3453
3454   D (emitcode (";", "genLabel ");
3455     );
3456
3457   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3458 }
3459
3460 /*-----------------------------------------------------------------*/
3461 /* genGoto - generates a ljmp                                      */
3462 /*-----------------------------------------------------------------*/
3463 static void
3464 genGoto (iCode * ic)
3465 {
3466   D (emitcode (";", "genGoto ");
3467     );
3468   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3469 }
3470
3471 /*-----------------------------------------------------------------*/
3472 /* findLabelBackwards: walks back through the iCode chain looking  */
3473 /* for the given label. Returns number of iCode instructions     */
3474 /* between that label and given ic.          */
3475 /* Returns zero if label not found.          */
3476 /*-----------------------------------------------------------------*/
3477 static int
3478 findLabelBackwards (iCode * ic, int key)
3479 {
3480   int count = 0;
3481
3482   while (ic->prev)
3483     {
3484       ic = ic->prev;
3485       count++;
3486
3487       /* If we have any pushes or pops, we cannot predict the distance.
3488          I don't like this at all, this should be dealt with in the 
3489          back-end */
3490       if (ic->op == IPUSH || ic->op == IPOP) {
3491         return 0;
3492       }
3493
3494       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3495         {
3496           /* printf("findLabelBackwards = %d\n", count); */
3497           return count;
3498         }
3499     }
3500
3501   return 0;
3502 }
3503
3504 /*-----------------------------------------------------------------*/
3505 /* genPlusIncr :- does addition with increment if possible         */
3506 /*-----------------------------------------------------------------*/
3507 static bool
3508 genPlusIncr (iCode * ic)
3509 {
3510   unsigned int icount;
3511   unsigned int size = getDataSize (IC_RESULT (ic));
3512
3513   /* will try to generate an increment */
3514   /* if the right side is not a literal
3515      we cannot */
3516   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3517     return FALSE;
3518
3519   /* if the literal value of the right hand side
3520      is greater than 4 then it is not worth it */
3521   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3522     return FALSE;
3523
3524   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3525       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3526       while (icount--) {
3527           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3528       }
3529       return TRUE;
3530   }
3531   /* if increment 16 bits in register */
3532   if (
3533        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3534        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3535        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3536        (size > 1) &&
3537        (icount == 1))
3538     {
3539       symbol  *tlbl;
3540       int     emitTlbl;
3541       int     labelRange;
3542       char    *l;
3543
3544       /* If the next instruction is a goto and the goto target
3545        * is <= 5 instructions previous to this, we can generate
3546        * jumps straight to that target.
3547        */
3548       if (ic->next && ic->next->op == GOTO
3549           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3550           && labelRange <= 5)
3551         {
3552           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3553           tlbl = IC_LABEL (ic->next);
3554           emitTlbl = 0;
3555         }
3556       else
3557         {
3558           tlbl = newiTempLabel (NULL);
3559           emitTlbl = 1;
3560         }
3561         
3562       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3563       emitcode ("inc", "%s", l);
3564       
3565       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3566           IS_AOP_PREG (IC_RESULT (ic)))
3567       {   
3568         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3569       }
3570       else
3571       {
3572           emitcode ("clr", "a");
3573           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3574       }
3575
3576       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3577       emitcode ("inc", "%s", l);
3578       if (size > 2)
3579         {
3580             if (!strcmp(l, "acc"))
3581             {
3582                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3583             }
3584             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3585                      IS_AOP_PREG (IC_RESULT (ic)))
3586             {
3587                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3588             }
3589             else
3590             {
3591                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3592             }
3593
3594             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3595             emitcode ("inc", "%s", l);
3596         }
3597       if (size > 3)
3598         {
3599             if (!strcmp(l, "acc"))
3600             {
3601                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3602             }
3603             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3604                      IS_AOP_PREG (IC_RESULT (ic)))
3605             {
3606                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3607             }
3608             else
3609             {
3610                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3611             }
3612
3613             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3614             emitcode ("inc", "%s", l);  }
3615
3616       if (emitTlbl)
3617         {
3618           emitcode ("", "!tlabeldef", tlbl->key + 100);
3619         }
3620       return TRUE;
3621     }
3622
3623   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3624       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3625       options.model == MODEL_FLAT24 ) {
3626
3627       switch (size) {
3628       case 3:
3629           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3630       case 2:
3631           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3632       case 1:
3633           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3634           break;
3635       }
3636       while (icount--) emitcode ("inc","dptr");      
3637       return TRUE;
3638   }
3639
3640   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3641       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3642       icount <= 5 ) {
3643       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3644       while (icount--) emitcode ("inc","dptr");
3645       emitcode ("mov","dps,#0");
3646       return TRUE;
3647   }
3648
3649   /* if the sizes are greater than 1 then we cannot */
3650   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3651       AOP_SIZE (IC_LEFT (ic)) > 1)
3652     return FALSE;
3653
3654   /* we can if the aops of the left & result match or
3655      if they are in registers and the registers are the
3656      same */
3657   if (
3658        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3659        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3660        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3661     {
3662
3663       if (icount > 3)
3664         {
3665           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3666           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3667           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3668         }
3669       else
3670         {
3671
3672           _startLazyDPSEvaluation ();
3673           while (icount--)
3674             {
3675               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3676             }
3677           _endLazyDPSEvaluation ();
3678         }
3679
3680       return TRUE;
3681     }
3682
3683   return FALSE;
3684 }
3685
3686 /*-----------------------------------------------------------------*/
3687 /* outBitAcc - output a bit in acc                                 */
3688 /*-----------------------------------------------------------------*/
3689 static void
3690 outBitAcc (operand * result)
3691 {
3692   symbol *tlbl = newiTempLabel (NULL);
3693   /* if the result is a bit */
3694   if (AOP_TYPE (result) == AOP_CRY)
3695     {
3696       aopPut (AOP (result), "a", 0);
3697     }
3698   else
3699     {
3700       emitcode ("jz", "!tlabel", tlbl->key + 100);
3701       emitcode ("mov", "a,%s", one);
3702       emitcode ("", "!tlabeldef", tlbl->key + 100);
3703       outAcc (result);
3704     }
3705 }
3706
3707 /*-----------------------------------------------------------------*/
3708 /* genPlusBits - generates code for addition of two bits           */
3709 /*-----------------------------------------------------------------*/
3710 static void
3711 genPlusBits (iCode * ic)
3712 {
3713   D (emitcode (";", "genPlusBits "););
3714     
3715   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3716     {
3717       symbol *lbl = newiTempLabel (NULL);
3718       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3719       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3720       emitcode ("cpl", "c");
3721       emitcode ("", "!tlabeldef", (lbl->key + 100));
3722       outBitC (IC_RESULT (ic));
3723     }
3724   else
3725     {
3726       emitcode ("clr", "a");
3727       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3728       emitcode ("rlc", "a");
3729       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3730       emitcode ("addc", "a,#0");
3731       outAcc (IC_RESULT (ic));
3732     }
3733 }
3734
3735 static void
3736 adjustArithmeticResult (iCode * ic)
3737 {
3738   if (opIsGptr (IC_RESULT (ic)) &&
3739       opIsGptr (IC_LEFT (ic)) &&
3740       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3741     {
3742       aopPut (AOP (IC_RESULT (ic)),
3743               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3744               GPTRSIZE - 1);
3745     }
3746
3747   if (opIsGptr (IC_RESULT (ic)) &&
3748       opIsGptr (IC_RIGHT (ic)) &&
3749       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3750     {
3751       aopPut (AOP (IC_RESULT (ic)),
3752             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3753               GPTRSIZE - 1);
3754     }
3755
3756   if (opIsGptr (IC_RESULT (ic)) &&
3757       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3758       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3759       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3760       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3761     {
3762       char buff[5];
3763       SNPRINTF (buff, sizeof(buff), 
3764                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3765       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3766     }
3767 }
3768
3769 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3770 // generates the result if possible. If result is generated, returns TRUE; otherwise
3771 // returns false and caller must deal with fact that result isn't aopOp'd.
3772 bool aopOp3(iCode * ic)
3773 {
3774     bool dp1InUse, dp2InUse;
3775     bool useDp2;
3776     
3777     // First, generate the right opcode. DPTR may be used if neither left nor result are
3778     // of type AOP_STR.
3779     
3780 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3781 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3782 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3783 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3784 //      );
3785 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3786 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3787 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3788 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3789 //      );
3790     
3791     // Right uses DPTR unless left or result is an AOP_STR; however,
3792     // if right is an AOP_STR, it must use DPTR regardless.
3793     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3794      && !AOP_IS_STR(IC_RIGHT(ic)))
3795     {
3796         useDp2 = TRUE;
3797     }
3798     else
3799     {
3800         useDp2 = FALSE;
3801     }
3802         
3803     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3804     
3805     // if the right used DPTR, left MUST use DPTR2.
3806     // if the right used DPTR2, left MUST use DPTR.
3807     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3808     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3809     // enabling us to assign DPTR to result.
3810      
3811     if (AOP_USESDPTR(IC_RIGHT(ic)))
3812     {
3813         useDp2 = TRUE;
3814     }
3815     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3816     {
3817         useDp2 = FALSE;
3818     }
3819     else
3820     {
3821         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3822         {
3823             useDp2 = TRUE;
3824         }
3825         else
3826         {
3827             useDp2 = FALSE;
3828         }
3829     }
3830
3831     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3832     
3833     // We've op'd the left & right. So, if left or right are the same operand as result, 
3834     // we know aopOp will succeed, and we can just do it & bail.
3835     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3836         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3837     {
3838 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3839         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3840         return TRUE;
3841     }
3842     
3843     // Note which dptrs are currently in use.
3844     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3845     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3846     
3847     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3848     // generate it.
3849     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3850     {
3851         return FALSE;
3852     }
3853     
3854     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3855     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3856     {
3857         return FALSE;
3858     }
3859     
3860     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3861     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3862     {
3863         return FALSE;
3864     }
3865
3866     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3867
3868     // Some sanity checking...
3869     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3870     {
3871         fprintf(stderr,
3872                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3873                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3874         emitcode(";", ">>> unexpected DPTR here.");
3875     }
3876     
3877     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3878     {
3879         fprintf(stderr,
3880                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3881                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3882         emitcode(";", ">>> unexpected DPTR2 here.");
3883     }    
3884     
3885     return TRUE;
3886 }
3887
3888 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3889 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3890 // will be set TRUE. The caller must then handle the case specially, noting
3891 // that the IC_RESULT operand is not aopOp'd.
3892 // 
3893 #define AOP_OP_3_NOFATAL(ic, rc) \
3894             do { rc = !aopOp3(ic); } while (0)
3895
3896 // aopOp the left & right operands of an ic.
3897 #define AOP_OP_2(ic) \
3898     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3899     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3900
3901 // convienience macro.
3902 #define AOP_SET_LOCALS(ic) \
3903     left = IC_LEFT(ic); \
3904     right = IC_RIGHT(ic); \
3905     result = IC_RESULT(ic);
3906
3907
3908 // Given an integer value of pushedSize bytes on the stack,
3909 // adjust it to be resultSize bytes, either by discarding
3910 // the most significant bytes or by zero-padding.
3911 //
3912 // On exit from this macro, pushedSize will have been adjusted to
3913 // equal resultSize, and ACC may be trashed.
3914 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3915       /* If the pushed data is bigger than the result,          \
3916        * simply discard unused bytes. Icky, but works.          \
3917        */                                                       \
3918       while (pushedSize > resultSize)                           \
3919       {                                                         \
3920           D (emitcode (";", "discarding unused result byte."););\
3921           emitcode ("pop", "acc");                              \
3922           pushedSize--;                                         \
3923       }                                                         \
3924       if (pushedSize < resultSize)                              \
3925       {                                                         \
3926           emitcode ("clr", "a");                                \
3927           /* Conversly, we haven't pushed enough here.          \
3928            * just zero-pad, and all is well.                    \
3929            */                                                   \
3930           while (pushedSize < resultSize)                       \
3931           {                                                     \
3932               emitcode("push", "acc");                          \
3933               pushedSize++;                                     \
3934           }                                                     \
3935       }                                                         \
3936       assert(pushedSize == resultSize);
3937
3938 /*-----------------------------------------------------------------*/
3939 /* genPlus - generates code for addition                           */
3940 /*-----------------------------------------------------------------*/
3941 static void
3942 genPlus (iCode * ic)
3943 {
3944   int size, offset = 0;
3945   bool pushResult;
3946   int rSize;
3947
3948   D (emitcode (";", "genPlus "););
3949
3950   /* special cases :- */
3951   if ( AOP_IS_STR(IC_LEFT(ic)) &&
3952       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3953       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3954       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3955       if (size <= 9) {
3956           while (size--) emitcode ("inc","dptr");
3957       } else {
3958           emitcode ("mov","a,dpl");
3959           emitcode ("add","a,#!constbyte",size & 0xff);
3960           emitcode ("mov","dpl,a");
3961           emitcode ("mov","a,dph");
3962           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3963           emitcode ("mov","dph,a");
3964           emitcode ("mov","a,dpx");
3965           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3966           emitcode ("mov","dpx,a");
3967       }
3968       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3969       return ;
3970   }
3971   if ( IS_SYMOP(IC_LEFT(ic)) && 
3972        OP_SYMBOL(IC_LEFT(ic))->remat &&
3973        isOperandInFarSpace(IC_RIGHT(ic))) {
3974       operand *op = IC_RIGHT(ic);
3975       IC_RIGHT(ic) = IC_LEFT(ic);
3976       IC_LEFT(ic) = op;
3977   }
3978                 
3979   AOP_OP_3_NOFATAL (ic, pushResult);
3980     
3981   if (pushResult)
3982     {
3983       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3984     }
3985
3986   if (!pushResult)
3987     {
3988       /* if literal, literal on the right or
3989          if left requires ACC or right is already
3990          in ACC */
3991       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3992        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3993           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3994         {
3995           operand *t = IC_RIGHT (ic);
3996           IC_RIGHT (ic) = IC_LEFT (ic);
3997           IC_LEFT (ic) = t;
3998           emitcode (";", "Swapped plus args.");
3999         }
4000
4001       /* if both left & right are in bit
4002          space */
4003       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4004           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4005         {
4006           genPlusBits (ic);
4007           goto release;
4008         }
4009
4010       /* if left in bit space & right literal */
4011       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4012           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4013         {
4014           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4015           /* if result in bit space */
4016           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4017             {
4018               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4019                 emitcode ("cpl", "c");
4020               outBitC (IC_RESULT (ic));
4021             }
4022           else
4023             {
4024               size = getDataSize (IC_RESULT (ic));
4025               _startLazyDPSEvaluation ();
4026               while (size--)
4027                 {
4028                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4029                   emitcode ("addc", "a,#0");
4030                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4031                 }
4032               _endLazyDPSEvaluation ();
4033             }
4034           goto release;
4035         }
4036
4037       /* if I can do an increment instead
4038          of add then GOOD for ME */
4039       if (genPlusIncr (ic) == TRUE)
4040         {
4041           emitcode (";", "did genPlusIncr");
4042           goto release;
4043         }
4044
4045     }
4046   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4047
4048   _startLazyDPSEvaluation ();
4049   while (size--)
4050     {
4051       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4052         {
4053           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4054           if (offset == 0)
4055             emitcode ("add", "a,%s",
4056                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4057           else
4058             emitcode ("addc", "a,%s",
4059                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4060         }
4061       else
4062         {
4063           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4064           {
4065               /* right is going to use ACC or we would have taken the
4066                * above branch.
4067                */
4068               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4069        TR_AP("#3");
4070               D(emitcode(";", "+ AOP_ACC special case."););
4071               emitcode("xch", "a, %s", DP2_RESULT_REG);
4072           }
4073           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4074           if (offset == 0)
4075           {
4076             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4077             {
4078          TR_AP("#4");
4079                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4080             }
4081             else
4082             {
4083                 emitcode ("add", "a,%s",
4084                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4085                                   DP2_RESULT_REG));
4086             }
4087           }
4088           else
4089           {
4090             emitcode ("addc", "a,%s",
4091                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4092                           DP2_RESULT_REG));
4093           }
4094         }
4095       if (!pushResult)
4096         {
4097           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4098         }
4099       else
4100         {
4101           emitcode ("push", "acc");
4102         }
4103       offset++;
4104     }
4105   _endLazyDPSEvaluation ();
4106
4107   if (pushResult)
4108     {
4109       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4110
4111       size = getDataSize (IC_LEFT (ic));
4112       rSize = getDataSize (IC_RESULT (ic));
4113
4114       ADJUST_PUSHED_RESULT(size, rSize);
4115
4116       _startLazyDPSEvaluation ();
4117       while (size--)
4118         {
4119           emitcode ("pop", "acc");
4120           aopPut (AOP (IC_RESULT (ic)), "a", size);
4121         }
4122       _endLazyDPSEvaluation ();
4123     }
4124
4125   adjustArithmeticResult (ic);
4126
4127 release:
4128   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4129   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4130   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4131 }
4132
4133 /*-----------------------------------------------------------------*/
4134 /* genMinusDec :- does subtraction with deccrement if possible     */
4135 /*-----------------------------------------------------------------*/
4136 static bool
4137 genMinusDec (iCode * ic)
4138 {
4139   unsigned int icount;
4140   unsigned int size = getDataSize (IC_RESULT (ic));
4141
4142   /* will try to generate an increment */
4143   /* if the right side is not a literal
4144      we cannot */
4145   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4146     return FALSE;
4147
4148   /* if the literal value of the right hand side
4149      is greater than 4 then it is not worth it */
4150   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4151     return FALSE;
4152
4153   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4154       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4155       while (icount--) {
4156           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4157       }
4158       return TRUE;
4159   }
4160   /* if decrement 16 bits in register */
4161   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4162       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4163       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4164       (size > 1) &&
4165       (icount == 1))
4166     {
4167       symbol *tlbl;
4168       int    emitTlbl;
4169       int    labelRange;
4170       char   *l;
4171
4172       /* If the next instruction is a goto and the goto target
4173          * is <= 5 instructions previous to this, we can generate
4174          * jumps straight to that target.
4175        */
4176       if (ic->next && ic->next->op == GOTO
4177           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4178           && labelRange <= 5)
4179         {
4180           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4181           tlbl = IC_LABEL (ic->next);
4182           emitTlbl = 0;
4183         }
4184       else
4185         {
4186           tlbl = newiTempLabel (NULL);
4187           emitTlbl = 1;
4188         }
4189
4190       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4191       emitcode ("dec", "%s", l);
4192  
4193       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4194           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4195           IS_AOP_PREG (IC_RESULT (ic)))
4196       {     
4197           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4198       }
4199       else
4200       {
4201           emitcode ("mov", "a,#!constbyte",0xff);
4202           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4203       }
4204       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4205       emitcode ("dec", "%s", l);
4206       if (size > 2)
4207         {
4208             if (!strcmp(l, "acc"))
4209             {
4210                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4211             }
4212             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4213                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4214                      IS_AOP_PREG (IC_RESULT (ic)))
4215             {       
4216                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4217             }
4218             else
4219             {
4220                 emitcode ("mov", "a,#!constbyte",0xff);
4221                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4222             }
4223             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4224             emitcode ("dec", "%s", l);
4225         }
4226       if (size > 3)
4227         {
4228             if (!strcmp(l, "acc"))
4229             {
4230                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4231             }
4232             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4233                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4234                      IS_AOP_PREG (IC_RESULT (ic)))
4235             {       
4236                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4237             }
4238             else
4239             {
4240                 emitcode ("mov", "a,#!constbyte",0xff);
4241                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4242             }       
4243             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4244             emitcode ("dec", "%s", l);
4245         }
4246       if (emitTlbl)
4247         {
4248           emitcode ("", "!tlabeldef", tlbl->key + 100);
4249         }
4250       return TRUE;
4251     }
4252
4253   /* if the sizes are greater than 1 then we cannot */
4254   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4255       AOP_SIZE (IC_LEFT (ic)) > 1)
4256     return FALSE;
4257
4258   /* we can if the aops of the left & result match or
4259      if they are in registers and the registers are the
4260      same */
4261   if (
4262        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4263        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4264        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4265     {
4266
4267       _startLazyDPSEvaluation ();
4268       while (icount--)
4269         {
4270           emitcode ("dec", "%s",
4271                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4272         }
4273       _endLazyDPSEvaluation ();
4274
4275       return TRUE;
4276     }
4277
4278   return FALSE;
4279 }
4280
4281 /*-----------------------------------------------------------------*/
4282 /* addSign - complete with sign                                    */
4283 /*-----------------------------------------------------------------*/
4284 static void
4285 addSign (operand * result, int offset, int sign)
4286 {
4287   int size = (getDataSize (result) - offset);
4288   if (size > 0)
4289     {
4290       _startLazyDPSEvaluation();
4291       if (sign)
4292         {
4293           emitcode ("rlc", "a");
4294           emitcode ("subb", "a,acc");
4295           while (size--)
4296           {
4297             aopPut (AOP (result), "a", offset++);
4298           }
4299         }
4300       else
4301       {
4302         while (size--)
4303         {
4304           aopPut (AOP (result), zero, offset++);
4305         }
4306       }
4307       _endLazyDPSEvaluation();
4308     }
4309 }
4310
4311 /*-----------------------------------------------------------------*/
4312 /* genMinusBits - generates code for subtraction  of two bits      */
4313 /*-----------------------------------------------------------------*/
4314 static void
4315 genMinusBits (iCode * ic)
4316 {
4317   symbol *lbl = newiTempLabel (NULL);
4318
4319   D (emitcode (";", "genMinusBits "););
4320
4321   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4322     {
4323       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4324       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4325       emitcode ("cpl", "c");
4326       emitcode ("", "!tlabeldef", (lbl->key + 100));
4327       outBitC (IC_RESULT (ic));
4328     }
4329   else
4330     {
4331       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4332       emitcode ("subb", "a,acc");
4333       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4334       emitcode ("inc", "a");
4335       emitcode ("", "!tlabeldef", (lbl->key + 100));
4336       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4337       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4338     }
4339 }
4340
4341 /*-----------------------------------------------------------------*/
4342 /* genMinus - generates code for subtraction                       */
4343 /*-----------------------------------------------------------------*/
4344 static void
4345 genMinus (iCode * ic)
4346 {
4347     int size, offset = 0;
4348     int rSize;
4349     long lit = 0L;
4350     bool pushResult;
4351
4352     D (emitcode (";", "genMinus "););
4353
4354     AOP_OP_3_NOFATAL(ic, pushResult);   
4355
4356     if (!pushResult)
4357     {
4358       /* special cases :- */
4359       /* if both left & right are in bit space */
4360       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4361           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4362         {
4363           genMinusBits (ic);
4364           goto release;
4365         }
4366
4367       /* if I can do an decrement instead
4368          of subtract then GOOD for ME */
4369       if (genMinusDec (ic) == TRUE)
4370         goto release;
4371
4372     }
4373
4374   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4375
4376   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4377     {
4378       CLRC;
4379     }
4380   else
4381     {
4382       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4383       lit = -lit;
4384     }
4385
4386
4387   /* if literal, add a,#-lit, else normal subb */
4388   _startLazyDPSEvaluation ();
4389   while (size--) {
4390       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4391           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4392               emitcode ("mov","b,%s",
4393                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4394               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4395               emitcode ("subb","a,b");
4396           } else {
4397               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4398               emitcode ("subb", "a,%s",
4399                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4400                                 DP2_RESULT_REG));
4401           }
4402       } else {
4403           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4404           /* first add without previous c */
4405           if (!offset) {
4406               if (!size && lit==-1) {
4407                   emitcode ("dec", "a");
4408               } else {
4409                   emitcode ("add", "a,#!constbyte",
4410                             (unsigned int) (lit & 0x0FFL));
4411               }
4412           } else {
4413               emitcode ("addc", "a,#!constbyte",
4414                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4415           }
4416       }
4417       
4418       if (pushResult) {
4419           emitcode ("push", "acc");
4420       } else {
4421           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4422       }
4423       offset++;
4424   }
4425   _endLazyDPSEvaluation ();
4426   
4427   if (pushResult)
4428     {
4429       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4430
4431       size = getDataSize (IC_LEFT (ic));
4432       rSize = getDataSize (IC_RESULT (ic));
4433
4434       ADJUST_PUSHED_RESULT(size, rSize);
4435
4436       _startLazyDPSEvaluation ();
4437       while (size--)
4438         {
4439           emitcode ("pop", "acc");
4440           aopPut (AOP (IC_RESULT (ic)), "a", size);
4441         }
4442       _endLazyDPSEvaluation ();
4443     }
4444
4445   adjustArithmeticResult (ic);
4446
4447 release:
4448   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4449   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4450   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4451 }
4452
4453
4454 /*-----------------------------------------------------------------*/
4455 /* genMultbits :- multiplication of bits                           */
4456 /*-----------------------------------------------------------------*/
4457 static void
4458 genMultbits (operand * left,
4459              operand * right,
4460              operand * result,
4461              iCode   * ic)
4462 {
4463   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4464   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4465   aopOp(result, ic, TRUE, FALSE);
4466   outBitC (result);
4467 }
4468
4469
4470 /*-----------------------------------------------------------------*/
4471 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4472 /*-----------------------------------------------------------------*/
4473 static void
4474 genMultOneByte (operand * left,
4475                 operand * right,
4476                 operand * result,
4477                 iCode   * ic)
4478 {
4479   sym_link *opetype = operandType (result);
4480   symbol *lbl;
4481
4482
4483   /* (if two literals: the value is computed before) */
4484   /* if one literal, literal on the right */
4485   if (AOP_TYPE (left) == AOP_LIT)
4486     {
4487       operand *t = right;
4488       right = left;
4489       left = t;
4490       emitcode (";", "swapped left and right");
4491     }
4492
4493   if (SPEC_USIGN(opetype)
4494       // ignore the sign of left and right, what else can we do?
4495       || (SPEC_USIGN(operandType(left)) && 
4496           SPEC_USIGN(operandType(right)))) {
4497     // just an unsigned 8*8=8/16 multiply
4498     //emitcode (";","unsigned");
4499     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4500     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4501     emitcode ("mul", "ab");
4502    
4503     _G.accInUse++; _G.bInUse++;
4504     aopOp(result, ic, TRUE, FALSE);
4505       
4506       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4507       {
4508           // this should never happen
4509           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4510                    AOP_SIZE(result), __FILE__, lineno);
4511           exit (1);
4512       }      
4513       
4514     aopPut (AOP (result), "a", 0);
4515     _G.accInUse--; _G.bInUse--;
4516     if (AOP_SIZE(result)==2) 
4517     {
4518       aopPut (AOP (result), "b", 1);
4519     }
4520     return;
4521   }
4522
4523   // we have to do a signed multiply
4524
4525   emitcode (";", "signed");
4526   emitcode ("clr", "F0"); // reset sign flag
4527   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4528
4529   lbl=newiTempLabel(NULL);
4530   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4531   // left side is negative, 8-bit two's complement, this fails for -128
4532   emitcode ("setb", "F0"); // set sign flag
4533   emitcode ("cpl", "a");
4534   emitcode ("inc", "a");
4535
4536   emitcode ("", "!tlabeldef", lbl->key+100);
4537
4538   /* if literal */
4539   if (AOP_TYPE(right)==AOP_LIT) {
4540     signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4541     /* AND literal negative */
4542     if ((int) val < 0) {
4543       emitcode ("cpl", "F0"); // complement sign flag
4544       emitcode ("mov", "b,#!constbyte", -val);
4545     } else {
4546       emitcode ("mov", "b,#!constbyte", val);
4547     }
4548   } else {
4549     lbl=newiTempLabel(NULL);
4550     emitcode ("mov", "b,a");
4551     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4552     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4553     // right side is negative, 8-bit two's complement
4554     emitcode ("cpl", "F0"); // complement sign flag
4555     emitcode ("cpl", "a");
4556     emitcode ("inc", "a");
4557     emitcode ("", "!tlabeldef", lbl->key+100);
4558   }
4559   emitcode ("mul", "ab");
4560     
4561   _G.accInUse++;_G.bInUse++;
4562   aopOp(result, ic, TRUE, FALSE);
4563     
4564   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4565   {
4566     // this should never happen
4567       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4568                AOP_SIZE(result), __FILE__, lineno);
4569       exit (1);
4570   }    
4571     
4572   lbl=newiTempLabel(NULL);
4573   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4574   // only ONE op was negative, we have to do a 8/16-bit two's complement
4575   emitcode ("cpl", "a"); // lsb
4576   if (AOP_SIZE(result)==1) {
4577     emitcode ("inc", "a");
4578   } else {
4579     emitcode ("add", "a,#1");
4580     emitcode ("xch", "a,b");
4581     emitcode ("cpl", "a"); // msb
4582     emitcode ("addc", "a,#0");
4583     emitcode ("xch", "a,b");
4584   }
4585
4586   emitcode ("", "!tlabeldef", lbl->key+100);
4587   aopPut (AOP (result), "a", 0);
4588   _G.accInUse--;_G.bInUse--;
4589   if (AOP_SIZE(result)==2) {
4590     aopPut (AOP (result), "b", 1);
4591   }
4592 }
4593
4594 /*-----------------------------------------------------------------*/
4595 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4596 /*-----------------------------------------------------------------*/
4597 static void genMultTwoByte (operand *left, operand *right, 
4598                             operand *result, iCode *ic)
4599 {
4600         sym_link *retype = getSpec(operandType(right));
4601         sym_link *letype = getSpec(operandType(left));
4602         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4603         symbol *lbl;
4604
4605         if (AOP_TYPE (left) == AOP_LIT) {
4606                 operand *t = right;
4607                 right = left;
4608                 left = t;
4609         }
4610         /* save EA bit in F1 */
4611         lbl = newiTempLabel(NULL);
4612         emitcode ("setb","F1");
4613         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4614         emitcode ("clr","F1");
4615         emitcode("","!tlabeldef",lbl->key+100);
4616
4617         /* load up MB with right */
4618         if (!umult) {
4619                 emitcode("clr","F0");
4620                 if (AOP_TYPE(right) == AOP_LIT) {
4621                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4622                         if (val < 0) {
4623                                 emitcode("setb","F0");
4624                                 val = -val;
4625                         }
4626                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4627                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4628                 } else {
4629                         lbl = newiTempLabel(NULL);
4630                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4631                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4632                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4633                         emitcode ("xch", "a,b");
4634                         emitcode ("cpl","a");
4635                         emitcode ("add", "a,#1");
4636                         emitcode ("xch", "a,b");
4637                         emitcode ("cpl", "a"); // msb
4638                         emitcode ("addc", "a,#0");
4639                         emitcode ("setb","F0");
4640                         emitcode ("","!tlabeldef",lbl->key+100);
4641                         emitcode ("mov","mb,b");
4642                         emitcode ("mov","mb,a");
4643                 }
4644         } else {
4645                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4646                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4647         }
4648         /* load up MA with left */
4649         if (!umult) {
4650                 lbl = newiTempLabel(NULL);
4651                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4652                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4653                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4654                 emitcode ("xch", "a,b");
4655                 emitcode ("cpl","a");
4656                 emitcode ("add", "a,#1");
4657                 emitcode ("xch", "a,b");
4658                 emitcode ("cpl", "a"); // msb
4659                 emitcode ("addc","a,#0");
4660                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4661                 emitcode ("setb","F0");
4662                 emitcode ("","!tlabeldef",lbl->key+100);
4663                 emitcode ("mov","ma,b");
4664                 emitcode ("mov","ma,a");
4665         } else {
4666                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4667                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4668         }
4669         /* wait for multiplication to finish */
4670         lbl = newiTempLabel(NULL);
4671         emitcode("","!tlabeldef", lbl->key+100);
4672         emitcode("mov","a,mcnt1");
4673         emitcode("anl","a,#!constbyte",0x80);
4674         emitcode("jnz","!tlabel",lbl->key+100);
4675         
4676         freeAsmop (left, NULL, ic, TRUE);
4677         freeAsmop (right, NULL, ic,TRUE);
4678         aopOp(result, ic, TRUE, FALSE);
4679
4680         /* if unsigned then simple */   
4681         if (umult) {
4682                 emitcode ("mov","a,ma");
4683                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4684                 emitcode ("mov","a,ma");
4685                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4686                 aopPut(AOP(result),"ma",1);
4687                 aopPut(AOP(result),"ma",0);
4688         } else {
4689                 emitcode("push","ma");
4690                 emitcode("push","ma");
4691                 emitcode("push","ma");
4692                 MOVA("ma");
4693                 /* negate result if needed */
4694                 lbl = newiTempLabel(NULL);      
4695                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4696                 emitcode("cpl","a");
4697                 emitcode("add","a,#1");
4698                 emitcode("","!tlabeldef", lbl->key+100);
4699                 if (AOP_TYPE(result) == AOP_ACC)
4700                 {
4701                     D(emitcode(";", "ACC special case."););
4702                     /* We know result is the only live aop, and 
4703                      * it's obviously not a DPTR2, so AP is available.
4704                      */
4705                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4706                 }
4707                 else
4708                 {
4709                     aopPut(AOP(result),"a",0);
4710                 }
4711             
4712                 emitcode("pop","acc");
4713                 lbl = newiTempLabel(NULL);      
4714                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4715                 emitcode("cpl","a");
4716                 emitcode("addc","a,#0");
4717                 emitcode("","!tlabeldef", lbl->key+100);
4718                 aopPut(AOP(result),"a",1);
4719                 emitcode("pop","acc");
4720                 if (AOP_SIZE(result) >= 3) {
4721                         lbl = newiTempLabel(NULL);      
4722                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4723                         emitcode("cpl","a");
4724                         emitcode("addc","a,#0");                        
4725                         emitcode("","!tlabeldef", lbl->key+100);
4726                         aopPut(AOP(result),"a",2);
4727                 }
4728                 emitcode("pop","acc");
4729                 if (AOP_SIZE(result) >= 4) {
4730                         lbl = newiTempLabel(NULL);      
4731                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4732                         emitcode("cpl","a");
4733                         emitcode("addc","a,#0");                        
4734                         emitcode("","!tlabeldef", lbl->key+100);
4735                         aopPut(AOP(result),"a",3);
4736                 }
4737                 if (AOP_TYPE(result) == AOP_ACC)
4738                 {
4739                     /* We stashed the result away above. */
4740                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4741                 }           
4742                 
4743         }
4744         freeAsmop (result, NULL, ic, TRUE);
4745
4746         /* restore EA bit in F1 */
4747         lbl = newiTempLabel(NULL);
4748         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4749         emitcode ("setb","EA");
4750         emitcode("","!tlabeldef",lbl->key+100);
4751         return ;
4752 }
4753
4754 /*-----------------------------------------------------------------*/
4755 /* genMult - generates code for multiplication                     */
4756 /*-----------------------------------------------------------------*/
4757 static void
4758 genMult (iCode * ic)
4759 {
4760   operand *left = IC_LEFT (ic);
4761   operand *right = IC_RIGHT (ic);
4762   operand *result = IC_RESULT (ic);
4763
4764   D (emitcode (";", "genMult "););
4765
4766   /* assign the amsops */
4767   AOP_OP_2 (ic);
4768
4769   /* special cases first */
4770   /* both are bits */
4771   if (AOP_TYPE (left) == AOP_CRY &&
4772       AOP_TYPE (right) == AOP_CRY)
4773     {
4774       genMultbits (left, right, result, ic);
4775       goto release;
4776     }
4777
4778   /* if both are of size == 1 */
4779   if (AOP_SIZE (left) == 1 &&
4780       AOP_SIZE (right) == 1)
4781     {
4782       genMultOneByte (left, right, result, ic);
4783       goto release;
4784     }
4785
4786   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4787           /* use the ds390 ARITHMETIC accel UNIT */
4788           genMultTwoByte (left, right, result, ic);
4789           return ;
4790   }
4791   /* should have been converted to function call */
4792   assert (0);
4793
4794 release:
4795   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4796   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4797   freeAsmop (result, NULL, ic, TRUE);
4798 }
4799
4800 /*-----------------------------------------------------------------*/
4801 /* genDivbits :- division of bits                                  */
4802 /*-----------------------------------------------------------------*/
4803 static void
4804 genDivbits (operand * left,
4805             operand * right,
4806             operand * result,
4807             iCode   * ic)
4808 {
4809
4810   char *l;
4811
4812   /* the result must be bit */
4813   LOAD_AB_FOR_DIV (left, right, l);
4814   emitcode ("div", "ab");
4815   emitcode ("rrc", "a");
4816   aopOp(result, ic, TRUE, FALSE);
4817     
4818   aopPut (AOP (result), "c", 0);
4819 }
4820
4821 /*-----------------------------------------------------------------*/
4822 /* genDivOneByte : 8 bit division                                  */
4823 /*-----------------------------------------------------------------*/
4824 static void
4825 genDivOneByte (operand * left,
4826                operand * right,
4827                operand * result,
4828                iCode   * ic)
4829 {
4830   sym_link *opetype = operandType (result);
4831   char *l;
4832   symbol *lbl;
4833   int size, offset;
4834
4835   offset = 1;
4836   /* signed or unsigned */
4837   if (SPEC_USIGN (opetype))
4838     {
4839         /* unsigned is easy */
4840         LOAD_AB_FOR_DIV (left, right, l);
4841         emitcode ("div", "ab");
4842
4843         _G.accInUse++;
4844         aopOp(result, ic, TRUE, FALSE);
4845         aopPut (AOP (result), "a", 0);
4846         _G.accInUse--;
4847
4848         size = AOP_SIZE (result) - 1;
4849         
4850         while (size--)
4851         {
4852             aopPut (AOP (result), zero, offset++);
4853         }
4854       return;
4855     }
4856
4857   /* signed is a little bit more difficult */
4858
4859   /* save the signs of the operands */
4860   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4861   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4862   emitcode ("push", "acc");     /* save it on the stack */
4863
4864   /* now sign adjust for both left & right */
4865   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4866   lbl = newiTempLabel (NULL);
4867   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4868   emitcode ("cpl", "a");
4869   emitcode ("inc", "a");
4870   emitcode ("", "!tlabeldef", (lbl->key + 100));
4871   emitcode ("mov", "b,a");
4872
4873   /* sign adjust left side */
4874   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4875
4876   lbl = newiTempLabel (NULL);
4877   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4878   emitcode ("cpl", "a");
4879   emitcode ("inc", "a");
4880   emitcode ("", "!tlabeldef", (lbl->key + 100));
4881
4882   /* now the division */
4883   emitcode ("nop", "; workaround for DS80C390 div bug.");
4884   emitcode ("div", "ab");
4885   /* we are interested in the lower order
4886      only */
4887   emitcode ("mov", "b,a");
4888   lbl = newiTempLabel (NULL);
4889   emitcode ("pop", "acc");
4890   /* if there was an over flow we don't
4891      adjust the sign of the result */
4892   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4893   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4894   CLRC;
4895   emitcode ("clr", "a");
4896   emitcode ("subb", "a,b");
4897   emitcode ("mov", "b,a");
4898   emitcode ("", "!tlabeldef", (lbl->key + 100));
4899
4900   /* now we are done */
4901   _G.accInUse++;     _G.bInUse++;
4902     aopOp(result, ic, TRUE, FALSE);
4903     
4904     aopPut (AOP (result), "b", 0);
4905     
4906     size = AOP_SIZE (result) - 1;
4907     
4908     if (size > 0)
4909     {
4910       emitcode ("mov", "c,b.7");
4911       emitcode ("subb", "a,acc");
4912     }
4913     while (size--)
4914     {
4915         aopPut (AOP (result), "a", offset++);
4916     }
4917     _G.accInUse--;     _G.bInUse--;
4918
4919 }
4920
4921 /*-----------------------------------------------------------------*/
4922 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4923 /*-----------------------------------------------------------------*/
4924 static void genDivTwoByte (operand *left, operand *right, 
4925                             operand *result, iCode *ic)
4926 {
4927         sym_link *retype = getSpec(operandType(right));
4928         sym_link *letype = getSpec(operandType(left));
4929         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4930         symbol *lbl;
4931
4932         /* save EA bit in F1 */
4933         lbl = newiTempLabel(NULL);
4934         emitcode ("setb","F1");
4935         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4936         emitcode ("clr","F1");
4937         emitcode("","!tlabeldef",lbl->key+100);
4938
4939         /* load up MA with left */
4940         if (!umult) {
4941                 emitcode("clr","F0");
4942                 lbl = newiTempLabel(NULL);
4943                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4944                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4945                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4946                 emitcode ("xch", "a,b");
4947                 emitcode ("cpl","a");
4948                 emitcode ("add", "a,#1");
4949                 emitcode ("xch", "a,b");
4950                 emitcode ("cpl", "a"); // msb
4951                 emitcode ("addc","a,#0");
4952                 emitcode ("setb","F0");
4953                 emitcode ("","!tlabeldef",lbl->key+100);
4954                 emitcode ("mov","ma,b");
4955                 emitcode ("mov","ma,a");
4956         } else {
4957                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4958                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4959         }
4960
4961         /* load up MB with right */
4962         if (!umult) {
4963                 if (AOP_TYPE(right) == AOP_LIT) {
4964                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4965                         if (val < 0) {
4966                                 lbl = newiTempLabel(NULL);
4967                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4968                                 emitcode("setb","F0");
4969                                 emitcode ("","!tlabeldef",lbl->key+100);
4970                                 val = -val;
4971                         } 
4972                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4973                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4974                 } else {
4975                         lbl = newiTempLabel(NULL);
4976                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4977                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4978                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4979                         emitcode ("xch", "a,b");
4980                         emitcode ("cpl","a");
4981                         emitcode ("add", "a,#1");
4982                         emitcode ("xch", "a,b");
4983                         emitcode ("cpl", "a"); // msb
4984                         emitcode ("addc", "a,#0");
4985                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
4986                         emitcode ("setb","F0");
4987                         emitcode ("","!tlabeldef",lbl->key+100);
4988                         emitcode ("mov","mb,b");
4989                         emitcode ("mov","mb,a");
4990                 }
4991         } else {
4992                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4993                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4994         }
4995
4996         /* wait for multiplication to finish */
4997         lbl = newiTempLabel(NULL);
4998         emitcode("","!tlabeldef", lbl->key+100);
4999         emitcode("mov","a,mcnt1");
5000         emitcode("anl","a,#!constbyte",0x80);
5001         emitcode("jnz","!tlabel",lbl->key+100);
5002         
5003         freeAsmop (left, NULL, ic, TRUE);
5004         freeAsmop (right, NULL, ic,TRUE);
5005         aopOp(result, ic, TRUE, FALSE);
5006
5007         /* if unsigned then simple */   
5008         if (umult) {
5009                 aopPut(AOP(result),"ma",1);
5010                 aopPut(AOP(result),"ma",0);
5011         } else {
5012                 emitcode("push","ma");
5013                 MOVA("ma");
5014                 /* negate result if needed */
5015                 lbl = newiTempLabel(NULL);      
5016                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5017                 emitcode("cpl","a");
5018                 emitcode("add","a,#1");
5019                 emitcode("","!tlabeldef", lbl->key+100);
5020                 aopPut(AOP(result),"a",0);
5021                 emitcode("pop","acc");
5022                 lbl = newiTempLabel(NULL);      
5023                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5024                 emitcode("cpl","a");
5025                 emitcode("addc","a,#0");
5026                 emitcode("","!tlabeldef", lbl->key+100);
5027                 aopPut(AOP(result),"a",1);
5028         }
5029         freeAsmop (result, NULL, ic, TRUE);
5030         /* restore EA bit in F1 */
5031         lbl = newiTempLabel(NULL);
5032         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5033         emitcode ("setb","EA");
5034         emitcode("","!tlabeldef",lbl->key+100);
5035         return ;
5036 }
5037
5038 /*-----------------------------------------------------------------*/
5039 /* genDiv - generates code for division                            */
5040 /*-----------------------------------------------------------------*/
5041 static void
5042 genDiv (iCode * ic)
5043 {
5044   operand *left = IC_LEFT (ic);
5045   operand *right = IC_RIGHT (ic);
5046   operand *result = IC_RESULT (ic);
5047
5048   D (emitcode (";", "genDiv "););
5049
5050   /* assign the amsops */
5051   AOP_OP_2 (ic);
5052
5053   /* special cases first */
5054   /* both are bits */
5055   if (AOP_TYPE (left) == AOP_CRY &&
5056       AOP_TYPE (right) == AOP_CRY)
5057     {
5058       genDivbits (left, right, result, ic);
5059       goto release;
5060     }
5061
5062   /* if both are of size == 1 */
5063   if (AOP_SIZE (left) == 1 &&
5064       AOP_SIZE (right) == 1)
5065     {
5066       genDivOneByte (left, right, result, ic);
5067       goto release;
5068     }
5069
5070   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5071           /* use the ds390 ARITHMETIC accel UNIT */
5072           genDivTwoByte (left, right, result, ic);
5073           return ;
5074   }
5075   /* should have been converted to function call */
5076   assert (0);
5077 release:
5078   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5079   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5080   freeAsmop (result, NULL, ic, TRUE);
5081 }
5082
5083 /*-----------------------------------------------------------------*/
5084 /* genModbits :- modulus of bits                                   */
5085 /*-----------------------------------------------------------------*/
5086 static void
5087 genModbits (operand * left,
5088             operand * right,
5089             operand * result,
5090             iCode   * ic)
5091 {
5092
5093   char *l;
5094
5095   /* the result must be bit */
5096   LOAD_AB_FOR_DIV (left, right, l);
5097   emitcode ("div", "ab");
5098   emitcode ("mov", "a,b");
5099   emitcode ("rrc", "a");
5100   aopOp(result, ic, TRUE, FALSE);
5101   aopPut (AOP (result), "c", 0);
5102 }
5103
5104 /*-----------------------------------------------------------------*/
5105 /* genModOneByte : 8 bit modulus                                   */
5106 /*-----------------------------------------------------------------*/
5107 static void
5108 genModOneByte (operand * left,
5109                operand * right,
5110                operand * result,
5111                iCode   * ic)
5112 {
5113   sym_link *opetype = operandType (result);
5114   char *l;
5115   symbol *lbl;
5116
5117   /* signed or unsigned */
5118   if (SPEC_USIGN (opetype))
5119     {
5120       /* unsigned is easy */
5121       LOAD_AB_FOR_DIV (left, right, l);
5122       emitcode ("div", "ab");
5123       aopOp(result, ic, TRUE, FALSE);   
5124       aopPut (AOP (result), "b", 0);
5125       return;
5126     }
5127
5128   /* signed is a little bit more difficult */
5129
5130   /* save the signs of the operands */
5131   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5132
5133   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5134   emitcode ("push", "acc");     /* save it on the stack */
5135
5136   /* now sign adjust for both left & right */
5137   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5138
5139   lbl = newiTempLabel (NULL);
5140   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5141   emitcode ("cpl", "a");
5142   emitcode ("inc", "a");
5143   emitcode ("", "!tlabeldef", (lbl->key + 100));
5144   emitcode ("mov", "b,a");
5145
5146   /* sign adjust left side */
5147   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5148
5149   lbl = newiTempLabel (NULL);
5150   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5151   emitcode ("cpl", "a");
5152   emitcode ("inc", "a");
5153   emitcode ("", "!tlabeldef", (lbl->key + 100));
5154
5155   /* now the multiplication */
5156   emitcode ("nop", "; workaround for DS80C390 div bug.");
5157   emitcode ("div", "ab");
5158   /* we are interested in the lower order
5159      only */
5160   lbl = newiTempLabel (NULL);
5161   emitcode ("pop", "acc");
5162   /* if there was an over flow we don't
5163      adjust the sign of the result */
5164   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5165   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5166   CLRC;
5167   emitcode ("clr", "a");
5168   emitcode ("subb", "a,b");
5169   emitcode ("mov", "b,a");
5170   emitcode ("", "!tlabeldef", (lbl->key + 100));
5171   
5172   _G.bInUse++;
5173   /* now we are done */
5174   aopOp(result, ic, TRUE, FALSE);    
5175   aopPut (AOP (result), "b", 0);
5176   _G.bInUse--;
5177
5178 }
5179
5180 /*-----------------------------------------------------------------*/
5181 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5182 /*-----------------------------------------------------------------*/
5183 static void genModTwoByte (operand *left, operand *right, 
5184                             operand *result, iCode *ic)
5185 {
5186         sym_link *retype = getSpec(operandType(right));
5187         sym_link *letype = getSpec(operandType(left));
5188         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5189         symbol *lbl;
5190
5191         /* load up MA with left */
5192         /* save EA bit in F1 */
5193         lbl = newiTempLabel(NULL);
5194         emitcode ("setb","F1");
5195         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5196         emitcode ("clr","F1");
5197         emitcode("","!tlabeldef",lbl->key+100);
5198
5199         if (!umult) {
5200                 lbl = newiTempLabel(NULL);
5201                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5202                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5203                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5204                 emitcode ("xch", "a,b");
5205                 emitcode ("cpl","a");
5206                 emitcode ("add", "a,#1");
5207                 emitcode ("xch", "a,b");
5208                 emitcode ("cpl", "a"); // msb
5209                 emitcode ("addc","a,#0");
5210                 emitcode ("","!tlabeldef",lbl->key+100);
5211                 emitcode ("mov","ma,b");
5212                 emitcode ("mov","ma,a");
5213         } else {
5214                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5215                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5216         }
5217
5218         /* load up MB with right */
5219         if (!umult) {
5220                 if (AOP_TYPE(right) == AOP_LIT) {
5221                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5222                         if (val < 0) {
5223                                 val = -val;
5224                         } 
5225                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5226                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5227                 } else {
5228                         lbl = newiTempLabel(NULL);
5229                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5230                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5231                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5232                         emitcode ("xch", "a,b");
5233                         emitcode ("cpl","a");
5234                         emitcode ("add", "a,#1");
5235                         emitcode ("xch", "a,b");
5236                         emitcode ("cpl", "a"); // msb
5237                         emitcode ("addc", "a,#0");
5238                         emitcode ("","!tlabeldef",lbl->key+100);
5239                         emitcode ("mov","mb,b");
5240                         emitcode ("mov","mb,a");
5241                 }
5242         } else {
5243                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5244                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5245         }
5246
5247         /* wait for multiplication to finish */
5248         lbl = newiTempLabel(NULL);
5249         emitcode("","!tlabeldef", lbl->key+100);
5250         emitcode("mov","a,mcnt1");
5251         emitcode("anl","a,#!constbyte",0x80);
5252         emitcode("jnz","!tlabel",lbl->key+100);
5253         
5254         freeAsmop (left, NULL, ic, TRUE);
5255         freeAsmop (right, NULL, ic,TRUE);
5256         aopOp(result, ic, TRUE, FALSE);
5257
5258         aopPut(AOP(result),"mb",1);
5259         aopPut(AOP(result),"mb",0);
5260         freeAsmop (result, NULL, ic, TRUE);
5261
5262         /* restore EA bit in F1 */
5263         lbl = newiTempLabel(NULL);
5264         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5265         emitcode ("setb","EA");
5266         emitcode("","!tlabeldef",lbl->key+100);
5267         return ;
5268 }
5269
5270 /*-----------------------------------------------------------------*/
5271 /* genMod - generates code for division                            */
5272 /*-----------------------------------------------------------------*/
5273 static void
5274 genMod (iCode * ic)
5275 {
5276   operand *left = IC_LEFT (ic);
5277   operand *right = IC_RIGHT (ic);
5278   operand *result = IC_RESULT (ic);
5279
5280   D (emitcode (";", "genMod "); );
5281
5282   /* assign the amsops */
5283   AOP_OP_2 (ic);
5284
5285   /* special cases first */
5286   /* both are bits */
5287   if (AOP_TYPE (left) == AOP_CRY &&
5288       AOP_TYPE (right) == AOP_CRY)
5289     {
5290       genModbits (left, right, result, ic);
5291       goto release;
5292     }
5293
5294   /* if both are of size == 1 */
5295   if (AOP_SIZE (left) == 1 &&
5296       AOP_SIZE (right) == 1)
5297     {
5298       genModOneByte (left, right, result, ic);
5299       goto release;
5300     }
5301
5302   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5303           /* use the ds390 ARITHMETIC accel UNIT */
5304           genModTwoByte (left, right, result, ic);
5305           return ;
5306   }
5307
5308   /* should have been converted to function call */
5309   assert (0);
5310
5311 release:
5312   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5313   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5314   freeAsmop (result, NULL, ic, TRUE);
5315 }
5316
5317 /*-----------------------------------------------------------------*/
5318 /* genIfxJump :- will create a jump depending on the ifx           */
5319 /*-----------------------------------------------------------------*/
5320 static void
5321 genIfxJump (iCode * ic, char *jval)
5322 {
5323   symbol *jlbl;
5324   symbol *tlbl = newiTempLabel (NULL);
5325   char *inst;
5326
5327   D (emitcode (";", "genIfxJump"););
5328
5329   /* if true label then we jump if condition
5330      supplied is true */
5331   if (IC_TRUE (ic))
5332     {
5333       jlbl = IC_TRUE (ic);
5334       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5335                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5336     }
5337   else
5338     {
5339       /* false label is present */
5340       jlbl = IC_FALSE (ic);
5341       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5342                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5343     }
5344   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5345     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5346   else
5347     emitcode (inst, "!tlabel", tlbl->key + 100);
5348   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5349   emitcode ("", "!tlabeldef", tlbl->key + 100);
5350
5351   /* mark the icode as generated */
5352   ic->generated = 1;
5353 }
5354
5355 /*-----------------------------------------------------------------*/
5356 /* genCmp :- greater or less than comparison                       */
5357 /*-----------------------------------------------------------------*/
5358 static void
5359 genCmp (operand * left, operand * right,
5360         iCode * ic, iCode * ifx, int sign)
5361 {
5362   int size, offset = 0;
5363   unsigned long lit = 0L;
5364   operand *result;
5365
5366   D (emitcode (";", "genCmp"););
5367
5368   result = IC_RESULT (ic);
5369
5370   /* if left & right are bit variables */
5371   if (AOP_TYPE (left) == AOP_CRY &&
5372       AOP_TYPE (right) == AOP_CRY)
5373     {
5374       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5375       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5376     }
5377   else
5378     {
5379       /* subtract right from left if at the
5380          end the carry flag is set then we know that
5381          left is greater than right */
5382       size = max (AOP_SIZE (left), AOP_SIZE (right));
5383
5384       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5385       if ((size == 1) && !sign 
5386           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5387         {
5388           symbol *lbl = newiTempLabel (NULL);
5389           emitcode ("cjne", "%s,%s,!tlabel",
5390                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5391                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5392                     lbl->key + 100);
5393           emitcode ("", "!tlabeldef", lbl->key + 100);
5394         }
5395       else
5396         {
5397           if (AOP_TYPE (right) == AOP_LIT)
5398             {
5399               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5400               /* optimize if(x < 0) or if(x >= 0) */
5401               if (lit == 0L)
5402                 {
5403                   if (!sign)
5404                     {
5405                       CLRC;
5406                     }
5407                   else
5408                     {
5409                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5410
5411                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5412                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5413
5414                       aopOp (result, ic, FALSE, FALSE);
5415
5416                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5417                         {
5418                           freeAsmop (result, NULL, ic, TRUE);
5419                           genIfxJump (ifx, "acc.7");
5420                           return;
5421                         }
5422                       else
5423                         {
5424                           emitcode ("rlc", "a");
5425                         }
5426                       goto release_freedLR;
5427                     }
5428                   goto release;
5429                 }
5430             }
5431           CLRC;
5432           while (size--)
5433             {
5434               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5435               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5436               // emitcode (";", "genCmp #2");
5437               if (sign && (size == 0))
5438                 {
5439                   // emitcode (";", "genCmp #3");
5440                   emitcode ("xrl", "a,#!constbyte",0x80);
5441                   if (AOP_TYPE (right) == AOP_LIT)
5442                     {
5443                       unsigned long lit = (unsigned long)
5444                       floatFromVal (AOP (right)->aopu.aop_lit);
5445                       // emitcode (";", "genCmp #3.1");
5446                       emitcode ("subb", "a,#!constbyte",
5447                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5448                     }
5449                   else
5450                     {
5451                       // emitcode (";", "genCmp #3.2");
5452                       saveAccWarn = 0;  
5453                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5454                       saveAccWarn = DEFAULT_ACC_WARNING;
5455                       emitcode ("xrl", "b,#!constbyte",0x80);
5456                       emitcode ("subb", "a,b");
5457                     }
5458                 }
5459               else
5460                 {
5461                   const char *s;
5462
5463                   // emitcode (";", "genCmp #4");
5464                   saveAccWarn = 0;
5465                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5466                   saveAccWarn = DEFAULT_ACC_WARNING;
5467
5468                   emitcode ("subb", "a,%s", s);
5469                 }
5470             }
5471         }
5472     }
5473
5474 release:
5475 /* Don't need the left & right operands any more; do need the result. */
5476   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5477   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5478
5479   aopOp (result, ic, FALSE, FALSE);
5480
5481 release_freedLR:
5482
5483   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5484     {
5485       outBitC (result);
5486     }
5487   else
5488     {
5489       /* if the result is used in the next
5490          ifx conditional branch then generate
5491          code a little differently */
5492       if (ifx)
5493         {
5494           genIfxJump (ifx, "c");
5495         }
5496       else
5497         {
5498           outBitC (result);
5499         }
5500       /* leave the result in acc */
5501     }
5502   freeAsmop (result, NULL, ic, TRUE);
5503 }
5504
5505 /*-----------------------------------------------------------------*/
5506 /* genCmpGt :- greater than comparison                             */
5507 /*-----------------------------------------------------------------*/
5508 static void
5509 genCmpGt (iCode * ic, iCode * ifx)
5510 {
5511   operand *left, *right;
5512   sym_link *letype, *retype;
5513   int sign;
5514
5515   D (emitcode (";", "genCmpGt ");
5516     );
5517
5518   left = IC_LEFT (ic);
5519   right = IC_RIGHT (ic);
5520
5521   letype = getSpec (operandType (left));
5522   retype = getSpec (operandType (right));
5523   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5524
5525   /* assign the left & right amsops */
5526   AOP_OP_2 (ic);
5527
5528   genCmp (right, left, ic, ifx, sign);
5529 }
5530
5531 /*-----------------------------------------------------------------*/
5532 /* genCmpLt - less than comparisons                                */
5533 /*-----------------------------------------------------------------*/
5534 static void
5535 genCmpLt (iCode * ic, iCode * ifx)
5536 {
5537   operand *left, *right;
5538   sym_link *letype, *retype;
5539   int sign;
5540
5541   D (emitcode (";", "genCmpLt "););
5542
5543   left = IC_LEFT (ic);
5544   right = IC_RIGHT (ic);
5545
5546   letype = getSpec (operandType (left));
5547   retype = getSpec (operandType (right));
5548   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5549
5550   /* assign the left & right amsops */
5551   AOP_OP_2 (ic);
5552
5553   genCmp (left, right, ic, ifx, sign);
5554 }
5555
5556 /*-----------------------------------------------------------------*/
5557 /* gencjneshort - compare and jump if not equal                    */
5558 /*-----------------------------------------------------------------*/
5559 static void
5560 gencjneshort (operand * left, operand * right, symbol * lbl)
5561 {
5562   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5563   int offset = 0;
5564   unsigned long lit = 0L;
5565
5566   D (emitcode (";", "gencjneshort");
5567     );
5568
5569   /* if the left side is a literal or
5570      if the right is in a pointer register and left
5571      is not */
5572   if ((AOP_TYPE (left) == AOP_LIT) ||
5573       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5574     {
5575       operand *t = right;
5576       right = left;
5577       left = t;
5578     }
5579
5580   if (AOP_TYPE (right) == AOP_LIT)
5581     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5582
5583   if (opIsGptr (left) || opIsGptr (right))
5584     {
5585       /* We are comparing a generic pointer to something.
5586        * Exclude the generic type byte from the comparison.
5587        */
5588       size--;
5589       D (emitcode (";", "cjneshort: generic ptr special case."););
5590     }
5591
5592
5593   /* if the right side is a literal then anything goes */
5594   if (AOP_TYPE (right) == AOP_LIT &&
5595       AOP_TYPE (left) != AOP_DIR)
5596     {
5597       while (size--)
5598         {
5599           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5600           emitcode ("cjne", "a,%s,!tlabel",
5601                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5602                     lbl->key + 100);
5603           offset++;
5604         }
5605     }
5606
5607   /* if the right side is in a register or in direct space or
5608      if the left is a pointer register & right is not */
5609   else if (AOP_TYPE (right) == AOP_REG ||
5610            AOP_TYPE (right) == AOP_DIR ||
5611            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5612            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5613     {
5614       while (size--)
5615         {
5616           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5617           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5618               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5619             emitcode ("jnz", "!tlabel", lbl->key + 100);
5620           else
5621             emitcode ("cjne", "a,%s,!tlabel",
5622                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5623                       lbl->key + 100);
5624           offset++;
5625         }
5626     }
5627   else
5628     {
5629       /* right is a pointer reg need both a & b */
5630       while (size--)
5631         {
5632           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5633           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5634           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5635           offset++;
5636         }
5637     }
5638 }
5639
5640 /*-----------------------------------------------------------------*/
5641 /* gencjne - compare and jump if not equal                         */
5642 /*-----------------------------------------------------------------*/
5643 static void
5644 gencjne (operand * left, operand * right, symbol * lbl)
5645 {
5646   symbol *tlbl = newiTempLabel (NULL);
5647
5648   D (emitcode (";", "gencjne");
5649     );
5650
5651   gencjneshort (left, right, lbl);
5652
5653   emitcode ("mov", "a,%s", one);
5654   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5655   emitcode ("", "!tlabeldef", lbl->key + 100);
5656   emitcode ("clr", "a");
5657   emitcode ("", "!tlabeldef", tlbl->key + 100);
5658 }
5659
5660 /*-----------------------------------------------------------------*/
5661 /* genCmpEq - generates code for equal to                          */
5662 /*-----------------------------------------------------------------*/
5663 static void
5664 genCmpEq (iCode * ic, iCode * ifx)
5665 {
5666   operand *left, *right, *result;
5667
5668   D (emitcode (";", "genCmpEq ");
5669     );
5670
5671   AOP_OP_2 (ic);
5672   AOP_SET_LOCALS (ic);
5673
5674   /* if literal, literal on the right or
5675      if the right is in a pointer register and left
5676      is not */
5677   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5678       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5679     {
5680       operand *t = IC_RIGHT (ic);
5681       IC_RIGHT (ic) = IC_LEFT (ic);
5682       IC_LEFT (ic) = t;
5683     }
5684
5685   if (ifx &&                    /* !AOP_SIZE(result) */
5686       OP_SYMBOL (result) &&
5687       OP_SYMBOL (result)->regType == REG_CND)
5688     {
5689       symbol *tlbl;
5690       /* if they are both bit variables */
5691       if (AOP_TYPE (left) == AOP_CRY &&
5692           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5693         {
5694           if (AOP_TYPE (right) == AOP_LIT)
5695             {
5696               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5697               if (lit == 0L)
5698                 {
5699                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5700                   emitcode ("cpl", "c");
5701                 }
5702               else if (lit == 1L)
5703                 {
5704                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5705                 }
5706               else
5707                 {
5708                   emitcode ("clr", "c");
5709                 }
5710               /* AOP_TYPE(right) == AOP_CRY */
5711             }
5712           else
5713             {
5714               symbol *lbl = newiTempLabel (NULL);
5715               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5716               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5717               emitcode ("cpl", "c");
5718               emitcode ("", "!tlabeldef", (lbl->key + 100));
5719             }
5720           /* if true label then we jump if condition
5721              supplied is true */
5722           tlbl = newiTempLabel (NULL);
5723           if (IC_TRUE (ifx))
5724             {
5725               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5726               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5727             }
5728           else
5729             {
5730               emitcode ("jc", "!tlabel", tlbl->key + 100);
5731               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5732             }
5733           emitcode ("", "!tlabeldef", tlbl->key + 100);
5734         }
5735       else
5736         {
5737           tlbl = newiTempLabel (NULL);
5738           gencjneshort (left, right, tlbl);
5739           if (IC_TRUE (ifx))
5740             {
5741               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5742               emitcode ("", "!tlabeldef", tlbl->key + 100);
5743             }
5744           else
5745             {
5746               symbol *lbl = newiTempLabel (NULL);
5747               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5748               emitcode ("", "!tlabeldef", tlbl->key + 100);
5749               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5750               emitcode ("", "!tlabeldef", lbl->key + 100);
5751             }
5752         }
5753       /* mark the icode as generated */
5754       ifx->generated = 1;
5755
5756       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5757       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5758       return;
5759     }
5760
5761   /* if they are both bit variables */
5762   if (AOP_TYPE (left) == AOP_CRY &&
5763       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5764     {
5765       if (AOP_TYPE (right) == AOP_LIT)
5766         {
5767           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5768           if (lit == 0L)
5769             {
5770               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5771               emitcode ("cpl", "c");
5772             }
5773           else if (lit == 1L)
5774             {
5775               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5776             }
5777           else
5778             {
5779               emitcode ("clr", "c");
5780             }
5781           /* AOP_TYPE(right) == AOP_CRY */
5782         }
5783       else
5784         {
5785           symbol *lbl = newiTempLabel (NULL);
5786           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5787           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5788           emitcode ("cpl", "c");
5789           emitcode ("", "!tlabeldef", (lbl->key + 100));
5790         }
5791
5792       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5793       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5794
5795       aopOp (result, ic, TRUE, FALSE);
5796
5797       /* c = 1 if egal */
5798       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5799         {
5800           outBitC (result);
5801           goto release;
5802         }
5803       if (ifx)
5804         {
5805           genIfxJump (ifx, "c");
5806           goto release;
5807         }
5808       /* if the result is used in an arithmetic operation
5809          then put the result in place */
5810       outBitC (result);
5811     }
5812   else
5813     {
5814       gencjne (left, right, newiTempLabel (NULL));
5815
5816       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5817       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5818
5819       aopOp (result, ic, TRUE, FALSE);
5820
5821       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5822         {
5823           aopPut (AOP (result), "a", 0);
5824           goto release;
5825         }
5826       if (ifx)
5827         {
5828           genIfxJump (ifx, "a");
5829           goto release;
5830         }
5831       /* if the result is used in an arithmetic operation
5832          then put the result in place */
5833       if (AOP_TYPE (result) != AOP_CRY)
5834         outAcc (result);
5835       /* leave the result in acc */
5836     }
5837
5838 release:
5839   freeAsmop (result, NULL, ic, TRUE);
5840 }
5841
5842 /*-----------------------------------------------------------------*/
5843 /* ifxForOp - returns the icode containing the ifx for operand     */
5844 /*-----------------------------------------------------------------*/
5845 static iCode *
5846 ifxForOp (operand * op, iCode * ic)
5847 {
5848   /* if true symbol then needs to be assigned */
5849   if (IS_TRUE_SYMOP (op))
5850     return NULL;
5851
5852   /* if this has register type condition and
5853      the next instruction is ifx with the same operand
5854      and live to of the operand is upto the ifx only then */
5855   if (ic->next &&
5856       ic->next->op == IFX &&
5857       IC_COND (ic->next)->key == op->key &&
5858       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5859     return ic->next;
5860
5861   return NULL;
5862 }
5863 /*-----------------------------------------------------------------*/
5864 /* hasInc - operand is incremented before any other use            */
5865 /*-----------------------------------------------------------------*/
5866 static iCode *
5867 hasInc (operand *op, iCode *ic, int osize)
5868 {
5869   sym_link *type = operandType(op);
5870   sym_link *retype = getSpec (type);
5871   iCode *lic = ic->next;
5872   int isize ;
5873   
5874   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5875   if (!IS_SYMOP(op)) return NULL;
5876
5877   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5878   if (IS_AGGREGATE(type->next)) return NULL;
5879   if (osize != (isize = getSize(type->next))) return NULL;
5880
5881   while (lic) {
5882       /* if operand of the form op = op + <sizeof *op> */
5883       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5884           isOperandEqual(IC_RESULT(lic),op) && 
5885           isOperandLiteral(IC_RIGHT(lic)) &&
5886           operandLitValue(IC_RIGHT(lic)) == isize) {
5887           return lic;
5888       }
5889       /* if the operand used or deffed */
5890       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5891           return NULL;
5892       }
5893       /* if GOTO or IFX */
5894       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5895       lic = lic->next;
5896   }
5897   return NULL;
5898 }
5899
5900 /*-----------------------------------------------------------------*/
5901 /* genAndOp - for && operation                                     */
5902 /*-----------------------------------------------------------------*/
5903 static void
5904 genAndOp (iCode * ic)
5905 {
5906   operand *left, *right, *result;
5907   symbol *tlbl;
5908
5909   D (emitcode (";", "genAndOp "););
5910
5911   /* note here that && operations that are in an
5912      if statement are taken away by backPatchLabels
5913      only those used in arthmetic operations remain */
5914   AOP_OP_2 (ic);
5915   AOP_SET_LOCALS (ic);
5916
5917   /* if both are bit variables */
5918   if (AOP_TYPE (left) == AOP_CRY &&
5919       AOP_TYPE (right) == AOP_CRY)
5920     {
5921       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5922       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5923       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5924       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5925   
5926       aopOp (result,ic,FALSE, FALSE);
5927       outBitC (result);
5928     }
5929   else
5930     {
5931       tlbl = newiTempLabel (NULL);
5932       toBoolean (left);
5933       emitcode ("jz", "!tlabel", tlbl->key + 100);
5934       toBoolean (right);
5935       emitcode ("", "!tlabeldef", tlbl->key + 100);
5936       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5937       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5938   
5939       aopOp (result,ic,FALSE, FALSE);
5940       outBitAcc (result);
5941     }
5942     freeAsmop (result, NULL, ic, TRUE);
5943 }
5944
5945
5946 /*-----------------------------------------------------------------*/
5947 /* genOrOp - for || operation                                      */
5948 /*-----------------------------------------------------------------*/
5949 static void
5950 genOrOp (iCode * ic)
5951 {
5952   operand *left, *right, *result;
5953   symbol *tlbl;
5954
5955   D (emitcode (";", "genOrOp "););
5956
5957   /* note here that || operations that are in an
5958      if statement are taken away by backPatchLabels
5959      only those used in arthmetic operations remain */
5960   AOP_OP_2 (ic);
5961   AOP_SET_LOCALS (ic);
5962
5963   /* if both are bit variables */
5964   if (AOP_TYPE (left) == AOP_CRY &&
5965       AOP_TYPE (right) == AOP_CRY)
5966     {
5967       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5968       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5969       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5970       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5971   
5972       aopOp (result,ic,FALSE, FALSE);
5973       
5974       outBitC (result);
5975     }
5976   else
5977     {
5978       tlbl = newiTempLabel (NULL);
5979       toBoolean (left);
5980       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5981       toBoolean (right);
5982       emitcode ("", "!tlabeldef", tlbl->key + 100);
5983       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5984       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5985   
5986       aopOp (result,ic,FALSE, FALSE);
5987       
5988       outBitAcc (result);
5989     }
5990
5991   freeAsmop (result, NULL, ic, TRUE);
5992 }
5993
5994 /*-----------------------------------------------------------------*/
5995 /* isLiteralBit - test if lit == 2^n                               */
5996 /*-----------------------------------------------------------------*/
5997 static int
5998 isLiteralBit (unsigned long lit)
5999 {
6000   unsigned long pw[32] =
6001   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6002    0x100L, 0x200L, 0x400L, 0x800L,
6003    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6004    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6005    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6006    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6007    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6008   int idx;
6009
6010   for (idx = 0; idx < 32; idx++)
6011     if (lit == pw[idx])
6012       return idx + 1;
6013   return 0;
6014 }
6015
6016 /*-----------------------------------------------------------------*/
6017 /* continueIfTrue -                                                */
6018 /*-----------------------------------------------------------------*/
6019 static void
6020 continueIfTrue (iCode * ic)
6021 {
6022   if (IC_TRUE (ic))
6023     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6024   ic->generated = 1;
6025 }
6026
6027 /*-----------------------------------------------------------------*/
6028 /* jmpIfTrue -                                                     */
6029 /*-----------------------------------------------------------------*/
6030 static void
6031 jumpIfTrue (iCode * ic)
6032 {
6033   if (!IC_TRUE (ic))
6034     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6035   ic->generated = 1;
6036 }
6037
6038 /*-----------------------------------------------------------------*/
6039 /* jmpTrueOrFalse -                                                */
6040 /*-----------------------------------------------------------------*/
6041 static void
6042 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6043 {
6044   // ugly but optimized by peephole
6045   if (IC_TRUE (ic))
6046     {
6047       symbol *nlbl = newiTempLabel (NULL);
6048       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6049       emitcode ("", "!tlabeldef", tlbl->key + 100);
6050       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6051       emitcode ("", "!tlabeldef", nlbl->key + 100);
6052     }
6053   else
6054     {
6055       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6056       emitcode ("", "!tlabeldef", tlbl->key + 100);
6057     }
6058   ic->generated = 1;
6059 }
6060
6061 // Generate code to perform a bit-wise logic operation
6062 // on two operands in far space (assumed to already have been 
6063 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6064 // in far space. This requires pushing the result on the stack
6065 // then popping it into the result.
6066 static void
6067 genFarFarLogicOp(iCode *ic, char *logicOp)
6068 {
6069       int size, resultSize, compSize;
6070       int offset = 0;
6071       
6072       TR_AP("#5");
6073       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6074       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6075                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6076       
6077       _startLazyDPSEvaluation();
6078       for (size = compSize; (size--); offset++)
6079       {
6080           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6081           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6082           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6083           
6084           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6085           emitcode ("push", "acc");
6086       }
6087       _endLazyDPSEvaluation();
6088      
6089       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6090       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6091       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6092      
6093       resultSize = AOP_SIZE(IC_RESULT(ic));
6094
6095       ADJUST_PUSHED_RESULT(compSize, resultSize);
6096
6097       _startLazyDPSEvaluation();
6098       while (compSize--)
6099       {
6100           emitcode ("pop", "acc");
6101           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6102       }
6103       _endLazyDPSEvaluation();
6104       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6105 }
6106
6107
6108 /*-----------------------------------------------------------------*/
6109 /* genAnd  - code for and                                          */
6110 /*-----------------------------------------------------------------*/
6111 static void
6112 genAnd (iCode * ic, iCode * ifx)
6113 {
6114   operand *left, *right, *result;
6115   int size, offset = 0;
6116   unsigned long lit = 0L;
6117   int bytelit;
6118   char buff[10];
6119   bool pushResult;
6120
6121   D (emitcode (";", "genAnd "););
6122
6123   AOP_OP_3_NOFATAL (ic, pushResult);
6124   AOP_SET_LOCALS (ic);
6125
6126   if (pushResult)
6127   {
6128       genFarFarLogicOp(ic, "anl");
6129       return;
6130   }  
6131
6132 #ifdef DEBUG_TYPE
6133   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6134             AOP_TYPE (result),
6135             AOP_TYPE (left), AOP_TYPE (right));
6136   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6137             AOP_SIZE (result),
6138             AOP_SIZE (left), AOP_SIZE (right));
6139 #endif
6140
6141   /* if left is a literal & right is not then exchange them */
6142   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6143 #ifdef LOGIC_OPS_BROKEN      
6144     ||  AOP_NEEDSACC (left)
6145 #endif
6146     )
6147     {
6148       operand *tmp = right;
6149       right = left;
6150       left = tmp;
6151     }
6152
6153   /* if result = right then exchange them */
6154   if (sameRegs (AOP (result), AOP (right)))
6155     {
6156       operand *tmp = right;
6157       right = left;
6158       left = tmp;
6159     }
6160
6161   /* if right is bit then exchange them */
6162   if (AOP_TYPE (right) == AOP_CRY &&
6163       AOP_TYPE (left) != AOP_CRY)
6164     {
6165       operand *tmp = right;
6166       right = left;
6167       left = tmp;
6168     }
6169   if (AOP_TYPE (right) == AOP_LIT)
6170     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6171
6172   size = AOP_SIZE (result);
6173
6174   // if(bit & yy)
6175   // result = bit & yy;
6176   if (AOP_TYPE (left) == AOP_CRY)
6177     {
6178       // c = bit & literal;
6179       if (AOP_TYPE (right) == AOP_LIT)
6180         {
6181           if (lit & 1)
6182             {
6183               if (size && sameRegs (AOP (result), AOP (left)))
6184                 // no change
6185                 goto release;
6186               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6187             }
6188           else
6189             {
6190               // bit(result) = 0;
6191               if (size && (AOP_TYPE (result) == AOP_CRY))
6192                 {
6193                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6194                   goto release;
6195                 }
6196               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6197                 {
6198                   jumpIfTrue (ifx);
6199                   goto release;
6200                 }
6201               emitcode ("clr", "c");
6202             }
6203         }
6204       else
6205         {
6206           if (AOP_TYPE (right) == AOP_CRY)
6207             {
6208               // c = bit & bit;
6209               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6210               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6211             }
6212           else
6213             {
6214               // c = bit & val;
6215               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6216               // c = lsb
6217               emitcode ("rrc", "a");
6218               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6219             }
6220         }
6221       // bit = c
6222       // val = c
6223       if (size)
6224         outBitC (result);
6225       // if(bit & ...)
6226       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6227         genIfxJump (ifx, "c");
6228       goto release;
6229     }
6230
6231   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6232   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6233   if ((AOP_TYPE (right) == AOP_LIT) &&
6234       (AOP_TYPE (result) == AOP_CRY) &&
6235       (AOP_TYPE (left) != AOP_CRY))
6236     {
6237       int posbit = isLiteralBit (lit);
6238       /* left &  2^n */
6239       if (posbit)
6240         {
6241           posbit--;
6242           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6243           // bit = left & 2^n
6244           if (size)
6245             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6246           // if(left &  2^n)
6247           else
6248             {
6249               if (ifx)
6250                 {
6251                   SNPRINTF (buff, sizeof(buff), 
6252                             "acc.%d", posbit & 0x07);
6253                   genIfxJump (ifx, buff);
6254                 }
6255               else 
6256                   {
6257                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6258                   }
6259               goto release;
6260             }
6261         }
6262       else
6263         {
6264           symbol *tlbl = newiTempLabel (NULL);
6265           int sizel = AOP_SIZE (left);
6266           if (size)
6267             emitcode ("setb", "c");
6268           while (sizel--)
6269             {
6270               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6271                 {
6272                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6273                   // byte ==  2^n ?
6274                   if ((posbit = isLiteralBit (bytelit)) != 0)
6275                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6276                   else
6277                     {
6278                       if (bytelit != 0x0FFL)
6279                         emitcode ("anl", "a,%s",
6280                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6281                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6282                     }
6283                 }
6284               offset++;
6285             }
6286           // bit = left & literal
6287           if (size)
6288             {
6289               emitcode ("clr", "c");
6290               emitcode ("", "!tlabeldef", tlbl->key + 100);
6291             }
6292           // if(left & literal)
6293           else
6294             {
6295               if (ifx)
6296                 jmpTrueOrFalse (ifx, tlbl);
6297               goto release;
6298             }
6299         }
6300       outBitC (result);
6301       goto release;
6302     }
6303
6304   /* if left is same as result */
6305   if (sameRegs (AOP (result), AOP (left)))
6306     {
6307       for (; size--; offset++)
6308         {
6309           if (AOP_TYPE (right) == AOP_LIT)
6310             {
6311               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6312                 continue;
6313               else if (bytelit == 0)
6314                 aopPut (AOP (result), zero, offset);
6315               else if (IS_AOP_PREG (result))
6316                 {
6317                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6318                   emitcode ("anl", "a,%s",
6319                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6320                   aopPut (AOP (result), "a", offset);
6321                 }
6322               else
6323                 emitcode ("anl", "%s,%s",
6324                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6325                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6326             }
6327           else
6328             {
6329               if (AOP_TYPE (left) == AOP_ACC)
6330                 emitcode ("anl", "a,%s",
6331                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6332               else
6333                 {
6334                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6335                   if (IS_AOP_PREG (result))
6336                     {
6337                       emitcode ("anl", "a,%s",
6338                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6339                       aopPut (AOP (result), "a", offset);
6340                     }
6341                   else
6342                     emitcode ("anl", "%s,a",
6343                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6344                 }
6345             }
6346         }
6347     }
6348   else
6349     {
6350       // left & result in different registers
6351       if (AOP_TYPE (result) == AOP_CRY)
6352         {
6353           // result = bit
6354           // if(size), result in bit
6355           // if(!size && ifx), conditional oper: if(left & right)
6356           symbol *tlbl = newiTempLabel (NULL);
6357           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6358           if (size)
6359             emitcode ("setb", "c");
6360           while (sizer--)
6361             {
6362               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6363                 emitcode ("anl", "a,%s",
6364                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6365               } else {
6366                 if (AOP_TYPE(left)==AOP_ACC) {
6367                   emitcode("mov", "b,a");
6368                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6369                   emitcode("anl", "a,b");
6370                 }else {
6371                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6372                   emitcode ("anl", "a,%s",
6373                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6374                 }
6375               }
6376               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6377               offset++;
6378             }
6379           if (size)
6380             {
6381               CLRC;
6382               emitcode ("", "!tlabeldef", tlbl->key + 100);
6383               outBitC (result);
6384             }
6385           else if (ifx)
6386             jmpTrueOrFalse (ifx, tlbl);
6387         }
6388       else
6389         {
6390           for (; (size--); offset++)
6391             {
6392               // normal case
6393               // result = left & right
6394               if (AOP_TYPE (right) == AOP_LIT)
6395                 {
6396                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6397                     {
6398                       aopPut (AOP (result),
6399                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6400                               offset);
6401                       continue;
6402                     }
6403                   else if (bytelit == 0)
6404                     {
6405                       aopPut (AOP (result), zero, offset);
6406                       continue;
6407                     }
6408                   D (emitcode (";", "better literal AND."););
6409                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6410                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6411                                                     FALSE, FALSE, DP2_RESULT_REG));
6412
6413                 }
6414               else
6415                 {
6416                   // faster than result <- left, anl result,right
6417                   // and better if result is SFR
6418                   if (AOP_TYPE (left) == AOP_ACC)
6419                     {
6420                       emitcode ("anl", "a,%s", 
6421                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6422                     }
6423                   else
6424                     {
6425                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6426                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6427                       {
6428                           emitcode("mov", "b,a");
6429                           rOp = "b";
6430                       }
6431                         
6432                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6433                       emitcode ("anl", "a,%s", rOp);
6434                     }                   
6435                 }
6436               aopPut (AOP (result), "a", offset);
6437             }
6438         }
6439     }
6440
6441 release:
6442   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6443   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6444   freeAsmop (result, NULL, ic, TRUE);
6445 }
6446
6447
6448 /*-----------------------------------------------------------------*/
6449 /* genOr  - code for or                                            */
6450 /*-----------------------------------------------------------------*/
6451 static void
6452 genOr (iCode * ic, iCode * ifx)
6453 {
6454   operand *left, *right, *result;
6455   int size, offset = 0;
6456   unsigned long lit = 0L;
6457   bool     pushResult;
6458
6459   D (emitcode (";", "genOr "););
6460
6461   AOP_OP_3_NOFATAL (ic, pushResult);
6462   AOP_SET_LOCALS (ic);
6463
6464   if (pushResult)
6465   {
6466       genFarFarLogicOp(ic, "orl");
6467       return;
6468   }
6469
6470
6471 #ifdef DEBUG_TYPE
6472   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6473             AOP_TYPE (result),
6474             AOP_TYPE (left), AOP_TYPE (right));
6475   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6476             AOP_SIZE (result),
6477             AOP_SIZE (left), AOP_SIZE (right));
6478 #endif
6479
6480   /* if left is a literal & right is not then exchange them */
6481   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6482 #ifdef LOGIC_OPS_BROKEN
6483    || AOP_NEEDSACC (left) // I think this is a net loss now.
6484 #endif      
6485       )
6486     {
6487       operand *tmp = right;
6488       right = left;
6489       left = tmp;
6490     }
6491
6492   /* if result = right then exchange them */
6493   if (sameRegs (AOP (result), AOP (right)))
6494     {
6495       operand *tmp = right;
6496       right = left;
6497       left = tmp;
6498     }
6499
6500   /* if right is bit then exchange them */
6501   if (AOP_TYPE (right) == AOP_CRY &&
6502       AOP_TYPE (left) != AOP_CRY)
6503     {
6504       operand *tmp = right;
6505       right = left;
6506       left = tmp;
6507     }
6508   if (AOP_TYPE (right) == AOP_LIT)
6509     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6510
6511   size = AOP_SIZE (result);
6512
6513   // if(bit | yy)
6514   // xx = bit | yy;
6515   if (AOP_TYPE (left) == AOP_CRY)
6516     {
6517       if (AOP_TYPE (right) == AOP_LIT)
6518         {
6519           // c = bit & literal;
6520           if (lit)
6521             {
6522               // lit != 0 => result = 1
6523               if (AOP_TYPE (result) == AOP_CRY)
6524                 {
6525                   if (size)
6526                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6527                   else if (ifx)
6528                     continueIfTrue (ifx);
6529                   goto release;
6530                 }
6531               emitcode ("setb", "c");
6532             }
6533           else
6534             {
6535               // lit == 0 => result = left
6536               if (size && sameRegs (AOP (result), AOP (left)))
6537                 goto release;
6538               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6539             }
6540         }
6541       else
6542         {
6543           if (AOP_TYPE (right) == AOP_CRY)
6544             {
6545               // c = bit | bit;
6546               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6547               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6548             }
6549           else
6550             {
6551               // c = bit | val;
6552               symbol *tlbl = newiTempLabel (NULL);
6553               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6554                 emitcode ("setb", "c");
6555               emitcode ("jb", "%s,!tlabel",
6556                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6557               toBoolean (right);
6558               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6559               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6560                 {
6561                   jmpTrueOrFalse (ifx, tlbl);
6562                   goto release;
6563                 }
6564               else
6565                 {
6566                   CLRC;
6567                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6568                 }
6569             }
6570         }
6571       // bit = c
6572       // val = c
6573       if (size)
6574         outBitC (result);
6575       // if(bit | ...)
6576       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6577            genIfxJump (ifx, "c");
6578       goto release;
6579     }
6580
6581   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6582   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6583   if ((AOP_TYPE (right) == AOP_LIT) &&
6584       (AOP_TYPE (result) == AOP_CRY) &&
6585       (AOP_TYPE (left) != AOP_CRY))
6586     {
6587       if (lit)
6588         {
6589           // result = 1
6590           if (size)
6591             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6592           else
6593             continueIfTrue (ifx);
6594           goto release;
6595         }
6596       else
6597         {
6598           // lit = 0, result = boolean(left)
6599           if (size)
6600             emitcode ("setb", "c");
6601           toBoolean (right);
6602           if (size)
6603             {
6604               symbol *tlbl = newiTempLabel (NULL);
6605               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6606               CLRC;
6607               emitcode ("", "!tlabeldef", tlbl->key + 100);
6608             }
6609           else
6610             {
6611               genIfxJump (ifx, "a");
6612               goto release;
6613             }
6614         }
6615       outBitC (result);
6616       goto release;
6617     }
6618
6619   /* if left is same as result */
6620   if (sameRegs (AOP (result), AOP (left)))
6621     {
6622       for (; size--; offset++)
6623         {
6624           if (AOP_TYPE (right) == AOP_LIT)
6625             {
6626               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6627                 {
6628                   continue;
6629                 }
6630               else
6631                 {
6632                   if (IS_AOP_PREG (left))
6633                     {
6634                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6635                       emitcode ("orl", "a,%s",
6636                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6637                       aopPut (AOP (result), "a", offset);
6638                     }
6639                   else
6640                     {
6641                       emitcode ("orl", "%s,%s",
6642                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6643                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6644                     }
6645                 }
6646             }
6647           else
6648             {
6649               if (AOP_TYPE (left) == AOP_ACC)
6650                 {
6651                   emitcode ("orl", "a,%s",
6652                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6653                 }
6654               else
6655                 {
6656                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6657                   if (IS_AOP_PREG (left))
6658                     {
6659                       emitcode ("orl", "a,%s", 
6660                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6661                       aopPut (AOP (result), "a", offset);
6662                     }
6663                   else
6664                     {
6665                       emitcode ("orl", "%s,a",
6666                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6667                     }
6668                 }
6669             }
6670         }
6671     }
6672   else
6673     {
6674       // left & result in different registers
6675       if (AOP_TYPE (result) == AOP_CRY)
6676         {
6677           // result = bit
6678           // if(size), result in bit
6679           // if(!size && ifx), conditional oper: if(left | right)
6680           symbol *tlbl = newiTempLabel (NULL);
6681           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6682           if (size)
6683             emitcode ("setb", "c");
6684           while (sizer--)
6685             {
6686               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6687                 emitcode ("orl", "a,%s",
6688                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6689               } else {
6690                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6691                 emitcode ("orl", "a,%s",
6692                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6693               }
6694               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6695               offset++;
6696             }
6697           if (size)
6698             {
6699               CLRC;
6700               emitcode ("", "!tlabeldef", tlbl->key + 100);
6701               outBitC (result);
6702             }
6703           else if (ifx)
6704             jmpTrueOrFalse (ifx, tlbl);
6705         }
6706       else
6707         {
6708             _startLazyDPSEvaluation();
6709           for (; (size--); offset++)
6710             {
6711               // normal case
6712               // result = left & right
6713               if (AOP_TYPE (right) == AOP_LIT)
6714                 {
6715                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6716                     {
6717                       aopPut (AOP (result),
6718                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6719                               offset);
6720                       continue;
6721                     }
6722                   D (emitcode (";", "better literal OR."););
6723                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6724                   emitcode ("orl", "a, %s",
6725                             aopGet (AOP (right), offset,
6726                                     FALSE, FALSE, DP2_RESULT_REG));
6727
6728                 }
6729               else
6730                 {
6731                   // faster than result <- left, anl result,right
6732                   // and better if result is SFR
6733                   if (AOP_TYPE (left) == AOP_ACC)
6734                     {
6735                       emitcode ("orl", "a,%s",
6736                                 aopGet (AOP (right), offset,
6737                                         FALSE, FALSE, DP2_RESULT_REG));
6738                     }
6739                   else
6740                     {
6741                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6742                         
6743                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6744                       {
6745                           emitcode("mov", "b,a");
6746                           rOp = "b";
6747                       }
6748                         
6749                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6750                       emitcode ("orl", "a,%s", rOp);
6751                     }
6752                 }
6753               aopPut (AOP (result), "a", offset);
6754             }
6755             _endLazyDPSEvaluation();
6756         }
6757     }
6758
6759 release:
6760   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6761   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6762   freeAsmop (result, NULL, ic, TRUE);
6763 }
6764
6765 /*-----------------------------------------------------------------*/
6766 /* genXor - code for xclusive or                                   */
6767 /*-----------------------------------------------------------------*/
6768 static void
6769 genXor (iCode * ic, iCode * ifx)
6770 {
6771   operand *left, *right, *result;
6772   int size, offset = 0;
6773   unsigned long lit = 0L;
6774   bool pushResult;
6775
6776   D (emitcode (";", "genXor "););
6777
6778   AOP_OP_3_NOFATAL (ic, pushResult);
6779   AOP_SET_LOCALS (ic);
6780
6781   if (pushResult)
6782   {
6783       genFarFarLogicOp(ic, "xrl");
6784       return;
6785   }  
6786
6787 #ifdef DEBUG_TYPE
6788   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6789             AOP_TYPE (result),
6790             AOP_TYPE (left), AOP_TYPE (right));
6791   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6792             AOP_SIZE (result),
6793             AOP_SIZE (left), AOP_SIZE (right));
6794 #endif
6795
6796   /* if left is a literal & right is not ||
6797      if left needs acc & right does not */
6798   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6799 #ifdef LOGIC_OPS_BROKEN      
6800       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6801 #endif
6802      )
6803     {
6804       operand *tmp = right;
6805       right = left;
6806       left = tmp;
6807     }
6808
6809   /* if result = right then exchange them */
6810   if (sameRegs (AOP (result), AOP (right)))
6811     {
6812       operand *tmp = right;
6813       right = left;
6814       left = tmp;
6815     }
6816
6817   /* if right is bit then exchange them */
6818   if (AOP_TYPE (right) == AOP_CRY &&
6819       AOP_TYPE (left) != AOP_CRY)
6820     {
6821       operand *tmp = right;
6822       right = left;
6823       left = tmp;
6824     }
6825   if (AOP_TYPE (right) == AOP_LIT)
6826     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6827
6828   size = AOP_SIZE (result);
6829
6830   // if(bit ^ yy)
6831   // xx = bit ^ yy;
6832   if (AOP_TYPE (left) == AOP_CRY)
6833     {
6834       if (AOP_TYPE (right) == AOP_LIT)
6835         {
6836           // c = bit & literal;
6837           if (lit >> 1)
6838             {
6839               // lit>>1  != 0 => result = 1
6840               if (AOP_TYPE (result) == AOP_CRY)
6841                 {
6842                   if (size)
6843                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6844                   else if (ifx)
6845                     continueIfTrue (ifx);
6846                   goto release;
6847                 }
6848               emitcode ("setb", "c");
6849             }
6850           else
6851             {
6852               // lit == (0 or 1)
6853               if (lit == 0)
6854                 {
6855                   // lit == 0, result = left
6856                   if (size && sameRegs (AOP (result), AOP (left)))
6857                     goto release;
6858                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6859                 }
6860               else
6861                 {
6862                   // lit == 1, result = not(left)
6863                   if (size && sameRegs (AOP (result), AOP (left)))
6864                     {
6865                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6866                       goto release;
6867                     }
6868                   else
6869                     {
6870                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6871                       emitcode ("cpl", "c");
6872                     }
6873                 }
6874             }
6875
6876         }
6877       else
6878         {
6879           // right != literal
6880           symbol *tlbl = newiTempLabel (NULL);
6881           if (AOP_TYPE (right) == AOP_CRY)
6882             {
6883               // c = bit ^ bit;
6884               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6885             }
6886           else
6887             {
6888               int sizer = AOP_SIZE (right);
6889               // c = bit ^ val
6890               // if val>>1 != 0, result = 1
6891               emitcode ("setb", "c");
6892               while (sizer)
6893                 {
6894                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6895                   if (sizer == 1)
6896                     // test the msb of the lsb
6897                     emitcode ("anl", "a,#!constbyte",0xfe);
6898                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6899                   sizer--;
6900                 }
6901               // val = (0,1)
6902               emitcode ("rrc", "a");
6903             }
6904           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6905           emitcode ("cpl", "c");
6906           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6907         }
6908       // bit = c
6909       // val = c
6910       if (size)
6911         outBitC (result);
6912       // if(bit | ...)
6913       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6914         genIfxJump (ifx, "c");
6915       goto release;
6916     }
6917
6918   if (sameRegs (AOP (result), AOP (left)))
6919     {
6920       /* if left is same as result */
6921       for (; size--; offset++)
6922         {
6923           if (AOP_TYPE (right) == AOP_LIT)
6924             {
6925               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6926                 continue;
6927               else if (IS_AOP_PREG (left))
6928                 {
6929                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6930                   emitcode ("xrl", "a,%s",
6931                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6932                   aopPut (AOP (result), "a", offset);
6933                 }
6934               else
6935                 emitcode ("xrl", "%s,%s",
6936                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6937                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6938             }
6939           else
6940             {
6941               if (AOP_TYPE (left) == AOP_ACC)
6942                 emitcode ("xrl", "a,%s",
6943                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6944               else
6945                 {
6946                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6947                   if (IS_AOP_PREG (left))
6948                     {
6949                       emitcode ("xrl", "a,%s",
6950                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6951                       aopPut (AOP (result), "a", offset);
6952                     }
6953                   else
6954                     emitcode ("xrl", "%s,a",
6955                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6956                 }
6957             }
6958         }
6959     }
6960   else
6961     {
6962       // left & result in different registers
6963       if (AOP_TYPE (result) == AOP_CRY)
6964         {
6965           // result = bit
6966           // if(size), result in bit
6967           // if(!size && ifx), conditional oper: if(left ^ right)
6968           symbol *tlbl = newiTempLabel (NULL);
6969           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6970                   
6971           if (size)
6972             emitcode ("setb", "c");
6973           while (sizer--)
6974             {
6975               if ((AOP_TYPE (right) == AOP_LIT) &&
6976                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6977                 {
6978                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6979                 }
6980               else
6981                 {
6982                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6983                     emitcode ("xrl", "a,%s",
6984                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6985                   } else {
6986                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6987                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6988                       {
6989                           emitcode("mov", "b,a");
6990                           rOp = "b";
6991                       }
6992                         
6993                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6994                       emitcode ("xrl", "a,%s", rOp);                  
6995                   }
6996                 }
6997               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6998               offset++;
6999             }
7000           if (size)
7001             {
7002               CLRC;
7003               emitcode ("", "!tlabeldef", tlbl->key + 100);
7004               outBitC (result);
7005             }
7006           else if (ifx)
7007             jmpTrueOrFalse (ifx, tlbl);
7008         }
7009       else
7010         {
7011         for (; (size--); offset++)
7012           {
7013             // normal case
7014             // result = left & right
7015             if (AOP_TYPE (right) == AOP_LIT)
7016               {
7017                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7018                   {
7019                     aopPut (AOP (result),
7020                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7021                             offset);
7022                     continue;
7023                   }
7024                 D (emitcode (";", "better literal XOR."););
7025                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7026                 emitcode ("xrl", "a, %s",
7027                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7028               }
7029             else
7030               {
7031                 // faster than result <- left, anl result,right
7032                 // and better if result is SFR
7033                 if (AOP_TYPE (left) == AOP_ACC)
7034                   {
7035                     emitcode ("xrl", "a,%s",
7036                               aopGet (AOP (right), offset,
7037                                       FALSE, FALSE, DP2_RESULT_REG));
7038                   }
7039                 else
7040                   {
7041                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7042                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7043                       {
7044                           emitcode("mov", "b,a");
7045                           rOp = "b";
7046                       }
7047                         
7048                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7049                       emitcode ("xrl", "a,%s", rOp);
7050                   }
7051               }
7052             aopPut (AOP (result), "a", offset);
7053           }
7054         }
7055         
7056     }
7057
7058 release:
7059   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7060   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7061   freeAsmop (result, NULL, ic, TRUE);
7062 }
7063
7064 /*-----------------------------------------------------------------*/
7065 /* genInline - write the inline code out                           */
7066 /*-----------------------------------------------------------------*/
7067 static void
7068 genInline (iCode * ic)
7069 {
7070   char *buffer, *bp, *bp1;
7071
7072   D (emitcode (";", "genInline "); );
7073
7074   _G.inLine += (!options.asmpeep);
7075
7076   buffer = Safe_strdup(IC_INLINE(ic));
7077   bp = buffer;
7078   bp1 = buffer;
7079
7080   /* emit each line as a code */
7081   while (*bp)
7082     {
7083       if (*bp == '\n')
7084         {
7085           *bp++ = '\0';
7086           emitcode (bp1, "");
7087           bp1 = bp;
7088         }
7089       else
7090         {
7091           if (*bp == ':')
7092             {
7093               bp++;
7094               *bp = '\0';
7095               bp++;
7096               emitcode (bp1, "");
7097               bp1 = bp;
7098             }
7099           else
7100             bp++;
7101         }
7102     }
7103   if (bp1 != bp)
7104     emitcode (bp1, "");
7105   /*     emitcode("",buffer); */
7106   _G.inLine -= (!options.asmpeep);
7107 }
7108
7109 /*-----------------------------------------------------------------*/
7110 /* genRRC - rotate right with carry                                */
7111 /*-----------------------------------------------------------------*/
7112 static void
7113 genRRC (iCode * ic)
7114 {
7115   operand *left, *result;
7116   int     size, offset;
7117
7118   D (emitcode (";", "genRRC "););
7119
7120   /* rotate right with carry */
7121   left = IC_LEFT (ic);
7122   result = IC_RESULT (ic);
7123   aopOp (left, ic, FALSE, FALSE);
7124   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7125
7126   /* move it to the result */
7127   size = AOP_SIZE (result);
7128   offset = size - 1;
7129   CLRC;
7130
7131   _startLazyDPSEvaluation ();
7132   while (size--)
7133     {
7134       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7135       emitcode ("rrc", "a");
7136       if (AOP_SIZE (result) > 1)
7137         aopPut (AOP (result), "a", offset--);
7138     }
7139   _endLazyDPSEvaluation ();
7140
7141   /* now we need to put the carry into the
7142      highest order byte of the result */
7143   if (AOP_SIZE (result) > 1)
7144     {
7145       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7146     }
7147   emitcode ("mov", "acc.7,c");
7148   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7149   freeAsmop (left, NULL, ic, TRUE);
7150   freeAsmop (result, NULL, ic, TRUE);
7151 }
7152
7153 /*-----------------------------------------------------------------*/
7154 /* genRLC - generate code for rotate left with carry               */
7155 /*-----------------------------------------------------------------*/
7156 static void
7157 genRLC (iCode * ic)
7158 {
7159   operand *left, *result;
7160   int size, offset;
7161   char *l;
7162
7163   D (emitcode (";", "genRLC "););
7164
7165   /* rotate right with carry */
7166   left = IC_LEFT (ic);
7167   result = IC_RESULT (ic);
7168   aopOp (left, ic, FALSE, FALSE);
7169   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7170
7171   /* move it to the result */
7172   size = AOP_SIZE (result);
7173   offset = 0;
7174   if (size--)
7175     {
7176       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7177       MOVA (l);
7178       emitcode ("add", "a,acc");
7179       if (AOP_SIZE (result) > 1)
7180         {
7181           aopPut (AOP (result), "a", offset++);
7182         }
7183
7184       _startLazyDPSEvaluation ();
7185       while (size--)
7186         {
7187           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7188           MOVA (l);
7189           emitcode ("rlc", "a");
7190           if (AOP_SIZE (result) > 1)
7191             aopPut (AOP (result), "a", offset++);
7192         }
7193       _endLazyDPSEvaluation ();
7194     }
7195   /* now we need to put the carry into the
7196      highest order byte of the result */
7197   if (AOP_SIZE (result) > 1)
7198     {
7199       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7200       MOVA (l);
7201     }
7202   emitcode ("mov", "acc.0,c");
7203   aopPut (AOP (result), "a", 0);
7204   freeAsmop (left, NULL, ic, TRUE);
7205   freeAsmop (result, NULL, ic, TRUE);
7206 }
7207
7208 /*-----------------------------------------------------------------*/
7209 /* genGetHbit - generates code get highest order bit               */
7210 /*-----------------------------------------------------------------*/
7211 static void
7212 genGetHbit (iCode * ic)
7213 {
7214   operand *left, *result;
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   D (emitcode (";", "genGetHbit "););
7221
7222   /* get the highest order byte into a */
7223   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7224   if (AOP_TYPE (result) == AOP_CRY)
7225     {
7226       emitcode ("rlc", "a");
7227       outBitC (result);
7228     }
7229   else
7230     {
7231       emitcode ("rl", "a");
7232       emitcode ("anl", "a,#1");
7233       outAcc (result);
7234     }
7235
7236
7237   freeAsmop (left, NULL, ic, TRUE);
7238   freeAsmop (result, NULL, ic, TRUE);
7239 }
7240
7241 /*-----------------------------------------------------------------*/
7242 /* AccRol - rotate left accumulator by known count                 */
7243 /*-----------------------------------------------------------------*/
7244 static void
7245 AccRol (int shCount)
7246 {
7247   shCount &= 0x0007;            // shCount : 0..7
7248
7249   switch (shCount)
7250     {
7251     case 0:
7252       break;
7253     case 1:
7254       emitcode ("rl", "a");
7255       break;
7256     case 2:
7257       emitcode ("rl", "a");
7258       emitcode ("rl", "a");
7259       break;
7260     case 3:
7261       emitcode ("swap", "a");
7262       emitcode ("rr", "a");
7263       break;
7264     case 4:
7265       emitcode ("swap", "a");
7266       break;
7267     case 5:
7268       emitcode ("swap", "a");
7269       emitcode ("rl", "a");
7270       break;
7271     case 6:
7272       emitcode ("rr", "a");
7273       emitcode ("rr", "a");
7274       break;
7275     case 7:
7276       emitcode ("rr", "a");
7277       break;
7278     }
7279 }
7280
7281 /*-----------------------------------------------------------------*/
7282 /* AccLsh - left shift accumulator by known count                  */
7283 /*-----------------------------------------------------------------*/
7284 static void
7285 AccLsh (int shCount)
7286 {
7287   if (shCount != 0)
7288     {
7289       if (shCount == 1)
7290         emitcode ("add", "a,acc");
7291       else if (shCount == 2)
7292         {
7293           emitcode ("add", "a,acc");
7294           emitcode ("add", "a,acc");
7295         }
7296       else
7297         {
7298           /* rotate left accumulator */
7299           AccRol (shCount);
7300           /* and kill the lower order bits */
7301           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7302         }
7303     }
7304 }
7305
7306 /*-----------------------------------------------------------------*/
7307 /* AccRsh - right shift accumulator by known count                 */
7308 /*-----------------------------------------------------------------*/
7309 static void
7310 AccRsh (int shCount)
7311 {
7312   if (shCount != 0)
7313     {
7314       if (shCount == 1)
7315         {
7316           CLRC;
7317           emitcode ("rrc", "a");
7318         }
7319       else
7320         {
7321           /* rotate right accumulator */
7322           AccRol (8 - shCount);
7323           /* and kill the higher order bits */
7324           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7325         }
7326     }
7327 }
7328
7329 #ifdef BETTER_LITERAL_SHIFT
7330 /*-----------------------------------------------------------------*/
7331 /* AccSRsh - signed right shift accumulator by known count                 */
7332 /*-----------------------------------------------------------------*/
7333 static void
7334 AccSRsh (int shCount)
7335 {
7336   symbol *tlbl;
7337   if (shCount != 0)
7338     {
7339       if (shCount == 1)
7340         {
7341           emitcode ("mov", "c,acc.7");
7342           emitcode ("rrc", "a");
7343         }
7344       else if (shCount == 2)
7345         {
7346           emitcode ("mov", "c,acc.7");
7347           emitcode ("rrc", "a");
7348           emitcode ("mov", "c,acc.7");
7349           emitcode ("rrc", "a");
7350         }
7351       else
7352         {
7353           tlbl = newiTempLabel (NULL);
7354           /* rotate right accumulator */
7355           AccRol (8 - shCount);
7356           /* and kill the higher order bits */
7357           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7358           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7359           emitcode ("orl", "a,#!constbyte",
7360                     (unsigned char) ~SRMask[shCount]);
7361           emitcode ("", "!tlabeldef", tlbl->key + 100);
7362         }
7363     }
7364 }
7365 #endif
7366
7367 #ifdef BETTER_LITERAL_SHIFT
7368 /*-----------------------------------------------------------------*/
7369 /* shiftR1Left2Result - shift right one byte from left to result   */
7370 /*-----------------------------------------------------------------*/
7371 static void
7372 shiftR1Left2Result (operand * left, int offl,
7373                     operand * result, int offr,
7374                     int shCount, int sign)
7375 {
7376   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7377   /* shift right accumulator */
7378   if (sign)
7379     AccSRsh (shCount);
7380   else
7381     AccRsh (shCount);
7382   aopPut (AOP (result), "a", offr);
7383 }
7384 #endif
7385
7386 #ifdef BETTER_LITERAL_SHIFT
7387 /*-----------------------------------------------------------------*/
7388 /* shiftL1Left2Result - shift left one byte from left to result    */
7389 /*-----------------------------------------------------------------*/
7390 static void
7391 shiftL1Left2Result (operand * left, int offl,
7392                     operand * result, int offr, int shCount)
7393 {
7394   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7395   /* shift left accumulator */
7396   AccLsh (shCount);
7397   aopPut (AOP (result), "a", offr);
7398 }
7399 #endif
7400
7401 #ifdef BETTER_LITERAL_SHIFT
7402 /*-----------------------------------------------------------------*/
7403 /* movLeft2Result - move byte from left to result                  */
7404 /*-----------------------------------------------------------------*/
7405 static void
7406 movLeft2Result (operand * left, int offl,
7407                 operand * result, int offr, int sign)
7408 {
7409   char *l;
7410   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7411   {
7412       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7413
7414       if (*l == '@' && (IS_AOP_PREG (result)))
7415       {
7416           emitcode ("mov", "a,%s", l);
7417           aopPut (AOP (result), "a", offr);
7418       }
7419       else
7420       {
7421           if (!sign)
7422           {
7423             aopPut (AOP (result), l, offr);
7424           }
7425           else
7426             {
7427               /* MSB sign in acc.7 ! */
7428               if (getDataSize (left) == offl + 1)
7429                 {
7430                   emitcode ("mov", "a,%s", l);
7431                   aopPut (AOP (result), "a", offr);
7432                 }
7433             }
7434       }
7435   }
7436 }
7437 #endif
7438
7439 #ifdef BETTER_LITERAL_SHIFT
7440 /*-----------------------------------------------------------------*/
7441 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7442 /*-----------------------------------------------------------------*/
7443 static void
7444 AccAXRrl1 (char *x)
7445 {
7446   emitcode ("rrc", "a");
7447   emitcode ("xch", "a,%s", x);
7448   emitcode ("rrc", "a");
7449   emitcode ("xch", "a,%s", x);
7450 }
7451 #endif
7452
7453 #ifdef BETTER_LITERAL_SHIFT
7454 //REMOVE ME!!!
7455 /*-----------------------------------------------------------------*/
7456 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7457 /*-----------------------------------------------------------------*/
7458 static void
7459 AccAXLrl1 (char *x)
7460 {
7461   emitcode ("xch", "a,%s", x);
7462   emitcode ("rlc", "a");
7463   emitcode ("xch", "a,%s", x);
7464   emitcode ("rlc", "a");
7465 }
7466 #endif
7467
7468 #ifdef BETTER_LITERAL_SHIFT
7469 /*-----------------------------------------------------------------*/
7470 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7471 /*-----------------------------------------------------------------*/
7472 static void
7473 AccAXLsh1 (char *x)
7474 {
7475   emitcode ("xch", "a,%s", x);
7476   emitcode ("add", "a,acc");
7477   emitcode ("xch", "a,%s", x);
7478   emitcode ("rlc", "a");
7479 }
7480 #endif
7481
7482 #ifdef BETTER_LITERAL_SHIFT
7483 /*-----------------------------------------------------------------*/
7484 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7485 /*-----------------------------------------------------------------*/
7486 static void
7487 AccAXLsh (char *x, int shCount)
7488 {
7489   switch (shCount)
7490     {
7491     case 0:
7492       break;
7493     case 1:
7494       AccAXLsh1 (x);
7495       break;
7496     case 2:
7497       AccAXLsh1 (x);
7498       AccAXLsh1 (x);
7499       break;
7500     case 3:
7501     case 4:
7502     case 5:                     // AAAAABBB:CCCCCDDD
7503
7504       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7505
7506       emitcode ("anl", "a,#!constbyte",
7507                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7508
7509       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7510
7511       AccRol (shCount);         // DDDCCCCC:BBB00000
7512
7513       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7514
7515       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7516
7517       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7518
7519       emitcode ("anl", "a,#!constbyte",
7520                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7521
7522       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7523
7524       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7525
7526       break;
7527     case 6:                     // AAAAAABB:CCCCCCDD
7528       emitcode ("anl", "a,#!constbyte",
7529                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7530       emitcode ("mov", "c,acc.0");      // c = B
7531       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7532 #if 0
7533       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7534       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7535 #else
7536       emitcode("rrc","a"); 
7537       emitcode("xch","a,%s", x); 
7538       emitcode("rrc","a"); 
7539       emitcode("mov","c,acc.0"); //<< get correct bit 
7540       emitcode("xch","a,%s", x); 
7541
7542       emitcode("rrc","a"); 
7543       emitcode("xch","a,%s", x); 
7544       emitcode("rrc","a"); 
7545       emitcode("xch","a,%s", x); 
7546 #endif
7547       break;
7548     case 7:                     // a:x <<= 7
7549
7550       emitcode ("anl", "a,#!constbyte",
7551                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7552
7553       emitcode ("mov", "c,acc.0");      // c = B
7554
7555       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7556
7557       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7558
7559       break;
7560     default:
7561       break;
7562     }
7563 }
7564 #endif
7565
7566 #ifdef BETTER_LITERAL_SHIFT
7567 //REMOVE ME!!!
7568 /*-----------------------------------------------------------------*/
7569 /* AccAXRsh - right shift a:x known count (0..7)                   */
7570 /*-----------------------------------------------------------------*/
7571 static void
7572 AccAXRsh (char *x, int shCount)
7573 {
7574   switch (shCount)
7575     {
7576     case 0:
7577       break;
7578     case 1:
7579       CLRC;
7580       AccAXRrl1 (x);            // 0->a:x
7581
7582       break;
7583     case 2:
7584       CLRC;
7585       AccAXRrl1 (x);            // 0->a:x
7586
7587       CLRC;
7588       AccAXRrl1 (x);            // 0->a:x
7589
7590       break;
7591     case 3:
7592     case 4:
7593     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7594
7595       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7596
7597       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7598
7599       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7600
7601       emitcode ("anl", "a,#!constbyte",
7602                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7603
7604       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7605
7606       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7607
7608       emitcode ("anl", "a,#!constbyte",
7609                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7610
7611       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7612
7613       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7614
7615       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7616
7617       break;
7618     case 6:                     // AABBBBBB:CCDDDDDD
7619
7620       emitcode ("mov", "c,acc.7");
7621       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7622
7623       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7624
7625       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7626
7627       emitcode ("anl", "a,#!constbyte",
7628                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7629
7630       break;
7631     case 7:                     // ABBBBBBB:CDDDDDDD
7632
7633       emitcode ("mov", "c,acc.7");      // c = A
7634
7635       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7636
7637       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7638
7639       emitcode ("anl", "a,#!constbyte",
7640                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7641
7642       break;
7643     default:
7644       break;
7645     }
7646 }
7647 #endif
7648
7649 #ifdef BETTER_LITERAL_SHIFT
7650 /*-----------------------------------------------------------------*/
7651 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7652 /*-----------------------------------------------------------------*/
7653 static void
7654 AccAXRshS (char *x, int shCount)
7655 {
7656   symbol *tlbl;
7657   switch (shCount)
7658     {
7659     case 0:
7660       break;
7661     case 1:
7662       emitcode ("mov", "c,acc.7");
7663       AccAXRrl1 (x);            // s->a:x
7664
7665       break;
7666     case 2:
7667       emitcode ("mov", "c,acc.7");
7668       AccAXRrl1 (x);            // s->a:x
7669
7670       emitcode ("mov", "c,acc.7");
7671       AccAXRrl1 (x);            // s->a:x
7672
7673       break;
7674     case 3:
7675     case 4:
7676     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7677
7678       tlbl = newiTempLabel (NULL);
7679       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7680
7681       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7682
7683       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7684
7685       emitcode ("anl", "a,#!constbyte",
7686                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7687
7688       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7689
7690       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7691
7692       emitcode ("anl", "a,#!constbyte",
7693                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7694
7695       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7696
7697       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7698
7699       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7700
7701       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7702       emitcode ("orl", "a,#!constbyte",
7703                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7704
7705       emitcode ("", "!tlabeldef", tlbl->key + 100);
7706       break;                    // SSSSAAAA:BBBCCCCC
7707
7708     case 6:                     // AABBBBBB:CCDDDDDD
7709
7710       tlbl = newiTempLabel (NULL);
7711       emitcode ("mov", "c,acc.7");
7712       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7713
7714       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7715
7716       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7717
7718       emitcode ("anl", "a,#!constbyte",
7719                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7720
7721       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7722       emitcode ("orl", "a,#!constbyte",
7723                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7724
7725       emitcode ("", "!tlabeldef", tlbl->key + 100);
7726       break;
7727     case 7:                     // ABBBBBBB:CDDDDDDD
7728
7729       tlbl = newiTempLabel (NULL);
7730       emitcode ("mov", "c,acc.7");      // c = A
7731
7732       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7733
7734       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7735
7736       emitcode ("anl", "a,#!constbyte",
7737                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7738
7739       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7740       emitcode ("orl", "a,#!constbyte",
7741                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7742
7743       emitcode ("", "!tlabeldef", tlbl->key + 100);
7744       break;
7745     default:
7746       break;
7747     }
7748 }
7749 #endif
7750
7751 #ifdef BETTER_LITERAL_SHIFT
7752 static void
7753 _loadLeftIntoAx(char    **lsb, 
7754                 operand *left, 
7755                 operand *result,
7756                 int     offl,
7757                 int     offr)
7758 {
7759   // Get the initial value from left into a pair of registers.
7760   // MSB must be in A, LSB can be any register.
7761   //
7762   // If the result is held in registers, it is an optimization
7763   // if the LSB can be held in the register which will hold the,
7764   // result LSB since this saves us from having to copy it into
7765   // the result following AccAXLsh.
7766   //
7767   // If the result is addressed indirectly, this is not a gain.
7768   if (AOP_NEEDSACC(result))
7769   {
7770        char *leftByte;
7771        
7772        _startLazyDPSEvaluation();
7773       if (AOP_TYPE(left) == AOP_DPTR2)
7774        {
7775            // Get MSB in A.
7776            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7777            // get LSB in DP2_RESULT_REG.
7778            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7779            assert(!strcmp(leftByte, DP2_RESULT_REG));
7780        }
7781        else
7782        {
7783            // get LSB into DP2_RESULT_REG
7784            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7785            if (strcmp(leftByte, DP2_RESULT_REG))
7786            {
7787                TR_AP("#7");
7788                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7789            }
7790            // And MSB in A.
7791            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7792            assert(strcmp(leftByte, DP2_RESULT_REG));
7793            MOVA(leftByte);
7794        }
7795        _endLazyDPSEvaluation();
7796        *lsb = DP2_RESULT_REG;
7797   }
7798   else
7799   {
7800       if (sameRegs (AOP (result), AOP (left)) &&
7801         ((offl + MSB16) == offr))
7802       {
7803           /* don't crash result[offr] */
7804           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7805           emitcode ("xch", "a,%s", 
7806                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7807       }
7808       else
7809       {
7810           movLeft2Result (left, offl, result, offr, 0);
7811           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7812       }
7813       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7814       assert(strcmp(*lsb,"a"));      
7815   }
7816 }
7817
7818 static void
7819 _storeAxResults(char    *lsb,
7820                 operand *result,
7821                 int     offr)
7822 {
7823   _startLazyDPSEvaluation();
7824   if (AOP_NEEDSACC(result))
7825   {
7826       /* We have to explicitly update the result LSB.
7827        */
7828       emitcode("xch","a,%s", lsb);
7829       aopPut(AOP(result), "a", offr);
7830       emitcode("mov","a,%s", lsb);
7831   }
7832   if (getDataSize (result) > 1)
7833   {
7834       aopPut (AOP (result), "a", offr + MSB16);
7835   }
7836   _endLazyDPSEvaluation();
7837 }
7838
7839 /*-----------------------------------------------------------------*/
7840 /* shiftL2Left2Result - shift left two bytes from left to result   */
7841 /*-----------------------------------------------------------------*/
7842 static void
7843 shiftL2Left2Result (operand * left, int offl,
7844                     operand * result, int offr, int shCount)
7845 {
7846   char *lsb;
7847
7848   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7849   
7850   AccAXLsh (lsb, shCount);
7851   
7852   _storeAxResults(lsb, result, offr);
7853 }
7854 #endif
7855
7856 #ifdef BETTER_LITERAL_SHIFT
7857 /*-----------------------------------------------------------------*/
7858 /* shiftR2Left2Result - shift right two bytes from left to result  */
7859 /*-----------------------------------------------------------------*/
7860 static void
7861 shiftR2Left2Result (operand * left, int offl,
7862                     operand * result, int offr,
7863                     int shCount, int sign)
7864 {
7865   char *lsb;
7866   
7867   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7868   
7869   /* a:x >> shCount (x = lsb(result)) */
7870   if (sign)
7871   {
7872      AccAXRshS(lsb, shCount);
7873   }
7874   else
7875   {
7876     AccAXRsh(lsb, shCount);
7877   }
7878   
7879   _storeAxResults(lsb, result, offr);
7880 }
7881 #endif
7882
7883 /*-----------------------------------------------------------------*/
7884 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7885 /*-----------------------------------------------------------------*/
7886 static void
7887 shiftLLeftOrResult (operand * left, int offl,
7888                     operand * result, int offr, int shCount)
7889 {
7890   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7891   /* shift left accumulator */
7892   AccLsh (shCount);
7893   /* or with result */
7894   emitcode ("orl", "a,%s",
7895             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7896   /* back to result */
7897   aopPut (AOP (result), "a", offr);
7898 }
7899
7900 #if 0
7901 //REMOVE ME!!!
7902 /*-----------------------------------------------------------------*/
7903 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7904 /*-----------------------------------------------------------------*/
7905 static void
7906 shiftRLeftOrResult (operand * left, int offl,
7907                     operand * result, int offr, int shCount)
7908 {
7909   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7910   /* shift right accumulator */
7911   AccRsh (shCount);
7912   /* or with result */
7913   emitcode ("orl", "a,%s",
7914             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7915   /* back to result */
7916   aopPut (AOP (result), "a", offr);
7917 }
7918 #endif
7919
7920 #ifdef BETTER_LITERAL_SHIFT
7921 /*-----------------------------------------------------------------*/
7922 /* genlshOne - left shift a one byte quantity by known count       */
7923 /*-----------------------------------------------------------------*/
7924 static void
7925 genlshOne (operand * result, operand * left, int shCount)
7926 {
7927   D (emitcode (";", "genlshOne "););
7928   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7929 }
7930 #endif
7931
7932 #ifdef BETTER_LITERAL_SHIFT
7933 /*-----------------------------------------------------------------*/
7934 /* genlshTwo - left shift two bytes by known amount != 0           */
7935 /*-----------------------------------------------------------------*/
7936 static void
7937 genlshTwo (operand * result, operand * left, int shCount)
7938 {
7939   int size;
7940
7941   D (emitcode (";", "genlshTwo "););
7942
7943   size = getDataSize (result);
7944
7945   /* if shCount >= 8 */
7946   if (shCount >= 8)
7947   {
7948       shCount -= 8;
7949
7950       _startLazyDPSEvaluation();
7951
7952       if (size > 1)
7953         {
7954           if (shCount)
7955           {
7956             _endLazyDPSEvaluation();
7957             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7958             aopPut (AOP (result), zero, LSB);       
7959           }
7960           else
7961           {
7962             movLeft2Result (left, LSB, result, MSB16, 0);
7963             aopPut (AOP (result), zero, LSB);
7964             _endLazyDPSEvaluation();
7965           }
7966         }
7967         else
7968         {
7969           aopPut (AOP (result), zero, LSB);
7970           _endLazyDPSEvaluation();
7971         }
7972   }
7973
7974   /*  1 <= shCount <= 7 */
7975   else
7976     {
7977       if (size == 1)
7978       {
7979         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7980       }
7981       else
7982       {
7983         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7984       }
7985     }
7986 }
7987 #endif
7988
7989 #if 0
7990 //REMOVE ME!!!
7991 /*-----------------------------------------------------------------*/
7992 /* shiftLLong - shift left one long from left to result            */
7993 /* offl = LSB or MSB16                                             */
7994 /*-----------------------------------------------------------------*/
7995 static void
7996 shiftLLong (operand * left, operand * result, int offr)
7997 {
7998   char *l;
7999   int size = AOP_SIZE (result);
8000
8001   if (size >= LSB + offr)
8002     {
8003       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8004       MOVA (l);
8005       emitcode ("add", "a,acc");
8006       if (sameRegs (AOP (left), AOP (result)) &&
8007           size >= MSB16 + offr && offr != LSB)
8008         emitcode ("xch", "a,%s",
8009                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8010       else
8011         aopPut (AOP (result), "a", LSB + offr);
8012     }
8013
8014   if (size >= MSB16 + offr)
8015     {
8016       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8017         {
8018           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8019         }
8020       emitcode ("rlc", "a");
8021       if (sameRegs (AOP (left), AOP (result)) &&
8022           size >= MSB24 + offr && offr != LSB)
8023         emitcode ("xch", "a,%s",
8024                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8025       else
8026         aopPut (AOP (result), "a", MSB16 + offr);
8027     }
8028
8029   if (size >= MSB24 + offr)
8030     {
8031       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8032         {
8033           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8034         }
8035       emitcode ("rlc", "a");
8036       if (sameRegs (AOP (left), AOP (result)) &&
8037           size >= MSB32 + offr && offr != LSB)
8038         emitcode ("xch", "a,%s",
8039                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8040       else
8041         aopPut (AOP (result), "a", MSB24 + offr);
8042     }
8043
8044   if (size > MSB32 + offr)
8045     {
8046       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8047         {
8048           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8049         }
8050       emitcode ("rlc", "a");
8051       aopPut (AOP (result), "a", MSB32 + offr);
8052     }
8053   if (offr != LSB)
8054     aopPut (AOP (result), zero, LSB);
8055 }
8056 #endif
8057
8058 #if 0
8059 //REMOVE ME!!!
8060 /*-----------------------------------------------------------------*/
8061 /* genlshFour - shift four byte by a known amount != 0             */
8062 /*-----------------------------------------------------------------*/
8063 static void
8064 genlshFour (operand * result, operand * left, int shCount)
8065 {
8066   int size;
8067
8068   D (emitcode (";", "genlshFour ");
8069     );
8070
8071   size = AOP_SIZE (result);
8072
8073   /* if shifting more that 3 bytes */
8074   if (shCount >= 24)
8075     {
8076       shCount -= 24;
8077       if (shCount)
8078         /* lowest order of left goes to the highest
8079            order of the destination */
8080         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8081       else
8082         movLeft2Result (left, LSB, result, MSB32, 0);
8083       aopPut (AOP (result), zero, LSB);
8084       aopPut (AOP (result), zero, MSB16);
8085       aopPut (AOP (result), zero, MSB24);
8086       return;
8087     }
8088
8089   /* more than two bytes */
8090   else if (shCount >= 16)
8091     {
8092       /* lower order two bytes goes to higher order two bytes */
8093       shCount -= 16;
8094       /* if some more remaining */
8095       if (shCount)
8096         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8097       else
8098         {
8099           movLeft2Result (left, MSB16, result, MSB32, 0);
8100           movLeft2Result (left, LSB, result, MSB24, 0);
8101         }
8102       aopPut (AOP (result), zero, MSB16);
8103       aopPut (AOP (result), zero, LSB);
8104       return;
8105     }
8106
8107   /* if more than 1 byte */
8108   else if (shCount >= 8)
8109     {
8110       /* lower order three bytes goes to higher order  three bytes */
8111       shCount -= 8;
8112       if (size == 2)
8113         {
8114           if (shCount)
8115             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8116           else
8117             movLeft2Result (left, LSB, result, MSB16, 0);
8118         }
8119       else
8120         {                       /* size = 4 */
8121           if (shCount == 0)
8122             {
8123               movLeft2Result (left, MSB24, result, MSB32, 0);
8124               movLeft2Result (left, MSB16, result, MSB24, 0);
8125               movLeft2Result (left, LSB, result, MSB16, 0);
8126               aopPut (AOP (result), zero, LSB);
8127             }
8128           else if (shCount == 1)
8129             shiftLLong (left, result, MSB16);
8130           else
8131             {
8132               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8133               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8134               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8135               aopPut (AOP (result), zero, LSB);
8136             }
8137         }
8138     }
8139
8140   /* 1 <= shCount <= 7 */
8141   else if (shCount <= 2)
8142     {
8143       shiftLLong (left, result, LSB);
8144       if (shCount == 2)
8145         shiftLLong (result, result, LSB);
8146     }
8147   /* 3 <= shCount <= 7, optimize */
8148   else
8149     {
8150       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8151       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8152       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8153     }
8154 }
8155 #endif
8156
8157 #ifdef BETTER_LITERAL_SHIFT
8158 /*-----------------------------------------------------------------*/
8159 /* genLeftShiftLiteral - left shifting by known count              */
8160 /*-----------------------------------------------------------------*/
8161 static bool
8162 genLeftShiftLiteral (operand * left,
8163                      operand * right,
8164                      operand * result,
8165                      iCode * ic)
8166 {
8167   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8168   int size;
8169
8170   size = getSize (operandType (result));
8171
8172   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8173
8174   /* We only handle certain easy cases so far. */
8175   if ((shCount != 0)
8176    && (shCount < (size * 8))
8177    && (size != 1)
8178    && (size != 2))
8179   {
8180       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8181       return FALSE;
8182   }
8183
8184   freeAsmop (right, NULL, ic, TRUE);
8185
8186   aopOp(left, ic, FALSE, FALSE);
8187   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8188
8189 #if 0 // debug spew
8190   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8191   {
8192         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8193         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8194         {
8195            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8196         }
8197   }
8198   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8199   {
8200         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8201         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8202         {
8203            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8204         }       
8205   }  
8206 #endif
8207   
8208 #if VIEW_SIZE
8209   emitcode ("; shift left ", "result %d, left %d", size,
8210             AOP_SIZE (left));
8211 #endif
8212
8213   /* I suppose that the left size >= result size */
8214   if (shCount == 0)
8215   {
8216         _startLazyDPSEvaluation();
8217         while (size--)
8218         {
8219           movLeft2Result (left, size, result, size, 0);
8220         }
8221         _endLazyDPSEvaluation();
8222   }
8223   else if (shCount >= (size * 8))
8224   {
8225     _startLazyDPSEvaluation();
8226     while (size--)
8227     {
8228       aopPut (AOP (result), zero, size);
8229     }
8230     _endLazyDPSEvaluation();
8231   }
8232   else
8233   {
8234       switch (size)
8235         {
8236         case 1:
8237           genlshOne (result, left, shCount);
8238           break;
8239
8240         case 2:
8241           genlshTwo (result, left, shCount);
8242           break;
8243 #if 0
8244         case 4:
8245           genlshFour (result, left, shCount);
8246           break;
8247 #endif
8248         default:
8249           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8250           break;
8251         }
8252     }
8253   freeAsmop (left, NULL, ic, TRUE);
8254   freeAsmop (result, NULL, ic, TRUE);
8255   return TRUE;
8256 }
8257 #endif
8258
8259 /*-----------------------------------------------------------------*/
8260 /* genLeftShift - generates code for left shifting                 */
8261 /*-----------------------------------------------------------------*/
8262 static void
8263 genLeftShift (iCode * ic)
8264 {
8265   operand *left, *right, *result;
8266   int size, offset;
8267   char *l;
8268   symbol *tlbl, *tlbl1;
8269
8270   D (emitcode (";", "genLeftShift "););
8271
8272   right = IC_RIGHT (ic);
8273   left = IC_LEFT (ic);
8274   result = IC_RESULT (ic);
8275
8276   aopOp (right, ic, FALSE, FALSE);
8277
8278
8279 #ifdef BETTER_LITERAL_SHIFT
8280   /* if the shift count is known then do it
8281      as efficiently as possible */
8282   if (AOP_TYPE (right) == AOP_LIT)
8283     {
8284       if (genLeftShiftLiteral (left, right, result, ic))
8285       {
8286         return;
8287       }
8288     }
8289 #endif
8290
8291   /* shift count is unknown then we have to form
8292      a loop get the loop count in B : Note: we take
8293      only the lower order byte since shifting
8294      more that 32 bits make no sense anyway, ( the
8295      largest size of an object can be only 32 bits ) */
8296
8297   if (AOP_TYPE (right) == AOP_LIT)
8298   {
8299       /* Really should be handled by genLeftShiftLiteral,
8300        * but since I'm too lazy to fix that today, at least we can make
8301        * some small improvement.
8302        */
8303        emitcode("mov", "b,#!constbyte",
8304                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8305   }
8306   else
8307   {
8308       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8309       emitcode ("inc", "b");
8310   }
8311   freeAsmop (right, NULL, ic, TRUE);
8312   aopOp (left, ic, FALSE, FALSE);
8313   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8314
8315   /* now move the left to the result if they are not the
8316      same */
8317   if (!sameRegs (AOP (left), AOP (result)) &&
8318       AOP_SIZE (result) > 1)
8319     {
8320
8321       size = AOP_SIZE (result);
8322       offset = 0;
8323       _startLazyDPSEvaluation ();
8324       while (size--)
8325         {
8326           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8327           if (*l == '@' && (IS_AOP_PREG (result)))
8328             {
8329
8330               emitcode ("mov", "a,%s", l);
8331               aopPut (AOP (result), "a", offset);
8332             }
8333           else
8334             aopPut (AOP (result), l, offset);
8335           offset++;
8336         }
8337       _endLazyDPSEvaluation ();
8338     }
8339
8340   tlbl = newiTempLabel (NULL);
8341   size = AOP_SIZE (result);
8342   offset = 0;
8343   tlbl1 = newiTempLabel (NULL);
8344
8345   /* if it is only one byte then */
8346   if (size == 1)
8347     {
8348       symbol *tlbl1 = newiTempLabel (NULL);
8349
8350       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8351       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8352       emitcode ("", "!tlabeldef", tlbl->key + 100);
8353       emitcode ("add", "a,acc");
8354       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8355       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8356       aopPut (AOP (result), "a", 0);
8357       goto release;
8358     }
8359
8360   reAdjustPreg (AOP (result));
8361
8362   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8363   emitcode ("", "!tlabeldef", tlbl->key + 100);
8364   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8365   emitcode ("add", "a,acc");
8366   aopPut (AOP (result), "a", offset++);
8367   _startLazyDPSEvaluation ();
8368   while (--size)
8369     {
8370       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8371       emitcode ("rlc", "a");
8372       aopPut (AOP (result), "a", offset++);
8373     }
8374   _endLazyDPSEvaluation ();
8375   reAdjustPreg (AOP (result));
8376
8377   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8378   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8379 release:
8380   freeAsmop (left, NULL, ic, TRUE);
8381   freeAsmop (result, NULL, ic, TRUE);
8382 }
8383
8384 #ifdef BETTER_LITERAL_SHIFT
8385 /*-----------------------------------------------------------------*/
8386 /* genrshOne - right shift a one byte quantity by known count      */
8387 /*-----------------------------------------------------------------*/
8388 static void
8389 genrshOne (operand * result, operand * left,
8390            int shCount, int sign)
8391 {
8392   D (emitcode (";", "genrshOne"););
8393   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8394 }
8395 #endif
8396
8397 #ifdef BETTER_LITERAL_SHIFT
8398 /*-----------------------------------------------------------------*/
8399 /* genrshTwo - right shift two bytes by known amount != 0          */
8400 /*-----------------------------------------------------------------*/
8401 static void
8402 genrshTwo (operand * result, operand * left,
8403            int shCount, int sign)
8404 {
8405   D (emitcode (";", "genrshTwo"););
8406
8407   /* if shCount >= 8 */
8408   if (shCount >= 8)
8409     {
8410       shCount -= 8;
8411       _startLazyDPSEvaluation();
8412       if (shCount)
8413       {
8414         shiftR1Left2Result (left, MSB16, result, LSB,
8415                             shCount, sign);
8416       }                     
8417       else
8418       {
8419         movLeft2Result (left, MSB16, result, LSB, sign);
8420       }
8421       addSign (result, MSB16, sign);
8422       _endLazyDPSEvaluation();
8423     }
8424
8425   /*  1 <= shCount <= 7 */
8426   else
8427   {
8428     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8429   }
8430 }
8431 #endif
8432
8433 /*-----------------------------------------------------------------*/
8434 /* shiftRLong - shift right one long from left to result           */
8435 /* offl = LSB or MSB16                                             */
8436 /*-----------------------------------------------------------------*/
8437 static void
8438 shiftRLong (operand * left, int offl,
8439             operand * result, int sign)
8440 {
8441   int isSameRegs=sameRegs(AOP(left),AOP(result));
8442
8443   if (isSameRegs && offl>1) {
8444     // we are in big trouble, but this shouldn't happen
8445     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8446   }
8447
8448   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8449   
8450   if (offl==MSB16) {
8451     // shift is > 8
8452     if (sign) {
8453       emitcode ("rlc", "a");
8454       emitcode ("subb", "a,acc");
8455       emitcode ("xch", "a,%s",
8456                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8457     } else {
8458       aopPut (AOP(result), zero, MSB32);
8459     }
8460   }
8461
8462   if (!sign) {
8463     emitcode ("clr", "c");
8464   } else {
8465     emitcode ("mov", "c,acc.7");
8466   }
8467
8468   emitcode ("rrc", "a");
8469
8470   if (isSameRegs && offl==MSB16) {
8471     emitcode ("xch",
8472               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8473   } else {
8474     aopPut (AOP (result), "a", MSB32);
8475     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8476   }
8477
8478   emitcode ("rrc", "a");
8479   if (isSameRegs && offl==1) {
8480     emitcode ("xch", "a,%s",
8481               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8482   } else {
8483     aopPut (AOP (result), "a", MSB24);
8484     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8485   }
8486   emitcode ("rrc", "a");
8487   aopPut (AOP (result), "a", MSB16 - offl);
8488
8489   if (offl == LSB)
8490     {
8491       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8492       emitcode ("rrc", "a");
8493       aopPut (AOP (result), "a", LSB);
8494     }
8495 }
8496
8497 /*-----------------------------------------------------------------*/
8498 /* genrshFour - shift four byte by a known amount != 0             */
8499 /*-----------------------------------------------------------------*/
8500 static void
8501 genrshFour (operand * result, operand * left,
8502             int shCount, int sign)
8503 {
8504   D (emitcode (";", "genrshFour"););
8505
8506   /* if shifting more that 3 bytes */
8507   if (shCount >= 24)
8508     {
8509       shCount -= 24;
8510       _startLazyDPSEvaluation();
8511       if (shCount)
8512         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8513       else
8514         movLeft2Result (left, MSB32, result, LSB, sign);
8515       addSign (result, MSB16, sign);
8516       _endLazyDPSEvaluation();
8517     }
8518   else if (shCount >= 16)
8519     {
8520       shCount -= 16;
8521       _startLazyDPSEvaluation();
8522       if (shCount)
8523         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8524       else
8525         {
8526           movLeft2Result (left, MSB24, result, LSB, 0);
8527           movLeft2Result (left, MSB32, result, MSB16, sign);
8528         }
8529       addSign (result, MSB24, sign);
8530       _endLazyDPSEvaluation();
8531     }
8532   else if (shCount >= 8)
8533     {
8534       shCount -= 8;
8535       _startLazyDPSEvaluation();
8536       if (shCount == 1)
8537         {
8538             shiftRLong (left, MSB16, result, sign);
8539         }
8540       else if (shCount == 0)
8541         {
8542           movLeft2Result (left, MSB16, result, LSB, 0);
8543           movLeft2Result (left, MSB24, result, MSB16, 0);
8544           movLeft2Result (left, MSB32, result, MSB24, sign);
8545           addSign (result, MSB32, sign);
8546         }
8547       else
8548         {
8549           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8550           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8551           /* the last shift is signed */
8552           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8553           addSign (result, MSB32, sign);
8554         }
8555         _endLazyDPSEvaluation();
8556     }
8557   else
8558     {   
8559         /* 1 <= shCount <= 7 */
8560       if (shCount <= 2)
8561         {
8562           shiftRLong (left, LSB, result, sign);
8563           if (shCount == 2)
8564             shiftRLong (result, LSB, result, sign);
8565         }
8566       else
8567         {
8568           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8569           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8570           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8571         }
8572     }
8573 }
8574
8575 #ifdef BETTER_LITERAL_SHIFT
8576 /*-----------------------------------------------------------------*/
8577 /* genRightShiftLiteral - right shifting by known count            */
8578 /*-----------------------------------------------------------------*/
8579 static bool
8580 genRightShiftLiteral (operand * left,
8581                       operand * right,
8582                       operand * result,
8583                       iCode * ic,
8584                       int sign)
8585 {
8586   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8587   int size;
8588
8589   size = getSize (operandType (result));
8590
8591   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8592
8593   /* We only handle certain easy cases so far. */
8594   if ((shCount != 0)
8595    && (shCount < (size * 8))
8596    && (size != 1)
8597    && (size != 2)
8598    && (size != 4))
8599   {
8600       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8601       return FALSE;
8602   }
8603
8604   freeAsmop (right, NULL, ic, TRUE);
8605
8606   aopOp (left, ic, FALSE, FALSE);
8607   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8608
8609 #if VIEW_SIZE
8610   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8611             AOP_SIZE (left));
8612 #endif
8613
8614   /* test the LEFT size !!! */
8615
8616   /* I suppose that the left size >= result size */
8617   if (shCount == 0)
8618   {
8619       size = getDataSize (result);
8620       _startLazyDPSEvaluation();
8621       while (size--)
8622       {
8623         movLeft2Result (left, size, result, size, 0);
8624       }
8625       _endLazyDPSEvaluation();
8626   }
8627   else if (shCount >= (size * 8))
8628     {
8629       if (sign)
8630       {
8631         /* get sign in acc.7 */
8632         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8633       }
8634       addSign (result, LSB, sign);
8635     }
8636   else
8637     {
8638       switch (size)
8639         {
8640         case 1:
8641           genrshOne (result, left, shCount, sign);
8642           break;
8643
8644         case 2:
8645           genrshTwo (result, left, shCount, sign);
8646           break;
8647 #if 1
8648         case 4:
8649           genrshFour (result, left, shCount, sign);
8650           break;
8651 #endif    
8652         default:
8653           break;
8654         }
8655     }
8656   freeAsmop (left, NULL, ic, TRUE);
8657   freeAsmop (result, NULL, ic, TRUE);
8658   
8659   return TRUE;
8660 }
8661 #endif
8662
8663 /*-----------------------------------------------------------------*/
8664 /* genSignedRightShift - right shift of signed number              */
8665 /*-----------------------------------------------------------------*/
8666 static void
8667 genSignedRightShift (iCode * ic)
8668 {
8669   operand *right, *left, *result;
8670   int size, offset;
8671   char *l;
8672   symbol *tlbl, *tlbl1;
8673
8674   D (emitcode (";", "genSignedRightShift "););
8675
8676   /* we do it the hard way put the shift count in b
8677      and loop thru preserving the sign */
8678
8679   right = IC_RIGHT (ic);
8680   left = IC_LEFT (ic);
8681   result = IC_RESULT (ic);
8682
8683   aopOp (right, ic, FALSE, FALSE);
8684
8685 #ifdef BETTER_LITERAL_SHIFT
8686   if (AOP_TYPE (right) == AOP_LIT)
8687     {
8688       if (genRightShiftLiteral (left, right, result, ic, 1))
8689       {
8690         return;
8691       }
8692     }
8693 #endif
8694   /* shift count is unknown then we have to form
8695      a loop get the loop count in B : Note: we take
8696      only the lower order byte since shifting
8697      more that 32 bits make no sense anyway, ( the
8698      largest size of an object can be only 32 bits ) */
8699
8700   if (AOP_TYPE (right) == AOP_LIT)
8701   {
8702       /* Really should be handled by genRightShiftLiteral,
8703        * but since I'm too lazy to fix that today, at least we can make
8704        * some small improvement.
8705        */
8706        emitcode("mov", "b,#!constbyte",
8707                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8708   }
8709   else
8710   {
8711         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8712         emitcode ("inc", "b");
8713   }
8714   freeAsmop (right, NULL, ic, TRUE);
8715   aopOp (left, ic, FALSE, FALSE);
8716   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8717
8718   /* now move the left to the result if they are not the
8719      same */
8720   if (!sameRegs (AOP (left), AOP (result)) &&
8721       AOP_SIZE (result) > 1)
8722     {
8723
8724       size = AOP_SIZE (result);
8725       offset = 0;
8726       _startLazyDPSEvaluation ();
8727       while (size--)
8728         {
8729           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8730           if (*l == '@' && IS_AOP_PREG (result))
8731             {
8732
8733               emitcode ("mov", "a,%s", l);
8734               aopPut (AOP (result), "a", offset);
8735             }
8736           else
8737             aopPut (AOP (result), l, offset);
8738           offset++;
8739         }
8740       _endLazyDPSEvaluation ();
8741     }
8742
8743   /* mov the highest order bit to OVR */
8744   tlbl = newiTempLabel (NULL);
8745   tlbl1 = newiTempLabel (NULL);
8746
8747   size = AOP_SIZE (result);
8748   offset = size - 1;
8749   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8750   emitcode ("rlc", "a");
8751   emitcode ("mov", "ov,c");
8752   /* if it is only one byte then */
8753   if (size == 1)
8754     {
8755       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8756       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8757       emitcode ("", "!tlabeldef", tlbl->key + 100);
8758       emitcode ("mov", "c,ov");
8759       emitcode ("rrc", "a");
8760       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8761       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8762       aopPut (AOP (result), "a", 0);
8763       goto release;
8764     }
8765
8766   reAdjustPreg (AOP (result));
8767   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8768   emitcode ("", "!tlabeldef", tlbl->key + 100);
8769   emitcode ("mov", "c,ov");
8770   _startLazyDPSEvaluation ();
8771   while (size--)
8772     {
8773       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8774       emitcode ("rrc", "a");
8775       aopPut (AOP (result), "a", offset--);
8776     }
8777   _endLazyDPSEvaluation ();
8778   reAdjustPreg (AOP (result));
8779   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8780   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8781
8782 release:
8783   freeAsmop (left, NULL, ic, TRUE);
8784   freeAsmop (result, NULL, ic, TRUE);
8785 }
8786
8787 /*-----------------------------------------------------------------*/
8788 /* genRightShift - generate code for right shifting                */
8789 /*-----------------------------------------------------------------*/
8790 static void
8791 genRightShift (iCode * ic)
8792 {
8793   operand *right, *left, *result;
8794   sym_link *retype;
8795   int size, offset;
8796   char *l;
8797   symbol *tlbl, *tlbl1;
8798
8799   D (emitcode (";", "genRightShift "););
8800
8801   /* if signed then we do it the hard way preserve the
8802      sign bit moving it inwards */
8803   retype = getSpec (operandType (IC_RESULT (ic)));
8804
8805   if (!SPEC_USIGN (retype))
8806     {
8807       genSignedRightShift (ic);
8808       return;
8809     }
8810
8811   /* signed & unsigned types are treated the same : i.e. the
8812      signed is NOT propagated inwards : quoting from the
8813      ANSI - standard : "for E1 >> E2, is equivalent to division
8814      by 2**E2 if unsigned or if it has a non-negative value,
8815      otherwise the result is implementation defined ", MY definition
8816      is that the sign does not get propagated */
8817
8818   right = IC_RIGHT (ic);
8819   left = IC_LEFT (ic);
8820   result = IC_RESULT (ic);
8821
8822   aopOp (right, ic, FALSE, FALSE);
8823
8824 #ifdef BETTER_LITERAL_SHIFT
8825   /* if the shift count is known then do it
8826      as efficiently as possible */
8827   if (AOP_TYPE (right) == AOP_LIT)
8828     {
8829       if (genRightShiftLiteral (left, right, result, ic, 0))
8830       {
8831         return;
8832       }
8833     }
8834 #endif
8835
8836   /* shift count is unknown then we have to form
8837      a loop get the loop count in B : Note: we take
8838      only the lower order byte since shifting
8839      more that 32 bits make no sense anyway, ( the
8840      largest size of an object can be only 32 bits ) */
8841   
8842   if (AOP_TYPE (right) == AOP_LIT)
8843   {
8844       /* Really should be handled by genRightShiftLiteral,
8845        * but since I'm too lazy to fix that today, at least we can make
8846        * some small improvement.
8847        */
8848        emitcode("mov", "b,#!constbyte",
8849                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8850   }
8851   else
8852   {
8853       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8854       emitcode ("inc", "b");
8855   }
8856   freeAsmop (right, NULL, ic, TRUE);
8857   aopOp (left, ic, FALSE, FALSE);
8858   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8859
8860   /* now move the left to the result if they are not the
8861      same */
8862   if (!sameRegs (AOP (left), AOP (result)) &&
8863       AOP_SIZE (result) > 1)
8864     {
8865
8866       size = AOP_SIZE (result);
8867       offset = 0;
8868       _startLazyDPSEvaluation ();
8869       while (size--)
8870         {
8871           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8872           if (*l == '@' && IS_AOP_PREG (result))
8873             {
8874
8875               emitcode ("mov", "a,%s", l);
8876               aopPut (AOP (result), "a", offset);
8877             }
8878           else
8879             aopPut (AOP (result), l, offset);
8880           offset++;
8881         }
8882       _endLazyDPSEvaluation ();
8883     }
8884
8885   tlbl = newiTempLabel (NULL);
8886   tlbl1 = newiTempLabel (NULL);
8887   size = AOP_SIZE (result);
8888   offset = size - 1;
8889
8890   /* if it is only one byte then */
8891   if (size == 1)
8892     {
8893       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8894       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8895       emitcode ("", "!tlabeldef", tlbl->key + 100);
8896       CLRC;
8897       emitcode ("rrc", "a");
8898       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8899       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8900       aopPut (AOP (result), "a", 0);
8901       goto release;
8902     }
8903
8904   reAdjustPreg (AOP (result));
8905   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8906   emitcode ("", "!tlabeldef", tlbl->key + 100);
8907   CLRC;
8908   _startLazyDPSEvaluation ();
8909   while (size--)
8910     {
8911       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8912       emitcode ("rrc", "a");
8913       aopPut (AOP (result), "a", offset--);
8914     }
8915   _endLazyDPSEvaluation ();
8916   reAdjustPreg (AOP (result));
8917
8918   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8919   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8920
8921 release:
8922   freeAsmop (left, NULL, ic, TRUE);
8923   freeAsmop (result, NULL, ic, TRUE);
8924 }
8925
8926
8927 /*-----------------------------------------------------------------*/
8928 /* emitPtrByteGet - emits code to get a byte into A through a      */
8929 /*                  pointer register (R0, R1, or DPTR). The        */
8930 /*                  original value of A can be preserved in B.     */
8931 /*-----------------------------------------------------------------*/
8932 static void
8933 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8934 {
8935   switch (p_type)
8936     {
8937     case IPOINTER:
8938     case POINTER:
8939       if (preserveAinB)
8940         emitcode ("mov", "b,a");
8941       emitcode ("mov", "a,@%s", rname);
8942       break;
8943
8944     case PPOINTER:
8945       if (preserveAinB)
8946         emitcode ("mov", "b,a");
8947       emitcode ("movx", "a,@%s", rname);
8948       break;
8949       
8950     case FPOINTER:
8951       if (preserveAinB)
8952         emitcode ("mov", "b,a");
8953       emitcode ("movx", "a,@dptr");
8954       break;
8955
8956     case CPOINTER:
8957       if (preserveAinB)
8958         emitcode ("mov", "b,a");
8959       emitcode ("clr", "a");
8960       emitcode ("movc", "a,@a+dptr");
8961       break;
8962
8963     case GPOINTER:
8964       if (preserveAinB)
8965         {
8966           emitcode ("push", "b");
8967           emitcode ("push", "acc");
8968         }
8969       emitcode ("lcall", "__gptrget");
8970       if (preserveAinB)
8971         emitcode ("pop", "b");
8972       break;
8973     }
8974 }
8975
8976 /*-----------------------------------------------------------------*/
8977 /* emitPtrByteSet - emits code to set a byte from src through a    */
8978 /*                  pointer register (R0, R1, or DPTR).            */
8979 /*-----------------------------------------------------------------*/
8980 static void
8981 emitPtrByteSet (char *rname, int p_type, char *src)
8982 {
8983   switch (p_type)
8984     {
8985     case IPOINTER:
8986     case POINTER:
8987       if (*src=='@')
8988         {
8989           MOVA (src);
8990           emitcode ("mov", "@%s,a", rname);
8991         }
8992       else
8993         emitcode ("mov", "@%s,%s", rname, src);
8994       break;
8995
8996     case PPOINTER:
8997       MOVA (src);
8998       emitcode ("movx", "@%s,a", rname);
8999       break;
9000       
9001     case FPOINTER:
9002       MOVA (src);
9003       emitcode ("movx", "@dptr,a");
9004       break;
9005
9006     case GPOINTER:
9007       MOVA (src);
9008       emitcode ("lcall", "__gptrput");
9009       break;
9010     }
9011 }
9012
9013 /*-----------------------------------------------------------------*/
9014 /* genUnpackBits - generates code for unpacking bits               */
9015 /*-----------------------------------------------------------------*/
9016 static void
9017 genUnpackBits (operand * result, char *rname, int ptype)
9018 {
9019   int offset = 0;       /* result byte offset */
9020   int rsize;            /* result size */
9021   int rlen = 0;         /* remaining bitfield length */
9022   sym_link *etype;      /* bitfield type information */
9023   int blen;             /* bitfield length */
9024   int bstr;             /* bitfield starting bit within byte */
9025
9026   D(emitcode (";     genUnpackBits",""));
9027
9028   etype = getSpec (operandType (result));
9029   rsize = getSize (operandType (result));
9030   blen = SPEC_BLEN (etype);
9031   bstr = SPEC_BSTR (etype);
9032
9033   /* If the bitfield length is less than a byte */
9034   if (blen < 8)
9035     {
9036       emitPtrByteGet (rname, ptype, FALSE);
9037       AccRsh (bstr);
9038       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9039       aopPut (AOP (result), "a", offset++);
9040       goto finish;
9041     }
9042
9043   /* Bit field did not fit in a byte. Copy all
9044      but the partial byte at the end.  */
9045   for (rlen=blen;rlen>=8;rlen-=8)
9046     {
9047       emitPtrByteGet (rname, ptype, FALSE);
9048       aopPut (AOP (result), "a", offset++);
9049       if (rlen>8)
9050         emitcode ("inc", "%s", rname);
9051     }
9052
9053   /* Handle the partial byte at the end */
9054   if (rlen)
9055     {
9056       emitPtrByteGet (rname, ptype, FALSE);
9057       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9058       aopPut (AOP (result), "a", offset++);
9059     }
9060
9061 finish:
9062   if (offset < rsize)
9063     {
9064       rsize -= offset;
9065       while (rsize--)
9066         aopPut (AOP (result), zero, offset++);
9067     }
9068 }
9069
9070
9071 /*-----------------------------------------------------------------*/
9072 /* genDataPointerGet - generates code when ptr offset is known     */
9073 /*-----------------------------------------------------------------*/
9074 static void
9075 genDataPointerGet (operand * left,
9076                    operand * result,
9077                    iCode * ic)
9078 {
9079   char *l;
9080   char buff[256];
9081   int size, offset = 0;
9082   aopOp (result, ic, TRUE, FALSE);
9083
9084   /* get the string representation of the name */
9085   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9086   size = AOP_SIZE (result);
9087   _startLazyDPSEvaluation ();
9088   while (size--)
9089     {
9090         if (offset)
9091         {
9092             SNPRINTF (buff, sizeof(buff), 
9093                       "(%s + %d)", l + 1, offset);
9094         }
9095         else
9096         {
9097             SNPRINTF (buff, sizeof(buff), 
9098                       "%s", l + 1);
9099         }
9100       aopPut (AOP (result), buff, offset++);
9101     }
9102   _endLazyDPSEvaluation ();
9103
9104   freeAsmop (left, NULL, ic, TRUE);
9105   freeAsmop (result, NULL, ic, TRUE);
9106 }
9107
9108 /*-----------------------------------------------------------------*/
9109 /* genNearPointerGet - emitcode for near pointer fetch             */
9110 /*-----------------------------------------------------------------*/
9111 static void
9112 genNearPointerGet (operand * left,
9113                    operand * result,
9114                    iCode * ic,
9115                    iCode *pi)
9116 {
9117   asmop *aop = NULL;
9118   regs *preg;
9119   char *rname;
9120   sym_link *rtype, *retype, *letype;
9121   sym_link *ltype = operandType (left);
9122   char buff[80];
9123
9124   rtype = operandType (result);
9125   retype = getSpec (rtype);
9126   letype = getSpec (ltype);
9127
9128   aopOp (left, ic, FALSE, FALSE);
9129
9130   /* if left is rematerialisable and
9131      result is not bit variable type and
9132      the left is pointer to data space i.e
9133      lower 128 bytes of space */
9134   if (AOP_TYPE (left) == AOP_IMMD &&
9135       !IS_BITVAR (retype) &&
9136       !IS_BITVAR (letype) &&
9137       DCL_TYPE (ltype) == POINTER)
9138     {
9139       genDataPointerGet (left, result, ic);
9140       return;
9141     }
9142
9143   /* if the value is already in a pointer register
9144      then don't need anything more */
9145   if (!AOP_INPREG (AOP (left)))
9146     {
9147       /* otherwise get a free pointer register */
9148       aop = newAsmop (0);
9149       preg = getFreePtr (ic, &aop, FALSE);
9150       emitcode ("mov", "%s,%s",
9151                 preg->name,
9152                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9153       rname = preg->name;
9154     }
9155   else
9156     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9157
9158   freeAsmop (left, NULL, ic, TRUE);
9159   aopOp (result, ic, FALSE, FALSE);
9160
9161   /* if bitfield then unpack the bits */
9162   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9163     genUnpackBits (result, rname, POINTER);
9164   else
9165     {
9166       /* we have can just get the values */
9167       int size = AOP_SIZE (result);
9168       int offset = 0;
9169
9170       while (size--)
9171         {
9172           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9173             {
9174
9175               emitcode ("mov", "a,@%s", rname);
9176               aopPut (AOP (result), "a", offset);
9177             }
9178           else
9179             {
9180               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9181               aopPut (AOP (result), buff, offset);
9182             }
9183           offset++;
9184           if (size || pi)
9185             {
9186                 emitcode ("inc", "%s", rname);
9187             }
9188         }
9189     }
9190
9191   /* now some housekeeping stuff */
9192   if (aop)
9193     {
9194       /* we had to allocate for this iCode */
9195       if (pi) { /* post increment present */
9196         aopPut(AOP ( left ),rname,0);
9197       }
9198       freeAsmop (NULL, aop, ic, TRUE);
9199     }
9200   else
9201     {
9202       /* we did not allocate which means left
9203          already in a pointer register, then
9204          if size > 0 && this could be used again
9205          we have to point it back to where it
9206          belongs */
9207       if (AOP_SIZE (result) > 1 &&
9208           !OP_SYMBOL (left)->remat &&
9209           (OP_SYMBOL (left)->liveTo > ic->seq ||
9210            ic->depth) &&
9211           !pi)
9212         {
9213           int size = AOP_SIZE (result) - 1;
9214           while (size--)
9215             emitcode ("dec", "%s", rname);
9216         }
9217     }
9218
9219   /* done */
9220   freeAsmop (result, NULL, ic, TRUE);
9221   if (pi) pi->generated = 1;
9222 }
9223
9224 /*-----------------------------------------------------------------*/
9225 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9226 /*-----------------------------------------------------------------*/
9227 static void
9228 genPagedPointerGet (operand * left,
9229                     operand * result,
9230                     iCode * ic,
9231                     iCode * pi)
9232 {
9233   asmop *aop = NULL;
9234   regs *preg;
9235   char *rname;
9236   sym_link *rtype, *retype, *letype;
9237
9238   rtype = operandType (result);
9239   retype = getSpec (rtype);
9240   letype = getSpec (operandType (left));
9241   aopOp (left, ic, FALSE, FALSE);
9242
9243   /* if the value is already in a pointer register
9244      then don't need anything more */
9245   if (!AOP_INPREG (AOP (left)))
9246     {
9247       /* otherwise get a free pointer register */
9248       aop = newAsmop (0);
9249       preg = getFreePtr (ic, &aop, FALSE);
9250       emitcode ("mov", "%s,%s",
9251                 preg->name,
9252                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9253       rname = preg->name;
9254     }
9255   else
9256     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9257
9258   freeAsmop (left, NULL, ic, TRUE);
9259   aopOp (result, ic, FALSE, FALSE);
9260
9261   /* if bitfield then unpack the bits */
9262   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9263     genUnpackBits (result, rname, PPOINTER);
9264   else
9265     {
9266       /* we have can just get the values */
9267       int size = AOP_SIZE (result);
9268       int offset = 0;
9269
9270       while (size--)
9271         {
9272
9273           emitcode ("movx", "a,@%s", rname);
9274           aopPut (AOP (result), "a", offset);
9275
9276           offset++;
9277
9278           if (size || pi)
9279             emitcode ("inc", "%s", rname);
9280         }
9281     }
9282
9283   /* now some housekeeping stuff */
9284   if (aop)
9285     {
9286       /* we had to allocate for this iCode */
9287       if (pi) aopPut ( AOP (left), rname, 0);
9288       freeAsmop (NULL, aop, ic, TRUE);
9289     }
9290   else
9291     {
9292       /* we did not allocate which means left
9293          already in a pointer register, then
9294          if size > 0 && this could be used again
9295          we have to point it back to where it
9296          belongs */
9297       if (AOP_SIZE (result) > 1 &&
9298           !OP_SYMBOL (left)->remat &&
9299           (OP_SYMBOL (left)->liveTo > ic->seq ||
9300            ic->depth) &&
9301           !pi)
9302         {
9303           int size = AOP_SIZE (result) - 1;
9304           while (size--)
9305             emitcode ("dec", "%s", rname);
9306         }
9307     }
9308
9309   /* done */
9310   freeAsmop (result, NULL, ic, TRUE);
9311   if (pi) pi->generated = 1;
9312 }
9313
9314 /*-----------------------------------------------------------------*/
9315 /* genFarPointerGet - gget value from far space                    */
9316 /*-----------------------------------------------------------------*/
9317 static void
9318 genFarPointerGet (operand * left,
9319                   operand * result, iCode * ic, iCode *pi)
9320 {
9321     int size, offset, dopi=1;
9322   sym_link *retype = getSpec (operandType (result));
9323   sym_link *letype = getSpec (operandType (left));
9324   D (emitcode (";", "genFarPointerGet"););
9325
9326   aopOp (left, ic, FALSE, FALSE);
9327
9328   /* if the operand is already in dptr
9329      then we do nothing else we move the value to dptr */
9330   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9331     {
9332       /* if this is remateriazable */
9333       if (AOP_TYPE (left) == AOP_IMMD)
9334         {
9335           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9336         }
9337       else
9338         {
9339           /* we need to get it byte by byte */
9340           _startLazyDPSEvaluation ();
9341           if (AOP_TYPE (left) != AOP_DPTR)
9342             {
9343               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9344               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9345               if (options.model == MODEL_FLAT24)
9346                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9347             }
9348           else
9349             {
9350               /* We need to generate a load to DPTR indirect through DPTR. */
9351               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9352               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9353               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9354               if (options.model == MODEL_FLAT24)
9355                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9356               emitcode ("pop", "dph");
9357               emitcode ("pop", "dpl");
9358               dopi =0;
9359             }
9360           _endLazyDPSEvaluation ();
9361         }
9362     }
9363   /* so dptr know contains the address */
9364   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9365
9366   /* if bit then unpack */
9367   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9368       if (AOP_INDPTRn(left)) {
9369           genSetDPTR(AOP(left)->aopu.dptr);
9370       }
9371       genUnpackBits (result, "dptr", FPOINTER);
9372       if (AOP_INDPTRn(left)) {
9373           genSetDPTR(0);
9374       }
9375   } else
9376     {
9377       size = AOP_SIZE (result);
9378       offset = 0;
9379
9380       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9381           while (size--) {
9382               genSetDPTR(AOP(left)->aopu.dptr);
9383               emitcode ("movx", "a,@dptr");
9384               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9385                   emitcode ("inc", "dptr");
9386               genSetDPTR (0);
9387               aopPut (AOP (result), "a", offset++);
9388           }
9389       } else {
9390           _startLazyDPSEvaluation ();
9391           while (size--) {
9392               if (AOP_INDPTRn(left)) {
9393                   genSetDPTR(AOP(left)->aopu.dptr);
9394               } else {
9395                   genSetDPTR (0);
9396               }
9397               _flushLazyDPS ();
9398               
9399               emitcode ("movx", "a,@dptr");
9400               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9401                   emitcode ("inc", "dptr");
9402               
9403               aopPut (AOP (result), "a", offset++);
9404           }
9405           _endLazyDPSEvaluation ();
9406       }
9407     }
9408   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9409       if (!AOP_INDPTRn(left)) {
9410           _startLazyDPSEvaluation ();
9411           aopPut ( AOP (left), "dpl", 0);
9412           aopPut ( AOP (left), "dph", 1);
9413           if (options.model == MODEL_FLAT24)
9414               aopPut ( AOP (left), "dpx", 2);
9415           _endLazyDPSEvaluation ();
9416       }
9417     pi->generated = 1;
9418   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9419              AOP_SIZE(result) > 1 &&
9420              IS_SYMOP(left) &&
9421              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9422       
9423       size = AOP_SIZE (result) - 1;
9424       if (AOP_INDPTRn(left)) {
9425           genSetDPTR(AOP(left)->aopu.dptr);
9426       }
9427       while (size--) emitcode ("lcall","__decdptr");
9428       if (AOP_INDPTRn(left)) {
9429           genSetDPTR(0);
9430       }
9431   }
9432
9433   freeAsmop (left, NULL, ic, TRUE);
9434   freeAsmop (result, NULL, ic, TRUE);
9435 }
9436
9437 /*-----------------------------------------------------------------*/
9438 /* genCodePointerGet - get value from code space                  */
9439 /*-----------------------------------------------------------------*/
9440 static void
9441 genCodePointerGet (operand * left,
9442                     operand * result, iCode * ic, iCode *pi)
9443 {
9444   int size, offset, dopi=1;
9445   sym_link *retype = getSpec (operandType (result));
9446
9447   aopOp (left, ic, FALSE, FALSE);
9448
9449   /* if the operand is already in dptr
9450      then we do nothing else we move the value to dptr */
9451   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9452     {
9453       /* if this is remateriazable */
9454       if (AOP_TYPE (left) == AOP_IMMD)
9455         {
9456           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9457         }
9458       else
9459         {                       /* we need to get it byte by byte */
9460           _startLazyDPSEvaluation ();
9461           if (AOP_TYPE (left) != AOP_DPTR)
9462             {
9463               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9464               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9465               if (options.model == MODEL_FLAT24)
9466                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9467             }
9468           else
9469             {
9470               /* We need to generate a load to DPTR indirect through DPTR. */
9471               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9472               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9473               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9474               if (options.model == MODEL_FLAT24)
9475                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9476               emitcode ("pop", "dph");
9477               emitcode ("pop", "dpl");
9478               dopi=0;
9479             }
9480           _endLazyDPSEvaluation ();
9481         }
9482     }
9483   /* so dptr know contains the address */
9484   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9485
9486   /* if bit then unpack */
9487   if (IS_BITVAR (retype)) {
9488       if (AOP_INDPTRn(left)) {
9489           genSetDPTR(AOP(left)->aopu.dptr);
9490       }
9491       genUnpackBits (result, "dptr", CPOINTER);
9492       if (AOP_INDPTRn(left)) {
9493           genSetDPTR(0);
9494       }
9495   } else
9496     {
9497       size = AOP_SIZE (result);
9498       offset = 0;
9499       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9500           while (size--) {
9501               genSetDPTR(AOP(left)->aopu.dptr);
9502               emitcode ("clr", "a");
9503               emitcode ("movc", "a,@a+dptr");
9504               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9505                   emitcode ("inc", "dptr");
9506               genSetDPTR (0);
9507               aopPut (AOP (result), "a", offset++);
9508           }
9509       } else {
9510           _startLazyDPSEvaluation ();
9511           while (size--)
9512               {
9513                   if (AOP_INDPTRn(left)) {
9514                       genSetDPTR(AOP(left)->aopu.dptr);
9515                   } else {
9516                       genSetDPTR (0);
9517                   }
9518                   _flushLazyDPS ();
9519                   
9520                   emitcode ("clr", "a");
9521                   emitcode ("movc", "a,@a+dptr");
9522                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9523                       emitcode ("inc", "dptr");
9524                   aopPut (AOP (result), "a", offset++);
9525               }
9526           _endLazyDPSEvaluation ();
9527       }
9528     }
9529   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9530       if (!AOP_INDPTRn(left)) {
9531           _startLazyDPSEvaluation ();
9532           
9533           aopPut ( AOP (left), "dpl", 0);
9534           aopPut ( AOP (left), "dph", 1);
9535           if (options.model == MODEL_FLAT24)
9536               aopPut ( AOP (left), "dpx", 2);
9537
9538           _endLazyDPSEvaluation ();
9539       }
9540       pi->generated = 1;
9541   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9542              AOP_SIZE(result) > 1 &&
9543              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9544       
9545       size = AOP_SIZE (result) - 1;
9546       if (AOP_INDPTRn(left)) {
9547           genSetDPTR(AOP(left)->aopu.dptr);
9548       }
9549       while (size--) emitcode ("lcall","__decdptr");
9550       if (AOP_INDPTRn(left)) {
9551           genSetDPTR(0);
9552       }
9553   }
9554   
9555   freeAsmop (left, NULL, ic, TRUE);
9556   freeAsmop (result, NULL, ic, TRUE);
9557 }
9558
9559 /*-----------------------------------------------------------------*/
9560 /* genGenPointerGet - gget value from generic pointer space        */
9561 /*-----------------------------------------------------------------*/
9562 static void
9563 genGenPointerGet (operand * left,
9564                   operand * result, iCode * ic, iCode * pi)
9565 {
9566   int size, offset;
9567   sym_link *retype = getSpec (operandType (result));
9568   sym_link *letype = getSpec (operandType (left));
9569
9570   D (emitcode (";", "genGenPointerGet "); );
9571
9572   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9573
9574   /* if the operand is already in dptr
9575      then we do nothing else we move the value to dptr */
9576   if (AOP_TYPE (left) != AOP_STR)
9577     {
9578       /* if this is remateriazable */
9579       if (AOP_TYPE (left) == AOP_IMMD)
9580         {
9581           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9582           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9583             {
9584                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9585             }
9586             else
9587             {
9588                 emitcode ("mov", "b,#%d", pointerCode (retype));
9589             }
9590         }
9591       else
9592         {                       /* we need to get it byte by byte */
9593             _startLazyDPSEvaluation ();
9594             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9595             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9596             if (options.model == MODEL_FLAT24) {
9597                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9598                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9599             } else {
9600                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9601             }
9602             _endLazyDPSEvaluation ();
9603         }
9604     }
9605
9606   /* so dptr-b now contains the address */
9607   _G.bInUse++;
9608   aopOp (result, ic, FALSE, TRUE);
9609   _G.bInUse--;
9610
9611   /* if bit then unpack */
9612   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9613   {
9614     genUnpackBits (result, "dptr", GPOINTER);
9615   }
9616   else
9617     {
9618         size = AOP_SIZE (result);
9619         offset = 0;
9620
9621         while (size--)
9622         {
9623             if (size)
9624             {
9625                 // Get two bytes at a time, results in _AP & A.
9626                 // dptr will be incremented ONCE by __gptrgetWord.
9627                 //
9628                 // Note: any change here must be coordinated
9629                 // with the implementation of __gptrgetWord
9630                 // in device/lib/_gptrget.c
9631                 emitcode ("lcall", "__gptrgetWord");
9632                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9633                 aopPut (AOP (result), "a", offset++);
9634                 size--;
9635             }
9636             else
9637             {
9638                 // Only one byte to get.
9639                 emitcode ("lcall", "__gptrget");
9640                 aopPut (AOP (result), "a", offset++);
9641             }
9642             
9643             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9644             {
9645                 emitcode ("inc", "dptr");
9646             }
9647         }
9648     }
9649
9650   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9651     _startLazyDPSEvaluation ();
9652       
9653     aopPut ( AOP (left), "dpl", 0);
9654     aopPut ( AOP (left), "dph", 1);
9655     if (options.model == MODEL_FLAT24) {
9656         aopPut ( AOP (left), "dpx", 2);
9657         aopPut ( AOP (left), "b", 3);   
9658     } else  aopPut ( AOP (left), "b", 2);       
9659     
9660     _endLazyDPSEvaluation ();
9661       
9662     pi->generated = 1;
9663   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9664              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9665       
9666       size = AOP_SIZE (result) - 1;
9667       while (size--) emitcode ("lcall","__decdptr");
9668   }
9669
9670   freeAsmop (left, NULL, ic, TRUE);
9671   freeAsmop (result, NULL, ic, TRUE);
9672 }
9673
9674 /*-----------------------------------------------------------------*/
9675 /* genPointerGet - generate code for pointer get                   */
9676 /*-----------------------------------------------------------------*/
9677 static void
9678 genPointerGet (iCode * ic, iCode *pi)
9679 {
9680   operand *left, *result;
9681   sym_link *type, *etype;
9682   int p_type;
9683
9684   D (emitcode (";", "genPointerGet ");
9685     );
9686
9687   left = IC_LEFT (ic);
9688   result = IC_RESULT (ic);
9689
9690   /* depending on the type of pointer we need to
9691      move it to the correct pointer register */
9692   type = operandType (left);
9693   etype = getSpec (type);
9694   /* if left is of type of pointer then it is simple */
9695   if (IS_PTR (type) && !IS_FUNC (type->next))
9696     p_type = DCL_TYPE (type);
9697   else
9698     {
9699       /* we have to go by the storage class */
9700       p_type = PTR_TYPE (SPEC_OCLS (etype));
9701     }
9702   /* special case when cast remat */
9703   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9704       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9705           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9706           type = operandType (left);
9707           p_type = DCL_TYPE (type);
9708   }
9709   /* now that we have the pointer type we assign
9710      the pointer values */
9711   switch (p_type)
9712     {
9713
9714     case POINTER:
9715     case IPOINTER:
9716       genNearPointerGet (left, result, ic, pi);
9717       break;
9718
9719     case PPOINTER:
9720       genPagedPointerGet (left, result, ic, pi);
9721       break;
9722
9723     case FPOINTER:
9724       genFarPointerGet (left, result, ic, pi);
9725       break;
9726
9727     case CPOINTER:
9728       genCodePointerGet (left, result, ic, pi);
9729       break;
9730
9731     case GPOINTER:
9732       genGenPointerGet (left, result, ic, pi);
9733       break;
9734     }
9735
9736 }
9737
9738 /*-----------------------------------------------------------------*/
9739 /* genPackBits - generates code for packed bit storage             */
9740 /*-----------------------------------------------------------------*/
9741 static void
9742 genPackBits (sym_link * etype,
9743              operand * right,
9744              char *rname, int p_type)
9745 {
9746   int offset = 0;       /* source byte offset */
9747   int rlen = 0;         /* remaining bitfield length */
9748   int blen;             /* bitfield length */
9749   int bstr;             /* bitfield starting bit within byte */
9750   int litval;           /* source literal value (if AOP_LIT) */
9751   unsigned char mask;   /* bitmask within current byte */
9752
9753   D(emitcode (";     genPackBits",""));
9754
9755   blen = SPEC_BLEN (etype);
9756   bstr = SPEC_BSTR (etype);
9757
9758   /* If the bitfield length is less than a byte */
9759   if (blen < 8)
9760     {
9761       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9762               (unsigned char) (0xFF >> (8 - bstr)));
9763
9764       if (AOP_TYPE (right) == AOP_LIT)
9765         {
9766           /* Case with a bitfield length <8 and literal source
9767           */
9768           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9769           litval <<= bstr;
9770           litval &= (~mask) & 0xff;
9771           emitPtrByteGet (rname, p_type, FALSE);
9772           if ((mask|litval)!=0xff)
9773             emitcode ("anl","a,#!constbyte", mask);
9774           if (litval)
9775             emitcode ("orl","a,#!constbyte", litval);
9776         }
9777       else
9778         {
9779           if ((blen==1) && (p_type!=GPOINTER))
9780             {
9781               /* Case with a bitfield length == 1 and no generic pointer
9782               */
9783               if (AOP_TYPE (right) == AOP_CRY)
9784                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9785               else
9786                 {
9787                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9788                   emitcode ("rrc","a");
9789                 }
9790               emitPtrByteGet (rname, p_type, FALSE);
9791               emitcode ("mov","acc.%d,c",bstr);
9792             }
9793           else
9794             {
9795               /* Case with a bitfield length < 8 and arbitrary source
9796               */
9797               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9798               /* shift and mask source value */
9799               AccLsh (bstr);
9800               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9801
9802               /* transfer A to B and get next byte */
9803               emitPtrByteGet (rname, p_type, TRUE);
9804
9805               emitcode ("anl", "a,#!constbyte", mask);
9806               emitcode ("orl", "a,b");
9807               if (p_type == GPOINTER)
9808                 emitcode ("pop", "b");
9809            }
9810         }
9811
9812       emitPtrByteSet (rname, p_type, "a");
9813       return;
9814     }
9815
9816   /* Bit length is greater than 7 bits. In this case, copy  */
9817   /* all except the partial byte at the end                 */
9818   for (rlen=blen;rlen>=8;rlen-=8)
9819     {
9820       emitPtrByteSet (rname, p_type, 
9821                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9822       if (rlen>8)
9823         emitcode ("inc", "%s", rname);
9824     }
9825
9826   /* If there was a partial byte at the end */
9827   if (rlen)
9828     {
9829       mask = (((unsigned char) -1 << rlen) & 0xff);
9830       
9831       if (AOP_TYPE (right) == AOP_LIT)
9832         {
9833           /* Case with partial byte and literal source
9834           */
9835           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9836           litval >>= (blen-rlen);
9837           litval &= (~mask) & 0xff;
9838           emitPtrByteGet (rname, p_type, FALSE);
9839           if ((mask|litval)!=0xff)
9840             emitcode ("anl","a,#!constbyte", mask);
9841           if (litval)
9842             emitcode ("orl","a,#!constbyte", litval);
9843         }
9844       else
9845         {
9846           /* Case with partial byte and arbitrary source
9847           */
9848           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9849           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9850
9851           /* transfer A to B and get next byte */
9852           emitPtrByteGet (rname, p_type, TRUE);
9853
9854           emitcode ("anl", "a,#!constbyte", mask);
9855           emitcode ("orl", "a,b");
9856           if (p_type == GPOINTER)
9857             emitcode ("pop", "b");
9858         }
9859       emitPtrByteSet (rname, p_type, "a");
9860     }
9861
9862 }
9863
9864
9865 /*-----------------------------------------------------------------*/
9866 /* genDataPointerSet - remat pointer to data space                 */
9867 /*-----------------------------------------------------------------*/
9868 static void
9869 genDataPointerSet (operand * right,
9870                    operand * result,
9871                    iCode * ic)
9872 {
9873   int size, offset = 0;
9874   char *l, buff[256];
9875
9876   aopOp (right, ic, FALSE, FALSE);
9877
9878   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9879   size = AOP_SIZE (right);
9880   while (size--)
9881     {
9882       if (offset)
9883         {
9884             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9885         }
9886       else
9887         {
9888             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9889         }
9890         
9891       emitcode ("mov", "%s,%s", buff,
9892                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9893     }
9894
9895   freeAsmop (right, NULL, ic, TRUE);
9896   freeAsmop (result, NULL, ic, TRUE);
9897 }
9898
9899 /*-----------------------------------------------------------------*/
9900 /* genNearPointerSet - emitcode for near pointer put                */
9901 /*-----------------------------------------------------------------*/
9902 static void
9903 genNearPointerSet (operand * right,
9904                    operand * result,
9905                    iCode * ic,
9906                    iCode * pi)
9907 {
9908   asmop *aop = NULL;
9909   char *rname, *l;
9910   sym_link *retype, *letype;
9911   sym_link *ptype = operandType (result);
9912
9913   retype = getSpec (operandType (right));
9914   letype = getSpec (ptype);
9915
9916   aopOp (result, ic, FALSE, FALSE);
9917
9918   /* if the result is rematerializable &
9919      in data space & not a bit variable */
9920   if (AOP_TYPE (result) == AOP_IMMD &&
9921       DCL_TYPE (ptype) == POINTER &&
9922       !IS_BITVAR (retype) &&
9923       !IS_BITVAR (letype))
9924     {
9925       genDataPointerSet (right, result, ic);
9926       return;
9927     }
9928
9929   /* if the value is already in a pointer register
9930      then don't need anything more */
9931   if (!AOP_INPREG (AOP (result)))
9932     {
9933       /* otherwise get a free pointer register */
9934       regs *preg;
9935         
9936       aop = newAsmop (0);
9937       preg = getFreePtr (ic, &aop, FALSE);
9938       emitcode ("mov", "%s,%s",
9939                 preg->name,
9940                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9941       rname = preg->name;
9942     }
9943   else
9944     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9945
9946   aopOp (right, ic, FALSE, FALSE);
9947
9948   /* if bitfield then unpack the bits */
9949   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9950     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9951   else
9952     {
9953       /* we have can just get the values */
9954       int size = AOP_SIZE (right);
9955       int offset = 0;
9956
9957       while (size--)
9958         {
9959           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9960           if (*l == '@')
9961             {
9962               MOVA (l);
9963               emitcode ("mov", "@%s,a", rname);
9964             }
9965           else
9966             emitcode ("mov", "@%s,%s", rname, l);
9967           if (size || pi)
9968             emitcode ("inc", "%s", rname);
9969           offset++;
9970         }
9971     }
9972
9973   /* now some housekeeping stuff */
9974   if (aop)
9975     {
9976       /* we had to allocate for this iCode */
9977       if (pi) aopPut (AOP (result),rname,0);
9978       freeAsmop (NULL, aop, ic, TRUE);
9979     }
9980   else
9981     {
9982       /* we did not allocate which means left
9983          already in a pointer register, then
9984          if size > 0 && this could be used again
9985          we have to point it back to where it
9986          belongs */
9987       if (AOP_SIZE (right) > 1 &&
9988           !OP_SYMBOL (result)->remat &&
9989           (OP_SYMBOL (result)->liveTo > ic->seq ||
9990            ic->depth) &&
9991           !pi)
9992         {
9993           int size = AOP_SIZE (right) - 1;
9994           while (size--)
9995             emitcode ("dec", "%s", rname);
9996         }
9997     }
9998
9999   /* done */
10000   if (pi) pi->generated = 1;
10001   freeAsmop (result, NULL, ic, TRUE);
10002   freeAsmop (right, NULL, ic, TRUE);
10003
10004
10005 }
10006
10007 /*-----------------------------------------------------------------*/
10008 /* genPagedPointerSet - emitcode for Paged pointer put             */
10009 /*-----------------------------------------------------------------*/
10010 static void
10011 genPagedPointerSet (operand * right,
10012                     operand * result,
10013                     iCode * ic,
10014                     iCode *pi)
10015 {
10016   asmop *aop = NULL;
10017   char *rname;
10018   sym_link *retype, *letype;
10019
10020   retype = getSpec (operandType (right));
10021   letype = getSpec (operandType (result));
10022
10023   aopOp (result, ic, FALSE, FALSE);
10024
10025   /* if the value is already in a pointer register
10026      then don't need anything more */
10027   if (!AOP_INPREG (AOP (result)))
10028     {
10029       /* otherwise get a free pointer register */
10030       regs *preg;
10031         
10032       aop = newAsmop (0);
10033       preg = getFreePtr (ic, &aop, FALSE);
10034       emitcode ("mov", "%s,%s",
10035                 preg->name,
10036                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10037       rname = preg->name;
10038     }
10039   else
10040     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10041
10042   aopOp (right, ic, FALSE, FALSE);
10043
10044   /* if bitfield then unpack the bits */
10045   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10046     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10047   else
10048     {
10049       /* we have can just get the values */
10050       int size = AOP_SIZE (right);
10051       int offset = 0;
10052
10053       while (size--)
10054         {
10055           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10056
10057           emitcode ("movx", "@%s,a", rname);
10058
10059           if (size || pi)
10060             emitcode ("inc", "%s", rname);
10061
10062           offset++;
10063         }
10064     }
10065
10066   /* now some housekeeping stuff */
10067   if (aop)
10068     {
10069       if (pi) aopPut (AOP (result),rname,0);
10070       /* we had to allocate for this iCode */
10071       freeAsmop (NULL, aop, ic, TRUE);
10072     }
10073   else
10074     {
10075       /* we did not allocate which means left
10076          already in a pointer register, then
10077          if size > 0 && this could be used again
10078          we have to point it back to where it
10079          belongs */
10080       if (AOP_SIZE (right) > 1 &&
10081           !OP_SYMBOL (result)->remat &&
10082           (OP_SYMBOL (result)->liveTo > ic->seq ||
10083            ic->depth) &&
10084           !pi)
10085         {
10086           int size = AOP_SIZE (right) - 1;
10087           while (size--)
10088             emitcode ("dec", "%s", rname);
10089         }
10090     }
10091
10092   /* done */
10093   if (pi) pi->generated = 1;
10094   freeAsmop (result, NULL, ic, TRUE);
10095   freeAsmop (right, NULL, ic, TRUE);
10096
10097
10098 }
10099
10100 /*-----------------------------------------------------------------*/
10101 /* genFarPointerSet - set value from far space                     */
10102 /*-----------------------------------------------------------------*/
10103 static void
10104 genFarPointerSet (operand * right,
10105                   operand * result, iCode * ic, iCode *pi)
10106 {
10107   int size, offset, dopi=1;
10108   sym_link *retype = getSpec (operandType (right));
10109   sym_link *letype = getSpec (operandType (result));
10110
10111   aopOp (result, ic, FALSE, FALSE);
10112
10113   /* if the operand is already in dptr
10114      then we do nothing else we move the value to dptr */
10115   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10116     {
10117       /* if this is remateriazable */
10118       if (AOP_TYPE (result) == AOP_IMMD)
10119         emitcode ("mov", "dptr,%s", 
10120                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10121       else
10122         {
10123           /* we need to get it byte by byte */
10124           _startLazyDPSEvaluation ();
10125           if (AOP_TYPE (result) != AOP_DPTR)
10126             {
10127               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10128               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10129               if (options.model == MODEL_FLAT24)
10130                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10131             }
10132           else
10133             {
10134               /* We need to generate a load to DPTR indirect through DPTR. */
10135               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10136                 
10137               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10138               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10139               if (options.model == MODEL_FLAT24)
10140                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10141               emitcode ("pop", "dph");
10142               emitcode ("pop", "dpl");
10143               dopi=0;
10144             }
10145           _endLazyDPSEvaluation ();
10146         }
10147     }
10148   /* so dptr know contains the address */
10149   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10150
10151   /* if bit then unpack */
10152   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10153       if (AOP_INDPTRn(result)) {
10154           genSetDPTR(AOP(result)->aopu.dptr);
10155       }
10156       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10157       if (AOP_INDPTRn(result)) {
10158           genSetDPTR(0);
10159       }
10160   } else {
10161       size = AOP_SIZE (right);
10162       offset = 0;
10163       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10164           while (size--) {
10165               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10166               
10167               genSetDPTR(AOP(result)->aopu.dptr);
10168               emitcode ("movx", "@dptr,a");
10169               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10170                   emitcode ("inc", "dptr");
10171               genSetDPTR (0);
10172           }
10173       } else {
10174           _startLazyDPSEvaluation ();
10175           while (size--) {
10176               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10177               
10178               if (AOP_INDPTRn(result)) {
10179                   genSetDPTR(AOP(result)->aopu.dptr);
10180               } else {
10181                   genSetDPTR (0);
10182               }
10183               _flushLazyDPS ();
10184               
10185               emitcode ("movx", "@dptr,a");
10186               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10187                   emitcode ("inc", "dptr");
10188           }
10189           _endLazyDPSEvaluation ();
10190       }
10191   }
10192   
10193   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10194       if (!AOP_INDPTRn(result)) {
10195           _startLazyDPSEvaluation ();
10196           
10197           aopPut (AOP(result),"dpl",0);
10198           aopPut (AOP(result),"dph",1);
10199           if (options.model == MODEL_FLAT24)
10200               aopPut (AOP(result),"dpx",2);
10201
10202           _endLazyDPSEvaluation ();
10203       }
10204       pi->generated=1;
10205   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10206              AOP_SIZE(right) > 1 &&
10207              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10208       
10209       size = AOP_SIZE (right) - 1;
10210       if (AOP_INDPTRn(result)) {
10211           genSetDPTR(AOP(result)->aopu.dptr);
10212       } 
10213       while (size--) emitcode ("lcall","__decdptr");
10214       if (AOP_INDPTRn(result)) {
10215           genSetDPTR(0);
10216       }
10217   }
10218   freeAsmop (result, NULL, ic, TRUE);
10219   freeAsmop (right, NULL, ic, TRUE);
10220 }
10221
10222 /*-----------------------------------------------------------------*/
10223 /* genGenPointerSet - set value from generic pointer space         */
10224 /*-----------------------------------------------------------------*/
10225 static void
10226 genGenPointerSet (operand * right,
10227                   operand * result, iCode * ic, iCode *pi)
10228 {
10229   int size, offset;
10230   sym_link *retype = getSpec (operandType (right));
10231   sym_link *letype = getSpec (operandType (result));
10232
10233   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10234
10235   /* if the operand is already in dptr
10236      then we do nothing else we move the value to dptr */
10237   if (AOP_TYPE (result) != AOP_STR)
10238     {
10239       _startLazyDPSEvaluation ();
10240       /* if this is remateriazable */
10241       if (AOP_TYPE (result) == AOP_IMMD)
10242         {
10243           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10244           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10245           {
10246               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10247           }
10248           else
10249           {
10250               emitcode ("mov", 
10251                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10252           }
10253         }
10254       else
10255         {                       /* we need to get it byte by byte */
10256           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10257           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10258           if (options.model == MODEL_FLAT24) {
10259             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10260             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10261           } else {
10262             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10263           }
10264         }
10265       _endLazyDPSEvaluation ();
10266     }
10267   /* so dptr + b now contains the address */
10268   _G.bInUse++;
10269   aopOp (right, ic, FALSE, TRUE);
10270   _G.bInUse--;
10271     
10272
10273   /* if bit then unpack */
10274   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10275     {
10276         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10277     }
10278   else
10279     {
10280         size = AOP_SIZE (right);
10281         offset = 0;
10282
10283         _startLazyDPSEvaluation ();
10284         while (size--)
10285         {
10286             if (size)
10287             {
10288                 // Set two bytes at a time, passed in _AP & A.
10289                 // dptr will be incremented ONCE by __gptrputWord.
10290                 //
10291                 // Note: any change here must be coordinated
10292                 // with the implementation of __gptrputWord
10293                 // in device/lib/_gptrput.c
10294                 emitcode("mov", "_ap, %s", 
10295                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10296                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10297                 
10298                 genSetDPTR (0);
10299                 _flushLazyDPS ();
10300                 emitcode ("lcall", "__gptrputWord");
10301                 size--;
10302             }
10303             else
10304             {
10305                 // Only one byte to put.
10306                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10307
10308                 genSetDPTR (0);
10309                 _flushLazyDPS ();               
10310                 emitcode ("lcall", "__gptrput");
10311             }
10312             
10313             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10314             {
10315                 emitcode ("inc", "dptr");
10316             }
10317         }
10318         _endLazyDPSEvaluation ();
10319     }
10320
10321   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10322       _startLazyDPSEvaluation ();
10323       
10324       aopPut (AOP(result),"dpl",0);
10325       aopPut (AOP(result),"dph",1);
10326       if (options.model == MODEL_FLAT24) {
10327           aopPut (AOP(result),"dpx",2);
10328           aopPut (AOP(result),"b",3);
10329       } else {
10330           aopPut (AOP(result),"b",2);
10331       }
10332       _endLazyDPSEvaluation ();
10333       
10334       pi->generated=1;
10335   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10336              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10337       
10338       size = AOP_SIZE (right) - 1;
10339       while (size--) emitcode ("lcall","__decdptr");
10340   }
10341   freeAsmop (result, NULL, ic, TRUE);
10342   freeAsmop (right, NULL, ic, TRUE);
10343 }
10344
10345 /*-----------------------------------------------------------------*/
10346 /* genPointerSet - stores the value into a pointer location        */
10347 /*-----------------------------------------------------------------*/
10348 static void
10349 genPointerSet (iCode * ic, iCode *pi)
10350 {
10351   operand *right, *result;
10352   sym_link *type, *etype;
10353   int p_type;
10354
10355   D (emitcode (";", "genPointerSet "););
10356
10357   right = IC_RIGHT (ic);
10358   result = IC_RESULT (ic);
10359
10360   /* depending on the type of pointer we need to
10361      move it to the correct pointer register */
10362   type = operandType (result);
10363   etype = getSpec (type);
10364   /* if left is of type of pointer then it is simple */
10365   if (IS_PTR (type) && !IS_FUNC (type->next))
10366     {
10367       p_type = DCL_TYPE (type);
10368     }
10369   else
10370     {
10371       /* we have to go by the storage class */
10372       p_type = PTR_TYPE (SPEC_OCLS (etype));
10373     }
10374   /* special case when cast remat */
10375   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10376       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10377           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10378           type = operandType (result);
10379           p_type = DCL_TYPE (type);
10380   }
10381
10382   /* now that we have the pointer type we assign
10383      the pointer values */
10384   switch (p_type)
10385     {
10386
10387     case POINTER:
10388     case IPOINTER:
10389       genNearPointerSet (right, result, ic, pi);
10390       break;
10391
10392     case PPOINTER:
10393       genPagedPointerSet (right, result, ic, pi);
10394       break;
10395
10396     case FPOINTER:
10397       genFarPointerSet (right, result, ic, pi);
10398       break;
10399
10400     case GPOINTER:
10401       genGenPointerSet (right, result, ic, pi);
10402       break;
10403
10404     default:
10405       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10406               "genPointerSet: illegal pointer type");
10407     }
10408
10409 }
10410
10411 /*-----------------------------------------------------------------*/
10412 /* genIfx - generate code for Ifx statement                        */
10413 /*-----------------------------------------------------------------*/
10414 static void
10415 genIfx (iCode * ic, iCode * popIc)
10416 {
10417   operand *cond = IC_COND (ic);
10418   int isbit = 0;
10419
10420   D (emitcode (";", "genIfx "););
10421
10422   aopOp (cond, ic, FALSE, FALSE);
10423
10424   /* get the value into acc */
10425   if (AOP_TYPE (cond) != AOP_CRY)
10426     {
10427         toBoolean (cond);
10428     }
10429   else
10430     {
10431         isbit = 1;
10432     }
10433     
10434   /* the result is now in the accumulator */
10435   freeAsmop (cond, NULL, ic, TRUE);
10436
10437   /* if there was something to be popped then do it */
10438   if (popIc)
10439     genIpop (popIc);
10440
10441   /* if the condition is  a bit variable */
10442   if (isbit && IS_ITEMP (cond) &&
10443       SPIL_LOC (cond))
10444     {
10445         genIfxJump (ic, SPIL_LOC (cond)->rname);
10446     }
10447   else if (isbit && !IS_ITEMP (cond))
10448     {
10449         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10450     }
10451   else
10452     {
10453         genIfxJump (ic, "a");
10454     }
10455
10456   ic->generated = 1;
10457 }
10458
10459 /*-----------------------------------------------------------------*/
10460 /* genAddrOf - generates code for address of                       */
10461 /*-----------------------------------------------------------------*/
10462 static void
10463 genAddrOf (iCode * ic)
10464 {
10465   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10466   int size, offset;
10467
10468   D (emitcode (";", "genAddrOf ");
10469     );
10470
10471   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10472
10473   /* if the operand is on the stack then we
10474      need to get the stack offset of this
10475      variable */
10476   if (sym->onStack) {
10477       
10478       /* if 10 bit stack */
10479       if (options.stack10bit) {
10480           char buff[10];
10481           int  offset;
10482           
10483           tsprintf(buff, sizeof(buff), 
10484                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10485           /* if it has an offset then we need to compute it */
10486 /*        emitcode ("subb", "a,#!constbyte", */
10487 /*                  -((sym->stack < 0) ? */
10488 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10489 /*                    ((short) sym->stack)) & 0xff); */
10490 /*        emitcode ("mov","b,a"); */
10491 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10492 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10493 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10494           if (sym->stack) {
10495               emitcode ("mov", "a,_bpx");
10496               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10497                                              ((char) (sym->stack - _G.nRegsSaved)) :
10498                                              ((char) sym->stack )) & 0xff);
10499               emitcode ("mov", "b,a");
10500               emitcode ("mov", "a,_bpx+1");
10501               
10502               offset = (((sym->stack < 0) ? 
10503                          ((short) (sym->stack - _G.nRegsSaved)) :
10504                          ((short) sym->stack )) >> 8) & 0xff;
10505           
10506               emitcode ("addc","a,#!constbyte", offset);
10507
10508               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10509               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10510               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10511           } else {
10512               /* we can just move _bp */
10513               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10514               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10515               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10516           }       
10517       } else {
10518           /* if it has an offset then we need to compute it */
10519           if (sym->stack) {
10520               emitcode ("mov", "a,_bp");
10521               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10522               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10523           } else {
10524               /* we can just move _bp */
10525               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10526           }
10527           /* fill the result with zero */
10528           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10529           
10530           
10531           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10532               fprintf (stderr,
10533                        "*** warning: pointer to stack var truncated.\n");
10534           }
10535
10536           offset = 1;
10537           while (size--) {
10538               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10539           }      
10540       }
10541       goto release;
10542   }
10543
10544   /* object not on stack then we need the name */
10545   size = AOP_SIZE (IC_RESULT (ic));
10546   offset = 0;
10547
10548   while (size--)
10549     {
10550       char s[SDCC_NAME_MAX];
10551       if (offset) {
10552           switch (offset) {
10553           case 1:
10554               tsprintf(s, sizeof(s), "#!his",sym->rname);
10555               break;
10556           case 2:
10557               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10558               break;
10559           case 3:
10560               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10561               break;
10562           default: /* should not need this (just in case) */
10563               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10564                        sym->rname,
10565                        offset * 8);
10566           }
10567       } 
10568       else
10569       {
10570           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10571       }
10572         
10573       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10574     }
10575
10576 release:
10577   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10578
10579 }
10580
10581 #if 0 // obsolete, and buggy for != xdata
10582 /*-----------------------------------------------------------------*/
10583 /* genArrayInit - generates code for address of                       */
10584 /*-----------------------------------------------------------------*/
10585 static void
10586 genArrayInit (iCode * ic)
10587 {
10588     literalList *iLoop;
10589     int         ix, count;
10590     int         elementSize = 0, eIndex;
10591     unsigned    val, lastVal;
10592     sym_link    *type;
10593     operand     *left=IC_LEFT(ic);
10594     
10595     D (emitcode (";", "genArrayInit "););
10596
10597     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10598     
10599     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10600     {
10601         // Load immediate value into DPTR.
10602         emitcode("mov", "dptr, %s",
10603              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10604     }
10605     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10606     {
10607 #if 0
10608       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10609               "Unexpected operand to genArrayInit.\n");
10610       exit(1);
10611 #else
10612       // a regression because of SDCCcse.c:1.52
10613       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10614       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10615       if (options.model == MODEL_FLAT24)
10616         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10617 #endif
10618     }
10619     
10620     type = operandType(IC_LEFT(ic));
10621     
10622     if (type && type->next)
10623     {
10624         elementSize = getSize(type->next);
10625     }
10626     else
10627     {
10628         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10629                                 "can't determine element size in genArrayInit.\n");
10630         exit(1);
10631     }
10632     
10633     iLoop = IC_ARRAYILIST(ic);
10634     lastVal = 0xffff;
10635     
10636     while (iLoop)
10637     {
10638         bool firstpass = TRUE;
10639         
10640         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10641                  iLoop->count, (int)iLoop->literalValue, elementSize);
10642         
10643         ix = iLoop->count;
10644         
10645         while (ix)
10646         {
10647             symbol *tlbl = NULL;
10648             
10649             count = ix > 256 ? 256 : ix;
10650             
10651             if (count > 1)
10652             {
10653                 tlbl = newiTempLabel (NULL);
10654                 if (firstpass || (count & 0xff))
10655                 {
10656                     emitcode("mov", "b, #!constbyte", count & 0xff);
10657                 }
10658                 
10659                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10660             }
10661             
10662             firstpass = FALSE;
10663                 
10664             for (eIndex = 0; eIndex < elementSize; eIndex++)
10665             {
10666                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10667                 if (val != lastVal)
10668                 {
10669                     emitcode("mov", "a, #!constbyte", val);
10670                     lastVal = val;
10671                 }
10672                 
10673                 emitcode("movx", "@dptr, a");
10674                 emitcode("inc", "dptr");
10675             }
10676             
10677             if (count > 1)
10678             {
10679                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10680             }
10681             
10682             ix -= count;
10683         }
10684         
10685         iLoop = iLoop->next;
10686     }
10687     
10688     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10689 }
10690 #endif
10691
10692 /*-----------------------------------------------------------------*/
10693 /* genFarFarAssign - assignment when both are in far space         */
10694 /*-----------------------------------------------------------------*/
10695 static void
10696 genFarFarAssign (operand * result, operand * right, iCode * ic)
10697 {
10698   int size = AOP_SIZE (right);
10699   int offset = 0;
10700   symbol *rSym = NULL;
10701
10702   if (size == 1)
10703   {
10704       /* quick & easy case. */
10705       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10706       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10707       freeAsmop (right, NULL, ic, FALSE);
10708       /* now assign DPTR to result */
10709       _G.accInUse++;
10710       aopOp(result, ic, FALSE, FALSE);
10711       _G.accInUse--;
10712       aopPut(AOP(result), "a", 0);
10713       freeAsmop(result, NULL, ic, FALSE);
10714       return;
10715   }
10716   
10717   /* See if we've got an underlying symbol to abuse. */
10718   if (IS_SYMOP(result) && OP_SYMBOL(result))
10719   {
10720       if (IS_TRUE_SYMOP(result))
10721       {
10722           rSym = OP_SYMBOL(result);
10723       }
10724       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10725       {
10726           rSym = OP_SYMBOL(result)->usl.spillLoc;
10727       }
10728   }
10729              
10730   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10731   {
10732       /* We can use the '390 auto-toggle feature to good effect here. */
10733       
10734       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10735       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10736       emitcode ("mov", "dptr,#%s", rSym->rname); 
10737       /* DP2 = result, DP1 = right, DP1 is current. */
10738       while (size)
10739       {
10740           emitcode("movx", "a,@dptr");
10741           emitcode("movx", "@dptr,a");
10742           if (--size)
10743           {
10744                emitcode("inc", "dptr");
10745                emitcode("inc", "dptr");
10746           }
10747       }
10748       emitcode("mov", "dps,#0");
10749       freeAsmop (right, NULL, ic, FALSE);
10750 #if 0
10751 some alternative code for processors without auto-toggle
10752 no time to test now, so later well put in...kpb
10753         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10754         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10755         emitcode ("mov", "dptr,#%s", rSym->rname); 
10756         /* DP2 = result, DP1 = right, DP1 is current. */
10757         while (size)
10758         {
10759           --size;
10760           emitcode("movx", "a,@dptr");
10761           if (size)
10762             emitcode("inc", "dptr");
10763           emitcode("inc", "dps");
10764           emitcode("movx", "@dptr,a");
10765           if (size)
10766             emitcode("inc", "dptr");
10767           emitcode("inc", "dps");
10768         }
10769         emitcode("mov", "dps,#0");
10770         freeAsmop (right, NULL, ic, FALSE);
10771 #endif
10772   }
10773   else
10774   {
10775       D (emitcode (";", "genFarFarAssign"););
10776       aopOp (result, ic, TRUE, TRUE);
10777
10778       _startLazyDPSEvaluation ();
10779       
10780       while (size--)
10781         {
10782           aopPut (AOP (result),
10783                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10784           offset++;
10785         }
10786       _endLazyDPSEvaluation ();
10787       freeAsmop (result, NULL, ic, FALSE);
10788       freeAsmop (right, NULL, ic, FALSE);
10789   }
10790 }
10791
10792 /*-----------------------------------------------------------------*/
10793 /* genAssign - generate code for assignment                        */
10794 /*-----------------------------------------------------------------*/
10795 static void
10796 genAssign (iCode * ic)
10797 {
10798   operand *result, *right;
10799   int size, offset;
10800   unsigned long lit = 0L;
10801
10802   D (emitcode (";", "genAssign ");
10803     );
10804
10805   result = IC_RESULT (ic);
10806   right = IC_RIGHT (ic);
10807
10808   /* if they are the same */
10809   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10810     return;
10811
10812   aopOp (right, ic, FALSE, FALSE);
10813
10814   emitcode (";", "genAssign: resultIsFar = %s",
10815             isOperandInFarSpace (result) ?
10816             "TRUE" : "FALSE");
10817
10818   /* special case both in far space */
10819   if ((AOP_TYPE (right) == AOP_DPTR ||
10820        AOP_TYPE (right) == AOP_DPTR2) &&
10821   /* IS_TRUE_SYMOP(result)       && */
10822       isOperandInFarSpace (result))
10823     {
10824       genFarFarAssign (result, right, ic);
10825       return;
10826     }
10827
10828   aopOp (result, ic, TRUE, FALSE);
10829
10830   /* if they are the same registers */
10831   if (sameRegs (AOP (right), AOP (result)))
10832     goto release;
10833
10834   /* if the result is a bit */
10835   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10836     {
10837       /* if the right size is a literal then
10838          we know what the value is */
10839       if (AOP_TYPE (right) == AOP_LIT)
10840         {
10841           if (((int) operandLitValue (right)))
10842             aopPut (AOP (result), one, 0);
10843           else
10844             aopPut (AOP (result), zero, 0);
10845           goto release;
10846         }
10847
10848       /* the right is also a bit variable */
10849       if (AOP_TYPE (right) == AOP_CRY)
10850         {
10851           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10852           aopPut (AOP (result), "c", 0);
10853           goto release;
10854         }
10855
10856       /* we need to or */
10857       toBoolean (right);
10858       aopPut (AOP (result), "a", 0);
10859       goto release;
10860     }
10861
10862   /* bit variables done */
10863   /* general case */
10864   size = AOP_SIZE (result);
10865   offset = 0;
10866   if (AOP_TYPE (right) == AOP_LIT)
10867     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10868
10869   if ((size > 1) &&
10870       (AOP_TYPE (result) != AOP_REG) &&
10871       (AOP_TYPE (right) == AOP_LIT) &&
10872       !IS_FLOAT (operandType (right)))
10873     {
10874       _startLazyDPSEvaluation ();
10875       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10876         {
10877           aopPut (AOP (result),
10878                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10879                   offset);
10880           offset++;
10881           size--;
10882         }
10883       /* And now fill the rest with zeros. */
10884       if (size)
10885         {
10886           emitcode ("clr", "a");
10887         }
10888       while (size--)
10889         {
10890           aopPut (AOP (result), "a", offset++);
10891         }
10892       _endLazyDPSEvaluation ();
10893     }
10894   else
10895     {
10896       _startLazyDPSEvaluation ();
10897       while (size--)
10898         {
10899           aopPut (AOP (result),
10900                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10901                   offset);
10902           offset++;
10903         }
10904       _endLazyDPSEvaluation ();
10905     }
10906
10907 release:
10908   freeAsmop (right, NULL, ic, FALSE);
10909   freeAsmop (result, NULL, ic, TRUE);
10910 }
10911
10912 /*-----------------------------------------------------------------*/
10913 /* genJumpTab - generates code for jump table                      */
10914 /*-----------------------------------------------------------------*/
10915 static void
10916 genJumpTab (iCode * ic)
10917 {
10918   symbol *jtab;
10919   char *l;
10920
10921   D (emitcode (";", "genJumpTab ");
10922     );
10923
10924   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10925   /* get the condition into accumulator */
10926   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10927   MOVA (l);
10928   /* multiply by four! */
10929   emitcode ("add", "a,acc");
10930   emitcode ("add", "a,acc");
10931   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10932
10933   jtab = newiTempLabel (NULL);
10934   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10935   emitcode ("jmp", "@a+dptr");
10936   emitcode ("", "!tlabeldef", jtab->key + 100);
10937   /* now generate the jump labels */
10938   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10939        jtab = setNextItem (IC_JTLABELS (ic)))
10940     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10941
10942 }
10943
10944 /*-----------------------------------------------------------------*/
10945 /* genCast - gen code for casting                                  */
10946 /*-----------------------------------------------------------------*/
10947 static void
10948 genCast (iCode * ic)
10949 {
10950   operand *result = IC_RESULT (ic);
10951   sym_link *ctype = operandType (IC_LEFT (ic));
10952   sym_link *rtype = operandType (IC_RIGHT (ic));
10953   operand *right = IC_RIGHT (ic);
10954   int size, offset;
10955
10956   D (emitcode (";", "genCast "););
10957
10958   /* if they are equivalent then do nothing */
10959   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10960     return;
10961
10962   aopOp (right, ic, FALSE, FALSE);
10963   aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10964
10965   /* if the result is a bit */
10966   if (IS_BITVAR (OP_SYMBOL (result)->type)
10967       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10968     {
10969       /* if the right size is a literal then
10970          we know what the value is */
10971       if (AOP_TYPE (right) == AOP_LIT)
10972         {
10973           if (((int) operandLitValue (right)))
10974             aopPut (AOP (result), one, 0);
10975           else
10976             aopPut (AOP (result), zero, 0);
10977
10978           goto release;
10979         }
10980
10981       /* the right is also a bit variable */
10982       if (AOP_TYPE (right) == AOP_CRY)
10983         {
10984           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10985           aopPut (AOP (result), "c", 0);
10986           goto release;
10987         }
10988
10989       /* we need to or */
10990       toBoolean (right);
10991       aopPut (AOP (result), "a", 0);
10992       goto release;
10993     }
10994
10995   /* if they are the same size : or less */
10996   if (AOP_SIZE (result) <= AOP_SIZE (right))
10997     {
10998
10999       /* if they are in the same place */
11000       if (sameRegs (AOP (right), AOP (result)))
11001         goto release;
11002
11003       /* if they in different places then copy */
11004       size = AOP_SIZE (result);
11005       offset = 0;
11006       _startLazyDPSEvaluation ();
11007       while (size--)
11008         {
11009           aopPut (AOP (result),
11010                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11011                   offset);
11012           offset++;
11013         }
11014       _endLazyDPSEvaluation ();
11015       goto release;
11016     }
11017
11018
11019   /* if the result is of type pointer */
11020   if (IS_PTR (ctype))
11021     {
11022
11023       int p_type;
11024       sym_link *type = operandType (right);
11025
11026       /* pointer to generic pointer */
11027       if (IS_GENPTR (ctype))
11028         {
11029           if (IS_PTR (type))
11030             {
11031               p_type = DCL_TYPE (type);
11032             }
11033           else
11034             {
11035 #if OLD_CAST_BEHAVIOR
11036               /* KV: we are converting a non-pointer type to
11037                * a generic pointer. This (ifdef'd out) code
11038                * says that the resulting generic pointer
11039                * should have the same class as the storage
11040                * location of the non-pointer variable.
11041                *
11042                * For example, converting an int (which happens
11043                * to be stored in DATA space) to a pointer results
11044                * in a DATA generic pointer; if the original int
11045                * in XDATA space, so will be the resulting pointer.
11046                *
11047                * I don't like that behavior, and thus this change:
11048                * all such conversions will be forced to XDATA and
11049                * throw a warning. If you want some non-XDATA
11050                * type, or you want to suppress the warning, you
11051                * must go through an intermediate cast, like so:
11052                *
11053                * char _generic *gp = (char _xdata *)(intVar);
11054                */
11055               sym_link *etype = getSpec (type);
11056
11057               /* we have to go by the storage class */
11058               if (SPEC_OCLS (etype) != generic)
11059                 {
11060                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11061                 }
11062               else
11063 #endif
11064                 {
11065                   /* Converting unknown class (i.e. register variable)
11066                    * to generic pointer. This is not good, but
11067                    * we'll make a guess (and throw a warning).
11068                    */
11069                   p_type = FPOINTER;
11070                   werror (W_INT_TO_GEN_PTR_CAST);
11071                 }
11072             }
11073
11074           /* the first two bytes are known */
11075           size = GPTRSIZE - 1;
11076           offset = 0;
11077           _startLazyDPSEvaluation ();
11078           while (size--)
11079             {
11080               aopPut (AOP (result),
11081                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11082                       offset);
11083               offset++;
11084             }
11085           _endLazyDPSEvaluation ();
11086
11087           /* the last byte depending on type */
11088             {
11089                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11090                 char gpValStr[10];
11091             
11092                 if (gpVal == -1)
11093                 {
11094                     // pointerTypeToGPByte will have bitched.
11095                     exit(1);
11096                 }
11097             
11098                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11099                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11100             }
11101           goto release;
11102         }
11103
11104       /* just copy the pointers */
11105       size = AOP_SIZE (result);
11106       offset = 0;
11107       _startLazyDPSEvaluation ();
11108       while (size--)
11109         {
11110           aopPut (AOP (result),
11111                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11112                   offset);
11113           offset++;
11114         }
11115       _endLazyDPSEvaluation ();
11116       goto release;
11117     }
11118
11119   /* so we now know that the size of destination is greater
11120      than the size of the source */
11121   /* we move to result for the size of source */
11122   size = AOP_SIZE (right);
11123   offset = 0;
11124   _startLazyDPSEvaluation ();
11125   while (size--)
11126     {
11127       aopPut (AOP (result),
11128               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11129               offset);
11130       offset++;
11131     }
11132   _endLazyDPSEvaluation ();
11133
11134   /* now depending on the sign of the source && destination */
11135   size = AOP_SIZE (result) - AOP_SIZE (right);
11136   /* if unsigned or not an integral type */
11137   /* also, if the source is a bit, we don't need to sign extend, because
11138    * it can't possibly have set the sign bit.
11139    */
11140   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11141     {
11142       while (size--)
11143         {
11144           aopPut (AOP (result), zero, offset++);
11145         }
11146     }
11147   else
11148     {
11149       /* we need to extend the sign :{ */
11150       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11151                         FALSE, FALSE, NULL));
11152       emitcode ("rlc", "a");
11153       emitcode ("subb", "a,acc");
11154       while (size--)
11155         aopPut (AOP (result), "a", offset++);
11156     }
11157
11158   /* we are done hurray !!!! */
11159
11160 release:
11161   freeAsmop (right, NULL, ic, TRUE);
11162   freeAsmop (result, NULL, ic, TRUE);
11163
11164 }
11165
11166 /*-----------------------------------------------------------------*/
11167 /* genDjnz - generate decrement & jump if not zero instrucion      */
11168 /*-----------------------------------------------------------------*/
11169 static int
11170 genDjnz (iCode * ic, iCode * ifx)
11171 {
11172   symbol *lbl, *lbl1;
11173   if (!ifx)
11174     return 0;
11175
11176   /* if the if condition has a false label
11177      then we cannot save */
11178   if (IC_FALSE (ifx))
11179     return 0;
11180
11181   /* if the minus is not of the form
11182      a = a - 1 */
11183   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11184       !IS_OP_LITERAL (IC_RIGHT (ic)))
11185     return 0;
11186
11187   if (operandLitValue (IC_RIGHT (ic)) != 1)
11188     return 0;
11189
11190   /* if the size of this greater than one then no
11191      saving */
11192   if (getSize (operandType (IC_RESULT (ic))) > 1)
11193     return 0;
11194
11195   /* otherwise we can save BIG */
11196   D(emitcode(";", "genDjnz"););
11197
11198   lbl = newiTempLabel (NULL);
11199   lbl1 = newiTempLabel (NULL);
11200
11201   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11202
11203   if (AOP_NEEDSACC(IC_RESULT(ic)))
11204   {
11205       /* If the result is accessed indirectly via
11206        * the accumulator, we must explicitly write
11207        * it back after the decrement.
11208        */
11209       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11210       
11211       if (strcmp(rByte, "a"))
11212       {
11213            /* Something is hopelessly wrong */
11214            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11215                    __FILE__, __LINE__);
11216            /* We can just give up; the generated code will be inefficient,
11217             * but what the hey.
11218             */
11219            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11220            return 0;
11221       }
11222       emitcode ("dec", "%s", rByte);
11223       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11224       emitcode ("jnz", "!tlabel", lbl->key + 100);
11225   }
11226   else if (IS_AOP_PREG (IC_RESULT (ic)))
11227     {
11228       emitcode ("dec", "%s",
11229                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11230       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11231       emitcode ("jnz", "!tlabel", lbl->key + 100);
11232     }
11233   else
11234     {
11235       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11236                 lbl->key + 100);
11237     }
11238   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11239   emitcode ("", "!tlabeldef", lbl->key + 100);
11240   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11241   emitcode ("", "!tlabeldef", lbl1->key + 100);
11242
11243   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11244   ifx->generated = 1;
11245   return 1;
11246 }
11247
11248 /*-----------------------------------------------------------------*/
11249 /* genReceive - generate code for a receive iCode                  */
11250 /*-----------------------------------------------------------------*/
11251 static void
11252 genReceive (iCode * ic)
11253 {
11254     int size = getSize (operandType (IC_RESULT (ic)));
11255     int offset = 0;
11256     int rb1off ;
11257     
11258     D (emitcode (";", "genReceive "););
11259
11260     if (ic->argreg == 1) 
11261     {
11262         /* first parameter */
11263         if (AOP_IS_STR(IC_RESULT(ic)))
11264         {
11265             /* Nothing to do: it's already in the proper place. */
11266             return;
11267         }
11268         else
11269         {
11270             bool useDp2;
11271             
11272             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11273                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11274                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11275             
11276             _G.accInUse++;
11277             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11278             _G.accInUse--; 
11279             
11280             /* Sanity checking... */
11281             if (AOP_USESDPTR(IC_RESULT(ic)))
11282             {
11283                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11284                         "genReceive got unexpected DPTR.");
11285             }
11286             assignResultValue (IC_RESULT (ic));
11287         }
11288     } 
11289     else 
11290     { 
11291         /* second receive onwards */
11292         /* this gets a little tricky since unused recevies will be
11293          eliminated, we have saved the reg in the type field . and
11294          we use that to figure out which register to use */
11295         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11296         rb1off = ic->argreg;
11297         while (size--) 
11298         {
11299             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11300         }
11301     }
11302     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11303 }
11304
11305 /*-----------------------------------------------------------------*/
11306 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11307 /*-----------------------------------------------------------------*/
11308 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11309 {
11310     operand *from , *to , *count;
11311     symbol *lbl;
11312     bitVect *rsave;
11313     int i;
11314
11315     /* we know it has to be 3 parameters */
11316     assert (nparms == 3);
11317     
11318     rsave = newBitVect(16);
11319     /* save DPTR if it needs to be saved */
11320     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11321             if (bitVectBitValue(ic->rMask,i))
11322                     rsave = bitVectSetBit(rsave,i);
11323     }
11324     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11325                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11326     savermask(rsave);
11327     
11328     to = parms[0];
11329     from = parms[1];
11330     count = parms[2];
11331
11332     aopOp (from, ic->next, FALSE, FALSE);
11333
11334     /* get from into DPTR1 */
11335     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11336     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11337     if (options.model == MODEL_FLAT24) {
11338         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11339     }
11340
11341     freeAsmop (from, NULL, ic, FALSE);
11342     aopOp (to, ic, FALSE, FALSE);
11343     /* get "to" into DPTR */
11344     /* if the operand is already in dptr
11345        then we do nothing else we move the value to dptr */
11346     if (AOP_TYPE (to) != AOP_STR) {
11347         /* if already in DPTR then we need to push */
11348         if (AOP_TYPE(to) == AOP_DPTR) {
11349             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11350             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11351             if (options.model == MODEL_FLAT24)
11352                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11353             emitcode ("pop", "dph");
11354             emitcode ("pop", "dpl");        
11355         } else {
11356             _startLazyDPSEvaluation ();
11357             /* if this is remateriazable */
11358             if (AOP_TYPE (to) == AOP_IMMD) {
11359                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11360             } else {                    /* we need to get it byte by byte */
11361                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11362                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11363                 if (options.model == MODEL_FLAT24) {
11364                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11365                 }
11366             }
11367             _endLazyDPSEvaluation ();
11368         }
11369     }
11370     freeAsmop (to, NULL, ic, FALSE);
11371     _G.dptrInUse = _G.dptr1InUse = 1;
11372     aopOp (count, ic->next->next, FALSE,FALSE);
11373     lbl =newiTempLabel(NULL);
11374
11375     /* now for the actual copy */
11376     if (AOP_TYPE(count) == AOP_LIT && 
11377         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11378         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11379         if (fromc) {
11380             emitcode ("lcall","__bi_memcpyc2x_s");
11381         } else {
11382             emitcode ("lcall","__bi_memcpyx2x_s");
11383         }
11384         freeAsmop (count, NULL, ic, FALSE);
11385     } else {
11386         symbol *lbl1 = newiTempLabel(NULL);
11387         
11388         emitcode (";"," Auto increment but no djnz");
11389         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11390         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11391         freeAsmop (count, NULL, ic, FALSE);
11392         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11393         emitcode ("","!tlabeldef",lbl->key+100);
11394         if (fromc) {
11395             emitcode ("clr","a");
11396             emitcode ("movc", "a,@a+dptr");
11397         } else 
11398             emitcode ("movx", "a,@dptr");
11399         emitcode ("movx", "@dptr,a");
11400         emitcode ("inc", "dptr");
11401         emitcode ("inc", "dptr");
11402         emitcode ("mov","a,b");
11403         emitcode ("orl","a,_ap");
11404         emitcode ("jz","!tlabel",lbl1->key+100);
11405         emitcode ("mov","a,_ap");
11406         emitcode ("add","a,#!constbyte",0xFF);
11407         emitcode ("mov","_ap,a");
11408         emitcode ("mov","a,b");
11409         emitcode ("addc","a,#!constbyte",0xFF);
11410         emitcode ("mov","b,a");
11411         emitcode ("sjmp","!tlabel",lbl->key+100);
11412         emitcode ("","!tlabeldef",lbl1->key+100);
11413     }
11414     emitcode ("mov", "dps,#0"); 
11415     _G.dptrInUse = _G.dptr1InUse = 0;
11416     unsavermask(rsave);
11417
11418 }
11419
11420 /*-----------------------------------------------------------------*/
11421 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11422 /*-----------------------------------------------------------------*/
11423 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11424 {
11425     operand *from , *to , *count;
11426     symbol *lbl,*lbl2;
11427     bitVect *rsave;
11428     int i;
11429
11430     /* we know it has to be 3 parameters */
11431     assert (nparms == 3);
11432     
11433     rsave = newBitVect(16);
11434     /* save DPTR if it needs to be saved */
11435     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11436             if (bitVectBitValue(ic->rMask,i))
11437                     rsave = bitVectSetBit(rsave,i);
11438     }
11439     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11440                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11441     savermask(rsave);
11442     
11443     to = parms[0];
11444     from = parms[1];
11445     count = parms[2];
11446
11447     aopOp (from, ic->next, FALSE, FALSE);
11448
11449     /* get from into DPTR1 */
11450     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11451     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11452     if (options.model == MODEL_FLAT24) {
11453         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11454     }
11455
11456     freeAsmop (from, NULL, ic, FALSE);
11457     aopOp (to, ic, FALSE, FALSE);
11458     /* get "to" into DPTR */
11459     /* if the operand is already in dptr
11460        then we do nothing else we move the value to dptr */
11461     if (AOP_TYPE (to) != AOP_STR) {
11462         /* if already in DPTR then we need to push */
11463         if (AOP_TYPE(to) == AOP_DPTR) {
11464             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11465             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11466             if (options.model == MODEL_FLAT24)
11467                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11468             emitcode ("pop", "dph");
11469             emitcode ("pop", "dpl");        
11470         } else {
11471             _startLazyDPSEvaluation ();
11472             /* if this is remateriazable */
11473             if (AOP_TYPE (to) == AOP_IMMD) {
11474                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11475             } else {                    /* we need to get it byte by byte */
11476                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11477                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11478                 if (options.model == MODEL_FLAT24) {
11479                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11480                 }
11481             }
11482             _endLazyDPSEvaluation ();
11483         }
11484     }
11485     freeAsmop (to, NULL, ic, FALSE);
11486     _G.dptrInUse = _G.dptr1InUse = 1;
11487     aopOp (count, ic->next->next, FALSE,FALSE);
11488     lbl =newiTempLabel(NULL);
11489     lbl2 =newiTempLabel(NULL);
11490
11491     /* now for the actual compare */
11492     if (AOP_TYPE(count) == AOP_LIT && 
11493         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11494         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11495         if (fromc)
11496             emitcode("lcall","__bi_memcmpc2x_s");
11497         else
11498             emitcode("lcall","__bi_memcmpx2x_s");
11499         freeAsmop (count, NULL, ic, FALSE);
11500         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11501         aopPut(AOP(IC_RESULT(ic)),"a",0);
11502         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11503     } else {
11504         symbol *lbl1 = newiTempLabel(NULL);
11505
11506         emitcode("push","ar0");         
11507         emitcode (";"," Auto increment but no djnz");
11508         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11509         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11510         freeAsmop (count, NULL, ic, FALSE);
11511         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11512         emitcode ("","!tlabeldef",lbl->key+100);
11513         if (fromc) {
11514             emitcode ("clr","a");
11515             emitcode ("movc", "a,@a+dptr");
11516         } else 
11517             emitcode ("movx", "a,@dptr");
11518         emitcode ("mov","r0,a");
11519         emitcode ("movx", "a,@dptr");
11520         emitcode ("clr","c");
11521         emitcode ("subb","a,r0");
11522         emitcode ("jnz","!tlabel",lbl2->key+100);
11523         emitcode ("inc", "dptr");
11524         emitcode ("inc", "dptr");
11525         emitcode ("mov","a,b");
11526         emitcode ("orl","a,_ap");
11527         emitcode ("jz","!tlabel",lbl1->key+100);
11528         emitcode ("mov","a,_ap");
11529         emitcode ("add","a,#!constbyte",0xFF);
11530         emitcode ("mov","_ap,a");
11531         emitcode ("mov","a,b");
11532         emitcode ("addc","a,#!constbyte",0xFF);
11533         emitcode ("mov","b,a");
11534         emitcode ("sjmp","!tlabel",lbl->key+100);
11535         emitcode ("","!tlabeldef",lbl1->key+100);
11536         emitcode ("clr","a");
11537         emitcode ("","!tlabeldef",lbl2->key+100);
11538         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11539         aopPut(AOP(IC_RESULT(ic)),"a",0);
11540         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11541         emitcode("pop","ar0");
11542         emitcode ("mov", "dps,#0");      
11543     }
11544     _G.dptrInUse = _G.dptr1InUse = 0;
11545     unsavermask(rsave);
11546
11547 }
11548
11549 /*-----------------------------------------------------------------*/
11550 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11551 /* port, first parameter output area second parameter pointer to   */
11552 /* port third parameter count                                      */
11553 /*-----------------------------------------------------------------*/
11554 static void genInp( iCode *ic, int nparms, operand **parms)
11555 {
11556     operand *from , *to , *count;
11557     symbol *lbl;
11558     bitVect *rsave;
11559     int i;
11560
11561     /* we know it has to be 3 parameters */
11562     assert (nparms == 3);
11563     
11564     rsave = newBitVect(16);
11565     /* save DPTR if it needs to be saved */
11566     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11567             if (bitVectBitValue(ic->rMask,i))
11568                     rsave = bitVectSetBit(rsave,i);
11569     }
11570     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11571                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11572     savermask(rsave);
11573     
11574     to = parms[0];
11575     from = parms[1];
11576     count = parms[2];
11577
11578     aopOp (from, ic->next, FALSE, FALSE);
11579
11580     /* get from into DPTR1 */
11581     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11582     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11583     if (options.model == MODEL_FLAT24) {
11584         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11585     }
11586
11587     freeAsmop (from, NULL, ic, FALSE);
11588     aopOp (to, ic, FALSE, FALSE);
11589     /* get "to" into DPTR */
11590     /* if the operand is already in dptr
11591        then we do nothing else we move the value to dptr */
11592     if (AOP_TYPE (to) != AOP_STR) {
11593         /* if already in DPTR then we need to push */
11594         if (AOP_TYPE(to) == AOP_DPTR) {
11595             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11596             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11597             if (options.model == MODEL_FLAT24)
11598                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11599             emitcode ("pop", "dph");
11600             emitcode ("pop", "dpl");        
11601         } else {
11602             _startLazyDPSEvaluation ();
11603             /* if this is remateriazable */
11604             if (AOP_TYPE (to) == AOP_IMMD) {
11605                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11606             } else {                    /* we need to get it byte by byte */
11607                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11608                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11609                 if (options.model == MODEL_FLAT24) {
11610                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11611                 }
11612             }
11613             _endLazyDPSEvaluation ();
11614         }
11615     }
11616     freeAsmop (to, NULL, ic, FALSE);
11617
11618     _G.dptrInUse = _G.dptr1InUse = 1;
11619     aopOp (count, ic->next->next, FALSE,FALSE);
11620     lbl =newiTempLabel(NULL);
11621
11622     /* now for the actual copy */
11623     if (AOP_TYPE(count) == AOP_LIT && 
11624         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11625         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11626         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11627         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11628         freeAsmop (count, NULL, ic, FALSE);
11629         emitcode ("","!tlabeldef",lbl->key+100);
11630         emitcode ("movx", "a,@dptr");   /* read data from port */
11631         emitcode ("dec","dps");         /* switch to DPTR */
11632         emitcode ("movx", "@dptr,a");   /* save into location */
11633         emitcode ("inc", "dptr");       /* point to next area */
11634         emitcode ("inc","dps");         /* switch to DPTR2 */
11635         emitcode ("djnz","b,!tlabel",lbl->key+100);
11636     } else {
11637         symbol *lbl1 = newiTempLabel(NULL);
11638         
11639         emitcode (";"," Auto increment but no djnz");
11640         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11641         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11642         freeAsmop (count, NULL, ic, FALSE);
11643         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11644         emitcode ("","!tlabeldef",lbl->key+100);
11645         emitcode ("movx", "a,@dptr");
11646         emitcode ("dec","dps");         /* switch to DPTR */
11647         emitcode ("movx", "@dptr,a");
11648         emitcode ("inc", "dptr");
11649         emitcode ("inc","dps");         /* switch to DPTR2 */
11650 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11651 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11652         emitcode ("mov","a,b");
11653         emitcode ("orl","a,_ap");
11654         emitcode ("jz","!tlabel",lbl1->key+100);
11655         emitcode ("mov","a,_ap");
11656         emitcode ("add","a,#!constbyte",0xFF);
11657         emitcode ("mov","_ap,a");
11658         emitcode ("mov","a,b");
11659         emitcode ("addc","a,#!constbyte",0xFF);
11660         emitcode ("mov","b,a");
11661         emitcode ("sjmp","!tlabel",lbl->key+100);
11662         emitcode ("","!tlabeldef",lbl1->key+100);
11663     }
11664     emitcode ("mov", "dps,#0"); 
11665     _G.dptrInUse = _G.dptr1InUse = 0;
11666     unsavermask(rsave);
11667
11668 }
11669
11670 /*-----------------------------------------------------------------*/
11671 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11672 /* port, first parameter output area second parameter pointer to   */
11673 /* port third parameter count                                      */
11674 /*-----------------------------------------------------------------*/
11675 static void genOutp( iCode *ic, int nparms, operand **parms)
11676 {
11677     operand *from , *to , *count;
11678     symbol *lbl;
11679     bitVect *rsave;
11680     int i;
11681
11682     /* we know it has to be 3 parameters */
11683     assert (nparms == 3);
11684     
11685     rsave = newBitVect(16);
11686     /* save DPTR if it needs to be saved */
11687     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11688             if (bitVectBitValue(ic->rMask,i))
11689                     rsave = bitVectSetBit(rsave,i);
11690     }
11691     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11692                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11693     savermask(rsave);
11694     
11695     to = parms[0];
11696     from = parms[1];
11697     count = parms[2];
11698
11699     aopOp (from, ic->next, FALSE, FALSE);
11700
11701     /* get from into DPTR1 */
11702     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11703     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11704     if (options.model == MODEL_FLAT24) {
11705         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11706     }
11707
11708     freeAsmop (from, NULL, ic, FALSE);
11709     aopOp (to, ic, FALSE, FALSE);
11710     /* get "to" into DPTR */
11711     /* if the operand is already in dptr
11712        then we do nothing else we move the value to dptr */
11713     if (AOP_TYPE (to) != AOP_STR) {
11714         /* if already in DPTR then we need to push */
11715         if (AOP_TYPE(to) == AOP_DPTR) {
11716             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11717             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11718             if (options.model == MODEL_FLAT24)
11719                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11720             emitcode ("pop", "dph");
11721             emitcode ("pop", "dpl");        
11722         } else {
11723             _startLazyDPSEvaluation ();
11724             /* if this is remateriazable */
11725             if (AOP_TYPE (to) == AOP_IMMD) {
11726                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11727             } else {                    /* we need to get it byte by byte */
11728                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11729                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11730                 if (options.model == MODEL_FLAT24) {
11731                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11732                 }
11733             }
11734             _endLazyDPSEvaluation ();
11735         }
11736     }
11737     freeAsmop (to, NULL, ic, FALSE);
11738
11739     _G.dptrInUse = _G.dptr1InUse = 1;
11740     aopOp (count, ic->next->next, FALSE,FALSE);
11741     lbl =newiTempLabel(NULL);
11742
11743     /* now for the actual copy */
11744     if (AOP_TYPE(count) == AOP_LIT && 
11745         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11746         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11747         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11748         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11749         emitcode ("","!tlabeldef",lbl->key+100);
11750         emitcode ("movx", "a,@dptr");   /* read data from port */
11751         emitcode ("inc","dps");         /* switch to DPTR2 */
11752         emitcode ("movx", "@dptr,a");   /* save into location */
11753         emitcode ("inc", "dptr");       /* point to next area */
11754         emitcode ("dec","dps");         /* switch to DPTR */
11755         emitcode ("djnz","b,!tlabel",lbl->key+100);
11756         freeAsmop (count, NULL, ic, FALSE);
11757     } else {
11758         symbol *lbl1 = newiTempLabel(NULL);
11759         
11760         emitcode (";"," Auto increment but no djnz");
11761         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11762         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11763         freeAsmop (count, NULL, ic, FALSE);
11764         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11765         emitcode ("","!tlabeldef",lbl->key+100);
11766         emitcode ("movx", "a,@dptr");
11767         emitcode ("inc", "dptr");
11768         emitcode ("inc","dps");         /* switch to DPTR2 */
11769         emitcode ("movx", "@dptr,a");
11770         emitcode ("dec","dps");         /* switch to DPTR */
11771         emitcode ("mov","a,b");
11772         emitcode ("orl","a,_ap");
11773         emitcode ("jz","!tlabel",lbl1->key+100);
11774         emitcode ("mov","a,_ap");
11775         emitcode ("add","a,#!constbyte",0xFF);
11776         emitcode ("mov","_ap,a");
11777         emitcode ("mov","a,b");
11778         emitcode ("addc","a,#!constbyte",0xFF);
11779         emitcode ("mov","b,a");
11780         emitcode ("sjmp","!tlabel",lbl->key+100);
11781         emitcode ("","!tlabeldef",lbl1->key+100);
11782     }
11783     emitcode ("mov", "dps,#0"); 
11784     _G.dptrInUse = _G.dptr1InUse = 0;
11785     unsavermask(rsave);
11786
11787 }
11788
11789 /*-----------------------------------------------------------------*/
11790 /* genSwapW - swap lower & high order bytes                        */
11791 /*-----------------------------------------------------------------*/
11792 static void genSwapW(iCode *ic, int nparms, operand **parms)
11793 {
11794     operand *dest;
11795     operand *src;
11796     assert (nparms==1);
11797
11798     src = parms[0];
11799     dest=IC_RESULT(ic);
11800
11801     assert(getSize(operandType(src))==2);
11802
11803     aopOp (src, ic, FALSE, FALSE);
11804     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11805     _G.accInUse++;
11806     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11807     _G.accInUse--;
11808     freeAsmop (src, NULL, ic, FALSE);
11809     
11810     aopOp (dest,ic, FALSE, FALSE);
11811     aopPut(AOP(dest),"b",0);
11812     aopPut(AOP(dest),"a",1);
11813     freeAsmop (dest, NULL, ic, FALSE);    
11814 }
11815
11816 /*-----------------------------------------------------------------*/
11817 /* genMemsetX - gencode for memSetX data                           */
11818 /*-----------------------------------------------------------------*/
11819 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11820 {
11821     operand *to , *val , *count;
11822     symbol *lbl;
11823     char *l;
11824     int i;
11825     bitVect *rsave;
11826
11827     /* we know it has to be 3 parameters */
11828     assert (nparms == 3);
11829     
11830     to = parms[0];
11831     val = parms[1];
11832     count = parms[2];
11833         
11834     /* save DPTR if it needs to be saved */
11835     rsave = newBitVect(16);
11836     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11837             if (bitVectBitValue(ic->rMask,i))
11838                     rsave = bitVectSetBit(rsave,i);
11839     }
11840     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11841                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11842     savermask(rsave);
11843
11844     aopOp (to, ic, FALSE, FALSE);
11845     /* get "to" into DPTR */
11846     /* if the operand is already in dptr
11847        then we do nothing else we move the value to dptr */
11848     if (AOP_TYPE (to) != AOP_STR) {
11849         /* if already in DPTR then we need to push */
11850         if (AOP_TYPE(to) == AOP_DPTR) {
11851             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11852             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11853             if (options.model == MODEL_FLAT24)
11854                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11855             emitcode ("pop", "dph");
11856             emitcode ("pop", "dpl");        
11857         } else {
11858             _startLazyDPSEvaluation ();
11859             /* if this is remateriazable */
11860             if (AOP_TYPE (to) == AOP_IMMD) {
11861                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11862             } else {                    /* we need to get it byte by byte */
11863                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11864                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11865                 if (options.model == MODEL_FLAT24) {
11866                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11867                 }
11868             }
11869             _endLazyDPSEvaluation ();
11870         }
11871     }
11872     freeAsmop (to, NULL, ic, FALSE);
11873
11874     aopOp (val, ic->next->next, FALSE,FALSE);
11875     aopOp (count, ic->next->next, FALSE,FALSE);    
11876     lbl =newiTempLabel(NULL);
11877     /* now for the actual copy */
11878     if (AOP_TYPE(count) == AOP_LIT && 
11879         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11880         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11881         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11882         MOVA(l);
11883         emitcode ("","!tlabeldef",lbl->key+100);
11884         emitcode ("movx", "@dptr,a");
11885         emitcode ("inc", "dptr");
11886         emitcode ("djnz","b,!tlabel",lbl->key+100);
11887     } else {
11888         symbol *lbl1 = newiTempLabel(NULL);
11889         
11890         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11891         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11892         emitcode ("","!tlabeldef",lbl->key+100);
11893         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11894         emitcode ("movx", "@dptr,a");
11895         emitcode ("inc", "dptr");
11896         emitcode ("mov","a,b");
11897         emitcode ("orl","a,_ap");
11898         emitcode ("jz","!tlabel",lbl1->key+100);
11899         emitcode ("mov","a,_ap");
11900         emitcode ("add","a,#!constbyte",0xFF);
11901         emitcode ("mov","_ap,a");
11902         emitcode ("mov","a,b");
11903         emitcode ("addc","a,#!constbyte",0xFF);
11904         emitcode ("mov","b,a");
11905         emitcode ("sjmp","!tlabel",lbl->key+100);
11906         emitcode ("","!tlabeldef",lbl1->key+100);
11907     }
11908     freeAsmop (count, NULL, ic, FALSE);
11909     unsavermask(rsave);
11910 }
11911
11912 /*-----------------------------------------------------------------*/
11913 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11914 /*-----------------------------------------------------------------*/
11915 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11916 {
11917         bitVect *rsave ;
11918         operand *pnum, *result;
11919         int i;
11920     
11921         assert (nparms==1);
11922         /* save registers that need to be saved */
11923         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11924                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11925     
11926         pnum = parms[0]; 
11927         aopOp (pnum, ic, FALSE, FALSE);
11928         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11929         freeAsmop (pnum, NULL, ic, FALSE);
11930         emitcode ("lcall","NatLib_LoadPrimitive");
11931         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11932         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11933             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11934                 for (i = (size-1) ; i >= 0 ; i-- ) {
11935                         emitcode ("push","a%s",javaRet[i]);
11936                 }
11937                 for (i=0; i < size ; i++ ) {
11938                         emitcode ("pop","a%s",
11939                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11940                 }
11941         } else {
11942                 for (i = 0 ; i < size ; i++ ) {
11943                         aopPut(AOP(result),javaRet[i],i);
11944                 }
11945         }    
11946         freeAsmop (result, NULL, ic, FALSE);
11947         unsavermask(rsave);
11948 }
11949
11950 /*-----------------------------------------------------------------*/
11951 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11952 /*-----------------------------------------------------------------*/
11953 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11954 {
11955         bitVect *rsave ;
11956         operand *pnum, *result;
11957         int size = 3;
11958         int i;
11959     
11960         assert (nparms==1);
11961         /* save registers that need to be saved */
11962         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11963                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11964     
11965         pnum = parms[0]; 
11966         aopOp (pnum, ic, FALSE, FALSE);
11967         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11968         freeAsmop (pnum, NULL, ic, FALSE);
11969         emitcode ("lcall","NatLib_LoadPointer");
11970         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11971         if (AOP_TYPE(result)!=AOP_STR) {
11972                 for (i = 0 ; i < size ; i++ ) {
11973                         aopPut(AOP(result),fReturn[i],i);
11974                 }
11975         }    
11976         freeAsmop (result, NULL, ic, FALSE);
11977         unsavermask(rsave);
11978 }
11979
11980 /*-----------------------------------------------------------------*/
11981 /* genNatLibInstallStateBlock -                                    */
11982 /*-----------------------------------------------------------------*/
11983 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
11984                                        operand **parms, const char *name)
11985 {
11986         bitVect *rsave ;
11987         operand *psb, *handle;
11988         assert (nparms==2);
11989
11990         /* save registers that need to be saved */
11991         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11992                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11993         psb = parms[0];
11994         handle = parms[1];
11995
11996         /* put pointer to state block into DPTR1 */
11997         aopOp (psb, ic, FALSE, FALSE);
11998         if (AOP_TYPE (psb) == AOP_IMMD) {
11999                 emitcode ("mov","dps,#1");
12000                 emitcode ("mov", "dptr,%s",
12001                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12002                 emitcode ("mov","dps,#0");
12003         } else {
12004                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12005                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12006                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12007         }
12008         freeAsmop (psb, NULL, ic, FALSE);
12009
12010         /* put libraryID into DPTR */
12011         emitcode ("mov","dptr,#LibraryID");
12012
12013         /* put handle into r3:r2 */
12014         aopOp (handle, ic, FALSE, FALSE);
12015         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12016                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12017                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12018                 emitcode ("pop","ar3");
12019                 emitcode ("pop","ar2");
12020         } else {        
12021                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12022                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12023         }
12024         freeAsmop (psb, NULL, ic, FALSE);
12025
12026         /* make the call */
12027         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12028
12029         /* put return value into place*/
12030         _G.accInUse++;
12031         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12032         _G.accInUse--;
12033         aopPut(AOP(IC_RESULT(ic)),"a",0);
12034         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12035         unsavermask(rsave);
12036 }
12037
12038 /*-----------------------------------------------------------------*/
12039 /* genNatLibRemoveStateBlock -                                     */
12040 /*-----------------------------------------------------------------*/
12041 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12042 {
12043         bitVect *rsave ;
12044
12045         assert(nparms==0);
12046
12047         /* save registers that need to be saved */
12048         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12049                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12050
12051         /* put libraryID into DPTR */
12052         emitcode ("mov","dptr,#LibraryID");
12053         /* make the call */
12054         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12055         unsavermask(rsave);
12056 }
12057
12058 /*-----------------------------------------------------------------*/
12059 /* genNatLibGetStateBlock -                                        */
12060 /*-----------------------------------------------------------------*/
12061 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12062                                    operand **parms,const char *name)
12063 {
12064         bitVect *rsave ;
12065         symbol *lbl = newiTempLabel(NULL);
12066         
12067         assert(nparms==0);
12068         /* save registers that need to be saved */
12069         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12070                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12071
12072         /* put libraryID into DPTR */
12073         emitcode ("mov","dptr,#LibraryID");
12074         /* make the call */
12075         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12076         emitcode ("jnz","!tlabel",lbl->key+100);
12077
12078         /* put return value into place */
12079         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12080         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12081                 emitcode ("push","ar3");
12082                 emitcode ("push","ar2");
12083                 emitcode ("pop","%s",
12084                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12085                 emitcode ("pop","%s",
12086                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12087         } else {
12088                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12089                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12090         }
12091         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12092         emitcode ("","!tlabeldef",lbl->key+100);
12093         unsavermask(rsave);
12094 }
12095
12096 /*-----------------------------------------------------------------*/
12097 /* genMMMalloc -                                                   */
12098 /*-----------------------------------------------------------------*/
12099 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12100                          int size, const char *name)
12101 {
12102         bitVect *rsave ;
12103         operand *bsize;
12104         symbol *rsym;
12105         symbol *lbl = newiTempLabel(NULL);
12106
12107         assert (nparms == 1);
12108         /* save registers that need to be saved */
12109         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12110                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12111         
12112         bsize=parms[0];
12113         aopOp (bsize,ic,FALSE,FALSE);
12114
12115         /* put the size in R4-R2 */
12116         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12117                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12118                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12119                 if (size==3) {
12120                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12121                         emitcode("pop","ar4");
12122                 }
12123                 emitcode("pop","ar3");
12124                 emitcode("pop","ar2");          
12125         } else {
12126                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12127                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12128                 if (size==3) {
12129                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12130                 }
12131         }
12132         freeAsmop (bsize, NULL, ic, FALSE);
12133
12134         /* make the call */
12135         emitcode ("lcall","MM_%s",name);
12136         emitcode ("jz","!tlabel",lbl->key+100);
12137         emitcode ("mov","r2,#!constbyte",0xff);
12138         emitcode ("mov","r3,#!constbyte",0xff);
12139         emitcode ("","!tlabeldef",lbl->key+100);
12140         /* we don't care about the pointer : we just save the handle */
12141         rsym = OP_SYMBOL(IC_RESULT(ic));
12142         if (rsym->liveFrom != rsym->liveTo) {
12143                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12144                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12145                         emitcode ("push","ar3");
12146                         emitcode ("push","ar2");
12147                         emitcode ("pop","%s",
12148                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12149                         emitcode ("pop","%s",
12150                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12151                 } else {
12152                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12153                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12154                 }
12155                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12156         }
12157         unsavermask(rsave);
12158 }
12159
12160 /*-----------------------------------------------------------------*/
12161 /* genMMDeref -                                                    */
12162 /*-----------------------------------------------------------------*/
12163 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12164 {
12165         bitVect *rsave ;
12166         operand *handle;
12167
12168         assert (nparms == 1);
12169         /* save registers that need to be saved */
12170         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12171                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12172         
12173         handle=parms[0];
12174         aopOp (handle,ic,FALSE,FALSE);
12175
12176         /* put the size in R4-R2 */
12177         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12178                 emitcode("push","%s",
12179                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12180                 emitcode("push","%s",
12181                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12182                 emitcode("pop","ar3");
12183                 emitcode("pop","ar2");          
12184         } else {
12185                 emitcode ("mov","r2,%s",
12186                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12187                 emitcode ("mov","r3,%s",
12188                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12189         }
12190         freeAsmop (handle, NULL, ic, FALSE);
12191
12192         /* make the call */
12193         emitcode ("lcall","MM_Deref");
12194         
12195         {
12196                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12197                 if (rsym->liveFrom != rsym->liveTo) {                   
12198                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12199                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12200                             _startLazyDPSEvaluation ();
12201                             
12202                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12203                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12204                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12205
12206                             _endLazyDPSEvaluation ();
12207                             
12208                         }
12209                 }
12210         }
12211         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12212         unsavermask(rsave);
12213 }
12214
12215 /*-----------------------------------------------------------------*/
12216 /* genMMUnrestrictedPersist -                                      */
12217 /*-----------------------------------------------------------------*/
12218 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12219 {
12220         bitVect *rsave ;
12221         operand *handle;
12222
12223         assert (nparms == 1);
12224         /* save registers that need to be saved */
12225         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12226                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12227         
12228         handle=parms[0];
12229         aopOp (handle,ic,FALSE,FALSE);
12230
12231         /* put the size in R3-R2 */
12232         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12233                 emitcode("push","%s",
12234                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12235                 emitcode("push","%s",
12236                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12237                 emitcode("pop","ar3");
12238                 emitcode("pop","ar2");          
12239         } else {
12240                 emitcode ("mov","r2,%s",
12241                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12242                 emitcode ("mov","r3,%s",
12243                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12244         }
12245         freeAsmop (handle, NULL, ic, FALSE);
12246
12247         /* make the call */
12248         emitcode ("lcall","MM_UnrestrictedPersist");
12249
12250         {
12251                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12252                 if (rsym->liveFrom != rsym->liveTo) {   
12253                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12254                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12255                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12256                 }
12257         }
12258         unsavermask(rsave);
12259 }
12260
12261 /*-----------------------------------------------------------------*/
12262 /* genSystemExecJavaProcess -                                      */
12263 /*-----------------------------------------------------------------*/
12264 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12265 {
12266         bitVect *rsave ;
12267         operand *handle, *pp;
12268
12269         assert (nparms==2);
12270         /* save registers that need to be saved */
12271         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12272                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12273         
12274         pp = parms[0];
12275         handle = parms[1];
12276         
12277         /* put the handle in R3-R2 */
12278         aopOp (handle,ic,FALSE,FALSE);
12279         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12280                 emitcode("push","%s",
12281                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12282                 emitcode("push","%s",
12283                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12284                 emitcode("pop","ar3");
12285                 emitcode("pop","ar2");          
12286         } else {
12287                 emitcode ("mov","r2,%s",
12288                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12289                 emitcode ("mov","r3,%s",
12290                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12291         }
12292         freeAsmop (handle, NULL, ic, FALSE);
12293         
12294         /* put pointer in DPTR */
12295         aopOp (pp,ic,FALSE,FALSE);
12296         if (AOP_TYPE(pp) == AOP_IMMD) {
12297                 emitcode ("mov", "dptr,%s",
12298                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12299         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12300                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12301                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12302                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12303         }
12304         freeAsmop (handle, NULL, ic, FALSE);
12305
12306         /* make the call */
12307         emitcode ("lcall","System_ExecJavaProcess");
12308         
12309         /* put result in place */
12310         {
12311                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12312                 if (rsym->liveFrom != rsym->liveTo) {   
12313                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12314                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12315                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12316                 }
12317         }
12318         
12319         unsavermask(rsave);
12320 }
12321
12322 /*-----------------------------------------------------------------*/
12323 /* genSystemRTCRegisters -                                         */
12324 /*-----------------------------------------------------------------*/
12325 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12326                                   char *name)
12327 {
12328         bitVect *rsave ;
12329         operand *pp;
12330
12331         assert (nparms==1);
12332         /* save registers that need to be saved */
12333         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12334                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12335         
12336         pp=parms[0];
12337         /* put pointer in DPTR */
12338         aopOp (pp,ic,FALSE,FALSE);
12339         if (AOP_TYPE (pp) == AOP_IMMD) {
12340                 emitcode ("mov","dps,#1");
12341                 emitcode ("mov", "dptr,%s", 
12342                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12343                 emitcode ("mov","dps,#0");
12344         } else {
12345                 emitcode ("mov","dpl1,%s",
12346                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12347                 emitcode ("mov","dph1,%s",
12348                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12349                 emitcode ("mov","dpx1,%s",
12350                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12351         }
12352         freeAsmop (pp, NULL, ic, FALSE);
12353
12354         /* make the call */
12355         emitcode ("lcall","System_%sRTCRegisters",name);
12356
12357         unsavermask(rsave);
12358 }
12359
12360 /*-----------------------------------------------------------------*/
12361 /* genSystemThreadSleep -                                          */
12362 /*-----------------------------------------------------------------*/
12363 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12364 {
12365         bitVect *rsave ;
12366         operand *to, *s;
12367
12368         assert (nparms==1);
12369         /* save registers that need to be saved */
12370         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12371                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12372
12373         to = parms[0];
12374         aopOp(to,ic,FALSE,FALSE);
12375         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12376             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12377                 emitcode ("push","%s",
12378                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12379                 emitcode ("push","%s",
12380                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12381                 emitcode ("push","%s",
12382                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12383                 emitcode ("push","%s",
12384                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12385                 emitcode ("pop","ar3");
12386                 emitcode ("pop","ar2");
12387                 emitcode ("pop","ar1");
12388                 emitcode ("pop","ar0");
12389         } else {
12390                 emitcode ("mov","r0,%s",
12391                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12392                 emitcode ("mov","r1,%s",
12393                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12394                 emitcode ("mov","r2,%s",
12395                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12396                 emitcode ("mov","r3,%s",
12397                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12398         }
12399         freeAsmop (to, NULL, ic, FALSE);
12400
12401         /* suspend in acc */
12402         s = parms[1];
12403         aopOp(s,ic,FALSE,FALSE);
12404         emitcode ("mov","a,%s",
12405                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12406         freeAsmop (s, NULL, ic, FALSE);
12407
12408         /* make the call */
12409         emitcode ("lcall","System_%s",name);
12410
12411         unsavermask(rsave);
12412 }
12413
12414 /*-----------------------------------------------------------------*/
12415 /* genSystemThreadResume -                                         */
12416 /*-----------------------------------------------------------------*/
12417 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12418 {
12419         bitVect *rsave ;
12420         operand *tid,*pid;
12421
12422         assert (nparms==2);
12423         /* save registers that need to be saved */
12424         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12425                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12426         
12427         tid = parms[0];
12428         pid = parms[1];
12429         
12430         /* PID in R0 */
12431         aopOp(pid,ic,FALSE,FALSE);
12432         emitcode ("mov","r0,%s",
12433                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12434         freeAsmop (pid, NULL, ic, FALSE);
12435         
12436         /* tid into ACC */
12437         aopOp(tid,ic,FALSE,FALSE);
12438         emitcode ("mov","a,%s",
12439                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12440         freeAsmop (tid, NULL, ic, FALSE);
12441         
12442         emitcode ("lcall","System_ThreadResume");
12443
12444         /* put result into place */
12445         {
12446                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12447                 if (rsym->liveFrom != rsym->liveTo) {   
12448                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12449                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12450                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12451                 }
12452         }
12453         unsavermask(rsave);
12454 }
12455
12456 /*-----------------------------------------------------------------*/
12457 /* genSystemProcessResume -                                        */
12458 /*-----------------------------------------------------------------*/
12459 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12460 {
12461         bitVect *rsave ;
12462         operand *pid;
12463
12464         assert (nparms==1);
12465         /* save registers that need to be saved */
12466         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12467                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12468         
12469         pid = parms[0];
12470         
12471         /* pid into ACC */
12472         aopOp(pid,ic,FALSE,FALSE);
12473         emitcode ("mov","a,%s",
12474                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12475         freeAsmop (pid, NULL, ic, FALSE);
12476         
12477         emitcode ("lcall","System_ProcessResume");
12478
12479         unsavermask(rsave);
12480 }
12481
12482 /*-----------------------------------------------------------------*/
12483 /* genSystem -                                                     */
12484 /*-----------------------------------------------------------------*/
12485 static void genSystem (iCode *ic,int nparms,char *name)
12486 {
12487         assert(nparms == 0);
12488
12489         emitcode ("lcall","System_%s",name);
12490 }
12491
12492 /*-----------------------------------------------------------------*/
12493 /* genSystemPoll -                                                  */
12494 /*-----------------------------------------------------------------*/
12495 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12496 {
12497         bitVect *rsave ;
12498         operand *fp;
12499
12500         assert (nparms==1);
12501         /* save registers that need to be saved */
12502         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12503                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12504
12505         fp = parms[0];
12506         aopOp (fp,ic,FALSE,FALSE);
12507         if (AOP_TYPE (fp) == AOP_IMMD) {
12508                 emitcode ("mov", "dptr,%s", 
12509                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12510         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12511                 emitcode ("mov","dpl,%s",
12512                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12513                 emitcode ("mov","dph,%s",
12514                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12515                 emitcode ("mov","dpx,%s",
12516                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12517         }
12518         freeAsmop (fp, NULL, ic, FALSE);
12519
12520         emitcode ("lcall","System_%sPoll",name);
12521
12522         /* put result into place */
12523         {
12524                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12525                 if (rsym->liveFrom != rsym->liveTo) {   
12526                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12527                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12528                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12529                 }
12530         }
12531         unsavermask(rsave);
12532 }
12533
12534 /*-----------------------------------------------------------------*/
12535 /* genSystemGetCurrentID -                                         */
12536 /*-----------------------------------------------------------------*/
12537 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12538 {
12539         assert (nparms==0);
12540
12541         emitcode ("lcall","System_GetCurrent%sId",name);
12542         /* put result into place */
12543         {
12544                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12545                 if (rsym->liveFrom != rsym->liveTo) {   
12546                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12547                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12548                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12549                 }
12550         }
12551 }
12552
12553 /*-----------------------------------------------------------------*/
12554 /* genDummyRead - generate code for dummy read of volatiles        */
12555 /*-----------------------------------------------------------------*/
12556 static void
12557 genDummyRead (iCode * ic)
12558 {
12559   operand *right;
12560   int size, offset;
12561
12562   D(emitcode(";     genDummyRead",""));
12563
12564   right = IC_RIGHT (ic);
12565
12566   aopOp (right, ic, FALSE, FALSE);
12567
12568   /* if the result is a bit */
12569   if (AOP_TYPE (right) == AOP_CRY)
12570     {
12571       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12572       goto release;
12573     }
12574
12575   /* bit variables done */
12576   /* general case */
12577   size = AOP_SIZE (right);
12578   offset = 0;
12579   while (size--)
12580     {
12581       emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12582       offset++;
12583     }
12584
12585 release:
12586   freeAsmop (right, NULL, ic, TRUE);
12587 }
12588
12589 /*-----------------------------------------------------------------*/
12590 /* genBuiltIn - calls the appropriate function to  generating code */
12591 /* for a built in function                                         */
12592 /*-----------------------------------------------------------------*/
12593 static void genBuiltIn (iCode *ic)
12594 {
12595         operand *bi_parms[MAX_BUILTIN_ARGS];
12596         int nbi_parms;
12597         iCode *bi_iCode;
12598         symbol *bif;
12599
12600         /* get all the arguments for a built in function */
12601         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12602
12603         /* which function is it */
12604         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12605         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12606                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12607         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12608                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12609         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12610                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12611         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12612                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12613         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12614                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12615         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12616                 genInp(bi_iCode,nbi_parms,bi_parms);
12617         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12618                 genOutp(bi_iCode,nbi_parms,bi_parms);
12619         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12620                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12621                 /* JavaNative builtIns */               
12622         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12623                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12624         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12625                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12626         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12627                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12628         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12629                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12630         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12631                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12632         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12633                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12634         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12635                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12636         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12637                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12638         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12639                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12640         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12641                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12642         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12643                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12644         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12645                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12646         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12647                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12648         } else if (strcmp(bif->name,"MM_Free")==0) {
12649                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12650         } else if (strcmp(bif->name,"MM_Deref")==0) {
12651                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12652         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12653                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12654         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12655                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12656         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12657                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12658         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12659                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12660         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12661                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12662         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12663                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12664         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12665                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12666         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12667                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12668         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12669                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12670         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12671                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12672         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12673                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12674         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12675                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12676         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12677                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12678         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12679                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12680         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12681                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12682         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12683                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12684         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12685                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12686         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12687                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12688         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12689                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12690         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12691                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12692         } else {
12693                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12694                 return ;
12695         }
12696         return ;    
12697 }
12698
12699 /*-----------------------------------------------------------------*/
12700 /* gen390Code - generate code for Dallas 390 based controllers     */
12701 /*-----------------------------------------------------------------*/
12702 void
12703 gen390Code (iCode * lic)
12704 {
12705   iCode *ic;
12706   int cln = 0;
12707
12708   lineHead = lineCurr = NULL;
12709   dptrn[1][0] = "dpl1";
12710   dptrn[1][1] = "dph1";
12711   dptrn[1][2] = "dpx1";
12712   
12713   if (options.model == MODEL_FLAT24) {
12714     fReturnSizeDS390 = 5;
12715     fReturn = fReturn24;
12716   } else {
12717     fReturnSizeDS390 = 4;
12718     fReturn = fReturn16;
12719     options.stack10bit=0;
12720   }
12721 #if 1
12722   /* print the allocation information */
12723   if (allocInfo && currFunc)
12724     printAllocInfo (currFunc, codeOutFile);
12725 #endif
12726   /* if debug information required */
12727   if (options.debug && currFunc)
12728     {
12729       debugFile->writeFunction(currFunc);
12730       _G.debugLine = 1;
12731       if (IS_STATIC (currFunc->etype))
12732         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12733       else
12734         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12735       _G.debugLine = 0;
12736     }
12737   /* stack pointer name */
12738   if (options.useXstack)
12739     spname = "_spx";
12740   else
12741     spname = "sp";
12742
12743
12744   for (ic = lic; ic; ic = ic->next)
12745     {
12746
12747       if (ic->lineno && cln != ic->lineno)
12748         {
12749           if (options.debug)
12750             {
12751               _G.debugLine = 1;
12752               emitcode ("", "C$%s$%d$%d$%d ==.",
12753                         FileBaseName (ic->filename), ic->lineno,
12754                         ic->level, ic->block);
12755               _G.debugLine = 0;
12756             }
12757           if (!options.noCcodeInAsm) {
12758             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12759                       printCLine(ic->filename, ic->lineno));
12760           }
12761           cln = ic->lineno;
12762         }
12763       if (options.iCodeInAsm) {
12764         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12765       }
12766       /* if the result is marked as
12767          spilt and rematerializable or code for
12768          this has already been generated then
12769          do nothing */
12770       if (resultRemat (ic) || ic->generated)
12771         continue;
12772
12773       /* depending on the operation */
12774       switch (ic->op)
12775         {
12776         case '!':
12777           genNot (ic);
12778           break;
12779
12780         case '~':
12781           genCpl (ic);
12782           break;
12783
12784         case UNARYMINUS:
12785           genUminus (ic);
12786           break;
12787
12788         case IPUSH:
12789           genIpush (ic);
12790           break;
12791
12792         case IPOP:
12793           /* IPOP happens only when trying to restore a
12794              spilt live range, if there is an ifx statement
12795              following this pop then the if statement might
12796              be using some of the registers being popped which
12797              would destory the contents of the register so
12798              we need to check for this condition and handle it */
12799           if (ic->next &&
12800               ic->next->op == IFX &&
12801               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12802             genIfx (ic->next, ic);
12803           else
12804             genIpop (ic);
12805           break;
12806
12807         case CALL:
12808           genCall (ic);
12809           break;
12810
12811         case PCALL:
12812           genPcall (ic);
12813           break;
12814
12815         case FUNCTION:
12816           genFunction (ic);
12817           break;
12818
12819         case ENDFUNCTION:
12820           genEndFunction (ic);
12821           break;
12822
12823         case RETURN:
12824           genRet (ic);
12825           break;
12826
12827         case LABEL:
12828           genLabel (ic);
12829           break;
12830
12831         case GOTO:
12832           genGoto (ic);
12833           break;
12834
12835         case '+':
12836           genPlus (ic);
12837           break;
12838
12839         case '-':
12840           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12841             genMinus (ic);
12842           break;
12843
12844         case '*':
12845           genMult (ic);
12846           break;
12847
12848         case '/':
12849           genDiv (ic);
12850           break;
12851
12852         case '%':
12853           genMod (ic);
12854           break;
12855
12856         case '>':
12857           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12858           break;
12859
12860         case '<':
12861           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12862           break;
12863
12864         case LE_OP:
12865         case GE_OP:
12866         case NE_OP:
12867
12868           /* note these two are xlated by algebraic equivalence
12869              during parsing SDCC.y */
12870           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12871                   "got '>=' or '<=' shouldn't have come here");
12872           break;
12873
12874         case EQ_OP:
12875           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12876           break;
12877
12878         case AND_OP:
12879           genAndOp (ic);
12880           break;
12881
12882         case OR_OP:
12883           genOrOp (ic);
12884           break;
12885
12886         case '^':
12887           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12888           break;
12889
12890         case '|':
12891           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12892           break;
12893
12894         case BITWISEAND:
12895           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12896           break;
12897
12898         case INLINEASM:
12899           genInline (ic);
12900           break;
12901
12902         case RRC:
12903           genRRC (ic);
12904           break;
12905
12906         case RLC:
12907           genRLC (ic);
12908           break;
12909
12910         case GETHBIT:
12911           genGetHbit (ic);
12912           break;
12913
12914         case LEFT_OP:
12915           genLeftShift (ic);
12916           break;
12917
12918         case RIGHT_OP:
12919           genRightShift (ic);
12920           break;
12921
12922         case GET_VALUE_AT_ADDRESS:
12923           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12924           break;
12925
12926         case '=':
12927           if (POINTER_SET (ic))
12928             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12929           else
12930             genAssign (ic);
12931           break;
12932
12933         case IFX:
12934           genIfx (ic, NULL);
12935           break;
12936
12937         case ADDRESS_OF:
12938           genAddrOf (ic);
12939           break;
12940
12941         case JUMPTABLE:
12942           genJumpTab (ic);
12943           break;
12944
12945         case CAST:
12946           genCast (ic);
12947           break;
12948
12949         case RECEIVE:
12950           genReceive (ic);
12951           break;
12952
12953         case SEND:
12954           if (ic->builtinSEND) genBuiltIn(ic);
12955           else addSet (&_G.sendSet, ic);
12956           break;
12957
12958         case DUMMY_READ_VOLATILE:
12959           genDummyRead (ic);
12960           break;
12961
12962 #if 0 // obsolete, and buggy for != xdata
12963         case ARRAYINIT:
12964             genArrayInit(ic);
12965             break;
12966 #endif
12967             
12968         default:
12969           ic = ic;
12970         }
12971     }
12972
12973
12974   /* now we are ready to call the
12975      peep hole optimizer */
12976   if (!options.nopeep)
12977     peepHole (&lineHead);
12978
12979   /* now do the actual printing */
12980   printLine (lineHead, codeOutFile);
12981   return;
12982 }