Made bitfield a distinct type from bit so that bitfields
[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 /* genNotFloat - generates not for float operations              */
1612 /*-----------------------------------------------------------------*/
1613 static void
1614 genNotFloat (operand * op, operand * res)
1615 {
1616   int size, offset;
1617   symbol *tlbl;
1618
1619   D (emitcode (";", "genNotFloat "););
1620
1621   /* we will put 127 in the first byte of
1622      the result */
1623   aopPut (AOP (res), "#127", 0);
1624   size = AOP_SIZE (op) - 1;
1625   offset = 1;
1626
1627   _startLazyDPSEvaluation ();
1628   MOVA(aopGet(op->aop, offset++, FALSE, FALSE, NULL));
1629
1630   while (size--)
1631     {
1632       emitcode ("orl", "a,%s",
1633                 aopGet (op->aop,
1634                         offset++, FALSE, FALSE,
1635                         DP2_RESULT_REG));
1636     }
1637   _endLazyDPSEvaluation ();
1638
1639   tlbl = newiTempLabel (NULL);
1640   aopPut (res->aop, one, 1);
1641   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1642   aopPut (res->aop, zero, 1);
1643   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1644
1645   size = res->aop->size - 2;
1646   offset = 2;
1647   /* put zeros in the rest */
1648   while (size--)
1649     aopPut (res->aop, zero, offset++);
1650 }
1651
1652 /*-----------------------------------------------------------------*/
1653 /* opIsGptr: returns non-zero if the passed operand is       */
1654 /* a generic pointer type.             */
1655 /*-----------------------------------------------------------------*/
1656 static int
1657 opIsGptr (operand * op)
1658 {
1659   sym_link *type = operandType (op);
1660
1661   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1662     {
1663       return 1;
1664     }
1665   return 0;
1666 }
1667
1668 /*-----------------------------------------------------------------*/
1669 /* getDataSize - get the operand data size                         */
1670 /*-----------------------------------------------------------------*/
1671 static int
1672 getDataSize (operand * op)
1673 {
1674   int size;
1675   size = AOP_SIZE (op);
1676   if (size == GPTRSIZE)
1677     {
1678       sym_link *type = operandType (op);
1679       if (IS_GENPTR (type))
1680         {
1681           /* generic pointer; arithmetic operations
1682            * should ignore the high byte (pointer type).
1683            */
1684           size--;
1685         }
1686     }
1687   return size;
1688 }
1689
1690 /*-----------------------------------------------------------------*/
1691 /* outAcc - output Acc                                             */
1692 /*-----------------------------------------------------------------*/
1693 static void
1694 outAcc (operand * result)
1695 {
1696   int size, offset;
1697   size = getDataSize (result);
1698   if (size)
1699     {
1700       aopPut (AOP (result), "a", 0);
1701       size--;
1702       offset = 1;
1703       /* unsigned or positive */
1704       while (size--)
1705         {
1706           aopPut (AOP (result), zero, offset++);
1707         }
1708     }
1709 }
1710
1711 /*-----------------------------------------------------------------*/
1712 /* outBitC - output a bit C                                        */
1713 /*-----------------------------------------------------------------*/
1714 static void
1715 outBitC (operand * result)
1716 {
1717   /* if the result is bit */
1718   if (AOP_TYPE (result) == AOP_CRY)
1719     {
1720       aopPut (AOP (result), "c", 0);
1721     }
1722   else
1723     {
1724       emitcode ("clr", "a");
1725       emitcode ("rlc", "a");
1726       outAcc (result);
1727     }
1728 }
1729
1730 /*-----------------------------------------------------------------*/
1731 /* toBoolean - emit code for orl a,operator(sizeop)                */
1732 /*-----------------------------------------------------------------*/
1733 static void
1734 toBoolean (operand * oper)
1735 {
1736   int   size = AOP_SIZE (oper) - 1;
1737   int   offset = 1;
1738   bool usedB = FALSE;
1739
1740   /* The generic part of a generic pointer should
1741    * not participate in it's truth value.
1742    *
1743    * i.e. 0x10000000 is zero.
1744    */
1745   if (opIsGptr (oper))
1746     {
1747       D (emitcode (";", "toBoolean: generic ptr special case."););
1748       size--;
1749     }
1750
1751   _startLazyDPSEvaluation ();
1752   if (AOP_NEEDSACC (oper) && size)
1753     {
1754       usedB = TRUE;
1755       if (_G.bInUse)
1756       {
1757           emitcode ("push", "b");
1758       }
1759       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1760     }
1761   else
1762     {
1763       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1764     }
1765     
1766   while (size--)
1767     {
1768       if (usedB)
1769         {
1770           emitcode ("orl", "b,%s",
1771                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1772         }
1773       else
1774         {
1775           emitcode ("orl", "a,%s",
1776                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1777         }
1778     }
1779   _endLazyDPSEvaluation ();
1780
1781   if (usedB)
1782     {
1783       emitcode ("mov", "a,b");
1784       if (_G.bInUse)
1785       {
1786           emitcode ("pop", "b");
1787       }
1788         
1789     }
1790 }
1791
1792
1793 /*-----------------------------------------------------------------*/
1794 /* genNot - generate code for ! operation                          */
1795 /*-----------------------------------------------------------------*/
1796 static void
1797 genNot (iCode * ic)
1798 {
1799   symbol *tlbl;
1800   sym_link *optype = operandType (IC_LEFT (ic));
1801
1802   D (emitcode (";", "genNot "););
1803
1804   /* assign asmOps to operand & result */
1805   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1806   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1807
1808   /* if in bit space then a special case */
1809   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1810     {
1811       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1812       emitcode ("cpl", "c");
1813       outBitC (IC_RESULT (ic));
1814       goto release;
1815     }
1816
1817   /* if type float then do float */
1818   if (IS_FLOAT (optype))
1819     {
1820       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1821       goto release;
1822     }
1823
1824   toBoolean (IC_LEFT (ic));
1825
1826   tlbl = newiTempLabel (NULL);
1827   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1828   emitcode ("", "!tlabeldef", tlbl->key + 100);
1829   outBitC (IC_RESULT (ic));
1830
1831 release:
1832   /* release the aops */
1833   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1834   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1835 }
1836
1837
1838 /*-----------------------------------------------------------------*/
1839 /* genCpl - generate code for complement                           */
1840 /*-----------------------------------------------------------------*/
1841 static void
1842 genCpl (iCode * ic)
1843 {
1844   int offset = 0;
1845   int size;
1846   symbol *tlbl;
1847
1848   D (emitcode (";", "genCpl "););
1849
1850
1851   /* assign asmOps to operand & result */
1852   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1853   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1854
1855   /* special case if in bit space */
1856   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1857     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1858       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1859       emitcode ("cpl", "c");
1860       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1861       goto release;
1862     }
1863     tlbl=newiTempLabel(NULL);
1864     emitcode ("cjne", "%s,#0x01,%05d$", 
1865               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1866     emitcode ("", "%05d$:", tlbl->key+100);
1867     outBitC (IC_RESULT(ic));
1868     goto release;
1869   }
1870
1871   size = AOP_SIZE (IC_RESULT (ic));
1872   _startLazyDPSEvaluation ();
1873   while (size--)
1874     {
1875       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1876       emitcode ("cpl", "a");
1877       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1878     }
1879   _endLazyDPSEvaluation ();
1880
1881
1882 release:
1883   /* release the aops */
1884   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1885   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1886 }
1887
1888 /*-----------------------------------------------------------------*/
1889 /* genUminusFloat - unary minus for floating points                */
1890 /*-----------------------------------------------------------------*/
1891 static void
1892 genUminusFloat (operand * op, operand * result)
1893 {
1894   int size, offset = 0;
1895     
1896   D(emitcode (";", "genUminusFloat"););
1897   
1898   /* for this we just copy and then flip the bit */
1899     
1900   _startLazyDPSEvaluation ();
1901   size = AOP_SIZE (op) - 1;
1902
1903   while (size--)
1904   {
1905       aopPut (AOP (result),
1906               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1907               offset);
1908       offset++;
1909     }
1910   
1911   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1912
1913   emitcode ("cpl", "acc.7");
1914   aopPut (AOP (result), "a", offset);    
1915   _endLazyDPSEvaluation ();
1916 }
1917
1918 /*-----------------------------------------------------------------*/
1919 /* genUminus - unary minus code generation                         */
1920 /*-----------------------------------------------------------------*/
1921 static void
1922 genUminus (iCode * ic)
1923 {
1924   int offset, size;
1925   sym_link *optype;
1926
1927   D (emitcode (";", "genUminus "););
1928
1929   /* assign asmops */
1930   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1931   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1932
1933   /* if both in bit space then special
1934      case */
1935   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1936       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1937     {
1938
1939       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1940       emitcode ("cpl", "c");
1941       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1942       goto release;
1943     }
1944
1945   optype = operandType (IC_LEFT (ic));
1946
1947   /* if float then do float stuff */
1948   if (IS_FLOAT (optype))
1949     {
1950       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1951       goto release;
1952     }
1953
1954   /* otherwise subtract from zero */
1955   size = AOP_SIZE (IC_LEFT (ic));
1956   offset = 0;
1957   _startLazyDPSEvaluation ();
1958   while (size--)
1959     {
1960       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1961       if (!strcmp (l, "a"))
1962         {
1963           if (offset == 0)
1964             SETC;
1965           emitcode ("cpl", "a");
1966           emitcode ("addc", "a,#0");
1967         }
1968       else
1969         {
1970           if (offset == 0)
1971             CLRC;
1972           emitcode ("clr", "a");
1973           emitcode ("subb", "a,%s", l);
1974         }
1975       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1976     }
1977   _endLazyDPSEvaluation ();
1978
1979   /* if any remaining bytes in the result */
1980   /* we just need to propagate the sign   */
1981   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1982     {
1983       emitcode ("rlc", "a");
1984       emitcode ("subb", "a,acc");
1985       while (size--)
1986         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1987     }
1988
1989 release:
1990   /* release the aops */
1991   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1992   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1993 }
1994
1995 /*-----------------------------------------------------------------*/
1996 /* savermask - saves registers in the mask                         */
1997 /*-----------------------------------------------------------------*/
1998 static void savermask(bitVect *rs_mask)
1999 {
2000     int i;
2001     if (options.useXstack) {
2002         if (bitVectBitValue (rs_mask, R0_IDX))
2003             emitcode ("mov", "b,r0");
2004         emitcode ("mov", "r0,%s", spname);
2005         for (i = 0; i < ds390_nRegs; i++) {
2006             if (bitVectBitValue (rs_mask, i)) {
2007                 if (i == R0_IDX)
2008                     emitcode ("mov", "a,b");
2009                 else
2010                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2011                 emitcode ("movx", "@r0,a");
2012                 emitcode ("inc", "r0");
2013             }
2014         }
2015         emitcode ("mov", "%s,r0", spname);
2016         if (bitVectBitValue (rs_mask, R0_IDX))
2017             emitcode ("mov", "r0,b");
2018     } else {
2019         for (i = 0; i < ds390_nRegs; i++) {
2020             if (bitVectBitValue (rs_mask, i))
2021                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2022         }
2023     }
2024 }
2025
2026 /*-----------------------------------------------------------------*/
2027 /* saveRegisters - will look for a call and save the registers     */
2028 /*-----------------------------------------------------------------*/
2029 static void
2030 saveRegisters (iCode * lic)
2031 {
2032   iCode *ic;
2033   bitVect *rsave;
2034
2035   /* look for call */
2036   for (ic = lic; ic; ic = ic->next)
2037     if (ic->op == CALL || ic->op == PCALL)
2038       break;
2039
2040   if (!ic)
2041     {
2042       fprintf (stderr, "found parameter push with no function call\n");
2043       return;
2044     }
2045
2046   /* if the registers have been saved already then
2047      do nothing */
2048   if (ic->regsSaved 
2049       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2050     return ;
2051
2052   /* special case if DPTR alive across a function call then must save it 
2053      even though callee saves */
2054   if (IS_SYMOP(IC_LEFT(ic)) &&
2055       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2056       int i;
2057       rsave = newBitVect(ic->rMask->size);
2058       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2059           if (bitVectBitValue(ic->rMask,i))
2060               rsave = bitVectSetBit(rsave,i);
2061       }
2062       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2063   } else {
2064     /* safe the registers in use at this time but skip the
2065        ones for the result */
2066     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2067                            ds390_rUmaskForOp (IC_RESULT(ic)));
2068   }
2069   ic->regsSaved = 1;
2070   savermask(rsave);
2071 }
2072
2073 /*-----------------------------------------------------------------*/
2074 /* usavermask - restore registers with mask                        */
2075 /*-----------------------------------------------------------------*/
2076 static void unsavermask(bitVect *rs_mask)
2077 {
2078     int i;
2079     if (options.useXstack) {
2080         emitcode ("mov", "r0,%s", spname);
2081         for (i = ds390_nRegs; i >= 0; i--) {
2082             if (bitVectBitValue (rs_mask, i)) {
2083                 emitcode ("dec", "r0");
2084                 emitcode ("movx", "a,@r0");
2085                 if (i == R0_IDX)
2086                     emitcode ("mov", "b,a");
2087                 else
2088                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2089             }       
2090         }
2091         emitcode ("mov", "%s,r0", spname);
2092         if (bitVectBitValue (rs_mask, R0_IDX))
2093             emitcode ("mov", "r0,b");
2094     } else {
2095         for (i = ds390_nRegs; i >= 0; i--) {
2096             if (bitVectBitValue (rs_mask, i))
2097                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2098         }
2099     }
2100 }
2101
2102 /*-----------------------------------------------------------------*/
2103 /* unsaveRegisters - pop the pushed registers                      */
2104 /*-----------------------------------------------------------------*/
2105 static void
2106 unsaveRegisters (iCode * ic)
2107 {
2108   bitVect *rsave;
2109
2110   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2111       int i;
2112       rsave = newBitVect(ic->rMask->size);
2113       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2114           if (bitVectBitValue(ic->rMask,i))
2115               rsave = bitVectSetBit(rsave,i);
2116       }
2117       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2118   } else {
2119     /* restore the registers in use at this time but skip the
2120        ones for the result */
2121     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2122                            ds390_rUmaskForOp (IC_RESULT(ic)));
2123   }
2124   unsavermask(rsave);
2125 }
2126
2127
2128 /*-----------------------------------------------------------------*/
2129 /* pushSide -                */
2130 /*-----------------------------------------------------------------*/
2131 static void
2132 pushSide (operand * oper, int size)
2133 {
2134   int offset = 0;
2135   _startLazyDPSEvaluation ();
2136   while (size--)
2137     {
2138       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2139       if (AOP_TYPE (oper) != AOP_REG &&
2140           AOP_TYPE (oper) != AOP_DIR &&
2141           strcmp (l, "a"))
2142         {
2143           emitcode ("mov", "a,%s", l);
2144           emitcode ("push", "acc");
2145         }
2146       else
2147         emitcode ("push", "%s", l);
2148     }
2149   _endLazyDPSEvaluation ();
2150 }
2151
2152 /*-----------------------------------------------------------------*/
2153 /* assignResultValue -               */
2154 /*-----------------------------------------------------------------*/
2155 static void
2156 assignResultValue (operand * oper)
2157 {
2158   int offset = 0;
2159   int size = AOP_SIZE (oper);
2160   bool pushedAcc = FALSE;
2161
2162   if (size == fReturnSizeDS390)
2163   {
2164       /* I don't think this case can ever happen... */
2165       /* ACC is the last part of this. If writing the result
2166        * uses AC, we must preserve it.
2167        */
2168       if (AOP_NEEDSACC(oper))
2169       {
2170           emitcode(";", "assignResultValue special case for ACC.");
2171           emitcode("push", "acc");
2172           pushedAcc = TRUE;
2173           size--;
2174       }
2175   }
2176     
2177     
2178   _startLazyDPSEvaluation ();
2179   while (size--)
2180     {
2181       aopPut (AOP (oper), fReturn[offset], offset);
2182       offset++;
2183     }
2184   _endLazyDPSEvaluation ();
2185     
2186   if (pushedAcc)
2187     {
2188         emitcode("pop", "acc");
2189         aopPut(AOP(oper), "a", offset);
2190     }
2191 }
2192
2193
2194 /*-----------------------------------------------------------------*/
2195 /* genXpush - pushes onto the external stack                       */
2196 /*-----------------------------------------------------------------*/
2197 static void
2198 genXpush (iCode * ic)
2199 {
2200   asmop *aop = newAsmop (0);
2201   regs *r;
2202   int size, offset = 0;
2203
2204   D (emitcode (";", "genXpush ");
2205     );
2206
2207   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2208   r = getFreePtr (ic, &aop, FALSE);
2209
2210
2211   emitcode ("mov", "%s,_spx", r->name);
2212
2213   size = AOP_SIZE (IC_LEFT (ic));
2214   _startLazyDPSEvaluation ();
2215   while (size--)
2216     {
2217
2218       MOVA (aopGet (AOP (IC_LEFT (ic)),
2219                         offset++, FALSE, FALSE, NULL));
2220       emitcode ("movx", "@%s,a", r->name);
2221       emitcode ("inc", "%s", r->name);
2222
2223     }
2224   _endLazyDPSEvaluation ();
2225
2226
2227   emitcode ("mov", "_spx,%s", r->name);
2228
2229   freeAsmop (NULL, aop, ic, TRUE);
2230   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2231 }
2232
2233 /*-----------------------------------------------------------------*/
2234 /* genIpush - generate code for pushing this gets a little complex  */
2235 /*-----------------------------------------------------------------*/
2236 static void
2237 genIpush (iCode * ic)
2238 {
2239   int size, offset = 0;
2240   char *l;
2241
2242   D (emitcode (";", "genIpush ");
2243     );
2244
2245   /* if this is not a parm push : ie. it is spill push
2246      and spill push is always done on the local stack */
2247   if (!ic->parmPush)
2248     {
2249
2250       /* and the item is spilt then do nothing */
2251       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2252         return;
2253
2254       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2255       size = AOP_SIZE (IC_LEFT (ic));
2256       /* push it on the stack */
2257       _startLazyDPSEvaluation ();
2258       while (size--)
2259         {
2260           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2261           if (*l == '#')
2262             {
2263               MOVA (l);
2264               l = "acc";
2265             }
2266           emitcode ("push", "%s", l);
2267         }
2268       _endLazyDPSEvaluation ();
2269       return;
2270     }
2271
2272   /* this is a paramter push: in this case we call
2273      the routine to find the call and save those
2274      registers that need to be saved */
2275   saveRegisters (ic);
2276
2277   /* if use external stack then call the external
2278      stack pushing routine */
2279   if (options.useXstack)
2280     {
2281       genXpush (ic);
2282       return;
2283     }
2284
2285   /* then do the push */
2286   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2287
2288   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2289   size = AOP_SIZE (IC_LEFT (ic));
2290
2291   _startLazyDPSEvaluation ();
2292   while (size--)
2293     {
2294       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2295       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2296           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2297           strcmp (l, "acc"))
2298         {
2299           emitcode ("mov", "a,%s", l);
2300           emitcode ("push", "acc");
2301         }
2302       else
2303         {
2304             emitcode ("push", "%s", l);
2305         }
2306     }
2307   _endLazyDPSEvaluation ();
2308
2309   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2310 }
2311
2312 /*-----------------------------------------------------------------*/
2313 /* genIpop - recover the registers: can happen only for spilling   */
2314 /*-----------------------------------------------------------------*/
2315 static void
2316 genIpop (iCode * ic)
2317 {
2318   int size, offset;
2319
2320   D (emitcode (";", "genIpop ");
2321     );
2322
2323
2324   /* if the temp was not pushed then */
2325   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2326     return;
2327
2328   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2329   size = AOP_SIZE (IC_LEFT (ic));
2330   offset = (size - 1);
2331   _startLazyDPSEvaluation ();
2332   while (size--)
2333     {
2334       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2335                                      FALSE, TRUE, NULL));
2336     }
2337   _endLazyDPSEvaluation ();
2338
2339   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2340 }
2341
2342 /*-----------------------------------------------------------------*/
2343 /* unsaveRBank - restores the resgister bank from stack            */
2344 /*-----------------------------------------------------------------*/
2345 static void
2346 unsaveRBank (int bank, iCode * ic, bool popPsw)
2347 {
2348   int i;
2349   asmop *aop = NULL;
2350   regs *r = NULL;
2351
2352   if (options.useXstack)
2353   {
2354       if (!ic)
2355       {
2356           /* Assume r0 is available for use. */
2357           r = ds390_regWithIdx (R0_IDX);;          
2358       } 
2359       else
2360       {
2361           aop = newAsmop (0);
2362           r = getFreePtr (ic, &aop, FALSE);
2363       }
2364       emitcode ("mov", "%s,_spx", r->name);      
2365   }
2366   
2367   if (popPsw)
2368     {
2369       if (options.useXstack)
2370       {
2371           emitcode ("movx", "a,@%s", r->name);
2372           emitcode ("mov", "psw,a");
2373           emitcode ("dec", "%s", r->name);
2374         }
2375       else
2376       {
2377         emitcode ("pop", "psw");
2378       }
2379     }
2380
2381   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2382     {
2383       if (options.useXstack)
2384         {
2385           emitcode ("movx", "a,@%s", r->name);
2386           emitcode ("mov", "(%s+%d),a",
2387                     regs390[i].base, 8 * bank + regs390[i].offset);
2388           emitcode ("dec", "%s", r->name);
2389
2390         }
2391       else
2392         emitcode ("pop", "(%s+%d)",
2393                   regs390[i].base, 8 * bank + regs390[i].offset);
2394     }
2395
2396   if (options.useXstack)
2397     {
2398       emitcode ("mov", "_spx,%s", r->name);
2399     }
2400     
2401   if (aop)
2402   {
2403       freeAsmop (NULL, aop, ic, TRUE);  
2404   }    
2405 }
2406
2407 /*-----------------------------------------------------------------*/
2408 /* saveRBank - saves an entire register bank on the stack          */
2409 /*-----------------------------------------------------------------*/
2410 static void
2411 saveRBank (int bank, iCode * ic, bool pushPsw)
2412 {
2413   int i;
2414   asmop *aop = NULL;
2415   regs *r = NULL;
2416
2417   if (options.useXstack)
2418     {
2419         if (!ic)
2420         {
2421           /* Assume r0 is available for use. */
2422                   r = ds390_regWithIdx (R0_IDX);;
2423         }
2424         else
2425         {
2426           aop = newAsmop (0);
2427           r = getFreePtr (ic, &aop, FALSE);
2428         }
2429         emitcode ("mov", "%s,_spx", r->name);    
2430     }
2431
2432   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2433     {
2434       if (options.useXstack)
2435         {
2436           emitcode ("inc", "%s", r->name);
2437           emitcode ("mov", "a,(%s+%d)",
2438                     regs390[i].base, 8 * bank + regs390[i].offset);
2439           emitcode ("movx", "@%s,a", r->name);
2440         }
2441       else
2442         emitcode ("push", "(%s+%d)",
2443                   regs390[i].base, 8 * bank + regs390[i].offset);
2444     }
2445
2446   if (pushPsw)
2447     {
2448       if (options.useXstack)
2449         {
2450           emitcode ("mov", "a,psw");
2451           emitcode ("movx", "@%s,a", r->name);
2452           emitcode ("inc", "%s", r->name);
2453           emitcode ("mov", "_spx,%s", r->name);
2454         }
2455       else
2456       {
2457         emitcode ("push", "psw");
2458       }
2459
2460       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2461     }
2462   
2463   if (aop)
2464   {
2465        freeAsmop (NULL, aop, ic, TRUE);
2466   }    
2467     
2468   if (ic)
2469   {  
2470       ic->bankSaved = 1;
2471   }
2472 }
2473
2474 /*-----------------------------------------------------------------*/
2475 /* genSend - gen code for SEND                                     */
2476 /*-----------------------------------------------------------------*/
2477 static void genSend(set *sendSet)
2478 {
2479     iCode *sic;
2480     int sendCount = 0 ;
2481     static int rb1_count = 0;
2482
2483     for (sic = setFirstItem (sendSet); sic;
2484          sic = setNextItem (sendSet)) {     
2485         int size, offset = 0;
2486         
2487         size=getSize(operandType(IC_LEFT(sic)));
2488         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2489         if (sendCount == 0) { /* first parameter */
2490             // we know that dpl(hxb) is the result, so
2491             rb1_count = 0 ;
2492             _startLazyDPSEvaluation ();
2493             if (size>1) {
2494                 aopOp (IC_LEFT (sic), sic, FALSE, 
2495                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2496             } else {
2497                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2498             }
2499             while (size--) {
2500                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2501                                   FALSE, FALSE, NULL);
2502                 if (strcmp (l, fReturn[offset])) {
2503                     emitcode ("mov", "%s,%s",
2504                               fReturn[offset],
2505                               l);
2506                 }
2507                 offset++;
2508             }
2509             _endLazyDPSEvaluation ();
2510             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2511             rb1_count =0;
2512         } else { /* if more parameter in registers */
2513             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2514             while (size--) {
2515                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2516                                                                 FALSE, FALSE, NULL));
2517             }
2518             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2519         }
2520         sendCount++;
2521     }
2522 }
2523
2524 static void
2525 adjustEsp(const char *reg)
2526 {
2527     emitcode ("anl","%s,#3", reg);
2528     if (TARGET_IS_DS400)
2529     {
2530         emitcode ("orl","%s,#!constbyte",
2531                   reg,
2532                   (options.stack_loc >> 8) & 0xff);
2533     }
2534 }
2535
2536 /*-----------------------------------------------------------------*/
2537 /* genCall - generates a call statement                            */
2538 /*-----------------------------------------------------------------*/
2539 static void
2540 genCall (iCode * ic)
2541 {
2542   sym_link *dtype;
2543   bool restoreBank = FALSE;
2544   bool swapBanks = FALSE;
2545
2546   D (emitcode (";", "genCall "););
2547
2548   /* if we are calling a not _naked function that is not using
2549      the same register bank then we need to save the
2550      destination registers on the stack */
2551   dtype = operandType (IC_LEFT (ic));
2552   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2553       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2554       IFFUNC_ISISR (currFunc->type))
2555   {
2556       if (!ic->bankSaved) 
2557       {
2558            /* This is unexpected; the bank should have been saved in
2559             * genFunction.
2560             */
2561            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2562            restoreBank = TRUE;
2563       }
2564       swapBanks = TRUE;
2565   }
2566   
2567     /* if caller saves & we have not saved then */
2568     if (!ic->regsSaved)
2569       saveRegisters (ic);
2570   
2571   /* if send set is not empty the assign */
2572   /* We've saved all the registers we care about;
2573   * therefore, we may clobber any register not used
2574   * in the calling convention (i.e. anything not in
2575   * fReturn.
2576   */
2577   if (_G.sendSet)
2578     {
2579         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2580             genSend(reverseSet(_G.sendSet));
2581         } else {
2582             genSend(_G.sendSet);
2583         }
2584       _G.sendSet = NULL;
2585     }  
2586     
2587   if (swapBanks)
2588   {
2589         emitcode ("mov", "psw,#!constbyte", 
2590            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2591   }
2592
2593   /* make the call */
2594   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2595                             OP_SYMBOL (IC_LEFT (ic))->rname :
2596                             OP_SYMBOL (IC_LEFT (ic))->name));
2597
2598   if (swapBanks)
2599   {
2600        emitcode ("mov", "psw,#!constbyte", 
2601           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2602   }
2603
2604   /* if we need assign a result value */
2605   if ((IS_ITEMP (IC_RESULT (ic)) &&
2606        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2607         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2608         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2609       IS_TRUE_SYMOP (IC_RESULT (ic)))
2610     {
2611       if (isOperandInFarSpace (IC_RESULT (ic))
2612           && getSize (operandType (IC_RESULT (ic))) <= 2)
2613         {
2614           int size = getSize (operandType (IC_RESULT (ic)));
2615
2616           /* Special case for 1 or 2 byte return in far space. */
2617           MOVA (fReturn[0]);
2618           if (size > 1)
2619             {
2620               emitcode ("mov", "b,%s", fReturn[1]);
2621             }
2622
2623           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2624           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2625
2626           if (size > 1)
2627             {
2628               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2629             }
2630           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2631         }
2632       else
2633         {
2634           _G.accInUse++;
2635           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2636           _G.accInUse--;
2637
2638           assignResultValue (IC_RESULT (ic));
2639
2640           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2641         }
2642     }
2643
2644   /* adjust the stack for parameters if
2645      required */
2646   if (ic->parmBytes) {
2647       int i;
2648       if (options.stack10bit) {
2649           if (ic->parmBytes <= 10) {
2650               emitcode(";","stack adjustment for parms");
2651               for (i=0; i < ic->parmBytes ; i++) {
2652                   emitcode("pop","acc");
2653               }
2654           } else {            
2655               PROTECT_SP;
2656               emitcode ("clr","c");
2657               emitcode ("mov","a,sp");
2658               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2659               emitcode ("mov","sp,a");
2660               emitcode ("mov","a,esp");
2661               adjustEsp("a");
2662               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2663               emitcode ("mov","esp,a");   
2664               UNPROTECT_SP;
2665           }
2666       } else {
2667           if (ic->parmBytes > 3) {
2668               emitcode ("mov", "a,%s", spname);
2669               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2670               emitcode ("mov", "%s,a", spname);
2671           } else
2672               for (i = 0; i < ic->parmBytes; i++)
2673                   emitcode ("dec", "%s", spname);
2674       }
2675   }
2676
2677   /* if we hade saved some registers then unsave them */
2678   if (ic->regsSaved)
2679     unsaveRegisters (ic);
2680
2681   /* if register bank was saved then pop them */
2682   if (restoreBank)
2683     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2684 }
2685
2686 /*-----------------------------------------------------------------*/
2687 /* genPcall - generates a call by pointer statement                */
2688 /*-----------------------------------------------------------------*/
2689 static void
2690 genPcall (iCode * ic)
2691 {
2692   sym_link *dtype;
2693   symbol *rlbl = newiTempLabel (NULL);
2694   bool restoreBank=FALSE;
2695
2696   D (emitcode (";", "genPcall ");
2697     );
2698
2699
2700   /* if caller saves & we have not saved then */
2701   if (!ic->regsSaved)
2702     saveRegisters (ic);
2703
2704   /* if we are calling a function that is not using
2705      the same register bank then we need to save the
2706      destination registers on the stack */
2707   dtype = operandType (IC_LEFT (ic));
2708   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2709       IFFUNC_ISISR (currFunc->type) &&
2710       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2711     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2712     restoreBank=TRUE;
2713   }
2714
2715   /* push the return address on to the stack */
2716   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2717   emitcode ("push", "acc");
2718   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2719   emitcode ("push", "acc");
2720
2721   if (options.model == MODEL_FLAT24)
2722     {
2723       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2724       emitcode ("push", "acc");
2725     }
2726
2727   /* now push the calling address */
2728   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2729
2730   pushSide (IC_LEFT (ic), FPTRSIZE);
2731
2732   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2733
2734   /* if send set is not empty the assign */
2735   if (_G.sendSet)
2736     {
2737         genSend(reverseSet(_G.sendSet));
2738         _G.sendSet = NULL;
2739     }
2740
2741   emitcode ("ret", "");
2742   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2743
2744
2745   /* if we need assign a result value */
2746   if ((IS_ITEMP (IC_RESULT (ic)) &&
2747        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2748         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2749       IS_TRUE_SYMOP (IC_RESULT (ic)))
2750     {
2751
2752       _G.accInUse++;
2753       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2754       _G.accInUse--;
2755
2756       assignResultValue (IC_RESULT (ic));
2757
2758       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2759     }
2760
2761   /* adjust the stack for parameters if
2762      required */
2763   if (ic->parmBytes)
2764     {
2765       int i;
2766       if (options.stack10bit) {
2767           if (ic->parmBytes <= 10) {
2768               emitcode(";","stack adjustment for parms");
2769               for (i=0; i < ic->parmBytes ; i++) {
2770                   emitcode("pop","acc");
2771               }
2772           } else {            
2773               PROTECT_SP;
2774               emitcode ("clr","c");
2775               emitcode ("mov","a,sp");
2776               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2777               emitcode ("mov","sp,a");
2778               emitcode ("mov","a,esp");
2779               adjustEsp("a");
2780               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2781               emitcode ("mov","esp,a");   
2782               UNPROTECT_SP;
2783           }
2784       } else {
2785           if (ic->parmBytes > 3) {
2786               emitcode ("mov", "a,%s", spname);
2787               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2788               emitcode ("mov", "%s,a", spname);
2789           }
2790           else
2791               for (i = 0; i < ic->parmBytes; i++)
2792                   emitcode ("dec", "%s", spname);
2793           
2794       }
2795     }
2796   /* if register bank was saved then unsave them */
2797   if (restoreBank)
2798     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2799   
2800   /* if we hade saved some registers then
2801      unsave them */
2802   if (ic->regsSaved)
2803     unsaveRegisters (ic);
2804
2805 }
2806
2807 /*-----------------------------------------------------------------*/
2808 /* resultRemat - result  is rematerializable                       */
2809 /*-----------------------------------------------------------------*/
2810 static int
2811 resultRemat (iCode * ic)
2812 {
2813   if (SKIP_IC (ic) || ic->op == IFX)
2814     return 0;
2815
2816   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2817     {
2818       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2819       if (sym->remat && !POINTER_SET (ic))
2820         return 1;
2821     }
2822
2823   return 0;
2824 }
2825
2826 #if defined(__BORLANDC__) || defined(_MSC_VER)
2827 #define STRCASECMP stricmp
2828 #else
2829 #define STRCASECMP strcasecmp
2830 #endif
2831
2832 /*-----------------------------------------------------------------*/
2833 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2834 /*-----------------------------------------------------------------*/
2835 static int
2836 regsCmp(void *p1, void *p2)
2837 {
2838   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2839 }
2840
2841 static bool
2842 inExcludeList (char *s)
2843 {
2844   const char *p = setFirstItem(options.excludeRegsSet);
2845
2846   if (p == NULL || STRCASECMP(p, "none") == 0)
2847     return FALSE;
2848
2849
2850   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2851 }
2852
2853 /*-----------------------------------------------------------------*/
2854 /* genFunction - generated code for function entry                 */
2855 /*-----------------------------------------------------------------*/
2856 static void
2857 genFunction (iCode * ic)
2858 {
2859   symbol *sym;
2860   sym_link *ftype;
2861   bool   switchedPSW = FALSE;
2862
2863   D (emitcode (";", "genFunction "););
2864
2865   _G.nRegsSaved = 0;
2866   /* create the function header */
2867   emitcode (";", "-----------------------------------------");
2868   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2869   emitcode (";", "-----------------------------------------");
2870
2871   emitcode ("", "%s:", sym->rname);
2872   ftype = operandType (IC_LEFT (ic));
2873
2874   if (IFFUNC_ISNAKED(ftype))
2875   {
2876       emitcode(";", "naked function: no prologue.");
2877       return;
2878   }
2879   
2880   if (options.stack_probe) 
2881       emitcode ("lcall","__stack_probe");
2882   /* if critical function then turn interrupts off */
2883   if (IFFUNC_ISCRITICAL (ftype))
2884     emitcode ("clr", "ea");
2885
2886   /* here we need to generate the equates for the
2887      register bank if required */
2888   if (FUNC_REGBANK (ftype) != rbank)
2889     {
2890       int i;
2891
2892       rbank = FUNC_REGBANK (ftype);
2893       for (i = 0; i < ds390_nRegs; i++)
2894         {
2895           if (regs390[i].print) {
2896               if (strcmp (regs390[i].base, "0") == 0)
2897                   emitcode ("", "%s !equ !constbyte",
2898                             regs390[i].dname,
2899                             8 * rbank + regs390[i].offset);
2900               else
2901                   emitcode ("", "%s !equ %s + !constbyte",
2902                             regs390[i].dname,
2903                             regs390[i].base,
2904                             8 * rbank + regs390[i].offset);
2905           }
2906         }
2907     }
2908
2909   /* if this is an interrupt service routine then
2910      save acc, b, dpl, dph  */
2911   if (IFFUNC_ISISR (sym->type))
2912       { /* is ISR */
2913       if (!inExcludeList ("acc"))
2914         emitcode ("push", "acc");
2915       if (!inExcludeList ("b"))
2916         emitcode ("push", "b");
2917       if (!inExcludeList ("dpl"))
2918         emitcode ("push", "dpl");
2919       if (!inExcludeList ("dph"))
2920         emitcode ("push", "dph");
2921       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2922         {
2923           emitcode ("push", "dpx");
2924           /* Make sure we're using standard DPTR */
2925           emitcode ("push", "dps");
2926           emitcode ("mov", "dps,#0");
2927           if (options.stack10bit)
2928             {
2929               /* This ISR could conceivably use DPTR2. Better save it. */
2930               emitcode ("push", "dpl1");
2931               emitcode ("push", "dph1");
2932               emitcode ("push", "dpx1");
2933               emitcode ("push",  DP2_RESULT_REG);
2934             }
2935         }
2936       /* if this isr has no bank i.e. is going to
2937          run with bank 0 , then we need to save more
2938          registers :-) */
2939       if (!FUNC_REGBANK (sym->type))
2940         {
2941             int i;
2942
2943           /* if this function does not call any other
2944              function then we can be economical and
2945              save only those registers that are used */
2946           if (!IFFUNC_HASFCALL(sym->type))
2947             {
2948
2949               /* if any registers used */
2950               if (sym->regsUsed)
2951                 {
2952                   /* save the registers used */
2953                   for (i = 0; i < sym->regsUsed->size; i++)
2954                     {
2955                       if (bitVectBitValue (sym->regsUsed, i) ||
2956                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2957                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2958                     }
2959                 }
2960
2961             }
2962           else
2963             {
2964               /* this function has  a function call cannot
2965                  determines register usage so we will have to push the
2966                  entire bank */
2967               saveRBank (0, ic, FALSE);
2968               if (options.parms_in_bank1) {
2969                   for (i=0; i < 8 ; i++ ) {
2970                       emitcode ("push","%s",rb1regs[i]);
2971                   }
2972               }
2973             }
2974         }
2975         else
2976         {
2977             /* This ISR uses a non-zero bank.
2978              *
2979              * We assume that the bank is available for our
2980              * exclusive use.
2981              *
2982              * However, if this ISR calls a function which uses some
2983              * other bank, we must save that bank entirely.
2984              */
2985             unsigned long banksToSave = 0;
2986             
2987             if (IFFUNC_HASFCALL(sym->type))
2988             {
2989
2990 #define MAX_REGISTER_BANKS 4
2991
2992                 iCode *i;
2993                 int ix;
2994
2995                 for (i = ic; i; i = i->next)
2996                 {
2997                     if (i->op == ENDFUNCTION)
2998                     {
2999                         /* we got to the end OK. */
3000                         break;
3001                     }
3002                     
3003                     if (i->op == CALL)
3004                     {
3005                         sym_link *dtype;
3006                         
3007                         dtype = operandType (IC_LEFT(i));
3008                         if (dtype 
3009                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3010                         {
3011                              /* Mark this bank for saving. */
3012                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3013                              {
3014                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3015                              }
3016                              else
3017                              {
3018                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3019                              }
3020                              
3021                              /* And note that we don't need to do it in 
3022                               * genCall.
3023                               */
3024                              i->bankSaved = 1;
3025                         }
3026                     }
3027                     if (i->op == PCALL)
3028                     {
3029                         /* This is a mess; we have no idea what
3030                          * register bank the called function might
3031                          * use.
3032                          *
3033                          * The only thing I can think of to do is
3034                          * throw a warning and hope.
3035                          */
3036                         werror(W_FUNCPTR_IN_USING_ISR);   
3037                     }
3038                 }
3039
3040                 if (banksToSave && options.useXstack)
3041                 {
3042                     /* Since we aren't passing it an ic, 
3043                      * saveRBank will assume r0 is available to abuse.
3044                      *
3045                      * So switch to our (trashable) bank now, so
3046                      * the caller's R0 isn't trashed.
3047                      */
3048                     emitcode ("push", "psw");
3049                     emitcode ("mov", "psw,#!constbyte", 
3050                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3051                     switchedPSW = TRUE;
3052                 }
3053                 
3054                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3055                 {
3056                      if (banksToSave & (1 << ix))
3057                      {
3058                          saveRBank(ix, NULL, FALSE);
3059                      }
3060                 }
3061             }
3062             // TODO: this needs a closer look
3063             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3064         }
3065     }
3066   else
3067     {
3068       /* if callee-save to be used for this function
3069          then save the registers being used in this function */
3070       if (IFFUNC_CALLEESAVES(sym->type))
3071         {
3072           int i;
3073
3074           /* if any registers used */
3075           if (sym->regsUsed)
3076             {
3077               /* save the registers used */
3078               for (i = 0; i < sym->regsUsed->size; i++)
3079                 {
3080                   if (bitVectBitValue (sym->regsUsed, i) ||
3081                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3082                     {
3083                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3084                       _G.nRegsSaved++;
3085                     }
3086                 }
3087             }
3088         }
3089     }
3090
3091   /* set the register bank to the desired value */
3092   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3093    && !switchedPSW)
3094     {
3095       emitcode ("push", "psw");
3096       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3097     }
3098
3099   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3100        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3101       if (options.stack10bit) {
3102           emitcode ("push","_bpx");
3103           emitcode ("push","_bpx+1");
3104           emitcode ("mov","_bpx,%s",spname);
3105           emitcode ("mov","_bpx+1,esp");
3106           adjustEsp("_bpx+1");
3107       } else {
3108           if (options.useXstack) {
3109               emitcode ("mov", "r0,%s", spname);
3110               emitcode ("mov", "a,_bp");
3111               emitcode ("movx", "@r0,a");
3112               emitcode ("inc", "%s", spname);
3113           } else {
3114               /* set up the stack */
3115               emitcode ("push", "_bp"); /* save the callers stack  */
3116           }
3117           emitcode ("mov", "_bp,%s", spname);
3118       }
3119   }
3120
3121   /* adjust the stack for the function */
3122   if (sym->stack) {
3123       int i = sym->stack;
3124       if (options.stack10bit) {
3125           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3126           assert (sym->recvSize <= 4);
3127           if (sym->stack <= 8) {
3128               while (i--) emitcode ("push","acc");
3129           } else {
3130               PROTECT_SP;
3131               emitcode ("mov","a,sp");
3132               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3133               emitcode ("mov","sp,a");
3134               emitcode ("mov","a,esp");
3135               adjustEsp("a");
3136               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3137               emitcode ("mov","esp,a");
3138               UNPROTECT_SP;
3139           }
3140       } else {
3141           if (i > 256)
3142               werror (W_STACK_OVERFLOW, sym->name);
3143           
3144           if (i > 3 && sym->recvSize < 4) {
3145               
3146               emitcode ("mov", "a,sp");
3147               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3148               emitcode ("mov", "sp,a");
3149               
3150           } else
3151               while (i--)
3152                   emitcode ("inc", "sp");
3153       }
3154   }
3155
3156   if (sym->xstack)
3157     {
3158
3159       emitcode ("mov", "a,_spx");
3160       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3161       emitcode ("mov", "_spx,a");
3162     }
3163
3164 }
3165
3166 /*-----------------------------------------------------------------*/
3167 /* genEndFunction - generates epilogue for functions               */
3168 /*-----------------------------------------------------------------*/
3169 static void
3170 genEndFunction (iCode * ic)
3171 {
3172   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3173
3174   D (emitcode (";", "genEndFunction "););
3175
3176   if (IFFUNC_ISNAKED(sym->type))
3177   {
3178       emitcode(";", "naked function: no epilogue.");
3179       return;
3180   }
3181
3182   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3183        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3184
3185       if (options.stack10bit) {
3186           PROTECT_SP;     
3187           emitcode ("mov", "sp,_bpx", spname);
3188           emitcode ("mov", "esp,_bpx+1", spname);
3189           UNPROTECT_SP;
3190       } else {
3191           emitcode ("mov", "%s,_bp", spname);
3192       }
3193   }
3194
3195   /* if use external stack but some variables were
3196      added to the local stack then decrement the
3197      local stack */
3198   if (options.useXstack && sym->stack) {
3199       emitcode ("mov", "a,sp");
3200       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3201       emitcode ("mov", "sp,a");
3202   }
3203
3204
3205   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3206        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3207
3208       if (options.useXstack) {
3209           emitcode ("mov", "r0,%s", spname);
3210           emitcode ("movx", "a,@r0");
3211           emitcode ("mov", "_bp,a");
3212           emitcode ("dec", "%s", spname);
3213       } else {
3214           if (options.stack10bit) {
3215               emitcode ("pop", "_bpx+1");
3216               emitcode ("pop", "_bpx");
3217           } else {
3218               emitcode ("pop", "_bp");
3219           }
3220       }
3221   }
3222
3223   /* restore the register bank  */
3224   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3225   {
3226     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3227      || !options.useXstack)
3228     {
3229         /* Special case of ISR using non-zero bank with useXstack
3230          * is handled below.
3231          */
3232         emitcode ("pop", "psw");
3233     }
3234   } 
3235
3236   if (IFFUNC_ISISR (sym->type))
3237       { /* is ISR */  
3238
3239       /* now we need to restore the registers */
3240       /* if this isr has no bank i.e. is going to
3241          run with bank 0 , then we need to save more
3242          registers :-) */
3243       if (!FUNC_REGBANK (sym->type))
3244         {
3245             int i;
3246           /* if this function does not call any other
3247              function then we can be economical and
3248              save only those registers that are used */
3249           if (!IFFUNC_HASFCALL(sym->type))
3250             {
3251
3252               /* if any registers used */
3253               if (sym->regsUsed)
3254                 {
3255                   /* save the registers used */
3256                   for (i = sym->regsUsed->size; i >= 0; i--)
3257                     {
3258                       if (bitVectBitValue (sym->regsUsed, i) ||
3259                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3260                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3261                     }
3262                 }
3263
3264             }
3265           else
3266             {
3267               /* this function has  a function call cannot
3268                  determines register usage so we will have to pop the
3269                  entire bank */
3270               if (options.parms_in_bank1) {
3271                   for (i = 7 ; i >= 0 ; i-- ) {
3272                       emitcode ("pop","%s",rb1regs[i]);
3273                   }
3274               }
3275               unsaveRBank (0, ic, FALSE);
3276             }
3277         }
3278         else
3279         {
3280             /* This ISR uses a non-zero bank.
3281              *
3282              * Restore any register banks saved by genFunction
3283              * in reverse order.
3284              */
3285             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3286             int ix;
3287           
3288             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3289             {
3290                 if (savedBanks & (1 << ix))
3291                 {
3292                     unsaveRBank(ix, NULL, FALSE);
3293                 }
3294             }
3295             
3296             if (options.useXstack)
3297             {
3298                 /* Restore bank AFTER calling unsaveRBank,
3299                  * since it can trash r0.
3300                  */
3301                 emitcode ("pop", "psw");
3302             }
3303         }
3304
3305       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3306         {
3307           if (options.stack10bit)
3308             {
3309               emitcode ("pop", DP2_RESULT_REG);
3310               emitcode ("pop", "dpx1");
3311               emitcode ("pop", "dph1");
3312               emitcode ("pop", "dpl1");
3313             }
3314           emitcode ("pop", "dps");
3315           emitcode ("pop", "dpx");
3316         }
3317       if (!inExcludeList ("dph"))
3318         emitcode ("pop", "dph");
3319       if (!inExcludeList ("dpl"))
3320         emitcode ("pop", "dpl");
3321       if (!inExcludeList ("b"))
3322         emitcode ("pop", "b");
3323       if (!inExcludeList ("acc"))
3324         emitcode ("pop", "acc");
3325
3326       if (IFFUNC_ISCRITICAL (sym->type))
3327         emitcode ("setb", "ea");
3328
3329       /* if debug then send end of function */
3330       if (options.debug && currFunc) {
3331           _G.debugLine = 1;
3332           emitcode ("", "C$%s$%d$%d$%d ==.",
3333                     FileBaseName (ic->filename), currFunc->lastLine,
3334                     ic->level, ic->block);
3335           if (IS_STATIC (currFunc->etype))
3336             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3337           else
3338             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3339           _G.debugLine = 0;
3340         }
3341
3342       emitcode ("reti", "");
3343     }
3344   else
3345     {
3346       if (IFFUNC_ISCRITICAL (sym->type))
3347         emitcode ("setb", "ea");
3348
3349       if (IFFUNC_CALLEESAVES(sym->type))
3350         {
3351           int i;
3352
3353           /* if any registers used */
3354           if (sym->regsUsed)
3355             {
3356               /* save the registers used */
3357               for (i = sym->regsUsed->size; i >= 0; i--)
3358                 {
3359                   if (bitVectBitValue (sym->regsUsed, i) ||
3360                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3361                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3362                 }
3363             }
3364
3365         }
3366
3367       /* if debug then send end of function */
3368       if (options.debug && currFunc)
3369         {
3370           _G.debugLine = 1;
3371           emitcode ("", "C$%s$%d$%d$%d ==.",
3372                     FileBaseName (ic->filename), currFunc->lastLine,
3373                     ic->level, ic->block);
3374           if (IS_STATIC (currFunc->etype))
3375             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3376           else
3377             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3378           _G.debugLine = 0;
3379         }
3380
3381       emitcode ("ret", "");
3382     }
3383
3384 }
3385
3386 /*-----------------------------------------------------------------*/
3387 /* genJavaNativeRet - generate code for return JavaNative          */
3388 /*-----------------------------------------------------------------*/
3389 static void genJavaNativeRet(iCode *ic)
3390 {
3391     int i, size;
3392
3393     aopOp (IC_LEFT (ic), ic, FALSE, 
3394            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3395     size = AOP_SIZE (IC_LEFT (ic));
3396
3397     assert (size <= 4);
3398
3399     /* it is assigned to GPR0-R3 then push them */
3400     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3401         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3402         for (i = 0 ; i < size ; i++ ) {
3403             emitcode ("push","%s",
3404                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3405         }
3406         for (i = (size-1) ; i >= 0 ; i--) {
3407             emitcode ("pop","a%s",javaRet[i]);
3408         }
3409     } else {
3410         for (i = 0 ; i < size ; i++) 
3411             emitcode ("mov","%s,%s",javaRet[i],
3412                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3413     }
3414     for (i = size ; i < 4 ; i++ )
3415             emitcode ("mov","%s,#0",javaRet[i]);
3416     return;
3417 }
3418
3419 /*-----------------------------------------------------------------*/
3420 /* genRet - generate code for return statement                     */
3421 /*-----------------------------------------------------------------*/
3422 static void
3423 genRet (iCode * ic)
3424 {
3425   int size, offset = 0, pushed = 0;
3426
3427   D (emitcode (";", "genRet "););
3428
3429   /* if we have no return value then
3430      just generate the "ret" */
3431   if (!IC_LEFT (ic))
3432     goto jumpret;
3433
3434   /* if this is a JavaNative function then return 
3435      value in different register */
3436   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3437       genJavaNativeRet(ic);
3438       goto jumpret;
3439   }
3440   /* we have something to return then
3441      move the return value into place */
3442   aopOp (IC_LEFT (ic), ic, FALSE, 
3443          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3444   size = AOP_SIZE (IC_LEFT (ic));
3445
3446   _startLazyDPSEvaluation ();
3447   while (size--)
3448     {
3449       char *l;
3450       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3451         {
3452           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3453                       FALSE, TRUE, NULL);
3454           emitcode ("push", "%s", l);
3455           pushed++;
3456         }
3457       else
3458         {
3459           /* Since A is the last element of fReturn,
3460            * is is OK to clobber it in the aopGet.
3461            */
3462           l = aopGet (AOP (IC_LEFT (ic)), offset,
3463                       FALSE, FALSE, NULL);
3464           if (strcmp (fReturn[offset], l))
3465             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3466         }
3467     }
3468   _endLazyDPSEvaluation ();
3469
3470   if (pushed)
3471     {
3472       while (pushed)
3473         {
3474           pushed--;
3475           if (strcmp (fReturn[pushed], "a"))
3476             emitcode ("pop", fReturn[pushed]);
3477           else
3478             emitcode ("pop", "acc");
3479         }
3480     }
3481   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3482
3483 jumpret:
3484   /* generate a jump to the return label
3485      if the next is not the return statement */
3486   if (!(ic->next && ic->next->op == LABEL &&
3487         IC_LABEL (ic->next) == returnLabel))
3488
3489     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3490
3491 }
3492
3493 /*-----------------------------------------------------------------*/
3494 /* genLabel - generates a label                                    */
3495 /*-----------------------------------------------------------------*/
3496 static void
3497 genLabel (iCode * ic)
3498 {
3499   /* special case never generate */
3500   if (IC_LABEL (ic) == entryLabel)
3501     return;
3502
3503   D (emitcode (";", "genLabel ");
3504     );
3505
3506   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3507 }
3508
3509 /*-----------------------------------------------------------------*/
3510 /* genGoto - generates a ljmp                                      */
3511 /*-----------------------------------------------------------------*/
3512 static void
3513 genGoto (iCode * ic)
3514 {
3515   D (emitcode (";", "genGoto ");
3516     );
3517   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3518 }
3519
3520 /*-----------------------------------------------------------------*/
3521 /* findLabelBackwards: walks back through the iCode chain looking  */
3522 /* for the given label. Returns number of iCode instructions     */
3523 /* between that label and given ic.          */
3524 /* Returns zero if label not found.          */
3525 /*-----------------------------------------------------------------*/
3526 static int
3527 findLabelBackwards (iCode * ic, int key)
3528 {
3529   int count = 0;
3530
3531   while (ic->prev)
3532     {
3533       ic = ic->prev;
3534       count++;
3535
3536       /* If we have any pushes or pops, we cannot predict the distance.
3537          I don't like this at all, this should be dealt with in the 
3538          back-end */
3539       if (ic->op == IPUSH || ic->op == IPOP) {
3540         return 0;
3541       }
3542
3543       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3544         {
3545           /* printf("findLabelBackwards = %d\n", count); */
3546           return count;
3547         }
3548     }
3549
3550   return 0;
3551 }
3552
3553 /*-----------------------------------------------------------------*/
3554 /* genPlusIncr :- does addition with increment if possible         */
3555 /*-----------------------------------------------------------------*/
3556 static bool
3557 genPlusIncr (iCode * ic)
3558 {
3559   unsigned int icount;
3560   unsigned int size = getDataSize (IC_RESULT (ic));
3561
3562   /* will try to generate an increment */
3563   /* if the right side is not a literal
3564      we cannot */
3565   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3566     return FALSE;
3567
3568   /* if the literal value of the right hand side
3569      is greater than 4 then it is not worth it */
3570   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3571     return FALSE;
3572
3573   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3574       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3575       while (icount--) {
3576           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3577       }
3578       return TRUE;
3579   }
3580   /* if increment 16 bits in register */
3581   if (
3582        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3583        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3584        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3585        (size > 1) &&
3586        (icount == 1))
3587     {
3588       symbol  *tlbl;
3589       int     emitTlbl;
3590       int     labelRange;
3591       char    *l;
3592
3593       /* If the next instruction is a goto and the goto target
3594        * is <= 5 instructions previous to this, we can generate
3595        * jumps straight to that target.
3596        */
3597       if (ic->next && ic->next->op == GOTO
3598           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3599           && labelRange <= 5)
3600         {
3601           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3602           tlbl = IC_LABEL (ic->next);
3603           emitTlbl = 0;
3604         }
3605       else
3606         {
3607           tlbl = newiTempLabel (NULL);
3608           emitTlbl = 1;
3609         }
3610         
3611       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3612       emitcode ("inc", "%s", l);
3613       
3614       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3615           IS_AOP_PREG (IC_RESULT (ic)))
3616       {   
3617         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3618       }
3619       else
3620       {
3621           emitcode ("clr", "a");
3622           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3623       }
3624
3625       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3626       emitcode ("inc", "%s", l);
3627       if (size > 2)
3628         {
3629             if (!strcmp(l, "acc"))
3630             {
3631                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3632             }
3633             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3634                      IS_AOP_PREG (IC_RESULT (ic)))
3635             {
3636                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3637             }
3638             else
3639             {
3640                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3641             }
3642
3643             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3644             emitcode ("inc", "%s", l);
3645         }
3646       if (size > 3)
3647         {
3648             if (!strcmp(l, "acc"))
3649             {
3650                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3651             }
3652             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3653                      IS_AOP_PREG (IC_RESULT (ic)))
3654             {
3655                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3656             }
3657             else
3658             {
3659                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3660             }
3661
3662             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3663             emitcode ("inc", "%s", l);  }
3664
3665       if (emitTlbl)
3666         {
3667           emitcode ("", "!tlabeldef", tlbl->key + 100);
3668         }
3669       return TRUE;
3670     }
3671
3672   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3673       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3674       options.model == MODEL_FLAT24 ) {
3675
3676       switch (size) {
3677       case 3:
3678           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3679       case 2:
3680           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3681       case 1:
3682           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3683           break;
3684       }
3685       while (icount--) emitcode ("inc","dptr");      
3686       return TRUE;
3687   }
3688
3689   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3690       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3691       icount <= 5 ) {
3692       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3693       while (icount--) emitcode ("inc","dptr");
3694       emitcode ("mov","dps,#0");
3695       return TRUE;
3696   }
3697
3698   /* if the sizes are greater than 1 then we cannot */
3699   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3700       AOP_SIZE (IC_LEFT (ic)) > 1)
3701     return FALSE;
3702
3703   /* we can if the aops of the left & result match or
3704      if they are in registers and the registers are the
3705      same */
3706   if (
3707        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3708        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3709        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3710     {
3711
3712       if (icount > 3)
3713         {
3714           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3715           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3716           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3717         }
3718       else
3719         {
3720
3721           _startLazyDPSEvaluation ();
3722           while (icount--)
3723             {
3724               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3725             }
3726           _endLazyDPSEvaluation ();
3727         }
3728
3729       return TRUE;
3730     }
3731
3732   return FALSE;
3733 }
3734
3735 /*-----------------------------------------------------------------*/
3736 /* outBitAcc - output a bit in acc                                 */
3737 /*-----------------------------------------------------------------*/
3738 static void
3739 outBitAcc (operand * result)
3740 {
3741   symbol *tlbl = newiTempLabel (NULL);
3742   /* if the result is a bit */
3743   if (AOP_TYPE (result) == AOP_CRY)
3744     {
3745       aopPut (AOP (result), "a", 0);
3746     }
3747   else
3748     {
3749       emitcode ("jz", "!tlabel", tlbl->key + 100);
3750       emitcode ("mov", "a,%s", one);
3751       emitcode ("", "!tlabeldef", tlbl->key + 100);
3752       outAcc (result);
3753     }
3754 }
3755
3756 /*-----------------------------------------------------------------*/
3757 /* genPlusBits - generates code for addition of two bits           */
3758 /*-----------------------------------------------------------------*/
3759 static void
3760 genPlusBits (iCode * ic)
3761 {
3762   D (emitcode (";", "genPlusBits "););
3763     
3764   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3765     {
3766       symbol *lbl = newiTempLabel (NULL);
3767       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3768       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3769       emitcode ("cpl", "c");
3770       emitcode ("", "!tlabeldef", (lbl->key + 100));
3771       outBitC (IC_RESULT (ic));
3772     }
3773   else
3774     {
3775       emitcode ("clr", "a");
3776       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3777       emitcode ("rlc", "a");
3778       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3779       emitcode ("addc", "a,#0");
3780       outAcc (IC_RESULT (ic));
3781     }
3782 }
3783
3784 static void
3785 adjustArithmeticResult (iCode * ic)
3786 {
3787   if (opIsGptr (IC_RESULT (ic)) &&
3788       opIsGptr (IC_LEFT (ic)) &&
3789       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3790     {
3791       aopPut (AOP (IC_RESULT (ic)),
3792               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3793               GPTRSIZE - 1);
3794     }
3795
3796   if (opIsGptr (IC_RESULT (ic)) &&
3797       opIsGptr (IC_RIGHT (ic)) &&
3798       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3799     {
3800       aopPut (AOP (IC_RESULT (ic)),
3801             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3802               GPTRSIZE - 1);
3803     }
3804
3805   if (opIsGptr (IC_RESULT (ic)) &&
3806       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3807       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3808       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3809       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3810     {
3811       char buff[5];
3812       SNPRINTF (buff, sizeof(buff), 
3813                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3814       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3815     }
3816 }
3817
3818 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3819 // generates the result if possible. If result is generated, returns TRUE; otherwise
3820 // returns false and caller must deal with fact that result isn't aopOp'd.
3821 bool aopOp3(iCode * ic)
3822 {
3823     bool dp1InUse, dp2InUse;
3824     bool useDp2;
3825     
3826     // First, generate the right opcode. DPTR may be used if neither left nor result are
3827     // of type AOP_STR.
3828     
3829 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3830 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3831 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3832 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3833 //      );
3834 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3835 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3836 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3837 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3838 //      );
3839     
3840     // Right uses DPTR unless left or result is an AOP_STR; however,
3841     // if right is an AOP_STR, it must use DPTR regardless.
3842     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3843      && !AOP_IS_STR(IC_RIGHT(ic)))
3844     {
3845         useDp2 = TRUE;
3846     }
3847     else
3848     {
3849         useDp2 = FALSE;
3850     }
3851         
3852     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3853     
3854     // if the right used DPTR, left MUST use DPTR2.
3855     // if the right used DPTR2, left MUST use DPTR.
3856     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3857     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3858     // enabling us to assign DPTR to result.
3859      
3860     if (AOP_USESDPTR(IC_RIGHT(ic)))
3861     {
3862         useDp2 = TRUE;
3863     }
3864     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3865     {
3866         useDp2 = FALSE;
3867     }
3868     else
3869     {
3870         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3871         {
3872             useDp2 = TRUE;
3873         }
3874         else
3875         {
3876             useDp2 = FALSE;
3877         }
3878     }
3879
3880     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3881     
3882     // We've op'd the left & right. So, if left or right are the same operand as result, 
3883     // we know aopOp will succeed, and we can just do it & bail.
3884     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3885         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3886     {
3887 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3888         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3889         return TRUE;
3890     }
3891     
3892     // Note which dptrs are currently in use.
3893     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3894     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3895     
3896     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3897     // generate it.
3898     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3899     {
3900         return FALSE;
3901     }
3902     
3903     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3904     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3905     {
3906         return FALSE;
3907     }
3908     
3909     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3910     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3911     {
3912         return FALSE;
3913     }
3914
3915     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3916
3917     // Some sanity checking...
3918     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3919     {
3920         fprintf(stderr,
3921                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3922                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3923         emitcode(";", ">>> unexpected DPTR here.");
3924     }
3925     
3926     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3927     {
3928         fprintf(stderr,
3929                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3930                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3931         emitcode(";", ">>> unexpected DPTR2 here.");
3932     }    
3933     
3934     return TRUE;
3935 }
3936
3937 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3938 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3939 // will be set TRUE. The caller must then handle the case specially, noting
3940 // that the IC_RESULT operand is not aopOp'd.
3941 // 
3942 #define AOP_OP_3_NOFATAL(ic, rc) \
3943             do { rc = !aopOp3(ic); } while (0)
3944
3945 // aopOp the left & right operands of an ic.
3946 #define AOP_OP_2(ic) \
3947     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3948     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3949
3950 // convienience macro.
3951 #define AOP_SET_LOCALS(ic) \
3952     left = IC_LEFT(ic); \
3953     right = IC_RIGHT(ic); \
3954     result = IC_RESULT(ic);
3955
3956
3957 // Given an integer value of pushedSize bytes on the stack,
3958 // adjust it to be resultSize bytes, either by discarding
3959 // the most significant bytes or by zero-padding.
3960 //
3961 // On exit from this macro, pushedSize will have been adjusted to
3962 // equal resultSize, and ACC may be trashed.
3963 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3964       /* If the pushed data is bigger than the result,          \
3965        * simply discard unused bytes. Icky, but works.          \
3966        */                                                       \
3967       while (pushedSize > resultSize)                           \
3968       {                                                         \
3969           D (emitcode (";", "discarding unused result byte."););\
3970           emitcode ("pop", "acc");                              \
3971           pushedSize--;                                         \
3972       }                                                         \
3973       if (pushedSize < resultSize)                              \
3974       {                                                         \
3975           emitcode ("clr", "a");                                \
3976           /* Conversly, we haven't pushed enough here.          \
3977            * just zero-pad, and all is well.                    \
3978            */                                                   \
3979           while (pushedSize < resultSize)                       \
3980           {                                                     \
3981               emitcode("push", "acc");                          \
3982               pushedSize++;                                     \
3983           }                                                     \
3984       }                                                         \
3985       assert(pushedSize == resultSize);
3986
3987 /*-----------------------------------------------------------------*/
3988 /* genPlus - generates code for addition                           */
3989 /*-----------------------------------------------------------------*/
3990 static void
3991 genPlus (iCode * ic)
3992 {
3993   int size, offset = 0;
3994   bool pushResult;
3995   int rSize;
3996
3997   D (emitcode (";", "genPlus "););
3998
3999   /* special cases :- */
4000   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4001       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4002       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4003       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4004       if (size <= 9) {
4005           while (size--) emitcode ("inc","dptr");
4006       } else {
4007           emitcode ("mov","a,dpl");
4008           emitcode ("add","a,#!constbyte",size & 0xff);
4009           emitcode ("mov","dpl,a");
4010           emitcode ("mov","a,dph");
4011           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4012           emitcode ("mov","dph,a");
4013           emitcode ("mov","a,dpx");
4014           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4015           emitcode ("mov","dpx,a");
4016       }
4017       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4018       return ;
4019   }
4020   if ( IS_SYMOP(IC_LEFT(ic)) && 
4021        OP_SYMBOL(IC_LEFT(ic))->remat &&
4022        isOperandInFarSpace(IC_RIGHT(ic))) {
4023       operand *op = IC_RIGHT(ic);
4024       IC_RIGHT(ic) = IC_LEFT(ic);
4025       IC_LEFT(ic) = op;
4026   }
4027                 
4028   AOP_OP_3_NOFATAL (ic, pushResult);
4029     
4030   if (pushResult)
4031     {
4032       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4033     }
4034
4035   if (!pushResult)
4036     {
4037       /* if literal, literal on the right or
4038          if left requires ACC or right is already
4039          in ACC */
4040       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4041        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4042           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4043         {
4044           operand *t = IC_RIGHT (ic);
4045           IC_RIGHT (ic) = IC_LEFT (ic);
4046           IC_LEFT (ic) = t;
4047           emitcode (";", "Swapped plus args.");
4048         }
4049
4050       /* if both left & right are in bit
4051          space */
4052       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4053           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4054         {
4055           genPlusBits (ic);
4056           goto release;
4057         }
4058
4059       /* if left in bit space & right literal */
4060       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4061           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4062         {
4063           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4064           /* if result in bit space */
4065           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4066             {
4067               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4068                 emitcode ("cpl", "c");
4069               outBitC (IC_RESULT (ic));
4070             }
4071           else
4072             {
4073               size = getDataSize (IC_RESULT (ic));
4074               _startLazyDPSEvaluation ();
4075               while (size--)
4076                 {
4077                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4078                   emitcode ("addc", "a,#0");
4079                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4080                 }
4081               _endLazyDPSEvaluation ();
4082             }
4083           goto release;
4084         }
4085
4086       /* if I can do an increment instead
4087          of add then GOOD for ME */
4088       if (genPlusIncr (ic) == TRUE)
4089         {
4090           emitcode (";", "did genPlusIncr");
4091           goto release;
4092         }
4093
4094     }
4095   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4096
4097   _startLazyDPSEvaluation ();
4098   while (size--)
4099     {
4100       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4101         {
4102           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4103           if (offset == 0)
4104             emitcode ("add", "a,%s",
4105                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4106           else
4107             emitcode ("addc", "a,%s",
4108                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4109         }
4110       else
4111         {
4112           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4113           {
4114               /* right is going to use ACC or we would have taken the
4115                * above branch.
4116                */
4117               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4118        TR_AP("#3");
4119               D(emitcode(";", "+ AOP_ACC special case."););
4120               emitcode("xch", "a, %s", DP2_RESULT_REG);
4121           }
4122           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4123           if (offset == 0)
4124           {
4125             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4126             {
4127          TR_AP("#4");
4128                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4129             }
4130             else
4131             {
4132                 emitcode ("add", "a,%s",
4133                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4134                                   DP2_RESULT_REG));
4135             }
4136           }
4137           else
4138           {
4139             emitcode ("addc", "a,%s",
4140                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4141                           DP2_RESULT_REG));
4142           }
4143         }
4144       if (!pushResult)
4145         {
4146           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4147         }
4148       else
4149         {
4150           emitcode ("push", "acc");
4151         }
4152       offset++;
4153     }
4154   _endLazyDPSEvaluation ();
4155
4156   if (pushResult)
4157     {
4158       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4159
4160       size = getDataSize (IC_LEFT (ic));
4161       rSize = getDataSize (IC_RESULT (ic));
4162
4163       ADJUST_PUSHED_RESULT(size, rSize);
4164
4165       _startLazyDPSEvaluation ();
4166       while (size--)
4167         {
4168           emitcode ("pop", "acc");
4169           aopPut (AOP (IC_RESULT (ic)), "a", size);
4170         }
4171       _endLazyDPSEvaluation ();
4172     }
4173
4174   adjustArithmeticResult (ic);
4175
4176 release:
4177   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4178   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4179   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4180 }
4181
4182 /*-----------------------------------------------------------------*/
4183 /* genMinusDec :- does subtraction with deccrement if possible     */
4184 /*-----------------------------------------------------------------*/
4185 static bool
4186 genMinusDec (iCode * ic)
4187 {
4188   unsigned int icount;
4189   unsigned int size = getDataSize (IC_RESULT (ic));
4190
4191   /* will try to generate an increment */
4192   /* if the right side is not a literal
4193      we cannot */
4194   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4195     return FALSE;
4196
4197   /* if the literal value of the right hand side
4198      is greater than 4 then it is not worth it */
4199   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4200     return FALSE;
4201
4202   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4203       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4204       while (icount--) {
4205           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4206       }
4207       return TRUE;
4208   }
4209   /* if decrement 16 bits in register */
4210   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4211       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4212       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4213       (size > 1) &&
4214       (icount == 1))
4215     {
4216       symbol *tlbl;
4217       int    emitTlbl;
4218       int    labelRange;
4219       char   *l;
4220
4221       /* If the next instruction is a goto and the goto target
4222          * is <= 5 instructions previous to this, we can generate
4223          * jumps straight to that target.
4224        */
4225       if (ic->next && ic->next->op == GOTO
4226           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4227           && labelRange <= 5)
4228         {
4229           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4230           tlbl = IC_LABEL (ic->next);
4231           emitTlbl = 0;
4232         }
4233       else
4234         {
4235           tlbl = newiTempLabel (NULL);
4236           emitTlbl = 1;
4237         }
4238
4239       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4240       emitcode ("dec", "%s", l);
4241  
4242       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4243           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4244           IS_AOP_PREG (IC_RESULT (ic)))
4245       {     
4246           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4247       }
4248       else
4249       {
4250           emitcode ("mov", "a,#!constbyte",0xff);
4251           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4252       }
4253       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4254       emitcode ("dec", "%s", l);
4255       if (size > 2)
4256         {
4257             if (!strcmp(l, "acc"))
4258             {
4259                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4260             }
4261             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4262                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4263                      IS_AOP_PREG (IC_RESULT (ic)))
4264             {       
4265                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4266             }
4267             else
4268             {
4269                 emitcode ("mov", "a,#!constbyte",0xff);
4270                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4271             }
4272             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4273             emitcode ("dec", "%s", l);
4274         }
4275       if (size > 3)
4276         {
4277             if (!strcmp(l, "acc"))
4278             {
4279                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4280             }
4281             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4282                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4283                      IS_AOP_PREG (IC_RESULT (ic)))
4284             {       
4285                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4286             }
4287             else
4288             {
4289                 emitcode ("mov", "a,#!constbyte",0xff);
4290                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4291             }       
4292             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4293             emitcode ("dec", "%s", l);
4294         }
4295       if (emitTlbl)
4296         {
4297           emitcode ("", "!tlabeldef", tlbl->key + 100);
4298         }
4299       return TRUE;
4300     }
4301
4302   /* if the sizes are greater than 1 then we cannot */
4303   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4304       AOP_SIZE (IC_LEFT (ic)) > 1)
4305     return FALSE;
4306
4307   /* we can if the aops of the left & result match or
4308      if they are in registers and the registers are the
4309      same */
4310   if (
4311        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4312        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4313        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4314     {
4315
4316       _startLazyDPSEvaluation ();
4317       while (icount--)
4318         {
4319           emitcode ("dec", "%s",
4320                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4321         }
4322       _endLazyDPSEvaluation ();
4323
4324       return TRUE;
4325     }
4326
4327   return FALSE;
4328 }
4329
4330 /*-----------------------------------------------------------------*/
4331 /* addSign - complete with sign                                    */
4332 /*-----------------------------------------------------------------*/
4333 static void
4334 addSign (operand * result, int offset, int sign)
4335 {
4336   int size = (getDataSize (result) - offset);
4337   if (size > 0)
4338     {
4339       _startLazyDPSEvaluation();
4340       if (sign)
4341         {
4342           emitcode ("rlc", "a");
4343           emitcode ("subb", "a,acc");
4344           while (size--)
4345           {
4346             aopPut (AOP (result), "a", offset++);
4347           }
4348         }
4349       else
4350       {
4351         while (size--)
4352         {
4353           aopPut (AOP (result), zero, offset++);
4354         }
4355       }
4356       _endLazyDPSEvaluation();
4357     }
4358 }
4359
4360 /*-----------------------------------------------------------------*/
4361 /* genMinusBits - generates code for subtraction  of two bits      */
4362 /*-----------------------------------------------------------------*/
4363 static void
4364 genMinusBits (iCode * ic)
4365 {
4366   symbol *lbl = newiTempLabel (NULL);
4367
4368   D (emitcode (";", "genMinusBits "););
4369
4370   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4371     {
4372       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4373       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4374       emitcode ("cpl", "c");
4375       emitcode ("", "!tlabeldef", (lbl->key + 100));
4376       outBitC (IC_RESULT (ic));
4377     }
4378   else
4379     {
4380       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4381       emitcode ("subb", "a,acc");
4382       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4383       emitcode ("inc", "a");
4384       emitcode ("", "!tlabeldef", (lbl->key + 100));
4385       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4386       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4387     }
4388 }
4389
4390 /*-----------------------------------------------------------------*/
4391 /* genMinus - generates code for subtraction                       */
4392 /*-----------------------------------------------------------------*/
4393 static void
4394 genMinus (iCode * ic)
4395 {
4396     int size, offset = 0;
4397     int rSize;
4398     long lit = 0L;
4399     bool pushResult;
4400
4401     D (emitcode (";", "genMinus "););
4402
4403     AOP_OP_3_NOFATAL(ic, pushResult);   
4404
4405     if (!pushResult)
4406     {
4407       /* special cases :- */
4408       /* if both left & right are in bit space */
4409       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4410           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4411         {
4412           genMinusBits (ic);
4413           goto release;
4414         }
4415
4416       /* if I can do an decrement instead
4417          of subtract then GOOD for ME */
4418       if (genMinusDec (ic) == TRUE)
4419         goto release;
4420
4421     }
4422
4423   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4424
4425   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4426     {
4427       CLRC;
4428     }
4429   else
4430     {
4431       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4432       lit = -lit;
4433     }
4434
4435
4436   /* if literal, add a,#-lit, else normal subb */
4437   _startLazyDPSEvaluation ();
4438   while (size--) {
4439       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4440           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4441               emitcode ("mov","b,%s",
4442                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4443               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4444               emitcode ("subb","a,b");
4445           } else {
4446               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4447               emitcode ("subb", "a,%s",
4448                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4449                                 DP2_RESULT_REG));
4450           }
4451       } else {
4452           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4453           /* first add without previous c */
4454           if (!offset) {
4455               if (!size && lit==-1) {
4456                   emitcode ("dec", "a");
4457               } else {
4458                   emitcode ("add", "a,#!constbyte",
4459                             (unsigned int) (lit & 0x0FFL));
4460               }
4461           } else {
4462               emitcode ("addc", "a,#!constbyte",
4463                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4464           }
4465       }
4466       
4467       if (pushResult) {
4468           emitcode ("push", "acc");
4469       } else {
4470           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4471       }
4472       offset++;
4473   }
4474   _endLazyDPSEvaluation ();
4475   
4476   if (pushResult)
4477     {
4478       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4479
4480       size = getDataSize (IC_LEFT (ic));
4481       rSize = getDataSize (IC_RESULT (ic));
4482
4483       ADJUST_PUSHED_RESULT(size, rSize);
4484
4485       _startLazyDPSEvaluation ();
4486       while (size--)
4487         {
4488           emitcode ("pop", "acc");
4489           aopPut (AOP (IC_RESULT (ic)), "a", size);
4490         }
4491       _endLazyDPSEvaluation ();
4492     }
4493
4494   adjustArithmeticResult (ic);
4495
4496 release:
4497   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4498   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4499   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4500 }
4501
4502
4503 /*-----------------------------------------------------------------*/
4504 /* genMultbits :- multiplication of bits                           */
4505 /*-----------------------------------------------------------------*/
4506 static void
4507 genMultbits (operand * left,
4508              operand * right,
4509              operand * result,
4510              iCode   * ic)
4511 {
4512   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4513   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4514   aopOp(result, ic, TRUE, FALSE);
4515   outBitC (result);
4516 }
4517
4518
4519 /*-----------------------------------------------------------------*/
4520 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4521 /*-----------------------------------------------------------------*/
4522 static void
4523 genMultOneByte (operand * left,
4524                 operand * right,
4525                 operand * result,
4526                 iCode   * ic)
4527 {
4528   sym_link *opetype = operandType (result);
4529   symbol *lbl;
4530
4531
4532   /* (if two literals: the value is computed before) */
4533   /* if one literal, literal on the right */
4534   if (AOP_TYPE (left) == AOP_LIT)
4535     {
4536       operand *t = right;
4537       right = left;
4538       left = t;
4539       emitcode (";", "swapped left and right");
4540     }
4541
4542   if (SPEC_USIGN(opetype)
4543       // ignore the sign of left and right, what else can we do?
4544       || (SPEC_USIGN(operandType(left)) && 
4545           SPEC_USIGN(operandType(right)))) {
4546     // just an unsigned 8*8=8/16 multiply
4547     //emitcode (";","unsigned");
4548     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4549     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4550     emitcode ("mul", "ab");
4551    
4552     _G.accInUse++; _G.bInUse++;
4553     aopOp(result, ic, TRUE, FALSE);
4554       
4555       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4556       {
4557           // this should never happen
4558           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4559                    AOP_SIZE(result), __FILE__, lineno);
4560           exit (1);
4561       }      
4562       
4563     aopPut (AOP (result), "a", 0);
4564     _G.accInUse--; _G.bInUse--;
4565     if (AOP_SIZE(result)==2) 
4566     {
4567       aopPut (AOP (result), "b", 1);
4568     }
4569     return;
4570   }
4571
4572   // we have to do a signed multiply
4573
4574   emitcode (";", "signed");
4575   emitcode ("clr", "F0"); // reset sign flag
4576   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4577
4578   lbl=newiTempLabel(NULL);
4579   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4580   // left side is negative, 8-bit two's complement, this fails for -128
4581   emitcode ("setb", "F0"); // set sign flag
4582   emitcode ("cpl", "a");
4583   emitcode ("inc", "a");
4584
4585   emitcode ("", "!tlabeldef", lbl->key+100);
4586
4587   /* if literal */
4588   if (AOP_TYPE(right)==AOP_LIT) {
4589     signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4590     /* AND literal negative */
4591     if ((int) val < 0) {
4592       emitcode ("cpl", "F0"); // complement sign flag
4593       emitcode ("mov", "b,#!constbyte", -val);
4594     } else {
4595       emitcode ("mov", "b,#!constbyte", val);
4596     }
4597   } else {
4598     lbl=newiTempLabel(NULL);
4599     emitcode ("mov", "b,a");
4600     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4601     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4602     // right side is negative, 8-bit two's complement
4603     emitcode ("cpl", "F0"); // complement sign flag
4604     emitcode ("cpl", "a");
4605     emitcode ("inc", "a");
4606     emitcode ("", "!tlabeldef", lbl->key+100);
4607   }
4608   emitcode ("mul", "ab");
4609     
4610   _G.accInUse++;_G.bInUse++;
4611   aopOp(result, ic, TRUE, FALSE);
4612     
4613   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4614   {
4615     // this should never happen
4616       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4617                AOP_SIZE(result), __FILE__, lineno);
4618       exit (1);
4619   }    
4620     
4621   lbl=newiTempLabel(NULL);
4622   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4623   // only ONE op was negative, we have to do a 8/16-bit two's complement
4624   emitcode ("cpl", "a"); // lsb
4625   if (AOP_SIZE(result)==1) {
4626     emitcode ("inc", "a");
4627   } else {
4628     emitcode ("add", "a,#1");
4629     emitcode ("xch", "a,b");
4630     emitcode ("cpl", "a"); // msb
4631     emitcode ("addc", "a,#0");
4632     emitcode ("xch", "a,b");
4633   }
4634
4635   emitcode ("", "!tlabeldef", lbl->key+100);
4636   aopPut (AOP (result), "a", 0);
4637   _G.accInUse--;_G.bInUse--;
4638   if (AOP_SIZE(result)==2) {
4639     aopPut (AOP (result), "b", 1);
4640   }
4641 }
4642
4643 /*-----------------------------------------------------------------*/
4644 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4645 /*-----------------------------------------------------------------*/
4646 static void genMultTwoByte (operand *left, operand *right, 
4647                             operand *result, iCode *ic)
4648 {
4649         sym_link *retype = getSpec(operandType(right));
4650         sym_link *letype = getSpec(operandType(left));
4651         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4652         symbol *lbl;
4653
4654         if (AOP_TYPE (left) == AOP_LIT) {
4655                 operand *t = right;
4656                 right = left;
4657                 left = t;
4658         }
4659         /* save EA bit in F1 */
4660         lbl = newiTempLabel(NULL);
4661         emitcode ("setb","F1");
4662         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4663         emitcode ("clr","F1");
4664         emitcode("","!tlabeldef",lbl->key+100);
4665
4666         /* load up MB with right */
4667         if (!umult) {
4668                 emitcode("clr","F0");
4669                 if (AOP_TYPE(right) == AOP_LIT) {
4670                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4671                         if (val < 0) {
4672                                 emitcode("setb","F0");
4673                                 val = -val;
4674                         }
4675                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4676                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4677                 } else {
4678                         lbl = newiTempLabel(NULL);
4679                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4680                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4681                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4682                         emitcode ("xch", "a,b");
4683                         emitcode ("cpl","a");
4684                         emitcode ("add", "a,#1");
4685                         emitcode ("xch", "a,b");
4686                         emitcode ("cpl", "a"); // msb
4687                         emitcode ("addc", "a,#0");
4688                         emitcode ("setb","F0");
4689                         emitcode ("","!tlabeldef",lbl->key+100);
4690                         emitcode ("mov","mb,b");
4691                         emitcode ("mov","mb,a");
4692                 }
4693         } else {
4694                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4695                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4696         }
4697         /* load up MA with left */
4698         if (!umult) {
4699                 lbl = newiTempLabel(NULL);
4700                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4701                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4702                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4703                 emitcode ("xch", "a,b");
4704                 emitcode ("cpl","a");
4705                 emitcode ("add", "a,#1");
4706                 emitcode ("xch", "a,b");
4707                 emitcode ("cpl", "a"); // msb
4708                 emitcode ("addc","a,#0");
4709                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4710                 emitcode ("setb","F0");
4711                 emitcode ("","!tlabeldef",lbl->key+100);
4712                 emitcode ("mov","ma,b");
4713                 emitcode ("mov","ma,a");
4714         } else {
4715                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4716                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4717         }
4718         /* wait for multiplication to finish */
4719         lbl = newiTempLabel(NULL);
4720         emitcode("","!tlabeldef", lbl->key+100);
4721         emitcode("mov","a,mcnt1");
4722         emitcode("anl","a,#!constbyte",0x80);
4723         emitcode("jnz","!tlabel",lbl->key+100);
4724         
4725         freeAsmop (left, NULL, ic, TRUE);
4726         freeAsmop (right, NULL, ic,TRUE);
4727         aopOp(result, ic, TRUE, FALSE);
4728
4729         /* if unsigned then simple */   
4730         if (umult) {
4731                 emitcode ("mov","a,ma");
4732                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4733                 emitcode ("mov","a,ma");
4734                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4735                 aopPut(AOP(result),"ma",1);
4736                 aopPut(AOP(result),"ma",0);
4737         } else {
4738                 emitcode("push","ma");
4739                 emitcode("push","ma");
4740                 emitcode("push","ma");
4741                 MOVA("ma");
4742                 /* negate result if needed */
4743                 lbl = newiTempLabel(NULL);      
4744                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4745                 emitcode("cpl","a");
4746                 emitcode("add","a,#1");
4747                 emitcode("","!tlabeldef", lbl->key+100);
4748                 if (AOP_TYPE(result) == AOP_ACC)
4749                 {
4750                     D(emitcode(";", "ACC special case."););
4751                     /* We know result is the only live aop, and 
4752                      * it's obviously not a DPTR2, so AP is available.
4753                      */
4754                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4755                 }
4756                 else
4757                 {
4758                     aopPut(AOP(result),"a",0);
4759                 }
4760             
4761                 emitcode("pop","acc");
4762                 lbl = newiTempLabel(NULL);      
4763                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4764                 emitcode("cpl","a");
4765                 emitcode("addc","a,#0");
4766                 emitcode("","!tlabeldef", lbl->key+100);
4767                 aopPut(AOP(result),"a",1);
4768                 emitcode("pop","acc");
4769                 if (AOP_SIZE(result) >= 3) {
4770                         lbl = newiTempLabel(NULL);      
4771                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4772                         emitcode("cpl","a");
4773                         emitcode("addc","a,#0");                        
4774                         emitcode("","!tlabeldef", lbl->key+100);
4775                         aopPut(AOP(result),"a",2);
4776                 }
4777                 emitcode("pop","acc");
4778                 if (AOP_SIZE(result) >= 4) {
4779                         lbl = newiTempLabel(NULL);      
4780                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4781                         emitcode("cpl","a");
4782                         emitcode("addc","a,#0");                        
4783                         emitcode("","!tlabeldef", lbl->key+100);
4784                         aopPut(AOP(result),"a",3);
4785                 }
4786                 if (AOP_TYPE(result) == AOP_ACC)
4787                 {
4788                     /* We stashed the result away above. */
4789                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4790                 }           
4791                 
4792         }
4793         freeAsmop (result, NULL, ic, TRUE);
4794
4795         /* restore EA bit in F1 */
4796         lbl = newiTempLabel(NULL);
4797         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4798         emitcode ("setb","EA");
4799         emitcode("","!tlabeldef",lbl->key+100);
4800         return ;
4801 }
4802
4803 /*-----------------------------------------------------------------*/
4804 /* genMult - generates code for multiplication                     */
4805 /*-----------------------------------------------------------------*/
4806 static void
4807 genMult (iCode * ic)
4808 {
4809   operand *left = IC_LEFT (ic);
4810   operand *right = IC_RIGHT (ic);
4811   operand *result = IC_RESULT (ic);
4812
4813   D (emitcode (";", "genMult "););
4814
4815   /* assign the amsops */
4816   AOP_OP_2 (ic);
4817
4818   /* special cases first */
4819   /* both are bits */
4820   if (AOP_TYPE (left) == AOP_CRY &&
4821       AOP_TYPE (right) == AOP_CRY)
4822     {
4823       genMultbits (left, right, result, ic);
4824       goto release;
4825     }
4826
4827   /* if both are of size == 1 */
4828   if (AOP_SIZE (left) == 1 &&
4829       AOP_SIZE (right) == 1)
4830     {
4831       genMultOneByte (left, right, result, ic);
4832       goto release;
4833     }
4834
4835   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4836           /* use the ds390 ARITHMETIC accel UNIT */
4837           genMultTwoByte (left, right, result, ic);
4838           return ;
4839   }
4840   /* should have been converted to function call */
4841   assert (0);
4842
4843 release:
4844   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4845   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4846   freeAsmop (result, NULL, ic, TRUE);
4847 }
4848
4849 /*-----------------------------------------------------------------*/
4850 /* genDivbits :- division of bits                                  */
4851 /*-----------------------------------------------------------------*/
4852 static void
4853 genDivbits (operand * left,
4854             operand * right,
4855             operand * result,
4856             iCode   * ic)
4857 {
4858
4859   char *l;
4860
4861   /* the result must be bit */
4862   LOAD_AB_FOR_DIV (left, right, l);
4863   emitcode ("div", "ab");
4864   emitcode ("rrc", "a");
4865   aopOp(result, ic, TRUE, FALSE);
4866     
4867   aopPut (AOP (result), "c", 0);
4868 }
4869
4870 /*-----------------------------------------------------------------*/
4871 /* genDivOneByte : 8 bit division                                  */
4872 /*-----------------------------------------------------------------*/
4873 static void
4874 genDivOneByte (operand * left,
4875                operand * right,
4876                operand * result,
4877                iCode   * ic)
4878 {
4879   sym_link *opetype = operandType (result);
4880   char *l;
4881   symbol *lbl;
4882   int size, offset;
4883
4884   offset = 1;
4885   /* signed or unsigned */
4886   if (SPEC_USIGN (opetype))
4887     {
4888         /* unsigned is easy */
4889         LOAD_AB_FOR_DIV (left, right, l);
4890         emitcode ("div", "ab");
4891
4892         _G.accInUse++;
4893         aopOp(result, ic, TRUE, FALSE);
4894         aopPut (AOP (result), "a", 0);
4895         _G.accInUse--;
4896
4897         size = AOP_SIZE (result) - 1;
4898         
4899         while (size--)
4900         {
4901             aopPut (AOP (result), zero, offset++);
4902         }
4903       return;
4904     }
4905
4906   /* signed is a little bit more difficult */
4907
4908   /* save the signs of the operands */
4909   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4910   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4911   emitcode ("push", "acc");     /* save it on the stack */
4912
4913   /* now sign adjust for both left & right */
4914   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4915   lbl = newiTempLabel (NULL);
4916   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4917   emitcode ("cpl", "a");
4918   emitcode ("inc", "a");
4919   emitcode ("", "!tlabeldef", (lbl->key + 100));
4920   emitcode ("mov", "b,a");
4921
4922   /* sign adjust left side */
4923   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4924
4925   lbl = newiTempLabel (NULL);
4926   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4927   emitcode ("cpl", "a");
4928   emitcode ("inc", "a");
4929   emitcode ("", "!tlabeldef", (lbl->key + 100));
4930
4931   /* now the division */
4932   emitcode ("nop", "; workaround for DS80C390 div bug.");
4933   emitcode ("div", "ab");
4934   /* we are interested in the lower order
4935      only */
4936   emitcode ("mov", "b,a");
4937   lbl = newiTempLabel (NULL);
4938   emitcode ("pop", "acc");
4939   /* if there was an over flow we don't
4940      adjust the sign of the result */
4941   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4942   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4943   CLRC;
4944   emitcode ("clr", "a");
4945   emitcode ("subb", "a,b");
4946   emitcode ("mov", "b,a");
4947   emitcode ("", "!tlabeldef", (lbl->key + 100));
4948
4949   /* now we are done */
4950   _G.accInUse++;     _G.bInUse++;
4951     aopOp(result, ic, TRUE, FALSE);
4952     
4953     aopPut (AOP (result), "b", 0);
4954     
4955     size = AOP_SIZE (result) - 1;
4956     
4957     if (size > 0)
4958     {
4959       emitcode ("mov", "c,b.7");
4960       emitcode ("subb", "a,acc");
4961     }
4962     while (size--)
4963     {
4964         aopPut (AOP (result), "a", offset++);
4965     }
4966     _G.accInUse--;     _G.bInUse--;
4967
4968 }
4969
4970 /*-----------------------------------------------------------------*/
4971 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4972 /*-----------------------------------------------------------------*/
4973 static void genDivTwoByte (operand *left, operand *right, 
4974                             operand *result, iCode *ic)
4975 {
4976         sym_link *retype = getSpec(operandType(right));
4977         sym_link *letype = getSpec(operandType(left));
4978         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4979         symbol *lbl;
4980
4981         /* save EA bit in F1 */
4982         lbl = newiTempLabel(NULL);
4983         emitcode ("setb","F1");
4984         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4985         emitcode ("clr","F1");
4986         emitcode("","!tlabeldef",lbl->key+100);
4987
4988         /* load up MA with left */
4989         if (!umult) {
4990                 emitcode("clr","F0");
4991                 lbl = newiTempLabel(NULL);
4992                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4993                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4994                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4995                 emitcode ("xch", "a,b");
4996                 emitcode ("cpl","a");
4997                 emitcode ("add", "a,#1");
4998                 emitcode ("xch", "a,b");
4999                 emitcode ("cpl", "a"); // msb
5000                 emitcode ("addc","a,#0");
5001                 emitcode ("setb","F0");
5002                 emitcode ("","!tlabeldef",lbl->key+100);
5003                 emitcode ("mov","ma,b");
5004                 emitcode ("mov","ma,a");
5005         } else {
5006                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5007                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5008         }
5009
5010         /* load up MB with right */
5011         if (!umult) {
5012                 if (AOP_TYPE(right) == AOP_LIT) {
5013                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5014                         if (val < 0) {
5015                                 lbl = newiTempLabel(NULL);
5016                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5017                                 emitcode("setb","F0");
5018                                 emitcode ("","!tlabeldef",lbl->key+100);
5019                                 val = -val;
5020                         } 
5021                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5022                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5023                 } else {
5024                         lbl = newiTempLabel(NULL);
5025                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5026                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5027                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5028                         emitcode ("xch", "a,b");
5029                         emitcode ("cpl","a");
5030                         emitcode ("add", "a,#1");
5031                         emitcode ("xch", "a,b");
5032                         emitcode ("cpl", "a"); // msb
5033                         emitcode ("addc", "a,#0");
5034                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5035                         emitcode ("setb","F0");
5036                         emitcode ("","!tlabeldef",lbl->key+100);
5037                         emitcode ("mov","mb,b");
5038                         emitcode ("mov","mb,a");
5039                 }
5040         } else {
5041                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5042                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5043         }
5044
5045         /* wait for multiplication to finish */
5046         lbl = newiTempLabel(NULL);
5047         emitcode("","!tlabeldef", lbl->key+100);
5048         emitcode("mov","a,mcnt1");
5049         emitcode("anl","a,#!constbyte",0x80);
5050         emitcode("jnz","!tlabel",lbl->key+100);
5051         
5052         freeAsmop (left, NULL, ic, TRUE);
5053         freeAsmop (right, NULL, ic,TRUE);
5054         aopOp(result, ic, TRUE, FALSE);
5055
5056         /* if unsigned then simple */   
5057         if (umult) {
5058                 aopPut(AOP(result),"ma",1);
5059                 aopPut(AOP(result),"ma",0);
5060         } else {
5061                 emitcode("push","ma");
5062                 MOVA("ma");
5063                 /* negate result if needed */
5064                 lbl = newiTempLabel(NULL);      
5065                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5066                 emitcode("cpl","a");
5067                 emitcode("add","a,#1");
5068                 emitcode("","!tlabeldef", lbl->key+100);
5069                 aopPut(AOP(result),"a",0);
5070                 emitcode("pop","acc");
5071                 lbl = newiTempLabel(NULL);      
5072                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5073                 emitcode("cpl","a");
5074                 emitcode("addc","a,#0");
5075                 emitcode("","!tlabeldef", lbl->key+100);
5076                 aopPut(AOP(result),"a",1);
5077         }
5078         freeAsmop (result, NULL, ic, TRUE);
5079         /* restore EA bit in F1 */
5080         lbl = newiTempLabel(NULL);
5081         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5082         emitcode ("setb","EA");
5083         emitcode("","!tlabeldef",lbl->key+100);
5084         return ;
5085 }
5086
5087 /*-----------------------------------------------------------------*/
5088 /* genDiv - generates code for division                            */
5089 /*-----------------------------------------------------------------*/
5090 static void
5091 genDiv (iCode * ic)
5092 {
5093   operand *left = IC_LEFT (ic);
5094   operand *right = IC_RIGHT (ic);
5095   operand *result = IC_RESULT (ic);
5096
5097   D (emitcode (";", "genDiv "););
5098
5099   /* assign the amsops */
5100   AOP_OP_2 (ic);
5101
5102   /* special cases first */
5103   /* both are bits */
5104   if (AOP_TYPE (left) == AOP_CRY &&
5105       AOP_TYPE (right) == AOP_CRY)
5106     {
5107       genDivbits (left, right, result, ic);
5108       goto release;
5109     }
5110
5111   /* if both are of size == 1 */
5112   if (AOP_SIZE (left) == 1 &&
5113       AOP_SIZE (right) == 1)
5114     {
5115       genDivOneByte (left, right, result, ic);
5116       goto release;
5117     }
5118
5119   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5120           /* use the ds390 ARITHMETIC accel UNIT */
5121           genDivTwoByte (left, right, result, ic);
5122           return ;
5123   }
5124   /* should have been converted to function call */
5125   assert (0);
5126 release:
5127   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5128   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5129   freeAsmop (result, NULL, ic, TRUE);
5130 }
5131
5132 /*-----------------------------------------------------------------*/
5133 /* genModbits :- modulus of bits                                   */
5134 /*-----------------------------------------------------------------*/
5135 static void
5136 genModbits (operand * left,
5137             operand * right,
5138             operand * result,
5139             iCode   * ic)
5140 {
5141
5142   char *l;
5143
5144   /* the result must be bit */
5145   LOAD_AB_FOR_DIV (left, right, l);
5146   emitcode ("div", "ab");
5147   emitcode ("mov", "a,b");
5148   emitcode ("rrc", "a");
5149   aopOp(result, ic, TRUE, FALSE);
5150   aopPut (AOP (result), "c", 0);
5151 }
5152
5153 /*-----------------------------------------------------------------*/
5154 /* genModOneByte : 8 bit modulus                                   */
5155 /*-----------------------------------------------------------------*/
5156 static void
5157 genModOneByte (operand * left,
5158                operand * right,
5159                operand * result,
5160                iCode   * ic)
5161 {
5162   sym_link *opetype = operandType (result);
5163   char *l;
5164   symbol *lbl;
5165
5166   /* signed or unsigned */
5167   if (SPEC_USIGN (opetype))
5168     {
5169       /* unsigned is easy */
5170       LOAD_AB_FOR_DIV (left, right, l);
5171       emitcode ("div", "ab");
5172       aopOp(result, ic, TRUE, FALSE);   
5173       aopPut (AOP (result), "b", 0);
5174       return;
5175     }
5176
5177   /* signed is a little bit more difficult */
5178
5179   /* save the signs of the operands */
5180   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5181
5182   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5183   emitcode ("push", "acc");     /* save it on the stack */
5184
5185   /* now sign adjust for both left & right */
5186   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5187
5188   lbl = newiTempLabel (NULL);
5189   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5190   emitcode ("cpl", "a");
5191   emitcode ("inc", "a");
5192   emitcode ("", "!tlabeldef", (lbl->key + 100));
5193   emitcode ("mov", "b,a");
5194
5195   /* sign adjust left side */
5196   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5197
5198   lbl = newiTempLabel (NULL);
5199   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5200   emitcode ("cpl", "a");
5201   emitcode ("inc", "a");
5202   emitcode ("", "!tlabeldef", (lbl->key + 100));
5203
5204   /* now the multiplication */
5205   emitcode ("nop", "; workaround for DS80C390 div bug.");
5206   emitcode ("div", "ab");
5207   /* we are interested in the lower order
5208      only */
5209   lbl = newiTempLabel (NULL);
5210   emitcode ("pop", "acc");
5211   /* if there was an over flow we don't
5212      adjust the sign of the result */
5213   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5214   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5215   CLRC;
5216   emitcode ("clr", "a");
5217   emitcode ("subb", "a,b");
5218   emitcode ("mov", "b,a");
5219   emitcode ("", "!tlabeldef", (lbl->key + 100));
5220   
5221   _G.bInUse++;
5222   /* now we are done */
5223   aopOp(result, ic, TRUE, FALSE);    
5224   aopPut (AOP (result), "b", 0);
5225   _G.bInUse--;
5226
5227 }
5228
5229 /*-----------------------------------------------------------------*/
5230 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5231 /*-----------------------------------------------------------------*/
5232 static void genModTwoByte (operand *left, operand *right, 
5233                             operand *result, iCode *ic)
5234 {
5235         sym_link *retype = getSpec(operandType(right));
5236         sym_link *letype = getSpec(operandType(left));
5237         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5238         symbol *lbl;
5239
5240         /* load up MA with left */
5241         /* save EA bit in F1 */
5242         lbl = newiTempLabel(NULL);
5243         emitcode ("setb","F1");
5244         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5245         emitcode ("clr","F1");
5246         emitcode("","!tlabeldef",lbl->key+100);
5247
5248         if (!umult) {
5249                 lbl = newiTempLabel(NULL);
5250                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5251                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5252                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5253                 emitcode ("xch", "a,b");
5254                 emitcode ("cpl","a");
5255                 emitcode ("add", "a,#1");
5256                 emitcode ("xch", "a,b");
5257                 emitcode ("cpl", "a"); // msb
5258                 emitcode ("addc","a,#0");
5259                 emitcode ("","!tlabeldef",lbl->key+100);
5260                 emitcode ("mov","ma,b");
5261                 emitcode ("mov","ma,a");
5262         } else {
5263                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5264                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5265         }
5266
5267         /* load up MB with right */
5268         if (!umult) {
5269                 if (AOP_TYPE(right) == AOP_LIT) {
5270                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5271                         if (val < 0) {
5272                                 val = -val;
5273                         } 
5274                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5275                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5276                 } else {
5277                         lbl = newiTempLabel(NULL);
5278                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5279                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5280                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5281                         emitcode ("xch", "a,b");
5282                         emitcode ("cpl","a");
5283                         emitcode ("add", "a,#1");
5284                         emitcode ("xch", "a,b");
5285                         emitcode ("cpl", "a"); // msb
5286                         emitcode ("addc", "a,#0");
5287                         emitcode ("","!tlabeldef",lbl->key+100);
5288                         emitcode ("mov","mb,b");
5289                         emitcode ("mov","mb,a");
5290                 }
5291         } else {
5292                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5293                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5294         }
5295
5296         /* wait for multiplication to finish */
5297         lbl = newiTempLabel(NULL);
5298         emitcode("","!tlabeldef", lbl->key+100);
5299         emitcode("mov","a,mcnt1");
5300         emitcode("anl","a,#!constbyte",0x80);
5301         emitcode("jnz","!tlabel",lbl->key+100);
5302         
5303         freeAsmop (left, NULL, ic, TRUE);
5304         freeAsmop (right, NULL, ic,TRUE);
5305         aopOp(result, ic, TRUE, FALSE);
5306
5307         aopPut(AOP(result),"mb",1);
5308         aopPut(AOP(result),"mb",0);
5309         freeAsmop (result, NULL, ic, TRUE);
5310
5311         /* restore EA bit in F1 */
5312         lbl = newiTempLabel(NULL);
5313         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5314         emitcode ("setb","EA");
5315         emitcode("","!tlabeldef",lbl->key+100);
5316         return ;
5317 }
5318
5319 /*-----------------------------------------------------------------*/
5320 /* genMod - generates code for division                            */
5321 /*-----------------------------------------------------------------*/
5322 static void
5323 genMod (iCode * ic)
5324 {
5325   operand *left = IC_LEFT (ic);
5326   operand *right = IC_RIGHT (ic);
5327   operand *result = IC_RESULT (ic);
5328
5329   D (emitcode (";", "genMod "); );
5330
5331   /* assign the amsops */
5332   AOP_OP_2 (ic);
5333
5334   /* special cases first */
5335   /* both are bits */
5336   if (AOP_TYPE (left) == AOP_CRY &&
5337       AOP_TYPE (right) == AOP_CRY)
5338     {
5339       genModbits (left, right, result, ic);
5340       goto release;
5341     }
5342
5343   /* if both are of size == 1 */
5344   if (AOP_SIZE (left) == 1 &&
5345       AOP_SIZE (right) == 1)
5346     {
5347       genModOneByte (left, right, result, ic);
5348       goto release;
5349     }
5350
5351   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5352           /* use the ds390 ARITHMETIC accel UNIT */
5353           genModTwoByte (left, right, result, ic);
5354           return ;
5355   }
5356
5357   /* should have been converted to function call */
5358   assert (0);
5359
5360 release:
5361   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5362   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5363   freeAsmop (result, NULL, ic, TRUE);
5364 }
5365
5366 /*-----------------------------------------------------------------*/
5367 /* genIfxJump :- will create a jump depending on the ifx           */
5368 /*-----------------------------------------------------------------*/
5369 static void
5370 genIfxJump (iCode * ic, char *jval)
5371 {
5372   symbol *jlbl;
5373   symbol *tlbl = newiTempLabel (NULL);
5374   char *inst;
5375
5376   D (emitcode (";", "genIfxJump"););
5377
5378   /* if true label then we jump if condition
5379      supplied is true */
5380   if (IC_TRUE (ic))
5381     {
5382       jlbl = IC_TRUE (ic);
5383       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5384                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5385     }
5386   else
5387     {
5388       /* false label is present */
5389       jlbl = IC_FALSE (ic);
5390       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5391                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5392     }
5393   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5394     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5395   else
5396     emitcode (inst, "!tlabel", tlbl->key + 100);
5397   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5398   emitcode ("", "!tlabeldef", tlbl->key + 100);
5399
5400   /* mark the icode as generated */
5401   ic->generated = 1;
5402 }
5403
5404 /*-----------------------------------------------------------------*/
5405 /* genCmp :- greater or less than comparison                       */
5406 /*-----------------------------------------------------------------*/
5407 static void
5408 genCmp (operand * left, operand * right,
5409         iCode * ic, iCode * ifx, int sign)
5410 {
5411   int size, offset = 0;
5412   unsigned long lit = 0L;
5413   operand *result;
5414
5415   D (emitcode (";", "genCmp"););
5416
5417   result = IC_RESULT (ic);
5418
5419   /* if left & right are bit variables */
5420   if (AOP_TYPE (left) == AOP_CRY &&
5421       AOP_TYPE (right) == AOP_CRY)
5422     {
5423       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5424       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5425     }
5426   else
5427     {
5428       /* subtract right from left if at the
5429          end the carry flag is set then we know that
5430          left is greater than right */
5431       size = max (AOP_SIZE (left), AOP_SIZE (right));
5432
5433       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5434       if ((size == 1) && !sign 
5435           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5436         {
5437           symbol *lbl = newiTempLabel (NULL);
5438           emitcode ("cjne", "%s,%s,!tlabel",
5439                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5440                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5441                     lbl->key + 100);
5442           emitcode ("", "!tlabeldef", lbl->key + 100);
5443         }
5444       else
5445         {
5446           if (AOP_TYPE (right) == AOP_LIT)
5447             {
5448               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5449               /* optimize if(x < 0) or if(x >= 0) */
5450               if (lit == 0L)
5451                 {
5452                   if (!sign)
5453                     {
5454                       CLRC;
5455                     }
5456                   else
5457                     {
5458                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5459
5460                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5461                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5462
5463                       aopOp (result, ic, FALSE, FALSE);
5464
5465                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5466                         {
5467                           freeAsmop (result, NULL, ic, TRUE);
5468                           genIfxJump (ifx, "acc.7");
5469                           return;
5470                         }
5471                       else
5472                         {
5473                           emitcode ("rlc", "a");
5474                         }
5475                       goto release_freedLR;
5476                     }
5477                   goto release;
5478                 }
5479             }
5480           CLRC;
5481           while (size--)
5482             {
5483               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5484               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5485               // emitcode (";", "genCmp #2");
5486               if (sign && (size == 0))
5487                 {
5488                   // emitcode (";", "genCmp #3");
5489                   emitcode ("xrl", "a,#!constbyte",0x80);
5490                   if (AOP_TYPE (right) == AOP_LIT)
5491                     {
5492                       unsigned long lit = (unsigned long)
5493                       floatFromVal (AOP (right)->aopu.aop_lit);
5494                       // emitcode (";", "genCmp #3.1");
5495                       emitcode ("subb", "a,#!constbyte",
5496                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5497                     }
5498                   else
5499                     {
5500                       // emitcode (";", "genCmp #3.2");
5501                       saveAccWarn = 0;  
5502                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5503                       saveAccWarn = DEFAULT_ACC_WARNING;
5504                       emitcode ("xrl", "b,#!constbyte",0x80);
5505                       emitcode ("subb", "a,b");
5506                     }
5507                 }
5508               else
5509                 {
5510                   const char *s;
5511
5512                   // emitcode (";", "genCmp #4");
5513                   saveAccWarn = 0;
5514                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5515                   saveAccWarn = DEFAULT_ACC_WARNING;
5516
5517                   emitcode ("subb", "a,%s", s);
5518                 }
5519             }
5520         }
5521     }
5522
5523 release:
5524 /* Don't need the left & right operands any more; do need the result. */
5525   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5526   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5527
5528   aopOp (result, ic, FALSE, FALSE);
5529
5530 release_freedLR:
5531
5532   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5533     {
5534       outBitC (result);
5535     }
5536   else
5537     {
5538       /* if the result is used in the next
5539          ifx conditional branch then generate
5540          code a little differently */
5541       if (ifx)
5542         {
5543           genIfxJump (ifx, "c");
5544         }
5545       else
5546         {
5547           outBitC (result);
5548         }
5549       /* leave the result in acc */
5550     }
5551   freeAsmop (result, NULL, ic, TRUE);
5552 }
5553
5554 /*-----------------------------------------------------------------*/
5555 /* genCmpGt :- greater than comparison                             */
5556 /*-----------------------------------------------------------------*/
5557 static void
5558 genCmpGt (iCode * ic, iCode * ifx)
5559 {
5560   operand *left, *right;
5561   sym_link *letype, *retype;
5562   int sign;
5563
5564   D (emitcode (";", "genCmpGt ");
5565     );
5566
5567   left = IC_LEFT (ic);
5568   right = IC_RIGHT (ic);
5569
5570   letype = getSpec (operandType (left));
5571   retype = getSpec (operandType (right));
5572   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5573
5574   /* assign the left & right amsops */
5575   AOP_OP_2 (ic);
5576
5577   genCmp (right, left, ic, ifx, sign);
5578 }
5579
5580 /*-----------------------------------------------------------------*/
5581 /* genCmpLt - less than comparisons                                */
5582 /*-----------------------------------------------------------------*/
5583 static void
5584 genCmpLt (iCode * ic, iCode * ifx)
5585 {
5586   operand *left, *right;
5587   sym_link *letype, *retype;
5588   int sign;
5589
5590   D (emitcode (";", "genCmpLt "););
5591
5592   left = IC_LEFT (ic);
5593   right = IC_RIGHT (ic);
5594
5595   letype = getSpec (operandType (left));
5596   retype = getSpec (operandType (right));
5597   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5598
5599   /* assign the left & right amsops */
5600   AOP_OP_2 (ic);
5601
5602   genCmp (left, right, ic, ifx, sign);
5603 }
5604
5605 /*-----------------------------------------------------------------*/
5606 /* gencjneshort - compare and jump if not equal                    */
5607 /*-----------------------------------------------------------------*/
5608 static void
5609 gencjneshort (operand * left, operand * right, symbol * lbl)
5610 {
5611   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5612   int offset = 0;
5613   unsigned long lit = 0L;
5614
5615   D (emitcode (";", "gencjneshort");
5616     );
5617
5618   /* if the left side is a literal or
5619      if the right is in a pointer register and left
5620      is not */
5621   if ((AOP_TYPE (left) == AOP_LIT) ||
5622       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5623     {
5624       operand *t = right;
5625       right = left;
5626       left = t;
5627     }
5628
5629   if (AOP_TYPE (right) == AOP_LIT)
5630     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5631
5632   if (opIsGptr (left) || opIsGptr (right))
5633     {
5634       /* We are comparing a generic pointer to something.
5635        * Exclude the generic type byte from the comparison.
5636        */
5637       size--;
5638       D (emitcode (";", "cjneshort: generic ptr special case."););
5639     }
5640
5641
5642   /* if the right side is a literal then anything goes */
5643   if (AOP_TYPE (right) == AOP_LIT &&
5644       AOP_TYPE (left) != AOP_DIR)
5645     {
5646       while (size--)
5647         {
5648           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5649           emitcode ("cjne", "a,%s,!tlabel",
5650                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5651                     lbl->key + 100);
5652           offset++;
5653         }
5654     }
5655
5656   /* if the right side is in a register or in direct space or
5657      if the left is a pointer register & right is not */
5658   else if (AOP_TYPE (right) == AOP_REG ||
5659            AOP_TYPE (right) == AOP_DIR ||
5660            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5661            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5662     {
5663       while (size--)
5664         {
5665           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5666           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5667               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5668             emitcode ("jnz", "!tlabel", lbl->key + 100);
5669           else
5670             emitcode ("cjne", "a,%s,!tlabel",
5671                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5672                       lbl->key + 100);
5673           offset++;
5674         }
5675     }
5676   else
5677     {
5678       /* right is a pointer reg need both a & b */
5679       while (size--)
5680         {
5681           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5682           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5683           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5684           offset++;
5685         }
5686     }
5687 }
5688
5689 /*-----------------------------------------------------------------*/
5690 /* gencjne - compare and jump if not equal                         */
5691 /*-----------------------------------------------------------------*/
5692 static void
5693 gencjne (operand * left, operand * right, symbol * lbl)
5694 {
5695   symbol *tlbl = newiTempLabel (NULL);
5696
5697   D (emitcode (";", "gencjne");
5698     );
5699
5700   gencjneshort (left, right, lbl);
5701
5702   emitcode ("mov", "a,%s", one);
5703   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5704   emitcode ("", "!tlabeldef", lbl->key + 100);
5705   emitcode ("clr", "a");
5706   emitcode ("", "!tlabeldef", tlbl->key + 100);
5707 }
5708
5709 /*-----------------------------------------------------------------*/
5710 /* genCmpEq - generates code for equal to                          */
5711 /*-----------------------------------------------------------------*/
5712 static void
5713 genCmpEq (iCode * ic, iCode * ifx)
5714 {
5715   operand *left, *right, *result;
5716
5717   D (emitcode (";", "genCmpEq ");
5718     );
5719
5720   AOP_OP_2 (ic);
5721   AOP_SET_LOCALS (ic);
5722
5723   /* if literal, literal on the right or
5724      if the right is in a pointer register and left
5725      is not */
5726   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5727       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5728     {
5729       operand *t = IC_RIGHT (ic);
5730       IC_RIGHT (ic) = IC_LEFT (ic);
5731       IC_LEFT (ic) = t;
5732     }
5733
5734   if (ifx &&                    /* !AOP_SIZE(result) */
5735       OP_SYMBOL (result) &&
5736       OP_SYMBOL (result)->regType == REG_CND)
5737     {
5738       symbol *tlbl;
5739       /* if they are both bit variables */
5740       if (AOP_TYPE (left) == AOP_CRY &&
5741           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5742         {
5743           if (AOP_TYPE (right) == AOP_LIT)
5744             {
5745               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5746               if (lit == 0L)
5747                 {
5748                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5749                   emitcode ("cpl", "c");
5750                 }
5751               else if (lit == 1L)
5752                 {
5753                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5754                 }
5755               else
5756                 {
5757                   emitcode ("clr", "c");
5758                 }
5759               /* AOP_TYPE(right) == AOP_CRY */
5760             }
5761           else
5762             {
5763               symbol *lbl = newiTempLabel (NULL);
5764               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5765               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5766               emitcode ("cpl", "c");
5767               emitcode ("", "!tlabeldef", (lbl->key + 100));
5768             }
5769           /* if true label then we jump if condition
5770              supplied is true */
5771           tlbl = newiTempLabel (NULL);
5772           if (IC_TRUE (ifx))
5773             {
5774               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5775               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5776             }
5777           else
5778             {
5779               emitcode ("jc", "!tlabel", tlbl->key + 100);
5780               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5781             }
5782           emitcode ("", "!tlabeldef", tlbl->key + 100);
5783         }
5784       else
5785         {
5786           tlbl = newiTempLabel (NULL);
5787           gencjneshort (left, right, tlbl);
5788           if (IC_TRUE (ifx))
5789             {
5790               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5791               emitcode ("", "!tlabeldef", tlbl->key + 100);
5792             }
5793           else
5794             {
5795               symbol *lbl = newiTempLabel (NULL);
5796               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5797               emitcode ("", "!tlabeldef", tlbl->key + 100);
5798               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5799               emitcode ("", "!tlabeldef", lbl->key + 100);
5800             }
5801         }
5802       /* mark the icode as generated */
5803       ifx->generated = 1;
5804
5805       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5806       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5807       return;
5808     }
5809
5810   /* if they are both bit variables */
5811   if (AOP_TYPE (left) == AOP_CRY &&
5812       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5813     {
5814       if (AOP_TYPE (right) == AOP_LIT)
5815         {
5816           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5817           if (lit == 0L)
5818             {
5819               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5820               emitcode ("cpl", "c");
5821             }
5822           else if (lit == 1L)
5823             {
5824               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5825             }
5826           else
5827             {
5828               emitcode ("clr", "c");
5829             }
5830           /* AOP_TYPE(right) == AOP_CRY */
5831         }
5832       else
5833         {
5834           symbol *lbl = newiTempLabel (NULL);
5835           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5836           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5837           emitcode ("cpl", "c");
5838           emitcode ("", "!tlabeldef", (lbl->key + 100));
5839         }
5840
5841       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5842       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5843
5844       aopOp (result, ic, TRUE, FALSE);
5845
5846       /* c = 1 if egal */
5847       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5848         {
5849           outBitC (result);
5850           goto release;
5851         }
5852       if (ifx)
5853         {
5854           genIfxJump (ifx, "c");
5855           goto release;
5856         }
5857       /* if the result is used in an arithmetic operation
5858          then put the result in place */
5859       outBitC (result);
5860     }
5861   else
5862     {
5863       gencjne (left, right, newiTempLabel (NULL));
5864
5865       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5866       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5867
5868       aopOp (result, ic, TRUE, FALSE);
5869
5870       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5871         {
5872           aopPut (AOP (result), "a", 0);
5873           goto release;
5874         }
5875       if (ifx)
5876         {
5877           genIfxJump (ifx, "a");
5878           goto release;
5879         }
5880       /* if the result is used in an arithmetic operation
5881          then put the result in place */
5882       if (AOP_TYPE (result) != AOP_CRY)
5883         outAcc (result);
5884       /* leave the result in acc */
5885     }
5886
5887 release:
5888   freeAsmop (result, NULL, ic, TRUE);
5889 }
5890
5891 /*-----------------------------------------------------------------*/
5892 /* ifxForOp - returns the icode containing the ifx for operand     */
5893 /*-----------------------------------------------------------------*/
5894 static iCode *
5895 ifxForOp (operand * op, iCode * ic)
5896 {
5897   /* if true symbol then needs to be assigned */
5898   if (IS_TRUE_SYMOP (op))
5899     return NULL;
5900
5901   /* if this has register type condition and
5902      the next instruction is ifx with the same operand
5903      and live to of the operand is upto the ifx only then */
5904   if (ic->next &&
5905       ic->next->op == IFX &&
5906       IC_COND (ic->next)->key == op->key &&
5907       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5908     return ic->next;
5909
5910   return NULL;
5911 }
5912 /*-----------------------------------------------------------------*/
5913 /* hasInc - operand is incremented before any other use            */
5914 /*-----------------------------------------------------------------*/
5915 static iCode *
5916 hasInc (operand *op, iCode *ic, int osize)
5917 {
5918   sym_link *type = operandType(op);
5919   sym_link *retype = getSpec (type);
5920   iCode *lic = ic->next;
5921   int isize ;
5922   
5923   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5924   if (!IS_SYMOP(op)) return NULL;
5925
5926   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5927   if (IS_AGGREGATE(type->next)) return NULL;
5928   if (osize != (isize = getSize(type->next))) return NULL;
5929
5930   while (lic) {
5931       /* if operand of the form op = op + <sizeof *op> */
5932       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5933           isOperandEqual(IC_RESULT(lic),op) && 
5934           isOperandLiteral(IC_RIGHT(lic)) &&
5935           operandLitValue(IC_RIGHT(lic)) == isize) {
5936           return lic;
5937       }
5938       /* if the operand used or deffed */
5939       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5940           return NULL;
5941       }
5942       /* if GOTO or IFX */
5943       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5944       lic = lic->next;
5945   }
5946   return NULL;
5947 }
5948
5949 /*-----------------------------------------------------------------*/
5950 /* genAndOp - for && operation                                     */
5951 /*-----------------------------------------------------------------*/
5952 static void
5953 genAndOp (iCode * ic)
5954 {
5955   operand *left, *right, *result;
5956   symbol *tlbl;
5957
5958   D (emitcode (";", "genAndOp "););
5959
5960   /* note here that && operations that are in an
5961      if statement are taken away by backPatchLabels
5962      only those used in arthmetic operations remain */
5963   AOP_OP_2 (ic);
5964   AOP_SET_LOCALS (ic);
5965
5966   /* if both are bit variables */
5967   if (AOP_TYPE (left) == AOP_CRY &&
5968       AOP_TYPE (right) == AOP_CRY)
5969     {
5970       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5971       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5972       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5973       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5974   
5975       aopOp (result,ic,FALSE, FALSE);
5976       outBitC (result);
5977     }
5978   else
5979     {
5980       tlbl = newiTempLabel (NULL);
5981       toBoolean (left);
5982       emitcode ("jz", "!tlabel", tlbl->key + 100);
5983       toBoolean (right);
5984       emitcode ("", "!tlabeldef", tlbl->key + 100);
5985       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5986       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5987   
5988       aopOp (result,ic,FALSE, FALSE);
5989       outBitAcc (result);
5990     }
5991     freeAsmop (result, NULL, ic, TRUE);
5992 }
5993
5994
5995 /*-----------------------------------------------------------------*/
5996 /* genOrOp - for || operation                                      */
5997 /*-----------------------------------------------------------------*/
5998 static void
5999 genOrOp (iCode * ic)
6000 {
6001   operand *left, *right, *result;
6002   symbol *tlbl;
6003
6004   D (emitcode (";", "genOrOp "););
6005
6006   /* note here that || operations that are in an
6007      if statement are taken away by backPatchLabels
6008      only those used in arthmetic operations remain */
6009   AOP_OP_2 (ic);
6010   AOP_SET_LOCALS (ic);
6011
6012   /* if both are bit variables */
6013   if (AOP_TYPE (left) == AOP_CRY &&
6014       AOP_TYPE (right) == AOP_CRY)
6015     {
6016       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6017       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6018       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6019       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6020   
6021       aopOp (result,ic,FALSE, FALSE);
6022       
6023       outBitC (result);
6024     }
6025   else
6026     {
6027       tlbl = newiTempLabel (NULL);
6028       toBoolean (left);
6029       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6030       toBoolean (right);
6031       emitcode ("", "!tlabeldef", tlbl->key + 100);
6032       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6033       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6034   
6035       aopOp (result,ic,FALSE, FALSE);
6036       
6037       outBitAcc (result);
6038     }
6039
6040   freeAsmop (result, NULL, ic, TRUE);
6041 }
6042
6043 /*-----------------------------------------------------------------*/
6044 /* isLiteralBit - test if lit == 2^n                               */
6045 /*-----------------------------------------------------------------*/
6046 static int
6047 isLiteralBit (unsigned long lit)
6048 {
6049   unsigned long pw[32] =
6050   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6051    0x100L, 0x200L, 0x400L, 0x800L,
6052    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6053    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6054    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6055    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6056    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6057   int idx;
6058
6059   for (idx = 0; idx < 32; idx++)
6060     if (lit == pw[idx])
6061       return idx + 1;
6062   return 0;
6063 }
6064
6065 /*-----------------------------------------------------------------*/
6066 /* continueIfTrue -                                                */
6067 /*-----------------------------------------------------------------*/
6068 static void
6069 continueIfTrue (iCode * ic)
6070 {
6071   if (IC_TRUE (ic))
6072     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6073   ic->generated = 1;
6074 }
6075
6076 /*-----------------------------------------------------------------*/
6077 /* jmpIfTrue -                                                     */
6078 /*-----------------------------------------------------------------*/
6079 static void
6080 jumpIfTrue (iCode * ic)
6081 {
6082   if (!IC_TRUE (ic))
6083     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6084   ic->generated = 1;
6085 }
6086
6087 /*-----------------------------------------------------------------*/
6088 /* jmpTrueOrFalse -                                                */
6089 /*-----------------------------------------------------------------*/
6090 static void
6091 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6092 {
6093   // ugly but optimized by peephole
6094   if (IC_TRUE (ic))
6095     {
6096       symbol *nlbl = newiTempLabel (NULL);
6097       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6098       emitcode ("", "!tlabeldef", tlbl->key + 100);
6099       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6100       emitcode ("", "!tlabeldef", nlbl->key + 100);
6101     }
6102   else
6103     {
6104       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6105       emitcode ("", "!tlabeldef", tlbl->key + 100);
6106     }
6107   ic->generated = 1;
6108 }
6109
6110 // Generate code to perform a bit-wise logic operation
6111 // on two operands in far space (assumed to already have been 
6112 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6113 // in far space. This requires pushing the result on the stack
6114 // then popping it into the result.
6115 static void
6116 genFarFarLogicOp(iCode *ic, char *logicOp)
6117 {
6118       int size, resultSize, compSize;
6119       int offset = 0;
6120       
6121       TR_AP("#5");
6122       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6123       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6124                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6125       
6126       _startLazyDPSEvaluation();
6127       for (size = compSize; (size--); offset++)
6128       {
6129           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6130           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6131           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6132           
6133           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6134           emitcode ("push", "acc");
6135       }
6136       _endLazyDPSEvaluation();
6137      
6138       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6139       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6140       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6141      
6142       resultSize = AOP_SIZE(IC_RESULT(ic));
6143
6144       ADJUST_PUSHED_RESULT(compSize, resultSize);
6145
6146       _startLazyDPSEvaluation();
6147       while (compSize--)
6148       {
6149           emitcode ("pop", "acc");
6150           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6151       }
6152       _endLazyDPSEvaluation();
6153       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6154 }
6155
6156
6157 /*-----------------------------------------------------------------*/
6158 /* genAnd  - code for and                                          */
6159 /*-----------------------------------------------------------------*/
6160 static void
6161 genAnd (iCode * ic, iCode * ifx)
6162 {
6163   operand *left, *right, *result;
6164   int size, offset = 0;
6165   unsigned long lit = 0L;
6166   int bytelit;
6167   char buff[10];
6168   bool pushResult;
6169
6170   D (emitcode (";", "genAnd "););
6171
6172   AOP_OP_3_NOFATAL (ic, pushResult);
6173   AOP_SET_LOCALS (ic);
6174
6175   if (pushResult)
6176   {
6177       genFarFarLogicOp(ic, "anl");
6178       return;
6179   }  
6180
6181 #ifdef DEBUG_TYPE
6182   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6183             AOP_TYPE (result),
6184             AOP_TYPE (left), AOP_TYPE (right));
6185   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6186             AOP_SIZE (result),
6187             AOP_SIZE (left), AOP_SIZE (right));
6188 #endif
6189
6190   /* if left is a literal & right is not then exchange them */
6191   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6192 #ifdef LOGIC_OPS_BROKEN      
6193     ||  AOP_NEEDSACC (left)
6194 #endif
6195     )
6196     {
6197       operand *tmp = right;
6198       right = left;
6199       left = tmp;
6200     }
6201
6202   /* if result = right then exchange them */
6203   if (sameRegs (AOP (result), AOP (right)))
6204     {
6205       operand *tmp = right;
6206       right = left;
6207       left = tmp;
6208     }
6209
6210   /* if right is bit then exchange them */
6211   if (AOP_TYPE (right) == AOP_CRY &&
6212       AOP_TYPE (left) != AOP_CRY)
6213     {
6214       operand *tmp = right;
6215       right = left;
6216       left = tmp;
6217     }
6218   if (AOP_TYPE (right) == AOP_LIT)
6219     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6220
6221   size = AOP_SIZE (result);
6222
6223   // if(bit & yy)
6224   // result = bit & yy;
6225   if (AOP_TYPE (left) == AOP_CRY)
6226     {
6227       // c = bit & literal;
6228       if (AOP_TYPE (right) == AOP_LIT)
6229         {
6230           if (lit & 1)
6231             {
6232               if (size && sameRegs (AOP (result), AOP (left)))
6233                 // no change
6234                 goto release;
6235               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6236             }
6237           else
6238             {
6239               // bit(result) = 0;
6240               if (size && (AOP_TYPE (result) == AOP_CRY))
6241                 {
6242                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6243                   goto release;
6244                 }
6245               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6246                 {
6247                   jumpIfTrue (ifx);
6248                   goto release;
6249                 }
6250               emitcode ("clr", "c");
6251             }
6252         }
6253       else
6254         {
6255           if (AOP_TYPE (right) == AOP_CRY)
6256             {
6257               // c = bit & bit;
6258               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6259               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6260             }
6261           else
6262             {
6263               // c = bit & val;
6264               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6265               // c = lsb
6266               emitcode ("rrc", "a");
6267               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6268             }
6269         }
6270       // bit = c
6271       // val = c
6272       if (size)
6273         outBitC (result);
6274       // if(bit & ...)
6275       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6276         genIfxJump (ifx, "c");
6277       goto release;
6278     }
6279
6280   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6281   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6282   if ((AOP_TYPE (right) == AOP_LIT) &&
6283       (AOP_TYPE (result) == AOP_CRY) &&
6284       (AOP_TYPE (left) != AOP_CRY))
6285     {
6286       int posbit = isLiteralBit (lit);
6287       /* left &  2^n */
6288       if (posbit)
6289         {
6290           posbit--;
6291           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6292           // bit = left & 2^n
6293           if (size)
6294             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6295           // if(left &  2^n)
6296           else
6297             {
6298               if (ifx)
6299                 {
6300                   SNPRINTF (buff, sizeof(buff), 
6301                             "acc.%d", posbit & 0x07);
6302                   genIfxJump (ifx, buff);
6303                 }
6304               else 
6305                   {
6306                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6307                   }
6308               goto release;
6309             }
6310         }
6311       else
6312         {
6313           symbol *tlbl = newiTempLabel (NULL);
6314           int sizel = AOP_SIZE (left);
6315           if (size)
6316             emitcode ("setb", "c");
6317           while (sizel--)
6318             {
6319               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6320                 {
6321                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6322                   // byte ==  2^n ?
6323                   if ((posbit = isLiteralBit (bytelit)) != 0)
6324                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6325                   else
6326                     {
6327                       if (bytelit != 0x0FFL)
6328                         emitcode ("anl", "a,%s",
6329                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6330                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6331                     }
6332                 }
6333               offset++;
6334             }
6335           // bit = left & literal
6336           if (size)
6337             {
6338               emitcode ("clr", "c");
6339               emitcode ("", "!tlabeldef", tlbl->key + 100);
6340             }
6341           // if(left & literal)
6342           else
6343             {
6344               if (ifx)
6345                 jmpTrueOrFalse (ifx, tlbl);
6346               goto release;
6347             }
6348         }
6349       outBitC (result);
6350       goto release;
6351     }
6352
6353   /* if left is same as result */
6354   if (sameRegs (AOP (result), AOP (left)))
6355     {
6356       for (; size--; offset++)
6357         {
6358           if (AOP_TYPE (right) == AOP_LIT)
6359             {
6360               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6361                 continue;
6362               else if (bytelit == 0)
6363                 aopPut (AOP (result), zero, offset);
6364               else if (IS_AOP_PREG (result))
6365                 {
6366                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6367                   emitcode ("anl", "a,%s",
6368                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6369                   aopPut (AOP (result), "a", offset);
6370                 }
6371               else
6372                 emitcode ("anl", "%s,%s",
6373                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6374                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6375             }
6376           else
6377             {
6378               if (AOP_TYPE (left) == AOP_ACC)
6379                 emitcode ("anl", "a,%s",
6380                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6381               else
6382                 {
6383                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6384                   if (IS_AOP_PREG (result))
6385                     {
6386                       emitcode ("anl", "a,%s",
6387                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6388                       aopPut (AOP (result), "a", offset);
6389                     }
6390                   else
6391                     emitcode ("anl", "%s,a",
6392                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6393                 }
6394             }
6395         }
6396     }
6397   else
6398     {
6399       // left & result in different registers
6400       if (AOP_TYPE (result) == AOP_CRY)
6401         {
6402           // result = bit
6403           // if(size), result in bit
6404           // if(!size && ifx), conditional oper: if(left & right)
6405           symbol *tlbl = newiTempLabel (NULL);
6406           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6407           if (size)
6408             emitcode ("setb", "c");
6409           while (sizer--)
6410             {
6411               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6412                 emitcode ("anl", "a,%s",
6413                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6414               } else {
6415                 if (AOP_TYPE(left)==AOP_ACC) {
6416                   emitcode("mov", "b,a");
6417                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6418                   emitcode("anl", "a,b");
6419                 }else {
6420                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6421                   emitcode ("anl", "a,%s",
6422                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6423                 }
6424               }
6425               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6426               offset++;
6427             }
6428           if (size)
6429             {
6430               CLRC;
6431               emitcode ("", "!tlabeldef", tlbl->key + 100);
6432               outBitC (result);
6433             }
6434           else if (ifx)
6435             jmpTrueOrFalse (ifx, tlbl);
6436         }
6437       else
6438         {
6439           for (; (size--); offset++)
6440             {
6441               // normal case
6442               // result = left & right
6443               if (AOP_TYPE (right) == AOP_LIT)
6444                 {
6445                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6446                     {
6447                       aopPut (AOP (result),
6448                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6449                               offset);
6450                       continue;
6451                     }
6452                   else if (bytelit == 0)
6453                     {
6454                       aopPut (AOP (result), zero, offset);
6455                       continue;
6456                     }
6457                   D (emitcode (";", "better literal AND."););
6458                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6459                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6460                                                     FALSE, FALSE, DP2_RESULT_REG));
6461
6462                 }
6463               else
6464                 {
6465                   // faster than result <- left, anl result,right
6466                   // and better if result is SFR
6467                   if (AOP_TYPE (left) == AOP_ACC)
6468                     {
6469                       emitcode ("anl", "a,%s", 
6470                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6471                     }
6472                   else
6473                     {
6474                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6475                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6476                       {
6477                           emitcode("mov", "b,a");
6478                           rOp = "b";
6479                       }
6480                         
6481                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6482                       emitcode ("anl", "a,%s", rOp);
6483                     }                   
6484                 }
6485               aopPut (AOP (result), "a", offset);
6486             }
6487         }
6488     }
6489
6490 release:
6491   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6492   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6493   freeAsmop (result, NULL, ic, TRUE);
6494 }
6495
6496
6497 /*-----------------------------------------------------------------*/
6498 /* genOr  - code for or                                            */
6499 /*-----------------------------------------------------------------*/
6500 static void
6501 genOr (iCode * ic, iCode * ifx)
6502 {
6503   operand *left, *right, *result;
6504   int size, offset = 0;
6505   unsigned long lit = 0L;
6506   bool     pushResult;
6507
6508   D (emitcode (";", "genOr "););
6509
6510   AOP_OP_3_NOFATAL (ic, pushResult);
6511   AOP_SET_LOCALS (ic);
6512
6513   if (pushResult)
6514   {
6515       genFarFarLogicOp(ic, "orl");
6516       return;
6517   }
6518
6519
6520 #ifdef DEBUG_TYPE
6521   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6522             AOP_TYPE (result),
6523             AOP_TYPE (left), AOP_TYPE (right));
6524   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6525             AOP_SIZE (result),
6526             AOP_SIZE (left), AOP_SIZE (right));
6527 #endif
6528
6529   /* if left is a literal & right is not then exchange them */
6530   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6531 #ifdef LOGIC_OPS_BROKEN
6532    || AOP_NEEDSACC (left) // I think this is a net loss now.
6533 #endif      
6534       )
6535     {
6536       operand *tmp = right;
6537       right = left;
6538       left = tmp;
6539     }
6540
6541   /* if result = right then exchange them */
6542   if (sameRegs (AOP (result), AOP (right)))
6543     {
6544       operand *tmp = right;
6545       right = left;
6546       left = tmp;
6547     }
6548
6549   /* if right is bit then exchange them */
6550   if (AOP_TYPE (right) == AOP_CRY &&
6551       AOP_TYPE (left) != AOP_CRY)
6552     {
6553       operand *tmp = right;
6554       right = left;
6555       left = tmp;
6556     }
6557   if (AOP_TYPE (right) == AOP_LIT)
6558     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6559
6560   size = AOP_SIZE (result);
6561
6562   // if(bit | yy)
6563   // xx = bit | yy;
6564   if (AOP_TYPE (left) == AOP_CRY)
6565     {
6566       if (AOP_TYPE (right) == AOP_LIT)
6567         {
6568           // c = bit & literal;
6569           if (lit)
6570             {
6571               // lit != 0 => result = 1
6572               if (AOP_TYPE (result) == AOP_CRY)
6573                 {
6574                   if (size)
6575                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6576                   else if (ifx)
6577                     continueIfTrue (ifx);
6578                   goto release;
6579                 }
6580               emitcode ("setb", "c");
6581             }
6582           else
6583             {
6584               // lit == 0 => result = left
6585               if (size && sameRegs (AOP (result), AOP (left)))
6586                 goto release;
6587               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6588             }
6589         }
6590       else
6591         {
6592           if (AOP_TYPE (right) == AOP_CRY)
6593             {
6594               // c = bit | bit;
6595               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6596               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6597             }
6598           else
6599             {
6600               // c = bit | val;
6601               symbol *tlbl = newiTempLabel (NULL);
6602               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6603                 emitcode ("setb", "c");
6604               emitcode ("jb", "%s,!tlabel",
6605                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6606               toBoolean (right);
6607               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6608               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6609                 {
6610                   jmpTrueOrFalse (ifx, tlbl);
6611                   goto release;
6612                 }
6613               else
6614                 {
6615                   CLRC;
6616                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6617                 }
6618             }
6619         }
6620       // bit = c
6621       // val = c
6622       if (size)
6623         outBitC (result);
6624       // if(bit | ...)
6625       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6626            genIfxJump (ifx, "c");
6627       goto release;
6628     }
6629
6630   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6631   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6632   if ((AOP_TYPE (right) == AOP_LIT) &&
6633       (AOP_TYPE (result) == AOP_CRY) &&
6634       (AOP_TYPE (left) != AOP_CRY))
6635     {
6636       if (lit)
6637         {
6638           // result = 1
6639           if (size)
6640             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6641           else
6642             continueIfTrue (ifx);
6643           goto release;
6644         }
6645       else
6646         {
6647           // lit = 0, result = boolean(left)
6648           if (size)
6649             emitcode ("setb", "c");
6650           toBoolean (right);
6651           if (size)
6652             {
6653               symbol *tlbl = newiTempLabel (NULL);
6654               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6655               CLRC;
6656               emitcode ("", "!tlabeldef", tlbl->key + 100);
6657             }
6658           else
6659             {
6660               genIfxJump (ifx, "a");
6661               goto release;
6662             }
6663         }
6664       outBitC (result);
6665       goto release;
6666     }
6667
6668   /* if left is same as result */
6669   if (sameRegs (AOP (result), AOP (left)))
6670     {
6671       for (; size--; offset++)
6672         {
6673           if (AOP_TYPE (right) == AOP_LIT)
6674             {
6675               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6676                 {
6677                   continue;
6678                 }
6679               else
6680                 {
6681                   if (IS_AOP_PREG (left))
6682                     {
6683                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6684                       emitcode ("orl", "a,%s",
6685                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6686                       aopPut (AOP (result), "a", offset);
6687                     }
6688                   else
6689                     {
6690                       emitcode ("orl", "%s,%s",
6691                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6692                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6693                     }
6694                 }
6695             }
6696           else
6697             {
6698               if (AOP_TYPE (left) == AOP_ACC)
6699                 {
6700                   emitcode ("orl", "a,%s",
6701                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6702                 }
6703               else
6704                 {
6705                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6706                   if (IS_AOP_PREG (left))
6707                     {
6708                       emitcode ("orl", "a,%s", 
6709                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6710                       aopPut (AOP (result), "a", offset);
6711                     }
6712                   else
6713                     {
6714                       emitcode ("orl", "%s,a",
6715                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6716                     }
6717                 }
6718             }
6719         }
6720     }
6721   else
6722     {
6723       // left & result in different registers
6724       if (AOP_TYPE (result) == AOP_CRY)
6725         {
6726           // result = bit
6727           // if(size), result in bit
6728           // if(!size && ifx), conditional oper: if(left | right)
6729           symbol *tlbl = newiTempLabel (NULL);
6730           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6731           if (size)
6732             emitcode ("setb", "c");
6733           while (sizer--)
6734             {
6735               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6736                 emitcode ("orl", "a,%s",
6737                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6738               } else {
6739                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6740                 emitcode ("orl", "a,%s",
6741                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6742               }
6743               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6744               offset++;
6745             }
6746           if (size)
6747             {
6748               CLRC;
6749               emitcode ("", "!tlabeldef", tlbl->key + 100);
6750               outBitC (result);
6751             }
6752           else if (ifx)
6753             jmpTrueOrFalse (ifx, tlbl);
6754         }
6755       else
6756         {
6757             _startLazyDPSEvaluation();
6758           for (; (size--); offset++)
6759             {
6760               // normal case
6761               // result = left & right
6762               if (AOP_TYPE (right) == AOP_LIT)
6763                 {
6764                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6765                     {
6766                       aopPut (AOP (result),
6767                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6768                               offset);
6769                       continue;
6770                     }
6771                   D (emitcode (";", "better literal OR."););
6772                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6773                   emitcode ("orl", "a, %s",
6774                             aopGet (AOP (right), offset,
6775                                     FALSE, FALSE, DP2_RESULT_REG));
6776
6777                 }
6778               else
6779                 {
6780                   // faster than result <- left, anl result,right
6781                   // and better if result is SFR
6782                   if (AOP_TYPE (left) == AOP_ACC)
6783                     {
6784                       emitcode ("orl", "a,%s",
6785                                 aopGet (AOP (right), offset,
6786                                         FALSE, FALSE, DP2_RESULT_REG));
6787                     }
6788                   else
6789                     {
6790                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6791                         
6792                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6793                       {
6794                           emitcode("mov", "b,a");
6795                           rOp = "b";
6796                       }
6797                         
6798                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6799                       emitcode ("orl", "a,%s", rOp);
6800                     }
6801                 }
6802               aopPut (AOP (result), "a", offset);
6803             }
6804             _endLazyDPSEvaluation();
6805         }
6806     }
6807
6808 release:
6809   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6810   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6811   freeAsmop (result, NULL, ic, TRUE);
6812 }
6813
6814 /*-----------------------------------------------------------------*/
6815 /* genXor - code for xclusive or                                   */
6816 /*-----------------------------------------------------------------*/
6817 static void
6818 genXor (iCode * ic, iCode * ifx)
6819 {
6820   operand *left, *right, *result;
6821   int size, offset = 0;
6822   unsigned long lit = 0L;
6823   bool pushResult;
6824
6825   D (emitcode (";", "genXor "););
6826
6827   AOP_OP_3_NOFATAL (ic, pushResult);
6828   AOP_SET_LOCALS (ic);
6829
6830   if (pushResult)
6831   {
6832       genFarFarLogicOp(ic, "xrl");
6833       return;
6834   }  
6835
6836 #ifdef DEBUG_TYPE
6837   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6838             AOP_TYPE (result),
6839             AOP_TYPE (left), AOP_TYPE (right));
6840   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6841             AOP_SIZE (result),
6842             AOP_SIZE (left), AOP_SIZE (right));
6843 #endif
6844
6845   /* if left is a literal & right is not ||
6846      if left needs acc & right does not */
6847   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6848 #ifdef LOGIC_OPS_BROKEN      
6849       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6850 #endif
6851      )
6852     {
6853       operand *tmp = right;
6854       right = left;
6855       left = tmp;
6856     }
6857
6858   /* if result = right then exchange them */
6859   if (sameRegs (AOP (result), AOP (right)))
6860     {
6861       operand *tmp = right;
6862       right = left;
6863       left = tmp;
6864     }
6865
6866   /* if right is bit then exchange them */
6867   if (AOP_TYPE (right) == AOP_CRY &&
6868       AOP_TYPE (left) != AOP_CRY)
6869     {
6870       operand *tmp = right;
6871       right = left;
6872       left = tmp;
6873     }
6874   if (AOP_TYPE (right) == AOP_LIT)
6875     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6876
6877   size = AOP_SIZE (result);
6878
6879   // if(bit ^ yy)
6880   // xx = bit ^ yy;
6881   if (AOP_TYPE (left) == AOP_CRY)
6882     {
6883       if (AOP_TYPE (right) == AOP_LIT)
6884         {
6885           // c = bit & literal;
6886           if (lit >> 1)
6887             {
6888               // lit>>1  != 0 => result = 1
6889               if (AOP_TYPE (result) == AOP_CRY)
6890                 {
6891                   if (size)
6892                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6893                   else if (ifx)
6894                     continueIfTrue (ifx);
6895                   goto release;
6896                 }
6897               emitcode ("setb", "c");
6898             }
6899           else
6900             {
6901               // lit == (0 or 1)
6902               if (lit == 0)
6903                 {
6904                   // lit == 0, result = left
6905                   if (size && sameRegs (AOP (result), AOP (left)))
6906                     goto release;
6907                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6908                 }
6909               else
6910                 {
6911                   // lit == 1, result = not(left)
6912                   if (size && sameRegs (AOP (result), AOP (left)))
6913                     {
6914                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6915                       goto release;
6916                     }
6917                   else
6918                     {
6919                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6920                       emitcode ("cpl", "c");
6921                     }
6922                 }
6923             }
6924
6925         }
6926       else
6927         {
6928           // right != literal
6929           symbol *tlbl = newiTempLabel (NULL);
6930           if (AOP_TYPE (right) == AOP_CRY)
6931             {
6932               // c = bit ^ bit;
6933               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6934             }
6935           else
6936             {
6937               int sizer = AOP_SIZE (right);
6938               // c = bit ^ val
6939               // if val>>1 != 0, result = 1
6940               emitcode ("setb", "c");
6941               while (sizer)
6942                 {
6943                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6944                   if (sizer == 1)
6945                     // test the msb of the lsb
6946                     emitcode ("anl", "a,#!constbyte",0xfe);
6947                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6948                   sizer--;
6949                 }
6950               // val = (0,1)
6951               emitcode ("rrc", "a");
6952             }
6953           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6954           emitcode ("cpl", "c");
6955           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6956         }
6957       // bit = c
6958       // val = c
6959       if (size)
6960         outBitC (result);
6961       // if(bit | ...)
6962       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6963         genIfxJump (ifx, "c");
6964       goto release;
6965     }
6966
6967   if (sameRegs (AOP (result), AOP (left)))
6968     {
6969       /* if left is same as result */
6970       for (; size--; offset++)
6971         {
6972           if (AOP_TYPE (right) == AOP_LIT)
6973             {
6974               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6975                 continue;
6976               else if (IS_AOP_PREG (left))
6977                 {
6978                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6979                   emitcode ("xrl", "a,%s",
6980                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6981                   aopPut (AOP (result), "a", offset);
6982                 }
6983               else
6984                 emitcode ("xrl", "%s,%s",
6985                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6986                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6987             }
6988           else
6989             {
6990               if (AOP_TYPE (left) == AOP_ACC)
6991                 emitcode ("xrl", "a,%s",
6992                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6993               else
6994                 {
6995                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6996                   if (IS_AOP_PREG (left))
6997                     {
6998                       emitcode ("xrl", "a,%s",
6999                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7000                       aopPut (AOP (result), "a", offset);
7001                     }
7002                   else
7003                     emitcode ("xrl", "%s,a",
7004                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7005                 }
7006             }
7007         }
7008     }
7009   else
7010     {
7011       // left & result in different registers
7012       if (AOP_TYPE (result) == AOP_CRY)
7013         {
7014           // result = bit
7015           // if(size), result in bit
7016           // if(!size && ifx), conditional oper: if(left ^ right)
7017           symbol *tlbl = newiTempLabel (NULL);
7018           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7019                   
7020           if (size)
7021             emitcode ("setb", "c");
7022           while (sizer--)
7023             {
7024               if ((AOP_TYPE (right) == AOP_LIT) &&
7025                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7026                 {
7027                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7028                 }
7029               else
7030                 {
7031                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7032                     emitcode ("xrl", "a,%s",
7033                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7034                   } else {
7035                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7036                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7037                       {
7038                           emitcode("mov", "b,a");
7039                           rOp = "b";
7040                       }
7041                         
7042                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7043                       emitcode ("xrl", "a,%s", rOp);                  
7044                   }
7045                 }
7046               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7047               offset++;
7048             }
7049           if (size)
7050             {
7051               CLRC;
7052               emitcode ("", "!tlabeldef", tlbl->key + 100);
7053               outBitC (result);
7054             }
7055           else if (ifx)
7056             jmpTrueOrFalse (ifx, tlbl);
7057         }
7058       else
7059         {
7060         for (; (size--); offset++)
7061           {
7062             // normal case
7063             // result = left & right
7064             if (AOP_TYPE (right) == AOP_LIT)
7065               {
7066                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7067                   {
7068                     aopPut (AOP (result),
7069                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7070                             offset);
7071                     continue;
7072                   }
7073                 D (emitcode (";", "better literal XOR."););
7074                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7075                 emitcode ("xrl", "a, %s",
7076                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7077               }
7078             else
7079               {
7080                 // faster than result <- left, anl result,right
7081                 // and better if result is SFR
7082                 if (AOP_TYPE (left) == AOP_ACC)
7083                   {
7084                     emitcode ("xrl", "a,%s",
7085                               aopGet (AOP (right), offset,
7086                                       FALSE, FALSE, DP2_RESULT_REG));
7087                   }
7088                 else
7089                   {
7090                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7091                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7092                       {
7093                           emitcode("mov", "b,a");
7094                           rOp = "b";
7095                       }
7096                         
7097                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7098                       emitcode ("xrl", "a,%s", rOp);
7099                   }
7100               }
7101             aopPut (AOP (result), "a", offset);
7102           }
7103         }
7104         
7105     }
7106
7107 release:
7108   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7109   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7110   freeAsmop (result, NULL, ic, TRUE);
7111 }
7112
7113 /*-----------------------------------------------------------------*/
7114 /* genInline - write the inline code out                           */
7115 /*-----------------------------------------------------------------*/
7116 static void
7117 genInline (iCode * ic)
7118 {
7119   char *buffer, *bp, *bp1;
7120
7121   D (emitcode (";", "genInline "); );
7122
7123   _G.inLine += (!options.asmpeep);
7124
7125   buffer = Safe_strdup(IC_INLINE(ic));
7126   bp = buffer;
7127   bp1 = buffer;
7128
7129   /* emit each line as a code */
7130   while (*bp)
7131     {
7132       if (*bp == '\n')
7133         {
7134           *bp++ = '\0';
7135           emitcode (bp1, "");
7136           bp1 = bp;
7137         }
7138       else
7139         {
7140           if (*bp == ':')
7141             {
7142               bp++;
7143               *bp = '\0';
7144               bp++;
7145               emitcode (bp1, "");
7146               bp1 = bp;
7147             }
7148           else
7149             bp++;
7150         }
7151     }
7152   if (bp1 != bp)
7153     emitcode (bp1, "");
7154   /*     emitcode("",buffer); */
7155   _G.inLine -= (!options.asmpeep);
7156 }
7157
7158 /*-----------------------------------------------------------------*/
7159 /* genRRC - rotate right with carry                                */
7160 /*-----------------------------------------------------------------*/
7161 static void
7162 genRRC (iCode * ic)
7163 {
7164   operand *left, *result;
7165   int     size, offset;
7166
7167   D (emitcode (";", "genRRC "););
7168
7169   /* rotate right with carry */
7170   left = IC_LEFT (ic);
7171   result = IC_RESULT (ic);
7172   aopOp (left, ic, FALSE, FALSE);
7173   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7174
7175   /* move it to the result */
7176   size = AOP_SIZE (result);
7177   offset = size - 1;
7178   CLRC;
7179
7180   _startLazyDPSEvaluation ();
7181   while (size--)
7182     {
7183       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7184       emitcode ("rrc", "a");
7185       if (AOP_SIZE (result) > 1)
7186         aopPut (AOP (result), "a", offset--);
7187     }
7188   _endLazyDPSEvaluation ();
7189
7190   /* now we need to put the carry into the
7191      highest order byte of the result */
7192   if (AOP_SIZE (result) > 1)
7193     {
7194       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7195     }
7196   emitcode ("mov", "acc.7,c");
7197   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7198   freeAsmop (left, NULL, ic, TRUE);
7199   freeAsmop (result, NULL, ic, TRUE);
7200 }
7201
7202 /*-----------------------------------------------------------------*/
7203 /* genRLC - generate code for rotate left with carry               */
7204 /*-----------------------------------------------------------------*/
7205 static void
7206 genRLC (iCode * ic)
7207 {
7208   operand *left, *result;
7209   int size, offset;
7210   char *l;
7211
7212   D (emitcode (";", "genRLC "););
7213
7214   /* rotate right with carry */
7215   left = IC_LEFT (ic);
7216   result = IC_RESULT (ic);
7217   aopOp (left, ic, FALSE, FALSE);
7218   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7219
7220   /* move it to the result */
7221   size = AOP_SIZE (result);
7222   offset = 0;
7223   if (size--)
7224     {
7225       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7226       MOVA (l);
7227       emitcode ("add", "a,acc");
7228       if (AOP_SIZE (result) > 1)
7229         {
7230           aopPut (AOP (result), "a", offset++);
7231         }
7232
7233       _startLazyDPSEvaluation ();
7234       while (size--)
7235         {
7236           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7237           MOVA (l);
7238           emitcode ("rlc", "a");
7239           if (AOP_SIZE (result) > 1)
7240             aopPut (AOP (result), "a", offset++);
7241         }
7242       _endLazyDPSEvaluation ();
7243     }
7244   /* now we need to put the carry into the
7245      highest order byte of the result */
7246   if (AOP_SIZE (result) > 1)
7247     {
7248       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7249       MOVA (l);
7250     }
7251   emitcode ("mov", "acc.0,c");
7252   aopPut (AOP (result), "a", 0);
7253   freeAsmop (left, NULL, ic, TRUE);
7254   freeAsmop (result, NULL, ic, TRUE);
7255 }
7256
7257 /*-----------------------------------------------------------------*/
7258 /* genGetHbit - generates code get highest order bit               */
7259 /*-----------------------------------------------------------------*/
7260 static void
7261 genGetHbit (iCode * ic)
7262 {
7263   operand *left, *result;
7264   left = IC_LEFT (ic);
7265   result = IC_RESULT (ic);
7266   aopOp (left, ic, FALSE, FALSE);
7267   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7268
7269   D (emitcode (";", "genGetHbit "););
7270
7271   /* get the highest order byte into a */
7272   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7273   if (AOP_TYPE (result) == AOP_CRY)
7274     {
7275       emitcode ("rlc", "a");
7276       outBitC (result);
7277     }
7278   else
7279     {
7280       emitcode ("rl", "a");
7281       emitcode ("anl", "a,#1");
7282       outAcc (result);
7283     }
7284
7285
7286   freeAsmop (left, NULL, ic, TRUE);
7287   freeAsmop (result, NULL, ic, TRUE);
7288 }
7289
7290 /*-----------------------------------------------------------------*/
7291 /* AccRol - rotate left accumulator by known count                 */
7292 /*-----------------------------------------------------------------*/
7293 static void
7294 AccRol (int shCount)
7295 {
7296   shCount &= 0x0007;            // shCount : 0..7
7297
7298   switch (shCount)
7299     {
7300     case 0:
7301       break;
7302     case 1:
7303       emitcode ("rl", "a");
7304       break;
7305     case 2:
7306       emitcode ("rl", "a");
7307       emitcode ("rl", "a");
7308       break;
7309     case 3:
7310       emitcode ("swap", "a");
7311       emitcode ("rr", "a");
7312       break;
7313     case 4:
7314       emitcode ("swap", "a");
7315       break;
7316     case 5:
7317       emitcode ("swap", "a");
7318       emitcode ("rl", "a");
7319       break;
7320     case 6:
7321       emitcode ("rr", "a");
7322       emitcode ("rr", "a");
7323       break;
7324     case 7:
7325       emitcode ("rr", "a");
7326       break;
7327     }
7328 }
7329
7330 /*-----------------------------------------------------------------*/
7331 /* AccLsh - left shift accumulator by known count                  */
7332 /*-----------------------------------------------------------------*/
7333 static void
7334 AccLsh (int shCount)
7335 {
7336   if (shCount != 0)
7337     {
7338       if (shCount == 1)
7339         emitcode ("add", "a,acc");
7340       else if (shCount == 2)
7341         {
7342           emitcode ("add", "a,acc");
7343           emitcode ("add", "a,acc");
7344         }
7345       else
7346         {
7347           /* rotate left accumulator */
7348           AccRol (shCount);
7349           /* and kill the lower order bits */
7350           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7351         }
7352     }
7353 }
7354
7355 /*-----------------------------------------------------------------*/
7356 /* AccRsh - right shift accumulator by known count                 */
7357 /*-----------------------------------------------------------------*/
7358 static void
7359 AccRsh (int shCount)
7360 {
7361   if (shCount != 0)
7362     {
7363       if (shCount == 1)
7364         {
7365           CLRC;
7366           emitcode ("rrc", "a");
7367         }
7368       else
7369         {
7370           /* rotate right accumulator */
7371           AccRol (8 - shCount);
7372           /* and kill the higher order bits */
7373           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7374         }
7375     }
7376 }
7377
7378 #ifdef BETTER_LITERAL_SHIFT
7379 /*-----------------------------------------------------------------*/
7380 /* AccSRsh - signed right shift accumulator by known count                 */
7381 /*-----------------------------------------------------------------*/
7382 static void
7383 AccSRsh (int shCount)
7384 {
7385   symbol *tlbl;
7386   if (shCount != 0)
7387     {
7388       if (shCount == 1)
7389         {
7390           emitcode ("mov", "c,acc.7");
7391           emitcode ("rrc", "a");
7392         }
7393       else if (shCount == 2)
7394         {
7395           emitcode ("mov", "c,acc.7");
7396           emitcode ("rrc", "a");
7397           emitcode ("mov", "c,acc.7");
7398           emitcode ("rrc", "a");
7399         }
7400       else
7401         {
7402           tlbl = newiTempLabel (NULL);
7403           /* rotate right accumulator */
7404           AccRol (8 - shCount);
7405           /* and kill the higher order bits */
7406           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7407           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7408           emitcode ("orl", "a,#!constbyte",
7409                     (unsigned char) ~SRMask[shCount]);
7410           emitcode ("", "!tlabeldef", tlbl->key + 100);
7411         }
7412     }
7413 }
7414 #endif
7415
7416 #ifdef BETTER_LITERAL_SHIFT
7417 /*-----------------------------------------------------------------*/
7418 /* shiftR1Left2Result - shift right one byte from left to result   */
7419 /*-----------------------------------------------------------------*/
7420 static void
7421 shiftR1Left2Result (operand * left, int offl,
7422                     operand * result, int offr,
7423                     int shCount, int sign)
7424 {
7425   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7426   /* shift right accumulator */
7427   if (sign)
7428     AccSRsh (shCount);
7429   else
7430     AccRsh (shCount);
7431   aopPut (AOP (result), "a", offr);
7432 }
7433 #endif
7434
7435 #ifdef BETTER_LITERAL_SHIFT
7436 /*-----------------------------------------------------------------*/
7437 /* shiftL1Left2Result - shift left one byte from left to result    */
7438 /*-----------------------------------------------------------------*/
7439 static void
7440 shiftL1Left2Result (operand * left, int offl,
7441                     operand * result, int offr, int shCount)
7442 {
7443   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7444   /* shift left accumulator */
7445   AccLsh (shCount);
7446   aopPut (AOP (result), "a", offr);
7447 }
7448 #endif
7449
7450 #ifdef BETTER_LITERAL_SHIFT
7451 /*-----------------------------------------------------------------*/
7452 /* movLeft2Result - move byte from left to result                  */
7453 /*-----------------------------------------------------------------*/
7454 static void
7455 movLeft2Result (operand * left, int offl,
7456                 operand * result, int offr, int sign)
7457 {
7458   char *l;
7459   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7460   {
7461       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7462
7463       if (*l == '@' && (IS_AOP_PREG (result)))
7464       {
7465           emitcode ("mov", "a,%s", l);
7466           aopPut (AOP (result), "a", offr);
7467       }
7468       else
7469       {
7470           if (!sign)
7471           {
7472             aopPut (AOP (result), l, offr);
7473           }
7474           else
7475             {
7476               /* MSB sign in acc.7 ! */
7477               if (getDataSize (left) == offl + 1)
7478                 {
7479                   emitcode ("mov", "a,%s", l);
7480                   aopPut (AOP (result), "a", offr);
7481                 }
7482             }
7483       }
7484   }
7485 }
7486 #endif
7487
7488 #ifdef BETTER_LITERAL_SHIFT
7489 /*-----------------------------------------------------------------*/
7490 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7491 /*-----------------------------------------------------------------*/
7492 static void
7493 AccAXRrl1 (char *x)
7494 {
7495   emitcode ("rrc", "a");
7496   emitcode ("xch", "a,%s", x);
7497   emitcode ("rrc", "a");
7498   emitcode ("xch", "a,%s", x);
7499 }
7500 #endif
7501
7502 #ifdef BETTER_LITERAL_SHIFT
7503 //REMOVE ME!!!
7504 /*-----------------------------------------------------------------*/
7505 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7506 /*-----------------------------------------------------------------*/
7507 static void
7508 AccAXLrl1 (char *x)
7509 {
7510   emitcode ("xch", "a,%s", x);
7511   emitcode ("rlc", "a");
7512   emitcode ("xch", "a,%s", x);
7513   emitcode ("rlc", "a");
7514 }
7515 #endif
7516
7517 #ifdef BETTER_LITERAL_SHIFT
7518 /*-----------------------------------------------------------------*/
7519 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7520 /*-----------------------------------------------------------------*/
7521 static void
7522 AccAXLsh1 (char *x)
7523 {
7524   emitcode ("xch", "a,%s", x);
7525   emitcode ("add", "a,acc");
7526   emitcode ("xch", "a,%s", x);
7527   emitcode ("rlc", "a");
7528 }
7529 #endif
7530
7531 #ifdef BETTER_LITERAL_SHIFT
7532 /*-----------------------------------------------------------------*/
7533 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7534 /*-----------------------------------------------------------------*/
7535 static void
7536 AccAXLsh (char *x, int shCount)
7537 {
7538   switch (shCount)
7539     {
7540     case 0:
7541       break;
7542     case 1:
7543       AccAXLsh1 (x);
7544       break;
7545     case 2:
7546       AccAXLsh1 (x);
7547       AccAXLsh1 (x);
7548       break;
7549     case 3:
7550     case 4:
7551     case 5:                     // AAAAABBB:CCCCCDDD
7552
7553       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7554
7555       emitcode ("anl", "a,#!constbyte",
7556                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7557
7558       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7559
7560       AccRol (shCount);         // DDDCCCCC:BBB00000
7561
7562       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7563
7564       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7565
7566       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7567
7568       emitcode ("anl", "a,#!constbyte",
7569                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7570
7571       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7572
7573       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7574
7575       break;
7576     case 6:                     // AAAAAABB:CCCCCCDD
7577       emitcode ("anl", "a,#!constbyte",
7578                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7579       emitcode ("mov", "c,acc.0");      // c = B
7580       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7581 #if 0
7582       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7583       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7584 #else
7585       emitcode("rrc","a"); 
7586       emitcode("xch","a,%s", x); 
7587       emitcode("rrc","a"); 
7588       emitcode("mov","c,acc.0"); //<< get correct bit 
7589       emitcode("xch","a,%s", x); 
7590
7591       emitcode("rrc","a"); 
7592       emitcode("xch","a,%s", x); 
7593       emitcode("rrc","a"); 
7594       emitcode("xch","a,%s", x); 
7595 #endif
7596       break;
7597     case 7:                     // a:x <<= 7
7598
7599       emitcode ("anl", "a,#!constbyte",
7600                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7601
7602       emitcode ("mov", "c,acc.0");      // c = B
7603
7604       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7605
7606       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7607
7608       break;
7609     default:
7610       break;
7611     }
7612 }
7613 #endif
7614
7615 #ifdef BETTER_LITERAL_SHIFT
7616 //REMOVE ME!!!
7617 /*-----------------------------------------------------------------*/
7618 /* AccAXRsh - right shift a:x known count (0..7)                   */
7619 /*-----------------------------------------------------------------*/
7620 static void
7621 AccAXRsh (char *x, int shCount)
7622 {
7623   switch (shCount)
7624     {
7625     case 0:
7626       break;
7627     case 1:
7628       CLRC;
7629       AccAXRrl1 (x);            // 0->a:x
7630
7631       break;
7632     case 2:
7633       CLRC;
7634       AccAXRrl1 (x);            // 0->a:x
7635
7636       CLRC;
7637       AccAXRrl1 (x);            // 0->a:x
7638
7639       break;
7640     case 3:
7641     case 4:
7642     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7643
7644       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7645
7646       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7647
7648       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7649
7650       emitcode ("anl", "a,#!constbyte",
7651                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7652
7653       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7654
7655       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7656
7657       emitcode ("anl", "a,#!constbyte",
7658                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7659
7660       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7661
7662       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7663
7664       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7665
7666       break;
7667     case 6:                     // AABBBBBB:CCDDDDDD
7668
7669       emitcode ("mov", "c,acc.7");
7670       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7671
7672       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7673
7674       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7675
7676       emitcode ("anl", "a,#!constbyte",
7677                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7678
7679       break;
7680     case 7:                     // ABBBBBBB:CDDDDDDD
7681
7682       emitcode ("mov", "c,acc.7");      // c = A
7683
7684       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7685
7686       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7687
7688       emitcode ("anl", "a,#!constbyte",
7689                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7690
7691       break;
7692     default:
7693       break;
7694     }
7695 }
7696 #endif
7697
7698 #ifdef BETTER_LITERAL_SHIFT
7699 /*-----------------------------------------------------------------*/
7700 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7701 /*-----------------------------------------------------------------*/
7702 static void
7703 AccAXRshS (char *x, int shCount)
7704 {
7705   symbol *tlbl;
7706   switch (shCount)
7707     {
7708     case 0:
7709       break;
7710     case 1:
7711       emitcode ("mov", "c,acc.7");
7712       AccAXRrl1 (x);            // s->a:x
7713
7714       break;
7715     case 2:
7716       emitcode ("mov", "c,acc.7");
7717       AccAXRrl1 (x);            // s->a:x
7718
7719       emitcode ("mov", "c,acc.7");
7720       AccAXRrl1 (x);            // s->a:x
7721
7722       break;
7723     case 3:
7724     case 4:
7725     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7726
7727       tlbl = newiTempLabel (NULL);
7728       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7729
7730       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7731
7732       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7733
7734       emitcode ("anl", "a,#!constbyte",
7735                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7736
7737       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7738
7739       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7740
7741       emitcode ("anl", "a,#!constbyte",
7742                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7743
7744       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7745
7746       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7747
7748       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7749
7750       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7751       emitcode ("orl", "a,#!constbyte",
7752                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7753
7754       emitcode ("", "!tlabeldef", tlbl->key + 100);
7755       break;                    // SSSSAAAA:BBBCCCCC
7756
7757     case 6:                     // AABBBBBB:CCDDDDDD
7758
7759       tlbl = newiTempLabel (NULL);
7760       emitcode ("mov", "c,acc.7");
7761       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7762
7763       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7764
7765       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7766
7767       emitcode ("anl", "a,#!constbyte",
7768                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7769
7770       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7771       emitcode ("orl", "a,#!constbyte",
7772                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7773
7774       emitcode ("", "!tlabeldef", tlbl->key + 100);
7775       break;
7776     case 7:                     // ABBBBBBB:CDDDDDDD
7777
7778       tlbl = newiTempLabel (NULL);
7779       emitcode ("mov", "c,acc.7");      // c = A
7780
7781       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7782
7783       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7784
7785       emitcode ("anl", "a,#!constbyte",
7786                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7787
7788       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7789       emitcode ("orl", "a,#!constbyte",
7790                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7791
7792       emitcode ("", "!tlabeldef", tlbl->key + 100);
7793       break;
7794     default:
7795       break;
7796     }
7797 }
7798 #endif
7799
7800 #ifdef BETTER_LITERAL_SHIFT
7801 static void
7802 _loadLeftIntoAx(char    **lsb, 
7803                 operand *left, 
7804                 operand *result,
7805                 int     offl,
7806                 int     offr)
7807 {
7808   // Get the initial value from left into a pair of registers.
7809   // MSB must be in A, LSB can be any register.
7810   //
7811   // If the result is held in registers, it is an optimization
7812   // if the LSB can be held in the register which will hold the,
7813   // result LSB since this saves us from having to copy it into
7814   // the result following AccAXLsh.
7815   //
7816   // If the result is addressed indirectly, this is not a gain.
7817   if (AOP_NEEDSACC(result))
7818   {
7819        char *leftByte;
7820        
7821        _startLazyDPSEvaluation();
7822       if (AOP_TYPE(left) == AOP_DPTR2)
7823        {
7824            // Get MSB in A.
7825            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7826            // get LSB in DP2_RESULT_REG.
7827            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7828            assert(!strcmp(leftByte, DP2_RESULT_REG));
7829        }
7830        else
7831        {
7832            // get LSB into DP2_RESULT_REG
7833            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7834            if (strcmp(leftByte, DP2_RESULT_REG))
7835            {
7836                TR_AP("#7");
7837                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7838            }
7839            // And MSB in A.
7840            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7841            assert(strcmp(leftByte, DP2_RESULT_REG));
7842            MOVA(leftByte);
7843        }
7844        _endLazyDPSEvaluation();
7845        *lsb = DP2_RESULT_REG;
7846   }
7847   else
7848   {
7849       if (sameRegs (AOP (result), AOP (left)) &&
7850         ((offl + MSB16) == offr))
7851       {
7852           /* don't crash result[offr] */
7853           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7854           emitcode ("xch", "a,%s", 
7855                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7856       }
7857       else
7858       {
7859           movLeft2Result (left, offl, result, offr, 0);
7860           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7861       }
7862       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7863       assert(strcmp(*lsb,"a"));      
7864   }
7865 }
7866
7867 static void
7868 _storeAxResults(char    *lsb,
7869                 operand *result,
7870                 int     offr)
7871 {
7872   _startLazyDPSEvaluation();
7873   if (AOP_NEEDSACC(result))
7874   {
7875       /* We have to explicitly update the result LSB.
7876        */
7877       emitcode("xch","a,%s", lsb);
7878       aopPut(AOP(result), "a", offr);
7879       emitcode("mov","a,%s", lsb);
7880   }
7881   if (getDataSize (result) > 1)
7882   {
7883       aopPut (AOP (result), "a", offr + MSB16);
7884   }
7885   _endLazyDPSEvaluation();
7886 }
7887
7888 /*-----------------------------------------------------------------*/
7889 /* shiftL2Left2Result - shift left two bytes from left to result   */
7890 /*-----------------------------------------------------------------*/
7891 static void
7892 shiftL2Left2Result (operand * left, int offl,
7893                     operand * result, int offr, int shCount)
7894 {
7895   char *lsb;
7896
7897   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7898   
7899   AccAXLsh (lsb, shCount);
7900   
7901   _storeAxResults(lsb, result, offr);
7902 }
7903 #endif
7904
7905 #ifdef BETTER_LITERAL_SHIFT
7906 /*-----------------------------------------------------------------*/
7907 /* shiftR2Left2Result - shift right two bytes from left to result  */
7908 /*-----------------------------------------------------------------*/
7909 static void
7910 shiftR2Left2Result (operand * left, int offl,
7911                     operand * result, int offr,
7912                     int shCount, int sign)
7913 {
7914   char *lsb;
7915   
7916   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7917   
7918   /* a:x >> shCount (x = lsb(result)) */
7919   if (sign)
7920   {
7921      AccAXRshS(lsb, shCount);
7922   }
7923   else
7924   {
7925     AccAXRsh(lsb, shCount);
7926   }
7927   
7928   _storeAxResults(lsb, result, offr);
7929 }
7930 #endif
7931
7932 /*-----------------------------------------------------------------*/
7933 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7934 /*-----------------------------------------------------------------*/
7935 static void
7936 shiftLLeftOrResult (operand * left, int offl,
7937                     operand * result, int offr, int shCount)
7938 {
7939   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7940   /* shift left accumulator */
7941   AccLsh (shCount);
7942   /* or with result */
7943   emitcode ("orl", "a,%s",
7944             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7945   /* back to result */
7946   aopPut (AOP (result), "a", offr);
7947 }
7948
7949 #if 0
7950 //REMOVE ME!!!
7951 /*-----------------------------------------------------------------*/
7952 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7953 /*-----------------------------------------------------------------*/
7954 static void
7955 shiftRLeftOrResult (operand * left, int offl,
7956                     operand * result, int offr, int shCount)
7957 {
7958   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7959   /* shift right accumulator */
7960   AccRsh (shCount);
7961   /* or with result */
7962   emitcode ("orl", "a,%s",
7963             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7964   /* back to result */
7965   aopPut (AOP (result), "a", offr);
7966 }
7967 #endif
7968
7969 #ifdef BETTER_LITERAL_SHIFT
7970 /*-----------------------------------------------------------------*/
7971 /* genlshOne - left shift a one byte quantity by known count       */
7972 /*-----------------------------------------------------------------*/
7973 static void
7974 genlshOne (operand * result, operand * left, int shCount)
7975 {
7976   D (emitcode (";", "genlshOne "););
7977   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7978 }
7979 #endif
7980
7981 #ifdef BETTER_LITERAL_SHIFT
7982 /*-----------------------------------------------------------------*/
7983 /* genlshTwo - left shift two bytes by known amount != 0           */
7984 /*-----------------------------------------------------------------*/
7985 static void
7986 genlshTwo (operand * result, operand * left, int shCount)
7987 {
7988   int size;
7989
7990   D (emitcode (";", "genlshTwo "););
7991
7992   size = getDataSize (result);
7993
7994   /* if shCount >= 8 */
7995   if (shCount >= 8)
7996   {
7997       shCount -= 8;
7998
7999       _startLazyDPSEvaluation();
8000
8001       if (size > 1)
8002         {
8003           if (shCount)
8004           {
8005             _endLazyDPSEvaluation();
8006             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8007             aopPut (AOP (result), zero, LSB);       
8008           }
8009           else
8010           {
8011             movLeft2Result (left, LSB, result, MSB16, 0);
8012             aopPut (AOP (result), zero, LSB);
8013             _endLazyDPSEvaluation();
8014           }
8015         }
8016         else
8017         {
8018           aopPut (AOP (result), zero, LSB);
8019           _endLazyDPSEvaluation();
8020         }
8021   }
8022
8023   /*  1 <= shCount <= 7 */
8024   else
8025     {
8026       if (size == 1)
8027       {
8028         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8029       }
8030       else
8031       {
8032         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8033       }
8034     }
8035 }
8036 #endif
8037
8038 #if 0
8039 //REMOVE ME!!!
8040 /*-----------------------------------------------------------------*/
8041 /* shiftLLong - shift left one long from left to result            */
8042 /* offl = LSB or MSB16                                             */
8043 /*-----------------------------------------------------------------*/
8044 static void
8045 shiftLLong (operand * left, operand * result, int offr)
8046 {
8047   char *l;
8048   int size = AOP_SIZE (result);
8049
8050   if (size >= LSB + offr)
8051     {
8052       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8053       MOVA (l);
8054       emitcode ("add", "a,acc");
8055       if (sameRegs (AOP (left), AOP (result)) &&
8056           size >= MSB16 + offr && offr != LSB)
8057         emitcode ("xch", "a,%s",
8058                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8059       else
8060         aopPut (AOP (result), "a", LSB + offr);
8061     }
8062
8063   if (size >= MSB16 + offr)
8064     {
8065       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8066         {
8067           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8068         }
8069       emitcode ("rlc", "a");
8070       if (sameRegs (AOP (left), AOP (result)) &&
8071           size >= MSB24 + offr && offr != LSB)
8072         emitcode ("xch", "a,%s",
8073                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8074       else
8075         aopPut (AOP (result), "a", MSB16 + offr);
8076     }
8077
8078   if (size >= MSB24 + offr)
8079     {
8080       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8081         {
8082           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8083         }
8084       emitcode ("rlc", "a");
8085       if (sameRegs (AOP (left), AOP (result)) &&
8086           size >= MSB32 + offr && offr != LSB)
8087         emitcode ("xch", "a,%s",
8088                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8089       else
8090         aopPut (AOP (result), "a", MSB24 + offr);
8091     }
8092
8093   if (size > MSB32 + offr)
8094     {
8095       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8096         {
8097           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8098         }
8099       emitcode ("rlc", "a");
8100       aopPut (AOP (result), "a", MSB32 + offr);
8101     }
8102   if (offr != LSB)
8103     aopPut (AOP (result), zero, LSB);
8104 }
8105 #endif
8106
8107 #if 0
8108 //REMOVE ME!!!
8109 /*-----------------------------------------------------------------*/
8110 /* genlshFour - shift four byte by a known amount != 0             */
8111 /*-----------------------------------------------------------------*/
8112 static void
8113 genlshFour (operand * result, operand * left, int shCount)
8114 {
8115   int size;
8116
8117   D (emitcode (";", "genlshFour ");
8118     );
8119
8120   size = AOP_SIZE (result);
8121
8122   /* if shifting more that 3 bytes */
8123   if (shCount >= 24)
8124     {
8125       shCount -= 24;
8126       if (shCount)
8127         /* lowest order of left goes to the highest
8128            order of the destination */
8129         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8130       else
8131         movLeft2Result (left, LSB, result, MSB32, 0);
8132       aopPut (AOP (result), zero, LSB);
8133       aopPut (AOP (result), zero, MSB16);
8134       aopPut (AOP (result), zero, MSB24);
8135       return;
8136     }
8137
8138   /* more than two bytes */
8139   else if (shCount >= 16)
8140     {
8141       /* lower order two bytes goes to higher order two bytes */
8142       shCount -= 16;
8143       /* if some more remaining */
8144       if (shCount)
8145         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8146       else
8147         {
8148           movLeft2Result (left, MSB16, result, MSB32, 0);
8149           movLeft2Result (left, LSB, result, MSB24, 0);
8150         }
8151       aopPut (AOP (result), zero, MSB16);
8152       aopPut (AOP (result), zero, LSB);
8153       return;
8154     }
8155
8156   /* if more than 1 byte */
8157   else if (shCount >= 8)
8158     {
8159       /* lower order three bytes goes to higher order  three bytes */
8160       shCount -= 8;
8161       if (size == 2)
8162         {
8163           if (shCount)
8164             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8165           else
8166             movLeft2Result (left, LSB, result, MSB16, 0);
8167         }
8168       else
8169         {                       /* size = 4 */
8170           if (shCount == 0)
8171             {
8172               movLeft2Result (left, MSB24, result, MSB32, 0);
8173               movLeft2Result (left, MSB16, result, MSB24, 0);
8174               movLeft2Result (left, LSB, result, MSB16, 0);
8175               aopPut (AOP (result), zero, LSB);
8176             }
8177           else if (shCount == 1)
8178             shiftLLong (left, result, MSB16);
8179           else
8180             {
8181               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8182               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8183               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8184               aopPut (AOP (result), zero, LSB);
8185             }
8186         }
8187     }
8188
8189   /* 1 <= shCount <= 7 */
8190   else if (shCount <= 2)
8191     {
8192       shiftLLong (left, result, LSB);
8193       if (shCount == 2)
8194         shiftLLong (result, result, LSB);
8195     }
8196   /* 3 <= shCount <= 7, optimize */
8197   else
8198     {
8199       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8200       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8201       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8202     }
8203 }
8204 #endif
8205
8206 #ifdef BETTER_LITERAL_SHIFT
8207 /*-----------------------------------------------------------------*/
8208 /* genLeftShiftLiteral - left shifting by known count              */
8209 /*-----------------------------------------------------------------*/
8210 static bool
8211 genLeftShiftLiteral (operand * left,
8212                      operand * right,
8213                      operand * result,
8214                      iCode * ic)
8215 {
8216   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8217   int size;
8218
8219   size = getSize (operandType (result));
8220
8221   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8222
8223   /* We only handle certain easy cases so far. */
8224   if ((shCount != 0)
8225    && (shCount < (size * 8))
8226    && (size != 1)
8227    && (size != 2))
8228   {
8229       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8230       return FALSE;
8231   }
8232
8233   freeAsmop (right, NULL, ic, TRUE);
8234
8235   aopOp(left, ic, FALSE, FALSE);
8236   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8237
8238 #if 0 // debug spew
8239   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8240   {
8241         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8242         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8243         {
8244            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8245         }
8246   }
8247   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8248   {
8249         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8250         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8251         {
8252            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8253         }       
8254   }  
8255 #endif
8256   
8257 #if VIEW_SIZE
8258   emitcode ("; shift left ", "result %d, left %d", size,
8259             AOP_SIZE (left));
8260 #endif
8261
8262   /* I suppose that the left size >= result size */
8263   if (shCount == 0)
8264   {
8265         _startLazyDPSEvaluation();
8266         while (size--)
8267         {
8268           movLeft2Result (left, size, result, size, 0);
8269         }
8270         _endLazyDPSEvaluation();
8271   }
8272   else if (shCount >= (size * 8))
8273   {
8274     _startLazyDPSEvaluation();
8275     while (size--)
8276     {
8277       aopPut (AOP (result), zero, size);
8278     }
8279     _endLazyDPSEvaluation();
8280   }
8281   else
8282   {
8283       switch (size)
8284         {
8285         case 1:
8286           genlshOne (result, left, shCount);
8287           break;
8288
8289         case 2:
8290           genlshTwo (result, left, shCount);
8291           break;
8292 #if 0
8293         case 4:
8294           genlshFour (result, left, shCount);
8295           break;
8296 #endif
8297         default:
8298           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8299           break;
8300         }
8301     }
8302   freeAsmop (left, NULL, ic, TRUE);
8303   freeAsmop (result, NULL, ic, TRUE);
8304   return TRUE;
8305 }
8306 #endif
8307
8308 /*-----------------------------------------------------------------*/
8309 /* genLeftShift - generates code for left shifting                 */
8310 /*-----------------------------------------------------------------*/
8311 static void
8312 genLeftShift (iCode * ic)
8313 {
8314   operand *left, *right, *result;
8315   int size, offset;
8316   char *l;
8317   symbol *tlbl, *tlbl1;
8318
8319   D (emitcode (";", "genLeftShift "););
8320
8321   right = IC_RIGHT (ic);
8322   left = IC_LEFT (ic);
8323   result = IC_RESULT (ic);
8324
8325   aopOp (right, ic, FALSE, FALSE);
8326
8327
8328 #ifdef BETTER_LITERAL_SHIFT
8329   /* if the shift count is known then do it
8330      as efficiently as possible */
8331   if (AOP_TYPE (right) == AOP_LIT)
8332     {
8333       if (genLeftShiftLiteral (left, right, result, ic))
8334       {
8335         return;
8336       }
8337     }
8338 #endif
8339
8340   /* shift count is unknown then we have to form
8341      a loop get the loop count in B : Note: we take
8342      only the lower order byte since shifting
8343      more that 32 bits make no sense anyway, ( the
8344      largest size of an object can be only 32 bits ) */
8345
8346   if (AOP_TYPE (right) == AOP_LIT)
8347   {
8348       /* Really should be handled by genLeftShiftLiteral,
8349        * but since I'm too lazy to fix that today, at least we can make
8350        * some small improvement.
8351        */
8352        emitcode("mov", "b,#!constbyte",
8353                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8354   }
8355   else
8356   {
8357       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8358       emitcode ("inc", "b");
8359   }
8360   freeAsmop (right, NULL, ic, TRUE);
8361   aopOp (left, ic, FALSE, FALSE);
8362   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8363
8364   /* now move the left to the result if they are not the
8365      same */
8366   if (!sameRegs (AOP (left), AOP (result)) &&
8367       AOP_SIZE (result) > 1)
8368     {
8369
8370       size = AOP_SIZE (result);
8371       offset = 0;
8372       _startLazyDPSEvaluation ();
8373       while (size--)
8374         {
8375           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8376           if (*l == '@' && (IS_AOP_PREG (result)))
8377             {
8378
8379               emitcode ("mov", "a,%s", l);
8380               aopPut (AOP (result), "a", offset);
8381             }
8382           else
8383             aopPut (AOP (result), l, offset);
8384           offset++;
8385         }
8386       _endLazyDPSEvaluation ();
8387     }
8388
8389   tlbl = newiTempLabel (NULL);
8390   size = AOP_SIZE (result);
8391   offset = 0;
8392   tlbl1 = newiTempLabel (NULL);
8393
8394   /* if it is only one byte then */
8395   if (size == 1)
8396     {
8397       symbol *tlbl1 = newiTempLabel (NULL);
8398
8399       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8400       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8401       emitcode ("", "!tlabeldef", tlbl->key + 100);
8402       emitcode ("add", "a,acc");
8403       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8404       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8405       aopPut (AOP (result), "a", 0);
8406       goto release;
8407     }
8408
8409   reAdjustPreg (AOP (result));
8410
8411   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8412   emitcode ("", "!tlabeldef", tlbl->key + 100);
8413   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8414   emitcode ("add", "a,acc");
8415   aopPut (AOP (result), "a", offset++);
8416   _startLazyDPSEvaluation ();
8417   while (--size)
8418     {
8419       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8420       emitcode ("rlc", "a");
8421       aopPut (AOP (result), "a", offset++);
8422     }
8423   _endLazyDPSEvaluation ();
8424   reAdjustPreg (AOP (result));
8425
8426   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8427   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8428 release:
8429   freeAsmop (left, NULL, ic, TRUE);
8430   freeAsmop (result, NULL, ic, TRUE);
8431 }
8432
8433 #ifdef BETTER_LITERAL_SHIFT
8434 /*-----------------------------------------------------------------*/
8435 /* genrshOne - right shift a one byte quantity by known count      */
8436 /*-----------------------------------------------------------------*/
8437 static void
8438 genrshOne (operand * result, operand * left,
8439            int shCount, int sign)
8440 {
8441   D (emitcode (";", "genrshOne"););
8442   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8443 }
8444 #endif
8445
8446 #ifdef BETTER_LITERAL_SHIFT
8447 /*-----------------------------------------------------------------*/
8448 /* genrshTwo - right shift two bytes by known amount != 0          */
8449 /*-----------------------------------------------------------------*/
8450 static void
8451 genrshTwo (operand * result, operand * left,
8452            int shCount, int sign)
8453 {
8454   D (emitcode (";", "genrshTwo"););
8455
8456   /* if shCount >= 8 */
8457   if (shCount >= 8)
8458     {
8459       shCount -= 8;
8460       _startLazyDPSEvaluation();
8461       if (shCount)
8462       {
8463         shiftR1Left2Result (left, MSB16, result, LSB,
8464                             shCount, sign);
8465       }                     
8466       else
8467       {
8468         movLeft2Result (left, MSB16, result, LSB, sign);
8469       }
8470       addSign (result, MSB16, sign);
8471       _endLazyDPSEvaluation();
8472     }
8473
8474   /*  1 <= shCount <= 7 */
8475   else
8476   {
8477     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8478   }
8479 }
8480 #endif
8481
8482 /*-----------------------------------------------------------------*/
8483 /* shiftRLong - shift right one long from left to result           */
8484 /* offl = LSB or MSB16                                             */
8485 /*-----------------------------------------------------------------*/
8486 static void
8487 shiftRLong (operand * left, int offl,
8488             operand * result, int sign)
8489 {
8490   int isSameRegs=sameRegs(AOP(left),AOP(result));
8491
8492   if (isSameRegs && offl>1) {
8493     // we are in big trouble, but this shouldn't happen
8494     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8495   }
8496
8497   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8498   
8499   if (offl==MSB16) {
8500     // shift is > 8
8501     if (sign) {
8502       emitcode ("rlc", "a");
8503       emitcode ("subb", "a,acc");
8504       emitcode ("xch", "a,%s",
8505                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8506     } else {
8507       aopPut (AOP(result), zero, MSB32);
8508     }
8509   }
8510
8511   if (!sign) {
8512     emitcode ("clr", "c");
8513   } else {
8514     emitcode ("mov", "c,acc.7");
8515   }
8516
8517   emitcode ("rrc", "a");
8518
8519   if (isSameRegs && offl==MSB16) {
8520     emitcode ("xch",
8521               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8522   } else {
8523     aopPut (AOP (result), "a", MSB32);
8524     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8525   }
8526
8527   emitcode ("rrc", "a");
8528   if (isSameRegs && offl==1) {
8529     emitcode ("xch", "a,%s",
8530               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8531   } else {
8532     aopPut (AOP (result), "a", MSB24);
8533     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8534   }
8535   emitcode ("rrc", "a");
8536   aopPut (AOP (result), "a", MSB16 - offl);
8537
8538   if (offl == LSB)
8539     {
8540       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8541       emitcode ("rrc", "a");
8542       aopPut (AOP (result), "a", LSB);
8543     }
8544 }
8545
8546 /*-----------------------------------------------------------------*/
8547 /* genrshFour - shift four byte by a known amount != 0             */
8548 /*-----------------------------------------------------------------*/
8549 static void
8550 genrshFour (operand * result, operand * left,
8551             int shCount, int sign)
8552 {
8553   D (emitcode (";", "genrshFour"););
8554
8555   /* if shifting more that 3 bytes */
8556   if (shCount >= 24)
8557     {
8558       shCount -= 24;
8559       _startLazyDPSEvaluation();
8560       if (shCount)
8561         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8562       else
8563         movLeft2Result (left, MSB32, result, LSB, sign);
8564       addSign (result, MSB16, sign);
8565       _endLazyDPSEvaluation();
8566     }
8567   else if (shCount >= 16)
8568     {
8569       shCount -= 16;
8570       _startLazyDPSEvaluation();
8571       if (shCount)
8572         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8573       else
8574         {
8575           movLeft2Result (left, MSB24, result, LSB, 0);
8576           movLeft2Result (left, MSB32, result, MSB16, sign);
8577         }
8578       addSign (result, MSB24, sign);
8579       _endLazyDPSEvaluation();
8580     }
8581   else if (shCount >= 8)
8582     {
8583       shCount -= 8;
8584       _startLazyDPSEvaluation();
8585       if (shCount == 1)
8586         {
8587             shiftRLong (left, MSB16, result, sign);
8588         }
8589       else if (shCount == 0)
8590         {
8591           movLeft2Result (left, MSB16, result, LSB, 0);
8592           movLeft2Result (left, MSB24, result, MSB16, 0);
8593           movLeft2Result (left, MSB32, result, MSB24, sign);
8594           addSign (result, MSB32, sign);
8595         }
8596       else
8597         {
8598           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8599           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8600           /* the last shift is signed */
8601           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8602           addSign (result, MSB32, sign);
8603         }
8604         _endLazyDPSEvaluation();
8605     }
8606   else
8607     {   
8608         /* 1 <= shCount <= 7 */
8609       if (shCount <= 2)
8610         {
8611           shiftRLong (left, LSB, result, sign);
8612           if (shCount == 2)
8613             shiftRLong (result, LSB, result, sign);
8614         }
8615       else
8616         {
8617           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8618           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8619           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8620         }
8621     }
8622 }
8623
8624 #ifdef BETTER_LITERAL_SHIFT
8625 /*-----------------------------------------------------------------*/
8626 /* genRightShiftLiteral - right shifting by known count            */
8627 /*-----------------------------------------------------------------*/
8628 static bool
8629 genRightShiftLiteral (operand * left,
8630                       operand * right,
8631                       operand * result,
8632                       iCode * ic,
8633                       int sign)
8634 {
8635   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8636   int size;
8637
8638   size = getSize (operandType (result));
8639
8640   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8641
8642   /* We only handle certain easy cases so far. */
8643   if ((shCount != 0)
8644    && (shCount < (size * 8))
8645    && (size != 1)
8646    && (size != 2)
8647    && (size != 4))
8648   {
8649       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8650       return FALSE;
8651   }
8652
8653   freeAsmop (right, NULL, ic, TRUE);
8654
8655   aopOp (left, ic, FALSE, FALSE);
8656   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8657
8658 #if VIEW_SIZE
8659   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8660             AOP_SIZE (left));
8661 #endif
8662
8663   /* test the LEFT size !!! */
8664
8665   /* I suppose that the left size >= result size */
8666   if (shCount == 0)
8667   {
8668       size = getDataSize (result);
8669       _startLazyDPSEvaluation();
8670       while (size--)
8671       {
8672         movLeft2Result (left, size, result, size, 0);
8673       }
8674       _endLazyDPSEvaluation();
8675   }
8676   else if (shCount >= (size * 8))
8677     {
8678       if (sign)
8679       {
8680         /* get sign in acc.7 */
8681         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8682       }
8683       addSign (result, LSB, sign);
8684     }
8685   else
8686     {
8687       switch (size)
8688         {
8689         case 1:
8690           genrshOne (result, left, shCount, sign);
8691           break;
8692
8693         case 2:
8694           genrshTwo (result, left, shCount, sign);
8695           break;
8696 #if 1
8697         case 4:
8698           genrshFour (result, left, shCount, sign);
8699           break;
8700 #endif    
8701         default:
8702           break;
8703         }
8704     }
8705   freeAsmop (left, NULL, ic, TRUE);
8706   freeAsmop (result, NULL, ic, TRUE);
8707   
8708   return TRUE;
8709 }
8710 #endif
8711
8712 /*-----------------------------------------------------------------*/
8713 /* genSignedRightShift - right shift of signed number              */
8714 /*-----------------------------------------------------------------*/
8715 static void
8716 genSignedRightShift (iCode * ic)
8717 {
8718   operand *right, *left, *result;
8719   int size, offset;
8720   char *l;
8721   symbol *tlbl, *tlbl1;
8722
8723   D (emitcode (";", "genSignedRightShift "););
8724
8725   /* we do it the hard way put the shift count in b
8726      and loop thru preserving the sign */
8727
8728   right = IC_RIGHT (ic);
8729   left = IC_LEFT (ic);
8730   result = IC_RESULT (ic);
8731
8732   aopOp (right, ic, FALSE, FALSE);
8733
8734 #ifdef BETTER_LITERAL_SHIFT
8735   if (AOP_TYPE (right) == AOP_LIT)
8736     {
8737       if (genRightShiftLiteral (left, right, result, ic, 1))
8738       {
8739         return;
8740       }
8741     }
8742 #endif
8743   /* shift count is unknown then we have to form
8744      a loop get the loop count in B : Note: we take
8745      only the lower order byte since shifting
8746      more that 32 bits make no sense anyway, ( the
8747      largest size of an object can be only 32 bits ) */
8748
8749   if (AOP_TYPE (right) == AOP_LIT)
8750   {
8751       /* Really should be handled by genRightShiftLiteral,
8752        * but since I'm too lazy to fix that today, at least we can make
8753        * some small improvement.
8754        */
8755        emitcode("mov", "b,#!constbyte",
8756                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8757   }
8758   else
8759   {
8760         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8761         emitcode ("inc", "b");
8762   }
8763   freeAsmop (right, NULL, ic, TRUE);
8764   aopOp (left, ic, FALSE, FALSE);
8765   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8766
8767   /* now move the left to the result if they are not the
8768      same */
8769   if (!sameRegs (AOP (left), AOP (result)) &&
8770       AOP_SIZE (result) > 1)
8771     {
8772
8773       size = AOP_SIZE (result);
8774       offset = 0;
8775       _startLazyDPSEvaluation ();
8776       while (size--)
8777         {
8778           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8779           if (*l == '@' && IS_AOP_PREG (result))
8780             {
8781
8782               emitcode ("mov", "a,%s", l);
8783               aopPut (AOP (result), "a", offset);
8784             }
8785           else
8786             aopPut (AOP (result), l, offset);
8787           offset++;
8788         }
8789       _endLazyDPSEvaluation ();
8790     }
8791
8792   /* mov the highest order bit to OVR */
8793   tlbl = newiTempLabel (NULL);
8794   tlbl1 = newiTempLabel (NULL);
8795
8796   size = AOP_SIZE (result);
8797   offset = size - 1;
8798   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8799   emitcode ("rlc", "a");
8800   emitcode ("mov", "ov,c");
8801   /* if it is only one byte then */
8802   if (size == 1)
8803     {
8804       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8805       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8806       emitcode ("", "!tlabeldef", tlbl->key + 100);
8807       emitcode ("mov", "c,ov");
8808       emitcode ("rrc", "a");
8809       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8810       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8811       aopPut (AOP (result), "a", 0);
8812       goto release;
8813     }
8814
8815   reAdjustPreg (AOP (result));
8816   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8817   emitcode ("", "!tlabeldef", tlbl->key + 100);
8818   emitcode ("mov", "c,ov");
8819   _startLazyDPSEvaluation ();
8820   while (size--)
8821     {
8822       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8823       emitcode ("rrc", "a");
8824       aopPut (AOP (result), "a", offset--);
8825     }
8826   _endLazyDPSEvaluation ();
8827   reAdjustPreg (AOP (result));
8828   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8829   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8830
8831 release:
8832   freeAsmop (left, NULL, ic, TRUE);
8833   freeAsmop (result, NULL, ic, TRUE);
8834 }
8835
8836 /*-----------------------------------------------------------------*/
8837 /* genRightShift - generate code for right shifting                */
8838 /*-----------------------------------------------------------------*/
8839 static void
8840 genRightShift (iCode * ic)
8841 {
8842   operand *right, *left, *result;
8843   sym_link *retype;
8844   int size, offset;
8845   char *l;
8846   symbol *tlbl, *tlbl1;
8847
8848   D (emitcode (";", "genRightShift "););
8849
8850   /* if signed then we do it the hard way preserve the
8851      sign bit moving it inwards */
8852   retype = getSpec (operandType (IC_RESULT (ic)));
8853
8854   if (!SPEC_USIGN (retype))
8855     {
8856       genSignedRightShift (ic);
8857       return;
8858     }
8859
8860   /* signed & unsigned types are treated the same : i.e. the
8861      signed is NOT propagated inwards : quoting from the
8862      ANSI - standard : "for E1 >> E2, is equivalent to division
8863      by 2**E2 if unsigned or if it has a non-negative value,
8864      otherwise the result is implementation defined ", MY definition
8865      is that the sign does not get propagated */
8866
8867   right = IC_RIGHT (ic);
8868   left = IC_LEFT (ic);
8869   result = IC_RESULT (ic);
8870
8871   aopOp (right, ic, FALSE, FALSE);
8872
8873 #ifdef BETTER_LITERAL_SHIFT
8874   /* if the shift count is known then do it
8875      as efficiently as possible */
8876   if (AOP_TYPE (right) == AOP_LIT)
8877     {
8878       if (genRightShiftLiteral (left, right, result, ic, 0))
8879       {
8880         return;
8881       }
8882     }
8883 #endif
8884
8885   /* shift count is unknown then we have to form
8886      a loop get the loop count in B : Note: we take
8887      only the lower order byte since shifting
8888      more that 32 bits make no sense anyway, ( the
8889      largest size of an object can be only 32 bits ) */
8890   
8891   if (AOP_TYPE (right) == AOP_LIT)
8892   {
8893       /* Really should be handled by genRightShiftLiteral,
8894        * but since I'm too lazy to fix that today, at least we can make
8895        * some small improvement.
8896        */
8897        emitcode("mov", "b,#!constbyte",
8898                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8899   }
8900   else
8901   {
8902       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8903       emitcode ("inc", "b");
8904   }
8905   freeAsmop (right, NULL, ic, TRUE);
8906   aopOp (left, ic, FALSE, FALSE);
8907   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8908
8909   /* now move the left to the result if they are not the
8910      same */
8911   if (!sameRegs (AOP (left), AOP (result)) &&
8912       AOP_SIZE (result) > 1)
8913     {
8914
8915       size = AOP_SIZE (result);
8916       offset = 0;
8917       _startLazyDPSEvaluation ();
8918       while (size--)
8919         {
8920           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8921           if (*l == '@' && IS_AOP_PREG (result))
8922             {
8923
8924               emitcode ("mov", "a,%s", l);
8925               aopPut (AOP (result), "a", offset);
8926             }
8927           else
8928             aopPut (AOP (result), l, offset);
8929           offset++;
8930         }
8931       _endLazyDPSEvaluation ();
8932     }
8933
8934   tlbl = newiTempLabel (NULL);
8935   tlbl1 = newiTempLabel (NULL);
8936   size = AOP_SIZE (result);
8937   offset = size - 1;
8938
8939   /* if it is only one byte then */
8940   if (size == 1)
8941     {
8942       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8943       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8944       emitcode ("", "!tlabeldef", tlbl->key + 100);
8945       CLRC;
8946       emitcode ("rrc", "a");
8947       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8948       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8949       aopPut (AOP (result), "a", 0);
8950       goto release;
8951     }
8952
8953   reAdjustPreg (AOP (result));
8954   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8955   emitcode ("", "!tlabeldef", tlbl->key + 100);
8956   CLRC;
8957   _startLazyDPSEvaluation ();
8958   while (size--)
8959     {
8960       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8961       emitcode ("rrc", "a");
8962       aopPut (AOP (result), "a", offset--);
8963     }
8964   _endLazyDPSEvaluation ();
8965   reAdjustPreg (AOP (result));
8966
8967   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8968   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8969
8970 release:
8971   freeAsmop (left, NULL, ic, TRUE);
8972   freeAsmop (result, NULL, ic, TRUE);
8973 }
8974
8975
8976 /*-----------------------------------------------------------------*/
8977 /* emitPtrByteGet - emits code to get a byte into A through a      */
8978 /*                  pointer register (R0, R1, or DPTR). The        */
8979 /*                  original value of A can be preserved in B.     */
8980 /*-----------------------------------------------------------------*/
8981 static void
8982 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8983 {
8984   switch (p_type)
8985     {
8986     case IPOINTER:
8987     case POINTER:
8988       if (preserveAinB)
8989         emitcode ("mov", "b,a");
8990       emitcode ("mov", "a,@%s", rname);
8991       break;
8992
8993     case PPOINTER:
8994       if (preserveAinB)
8995         emitcode ("mov", "b,a");
8996       emitcode ("movx", "a,@%s", rname);
8997       break;
8998       
8999     case FPOINTER:
9000       if (preserveAinB)
9001         emitcode ("mov", "b,a");
9002       emitcode ("movx", "a,@dptr");
9003       break;
9004
9005     case CPOINTER:
9006       if (preserveAinB)
9007         emitcode ("mov", "b,a");
9008       emitcode ("clr", "a");
9009       emitcode ("movc", "a,@a+dptr");
9010       break;
9011
9012     case GPOINTER:
9013       if (preserveAinB)
9014         {
9015           emitcode ("push", "b");
9016           emitcode ("push", "acc");
9017         }
9018       emitcode ("lcall", "__gptrget");
9019       if (preserveAinB)
9020         emitcode ("pop", "b");
9021       break;
9022     }
9023 }
9024
9025 /*-----------------------------------------------------------------*/
9026 /* emitPtrByteSet - emits code to set a byte from src through a    */
9027 /*                  pointer register (R0, R1, or DPTR).            */
9028 /*-----------------------------------------------------------------*/
9029 static void
9030 emitPtrByteSet (char *rname, int p_type, char *src)
9031 {
9032   switch (p_type)
9033     {
9034     case IPOINTER:
9035     case POINTER:
9036       if (*src=='@')
9037         {
9038           MOVA (src);
9039           emitcode ("mov", "@%s,a", rname);
9040         }
9041       else
9042         emitcode ("mov", "@%s,%s", rname, src);
9043       break;
9044
9045     case PPOINTER:
9046       MOVA (src);
9047       emitcode ("movx", "@%s,a", rname);
9048       break;
9049       
9050     case FPOINTER:
9051       MOVA (src);
9052       emitcode ("movx", "@dptr,a");
9053       break;
9054
9055     case GPOINTER:
9056       MOVA (src);
9057       emitcode ("lcall", "__gptrput");
9058       break;
9059     }
9060 }
9061
9062 /*-----------------------------------------------------------------*/
9063 /* genUnpackBits - generates code for unpacking bits               */
9064 /*-----------------------------------------------------------------*/
9065 static void
9066 genUnpackBits (operand * result, char *rname, int ptype)
9067 {
9068   int offset = 0;       /* result byte offset */
9069   int rsize;            /* result size */
9070   int rlen = 0;         /* remaining bitfield length */
9071   sym_link *etype;      /* bitfield type information */
9072   int blen;             /* bitfield length */
9073   int bstr;             /* bitfield starting bit within byte */
9074
9075   D(emitcode (";     genUnpackBits",""));
9076
9077   etype = getSpec (operandType (result));
9078   rsize = getSize (operandType (result));
9079   blen = SPEC_BLEN (etype);
9080   bstr = SPEC_BSTR (etype);
9081
9082   /* If the bitfield length is less than a byte */
9083   if (blen < 8)
9084     {
9085       emitPtrByteGet (rname, ptype, FALSE);
9086       AccRsh (bstr);
9087       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9088       aopPut (AOP (result), "a", offset++);
9089       goto finish;
9090     }
9091
9092   /* Bit field did not fit in a byte. Copy all
9093      but the partial byte at the end.  */
9094   for (rlen=blen;rlen>=8;rlen-=8)
9095     {
9096       emitPtrByteGet (rname, ptype, FALSE);
9097       aopPut (AOP (result), "a", offset++);
9098       if (rlen>8)
9099         emitcode ("inc", "%s", rname);
9100     }
9101
9102   /* Handle the partial byte at the end */
9103   if (rlen)
9104     {
9105       emitPtrByteGet (rname, ptype, FALSE);
9106       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9107       aopPut (AOP (result), "a", offset++);
9108     }
9109
9110 finish:
9111   if (offset < rsize)
9112     {
9113       rsize -= offset;
9114       while (rsize--)
9115         aopPut (AOP (result), zero, offset++);
9116     }
9117 }
9118
9119
9120 /*-----------------------------------------------------------------*/
9121 /* genDataPointerGet - generates code when ptr offset is known     */
9122 /*-----------------------------------------------------------------*/
9123 static void
9124 genDataPointerGet (operand * left,
9125                    operand * result,
9126                    iCode * ic)
9127 {
9128   char *l;
9129   char buff[256];
9130   int size, offset = 0;
9131   aopOp (result, ic, TRUE, FALSE);
9132
9133   /* get the string representation of the name */
9134   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9135   size = AOP_SIZE (result);
9136   _startLazyDPSEvaluation ();
9137   while (size--)
9138     {
9139         if (offset)
9140         {
9141             SNPRINTF (buff, sizeof(buff), 
9142                       "(%s + %d)", l + 1, offset);
9143         }
9144         else
9145         {
9146             SNPRINTF (buff, sizeof(buff), 
9147                       "%s", l + 1);
9148         }
9149       aopPut (AOP (result), buff, offset++);
9150     }
9151   _endLazyDPSEvaluation ();
9152
9153   freeAsmop (left, NULL, ic, TRUE);
9154   freeAsmop (result, NULL, ic, TRUE);
9155 }
9156
9157 /*-----------------------------------------------------------------*/
9158 /* genNearPointerGet - emitcode for near pointer fetch             */
9159 /*-----------------------------------------------------------------*/
9160 static void
9161 genNearPointerGet (operand * left,
9162                    operand * result,
9163                    iCode * ic,
9164                    iCode *pi)
9165 {
9166   asmop *aop = NULL;
9167   regs *preg;
9168   char *rname;
9169   sym_link *rtype, *retype, *letype;
9170   sym_link *ltype = operandType (left);
9171   char buff[80];
9172
9173   rtype = operandType (result);
9174   retype = getSpec (rtype);
9175   letype = getSpec (ltype);
9176
9177   aopOp (left, ic, FALSE, FALSE);
9178
9179   /* if left is rematerialisable and
9180      result is not bit variable type and
9181      the left is pointer to data space i.e
9182      lower 128 bytes of space */
9183   if (AOP_TYPE (left) == AOP_IMMD &&
9184       !IS_BITVAR (retype) &&
9185       !IS_BITVAR (letype) &&
9186       DCL_TYPE (ltype) == POINTER)
9187     {
9188       genDataPointerGet (left, result, ic);
9189       return;
9190     }
9191
9192   /* if the value is already in a pointer register
9193      then don't need anything more */
9194   if (!AOP_INPREG (AOP (left)))
9195     {
9196       /* otherwise get a free pointer register */
9197       aop = newAsmop (0);
9198       preg = getFreePtr (ic, &aop, FALSE);
9199       emitcode ("mov", "%s,%s",
9200                 preg->name,
9201                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9202       rname = preg->name;
9203     }
9204   else
9205     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9206
9207   freeAsmop (left, NULL, ic, TRUE);
9208   aopOp (result, ic, FALSE, FALSE);
9209
9210   /* if bitfield then unpack the bits */
9211   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9212     genUnpackBits (result, rname, POINTER);
9213   else
9214     {
9215       /* we have can just get the values */
9216       int size = AOP_SIZE (result);
9217       int offset = 0;
9218
9219       while (size--)
9220         {
9221           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9222             {
9223
9224               emitcode ("mov", "a,@%s", rname);
9225               aopPut (AOP (result), "a", offset);
9226             }
9227           else
9228             {
9229               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9230               aopPut (AOP (result), buff, offset);
9231             }
9232           offset++;
9233           if (size || pi)
9234             {
9235                 emitcode ("inc", "%s", rname);
9236             }
9237         }
9238     }
9239
9240   /* now some housekeeping stuff */
9241   if (aop)
9242     {
9243       /* we had to allocate for this iCode */
9244       if (pi) { /* post increment present */
9245         aopPut(AOP ( left ),rname,0);
9246       }
9247       freeAsmop (NULL, aop, ic, TRUE);
9248     }
9249   else
9250     {
9251       /* we did not allocate which means left
9252          already in a pointer register, then
9253          if size > 0 && this could be used again
9254          we have to point it back to where it
9255          belongs */
9256       if (AOP_SIZE (result) > 1 &&
9257           !OP_SYMBOL (left)->remat &&
9258           (OP_SYMBOL (left)->liveTo > ic->seq ||
9259            ic->depth) &&
9260           !pi)
9261         {
9262           int size = AOP_SIZE (result) - 1;
9263           while (size--)
9264             emitcode ("dec", "%s", rname);
9265         }
9266     }
9267
9268   /* done */
9269   freeAsmop (result, NULL, ic, TRUE);
9270   if (pi) pi->generated = 1;
9271 }
9272
9273 /*-----------------------------------------------------------------*/
9274 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9275 /*-----------------------------------------------------------------*/
9276 static void
9277 genPagedPointerGet (operand * left,
9278                     operand * result,
9279                     iCode * ic,
9280                     iCode * pi)
9281 {
9282   asmop *aop = NULL;
9283   regs *preg;
9284   char *rname;
9285   sym_link *rtype, *retype, *letype;
9286
9287   rtype = operandType (result);
9288   retype = getSpec (rtype);
9289   letype = getSpec (operandType (left));
9290   aopOp (left, ic, FALSE, FALSE);
9291
9292   /* if the value is already in a pointer register
9293      then don't need anything more */
9294   if (!AOP_INPREG (AOP (left)))
9295     {
9296       /* otherwise get a free pointer register */
9297       aop = newAsmop (0);
9298       preg = getFreePtr (ic, &aop, FALSE);
9299       emitcode ("mov", "%s,%s",
9300                 preg->name,
9301                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9302       rname = preg->name;
9303     }
9304   else
9305     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9306
9307   freeAsmop (left, NULL, ic, TRUE);
9308   aopOp (result, ic, FALSE, FALSE);
9309
9310   /* if bitfield then unpack the bits */
9311   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9312     genUnpackBits (result, rname, PPOINTER);
9313   else
9314     {
9315       /* we have can just get the values */
9316       int size = AOP_SIZE (result);
9317       int offset = 0;
9318
9319       while (size--)
9320         {
9321
9322           emitcode ("movx", "a,@%s", rname);
9323           aopPut (AOP (result), "a", offset);
9324
9325           offset++;
9326
9327           if (size || pi)
9328             emitcode ("inc", "%s", rname);
9329         }
9330     }
9331
9332   /* now some housekeeping stuff */
9333   if (aop)
9334     {
9335       /* we had to allocate for this iCode */
9336       if (pi) aopPut ( AOP (left), rname, 0);
9337       freeAsmop (NULL, aop, ic, TRUE);
9338     }
9339   else
9340     {
9341       /* we did not allocate which means left
9342          already in a pointer register, then
9343          if size > 0 && this could be used again
9344          we have to point it back to where it
9345          belongs */
9346       if (AOP_SIZE (result) > 1 &&
9347           !OP_SYMBOL (left)->remat &&
9348           (OP_SYMBOL (left)->liveTo > ic->seq ||
9349            ic->depth) &&
9350           !pi)
9351         {
9352           int size = AOP_SIZE (result) - 1;
9353           while (size--)
9354             emitcode ("dec", "%s", rname);
9355         }
9356     }
9357
9358   /* done */
9359   freeAsmop (result, NULL, ic, TRUE);
9360   if (pi) pi->generated = 1;
9361 }
9362
9363 /*-----------------------------------------------------------------*/
9364 /* genFarPointerGet - gget value from far space                    */
9365 /*-----------------------------------------------------------------*/
9366 static void
9367 genFarPointerGet (operand * left,
9368                   operand * result, iCode * ic, iCode *pi)
9369 {
9370     int size, offset, dopi=1;
9371   sym_link *retype = getSpec (operandType (result));
9372   sym_link *letype = getSpec (operandType (left));
9373   D (emitcode (";", "genFarPointerGet"););
9374
9375   aopOp (left, ic, FALSE, FALSE);
9376
9377   /* if the operand is already in dptr
9378      then we do nothing else we move the value to dptr */
9379   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9380     {
9381       /* if this is remateriazable */
9382       if (AOP_TYPE (left) == AOP_IMMD)
9383         {
9384           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9385         }
9386       else
9387         {
9388           /* we need to get it byte by byte */
9389           _startLazyDPSEvaluation ();
9390           if (AOP_TYPE (left) != AOP_DPTR)
9391             {
9392               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9393               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9394               if (options.model == MODEL_FLAT24)
9395                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9396             }
9397           else
9398             {
9399               /* We need to generate a load to DPTR indirect through DPTR. */
9400               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9401               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9402               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9403               if (options.model == MODEL_FLAT24)
9404                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9405               emitcode ("pop", "dph");
9406               emitcode ("pop", "dpl");
9407               dopi =0;
9408             }
9409           _endLazyDPSEvaluation ();
9410         }
9411     }
9412   /* so dptr know contains the address */
9413   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9414
9415   /* if bit then unpack */
9416   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9417       if (AOP_INDPTRn(left)) {
9418           genSetDPTR(AOP(left)->aopu.dptr);
9419       }
9420       genUnpackBits (result, "dptr", FPOINTER);
9421       if (AOP_INDPTRn(left)) {
9422           genSetDPTR(0);
9423       }
9424   } else
9425     {
9426       size = AOP_SIZE (result);
9427       offset = 0;
9428
9429       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9430           while (size--) {
9431               genSetDPTR(AOP(left)->aopu.dptr);
9432               emitcode ("movx", "a,@dptr");
9433               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9434                   emitcode ("inc", "dptr");
9435               genSetDPTR (0);
9436               aopPut (AOP (result), "a", offset++);
9437           }
9438       } else {
9439           _startLazyDPSEvaluation ();
9440           while (size--) {
9441               if (AOP_INDPTRn(left)) {
9442                   genSetDPTR(AOP(left)->aopu.dptr);
9443               } else {
9444                   genSetDPTR (0);
9445               }
9446               _flushLazyDPS ();
9447               
9448               emitcode ("movx", "a,@dptr");
9449               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9450                   emitcode ("inc", "dptr");
9451               
9452               aopPut (AOP (result), "a", offset++);
9453           }
9454           _endLazyDPSEvaluation ();
9455       }
9456     }
9457   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9458       if (!AOP_INDPTRn(left)) {
9459           _startLazyDPSEvaluation ();
9460           aopPut ( AOP (left), "dpl", 0);
9461           aopPut ( AOP (left), "dph", 1);
9462           if (options.model == MODEL_FLAT24)
9463               aopPut ( AOP (left), "dpx", 2);
9464           _endLazyDPSEvaluation ();
9465       }
9466     pi->generated = 1;
9467   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9468              AOP_SIZE(result) > 1 &&
9469              IS_SYMOP(left) &&
9470              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9471       
9472       size = AOP_SIZE (result) - 1;
9473       if (AOP_INDPTRn(left)) {
9474           genSetDPTR(AOP(left)->aopu.dptr);
9475       }
9476       while (size--) emitcode ("lcall","__decdptr");
9477       if (AOP_INDPTRn(left)) {
9478           genSetDPTR(0);
9479       }
9480   }
9481
9482   freeAsmop (left, NULL, ic, TRUE);
9483   freeAsmop (result, NULL, ic, TRUE);
9484 }
9485
9486 /*-----------------------------------------------------------------*/
9487 /* genCodePointerGet - get value from code space                  */
9488 /*-----------------------------------------------------------------*/
9489 static void
9490 genCodePointerGet (operand * left,
9491                     operand * result, iCode * ic, iCode *pi)
9492 {
9493   int size, offset, dopi=1;
9494   sym_link *retype = getSpec (operandType (result));
9495
9496   aopOp (left, ic, FALSE, FALSE);
9497
9498   /* if the operand is already in dptr
9499      then we do nothing else we move the value to dptr */
9500   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9501     {
9502       /* if this is remateriazable */
9503       if (AOP_TYPE (left) == AOP_IMMD)
9504         {
9505           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9506         }
9507       else
9508         {                       /* we need to get it byte by byte */
9509           _startLazyDPSEvaluation ();
9510           if (AOP_TYPE (left) != AOP_DPTR)
9511             {
9512               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9513               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9514               if (options.model == MODEL_FLAT24)
9515                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9516             }
9517           else
9518             {
9519               /* We need to generate a load to DPTR indirect through DPTR. */
9520               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9521               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9522               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9523               if (options.model == MODEL_FLAT24)
9524                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9525               emitcode ("pop", "dph");
9526               emitcode ("pop", "dpl");
9527               dopi=0;
9528             }
9529           _endLazyDPSEvaluation ();
9530         }
9531     }
9532   /* so dptr know contains the address */
9533   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9534
9535   /* if bit then unpack */
9536   if (IS_BITVAR (retype)) {
9537       if (AOP_INDPTRn(left)) {
9538           genSetDPTR(AOP(left)->aopu.dptr);
9539       }
9540       genUnpackBits (result, "dptr", CPOINTER);
9541       if (AOP_INDPTRn(left)) {
9542           genSetDPTR(0);
9543       }
9544   } else
9545     {
9546       size = AOP_SIZE (result);
9547       offset = 0;
9548       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9549           while (size--) {
9550               genSetDPTR(AOP(left)->aopu.dptr);
9551               emitcode ("clr", "a");
9552               emitcode ("movc", "a,@a+dptr");
9553               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9554                   emitcode ("inc", "dptr");
9555               genSetDPTR (0);
9556               aopPut (AOP (result), "a", offset++);
9557           }
9558       } else {
9559           _startLazyDPSEvaluation ();
9560           while (size--)
9561               {
9562                   if (AOP_INDPTRn(left)) {
9563                       genSetDPTR(AOP(left)->aopu.dptr);
9564                   } else {
9565                       genSetDPTR (0);
9566                   }
9567                   _flushLazyDPS ();
9568                   
9569                   emitcode ("clr", "a");
9570                   emitcode ("movc", "a,@a+dptr");
9571                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9572                       emitcode ("inc", "dptr");
9573                   aopPut (AOP (result), "a", offset++);
9574               }
9575           _endLazyDPSEvaluation ();
9576       }
9577     }
9578   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9579       if (!AOP_INDPTRn(left)) {
9580           _startLazyDPSEvaluation ();
9581           
9582           aopPut ( AOP (left), "dpl", 0);
9583           aopPut ( AOP (left), "dph", 1);
9584           if (options.model == MODEL_FLAT24)
9585               aopPut ( AOP (left), "dpx", 2);
9586
9587           _endLazyDPSEvaluation ();
9588       }
9589       pi->generated = 1;
9590   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9591              AOP_SIZE(result) > 1 &&
9592              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9593       
9594       size = AOP_SIZE (result) - 1;
9595       if (AOP_INDPTRn(left)) {
9596           genSetDPTR(AOP(left)->aopu.dptr);
9597       }
9598       while (size--) emitcode ("lcall","__decdptr");
9599       if (AOP_INDPTRn(left)) {
9600           genSetDPTR(0);
9601       }
9602   }
9603   
9604   freeAsmop (left, NULL, ic, TRUE);
9605   freeAsmop (result, NULL, ic, TRUE);
9606 }
9607
9608 /*-----------------------------------------------------------------*/
9609 /* genGenPointerGet - gget value from generic pointer space        */
9610 /*-----------------------------------------------------------------*/
9611 static void
9612 genGenPointerGet (operand * left,
9613                   operand * result, iCode * ic, iCode * pi)
9614 {
9615   int size, offset;
9616   sym_link *retype = getSpec (operandType (result));
9617   sym_link *letype = getSpec (operandType (left));
9618
9619   D (emitcode (";", "genGenPointerGet "); );
9620
9621   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9622
9623   /* if the operand is already in dptr
9624      then we do nothing else we move the value to dptr */
9625   if (AOP_TYPE (left) != AOP_STR)
9626     {
9627       /* if this is remateriazable */
9628       if (AOP_TYPE (left) == AOP_IMMD)
9629         {
9630           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9631           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9632             {
9633                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9634             }
9635             else
9636             {
9637                 emitcode ("mov", "b,#%d", pointerCode (retype));
9638             }
9639         }
9640       else
9641         {                       /* we need to get it byte by byte */
9642             _startLazyDPSEvaluation ();
9643             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9644             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9645             if (options.model == MODEL_FLAT24) {
9646                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9647                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9648             } else {
9649                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9650             }
9651             _endLazyDPSEvaluation ();
9652         }
9653     }
9654
9655   /* so dptr-b now contains the address */
9656   _G.bInUse++;
9657   aopOp (result, ic, FALSE, TRUE);
9658   _G.bInUse--;
9659
9660   /* if bit then unpack */
9661   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9662   {
9663     genUnpackBits (result, "dptr", GPOINTER);
9664   }
9665   else
9666     {
9667         size = AOP_SIZE (result);
9668         offset = 0;
9669
9670         while (size--)
9671         {
9672             if (size)
9673             {
9674                 // Get two bytes at a time, results in _AP & A.
9675                 // dptr will be incremented ONCE by __gptrgetWord.
9676                 //
9677                 // Note: any change here must be coordinated
9678                 // with the implementation of __gptrgetWord
9679                 // in device/lib/_gptrget.c
9680                 emitcode ("lcall", "__gptrgetWord");
9681                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9682                 aopPut (AOP (result), "a", offset++);
9683                 size--;
9684             }
9685             else
9686             {
9687                 // Only one byte to get.
9688                 emitcode ("lcall", "__gptrget");
9689                 aopPut (AOP (result), "a", offset++);
9690             }
9691             
9692             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9693             {
9694                 emitcode ("inc", "dptr");
9695             }
9696         }
9697     }
9698
9699   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9700     _startLazyDPSEvaluation ();
9701       
9702     aopPut ( AOP (left), "dpl", 0);
9703     aopPut ( AOP (left), "dph", 1);
9704     if (options.model == MODEL_FLAT24) {
9705         aopPut ( AOP (left), "dpx", 2);
9706         aopPut ( AOP (left), "b", 3);   
9707     } else  aopPut ( AOP (left), "b", 2);       
9708     
9709     _endLazyDPSEvaluation ();
9710       
9711     pi->generated = 1;
9712   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9713              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9714       
9715       size = AOP_SIZE (result) - 1;
9716       while (size--) emitcode ("lcall","__decdptr");
9717   }
9718
9719   freeAsmop (left, NULL, ic, TRUE);
9720   freeAsmop (result, NULL, ic, TRUE);
9721 }
9722
9723 /*-----------------------------------------------------------------*/
9724 /* genPointerGet - generate code for pointer get                   */
9725 /*-----------------------------------------------------------------*/
9726 static void
9727 genPointerGet (iCode * ic, iCode *pi)
9728 {
9729   operand *left, *result;
9730   sym_link *type, *etype;
9731   int p_type;
9732
9733   D (emitcode (";", "genPointerGet ");
9734     );
9735
9736   left = IC_LEFT (ic);
9737   result = IC_RESULT (ic);
9738
9739   /* depending on the type of pointer we need to
9740      move it to the correct pointer register */
9741   type = operandType (left);
9742   etype = getSpec (type);
9743   /* if left is of type of pointer then it is simple */
9744   if (IS_PTR (type) && !IS_FUNC (type->next))
9745     p_type = DCL_TYPE (type);
9746   else
9747     {
9748       /* we have to go by the storage class */
9749       p_type = PTR_TYPE (SPEC_OCLS (etype));
9750     }
9751   /* special case when cast remat */
9752   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9753       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9754           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9755           type = operandType (left);
9756           p_type = DCL_TYPE (type);
9757   }
9758   /* now that we have the pointer type we assign
9759      the pointer values */
9760   switch (p_type)
9761     {
9762
9763     case POINTER:
9764     case IPOINTER:
9765       genNearPointerGet (left, result, ic, pi);
9766       break;
9767
9768     case PPOINTER:
9769       genPagedPointerGet (left, result, ic, pi);
9770       break;
9771
9772     case FPOINTER:
9773       genFarPointerGet (left, result, ic, pi);
9774       break;
9775
9776     case CPOINTER:
9777       genCodePointerGet (left, result, ic, pi);
9778       break;
9779
9780     case GPOINTER:
9781       genGenPointerGet (left, result, ic, pi);
9782       break;
9783     }
9784
9785 }
9786
9787 /*-----------------------------------------------------------------*/
9788 /* genPackBits - generates code for packed bit storage             */
9789 /*-----------------------------------------------------------------*/
9790 static void
9791 genPackBits (sym_link * etype,
9792              operand * right,
9793              char *rname, int p_type)
9794 {
9795   int offset = 0;       /* source byte offset */
9796   int rlen = 0;         /* remaining bitfield length */
9797   int blen;             /* bitfield length */
9798   int bstr;             /* bitfield starting bit within byte */
9799   int litval;           /* source literal value (if AOP_LIT) */
9800   unsigned char mask;   /* bitmask within current byte */
9801
9802   D(emitcode (";     genPackBits",""));
9803
9804   blen = SPEC_BLEN (etype);
9805   bstr = SPEC_BSTR (etype);
9806
9807   /* If the bitfield length is less than a byte */
9808   if (blen < 8)
9809     {
9810       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9811               (unsigned char) (0xFF >> (8 - bstr)));
9812
9813       if (AOP_TYPE (right) == AOP_LIT)
9814         {
9815           /* Case with a bitfield length <8 and literal source
9816           */
9817           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9818           litval <<= bstr;
9819           litval &= (~mask) & 0xff;
9820           emitPtrByteGet (rname, p_type, FALSE);
9821           if ((mask|litval)!=0xff)
9822             emitcode ("anl","a,#!constbyte", mask);
9823           if (litval)
9824             emitcode ("orl","a,#!constbyte", litval);
9825         }
9826       else
9827         {
9828           if ((blen==1) && (p_type!=GPOINTER))
9829             {
9830               /* Case with a bitfield length == 1 and no generic pointer
9831               */
9832               if (AOP_TYPE (right) == AOP_CRY)
9833                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9834               else
9835                 {
9836                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9837                   emitcode ("rrc","a");
9838                 }
9839               emitPtrByteGet (rname, p_type, FALSE);
9840               emitcode ("mov","acc.%d,c",bstr);
9841             }
9842           else
9843             {
9844               /* Case with a bitfield length < 8 and arbitrary source
9845               */
9846               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9847               /* shift and mask source value */
9848               AccLsh (bstr);
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         }
9860
9861       emitPtrByteSet (rname, p_type, "a");
9862       return;
9863     }
9864
9865   /* Bit length is greater than 7 bits. In this case, copy  */
9866   /* all except the partial byte at the end                 */
9867   for (rlen=blen;rlen>=8;rlen-=8)
9868     {
9869       emitPtrByteSet (rname, p_type, 
9870                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9871       if (rlen>8)
9872         emitcode ("inc", "%s", rname);
9873     }
9874
9875   /* If there was a partial byte at the end */
9876   if (rlen)
9877     {
9878       mask = (((unsigned char) -1 << rlen) & 0xff);
9879       
9880       if (AOP_TYPE (right) == AOP_LIT)
9881         {
9882           /* Case with partial byte and literal source
9883           */
9884           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9885           litval >>= (blen-rlen);
9886           litval &= (~mask) & 0xff;
9887           emitPtrByteGet (rname, p_type, FALSE);
9888           if ((mask|litval)!=0xff)
9889             emitcode ("anl","a,#!constbyte", mask);
9890           if (litval)
9891             emitcode ("orl","a,#!constbyte", litval);
9892         }
9893       else
9894         {
9895           /* Case with partial byte and arbitrary source
9896           */
9897           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9898           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9899
9900           /* transfer A to B and get next byte */
9901           emitPtrByteGet (rname, p_type, TRUE);
9902
9903           emitcode ("anl", "a,#!constbyte", mask);
9904           emitcode ("orl", "a,b");
9905           if (p_type == GPOINTER)
9906             emitcode ("pop", "b");
9907         }
9908       emitPtrByteSet (rname, p_type, "a");
9909     }
9910
9911 }
9912
9913
9914 /*-----------------------------------------------------------------*/
9915 /* genDataPointerSet - remat pointer to data space                 */
9916 /*-----------------------------------------------------------------*/
9917 static void
9918 genDataPointerSet (operand * right,
9919                    operand * result,
9920                    iCode * ic)
9921 {
9922   int size, offset = 0;
9923   char *l, buff[256];
9924
9925   aopOp (right, ic, FALSE, FALSE);
9926
9927   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9928   size = AOP_SIZE (right);
9929   while (size--)
9930     {
9931       if (offset)
9932         {
9933             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9934         }
9935       else
9936         {
9937             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9938         }
9939         
9940       emitcode ("mov", "%s,%s", buff,
9941                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9942     }
9943
9944   freeAsmop (right, NULL, ic, TRUE);
9945   freeAsmop (result, NULL, ic, TRUE);
9946 }
9947
9948 /*-----------------------------------------------------------------*/
9949 /* genNearPointerSet - emitcode for near pointer put                */
9950 /*-----------------------------------------------------------------*/
9951 static void
9952 genNearPointerSet (operand * right,
9953                    operand * result,
9954                    iCode * ic,
9955                    iCode * pi)
9956 {
9957   asmop *aop = NULL;
9958   char *rname, *l;
9959   sym_link *retype, *letype;
9960   sym_link *ptype = operandType (result);
9961
9962   retype = getSpec (operandType (right));
9963   letype = getSpec (ptype);
9964
9965   aopOp (result, ic, FALSE, FALSE);
9966
9967   /* if the result is rematerializable &
9968      in data space & not a bit variable */
9969   if (AOP_TYPE (result) == AOP_IMMD &&
9970       DCL_TYPE (ptype) == POINTER &&
9971       !IS_BITVAR (retype) &&
9972       !IS_BITVAR (letype))
9973     {
9974       genDataPointerSet (right, result, ic);
9975       return;
9976     }
9977
9978   /* if the value is already in a pointer register
9979      then don't need anything more */
9980   if (!AOP_INPREG (AOP (result)))
9981     {
9982       /* otherwise get a free pointer register */
9983       regs *preg;
9984         
9985       aop = newAsmop (0);
9986       preg = getFreePtr (ic, &aop, FALSE);
9987       emitcode ("mov", "%s,%s",
9988                 preg->name,
9989                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9990       rname = preg->name;
9991     }
9992   else
9993     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9994
9995   aopOp (right, ic, FALSE, FALSE);
9996
9997   /* if bitfield then unpack the bits */
9998   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9999     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10000   else
10001     {
10002       /* we have can just get the values */
10003       int size = AOP_SIZE (right);
10004       int offset = 0;
10005
10006       while (size--)
10007         {
10008           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10009           if (*l == '@')
10010             {
10011               MOVA (l);
10012               emitcode ("mov", "@%s,a", rname);
10013             }
10014           else
10015             emitcode ("mov", "@%s,%s", rname, l);
10016           if (size || pi)
10017             emitcode ("inc", "%s", rname);
10018           offset++;
10019         }
10020     }
10021
10022   /* now some housekeeping stuff */
10023   if (aop)
10024     {
10025       /* we had to allocate for this iCode */
10026       if (pi) aopPut (AOP (result),rname,0);
10027       freeAsmop (NULL, aop, ic, TRUE);
10028     }
10029   else
10030     {
10031       /* we did not allocate which means left
10032          already in a pointer register, then
10033          if size > 0 && this could be used again
10034          we have to point it back to where it
10035          belongs */
10036       if (AOP_SIZE (right) > 1 &&
10037           !OP_SYMBOL (result)->remat &&
10038           (OP_SYMBOL (result)->liveTo > ic->seq ||
10039            ic->depth) &&
10040           !pi)
10041         {
10042           int size = AOP_SIZE (right) - 1;
10043           while (size--)
10044             emitcode ("dec", "%s", rname);
10045         }
10046     }
10047
10048   /* done */
10049   if (pi) pi->generated = 1;
10050   freeAsmop (result, NULL, ic, TRUE);
10051   freeAsmop (right, NULL, ic, TRUE);
10052
10053
10054 }
10055
10056 /*-----------------------------------------------------------------*/
10057 /* genPagedPointerSet - emitcode for Paged pointer put             */
10058 /*-----------------------------------------------------------------*/
10059 static void
10060 genPagedPointerSet (operand * right,
10061                     operand * result,
10062                     iCode * ic,
10063                     iCode *pi)
10064 {
10065   asmop *aop = NULL;
10066   char *rname;
10067   sym_link *retype, *letype;
10068
10069   retype = getSpec (operandType (right));
10070   letype = getSpec (operandType (result));
10071
10072   aopOp (result, ic, FALSE, FALSE);
10073
10074   /* if the value is already in a pointer register
10075      then don't need anything more */
10076   if (!AOP_INPREG (AOP (result)))
10077     {
10078       /* otherwise get a free pointer register */
10079       regs *preg;
10080         
10081       aop = newAsmop (0);
10082       preg = getFreePtr (ic, &aop, FALSE);
10083       emitcode ("mov", "%s,%s",
10084                 preg->name,
10085                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10086       rname = preg->name;
10087     }
10088   else
10089     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10090
10091   aopOp (right, ic, FALSE, FALSE);
10092
10093   /* if bitfield then unpack the bits */
10094   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10095     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10096   else
10097     {
10098       /* we have can just get the values */
10099       int size = AOP_SIZE (right);
10100       int offset = 0;
10101
10102       while (size--)
10103         {
10104           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10105
10106           emitcode ("movx", "@%s,a", rname);
10107
10108           if (size || pi)
10109             emitcode ("inc", "%s", rname);
10110
10111           offset++;
10112         }
10113     }
10114
10115   /* now some housekeeping stuff */
10116   if (aop)
10117     {
10118       if (pi) aopPut (AOP (result),rname,0);
10119       /* we had to allocate for this iCode */
10120       freeAsmop (NULL, aop, ic, TRUE);
10121     }
10122   else
10123     {
10124       /* we did not allocate which means left
10125          already in a pointer register, then
10126          if size > 0 && this could be used again
10127          we have to point it back to where it
10128          belongs */
10129       if (AOP_SIZE (right) > 1 &&
10130           !OP_SYMBOL (result)->remat &&
10131           (OP_SYMBOL (result)->liveTo > ic->seq ||
10132            ic->depth) &&
10133           !pi)
10134         {
10135           int size = AOP_SIZE (right) - 1;
10136           while (size--)
10137             emitcode ("dec", "%s", rname);
10138         }
10139     }
10140
10141   /* done */
10142   if (pi) pi->generated = 1;
10143   freeAsmop (result, NULL, ic, TRUE);
10144   freeAsmop (right, NULL, ic, TRUE);
10145
10146
10147 }
10148
10149 /*-----------------------------------------------------------------*/
10150 /* genFarPointerSet - set value from far space                     */
10151 /*-----------------------------------------------------------------*/
10152 static void
10153 genFarPointerSet (operand * right,
10154                   operand * result, iCode * ic, iCode *pi)
10155 {
10156   int size, offset, dopi=1;
10157   sym_link *retype = getSpec (operandType (right));
10158   sym_link *letype = getSpec (operandType (result));
10159
10160   aopOp (result, ic, FALSE, FALSE);
10161
10162   /* if the operand is already in dptr
10163      then we do nothing else we move the value to dptr */
10164   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10165     {
10166       /* if this is remateriazable */
10167       if (AOP_TYPE (result) == AOP_IMMD)
10168         emitcode ("mov", "dptr,%s", 
10169                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10170       else
10171         {
10172           /* we need to get it byte by byte */
10173           _startLazyDPSEvaluation ();
10174           if (AOP_TYPE (result) != AOP_DPTR)
10175             {
10176               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10177               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10178               if (options.model == MODEL_FLAT24)
10179                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10180             }
10181           else
10182             {
10183               /* We need to generate a load to DPTR indirect through DPTR. */
10184               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10185                 
10186               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10187               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10188               if (options.model == MODEL_FLAT24)
10189                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10190               emitcode ("pop", "dph");
10191               emitcode ("pop", "dpl");
10192               dopi=0;
10193             }
10194           _endLazyDPSEvaluation ();
10195         }
10196     }
10197   /* so dptr know contains the address */
10198   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10199
10200   /* if bit then unpack */
10201   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10202       if (AOP_INDPTRn(result)) {
10203           genSetDPTR(AOP(result)->aopu.dptr);
10204       }
10205       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10206       if (AOP_INDPTRn(result)) {
10207           genSetDPTR(0);
10208       }
10209   } else {
10210       size = AOP_SIZE (right);
10211       offset = 0;
10212       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10213           while (size--) {
10214               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10215               
10216               genSetDPTR(AOP(result)->aopu.dptr);
10217               emitcode ("movx", "@dptr,a");
10218               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10219                   emitcode ("inc", "dptr");
10220               genSetDPTR (0);
10221           }
10222       } else {
10223           _startLazyDPSEvaluation ();
10224           while (size--) {
10225               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10226               
10227               if (AOP_INDPTRn(result)) {
10228                   genSetDPTR(AOP(result)->aopu.dptr);
10229               } else {
10230                   genSetDPTR (0);
10231               }
10232               _flushLazyDPS ();
10233               
10234               emitcode ("movx", "@dptr,a");
10235               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10236                   emitcode ("inc", "dptr");
10237           }
10238           _endLazyDPSEvaluation ();
10239       }
10240   }
10241   
10242   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10243       if (!AOP_INDPTRn(result)) {
10244           _startLazyDPSEvaluation ();
10245           
10246           aopPut (AOP(result),"dpl",0);
10247           aopPut (AOP(result),"dph",1);
10248           if (options.model == MODEL_FLAT24)
10249               aopPut (AOP(result),"dpx",2);
10250
10251           _endLazyDPSEvaluation ();
10252       }
10253       pi->generated=1;
10254   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10255              AOP_SIZE(right) > 1 &&
10256              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10257       
10258       size = AOP_SIZE (right) - 1;
10259       if (AOP_INDPTRn(result)) {
10260           genSetDPTR(AOP(result)->aopu.dptr);
10261       } 
10262       while (size--) emitcode ("lcall","__decdptr");
10263       if (AOP_INDPTRn(result)) {
10264           genSetDPTR(0);
10265       }
10266   }
10267   freeAsmop (result, NULL, ic, TRUE);
10268   freeAsmop (right, NULL, ic, TRUE);
10269 }
10270
10271 /*-----------------------------------------------------------------*/
10272 /* genGenPointerSet - set value from generic pointer space         */
10273 /*-----------------------------------------------------------------*/
10274 static void
10275 genGenPointerSet (operand * right,
10276                   operand * result, iCode * ic, iCode *pi)
10277 {
10278   int size, offset;
10279   sym_link *retype = getSpec (operandType (right));
10280   sym_link *letype = getSpec (operandType (result));
10281
10282   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10283
10284   /* if the operand is already in dptr
10285      then we do nothing else we move the value to dptr */
10286   if (AOP_TYPE (result) != AOP_STR)
10287     {
10288       _startLazyDPSEvaluation ();
10289       /* if this is remateriazable */
10290       if (AOP_TYPE (result) == AOP_IMMD)
10291         {
10292           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10293           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10294           {
10295               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10296           }
10297           else
10298           {
10299               emitcode ("mov", 
10300                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10301           }
10302         }
10303       else
10304         {                       /* we need to get it byte by byte */
10305           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10306           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10307           if (options.model == MODEL_FLAT24) {
10308             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10309             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10310           } else {
10311             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10312           }
10313         }
10314       _endLazyDPSEvaluation ();
10315     }
10316   /* so dptr + b now contains the address */
10317   _G.bInUse++;
10318   aopOp (right, ic, FALSE, TRUE);
10319   _G.bInUse--;
10320     
10321
10322   /* if bit then unpack */
10323   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10324     {
10325         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10326     }
10327   else
10328     {
10329         size = AOP_SIZE (right);
10330         offset = 0;
10331
10332         _startLazyDPSEvaluation ();
10333         while (size--)
10334         {
10335             if (size)
10336             {
10337                 // Set two bytes at a time, passed in _AP & A.
10338                 // dptr will be incremented ONCE by __gptrputWord.
10339                 //
10340                 // Note: any change here must be coordinated
10341                 // with the implementation of __gptrputWord
10342                 // in device/lib/_gptrput.c
10343                 emitcode("mov", "_ap, %s", 
10344                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10345                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10346                 
10347                 genSetDPTR (0);
10348                 _flushLazyDPS ();
10349                 emitcode ("lcall", "__gptrputWord");
10350                 size--;
10351             }
10352             else
10353             {
10354                 // Only one byte to put.
10355                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10356
10357                 genSetDPTR (0);
10358                 _flushLazyDPS ();               
10359                 emitcode ("lcall", "__gptrput");
10360             }
10361             
10362             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10363             {
10364                 emitcode ("inc", "dptr");
10365             }
10366         }
10367         _endLazyDPSEvaluation ();
10368     }
10369
10370   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10371       _startLazyDPSEvaluation ();
10372       
10373       aopPut (AOP(result),"dpl",0);
10374       aopPut (AOP(result),"dph",1);
10375       if (options.model == MODEL_FLAT24) {
10376           aopPut (AOP(result),"dpx",2);
10377           aopPut (AOP(result),"b",3);
10378       } else {
10379           aopPut (AOP(result),"b",2);
10380       }
10381       _endLazyDPSEvaluation ();
10382       
10383       pi->generated=1;
10384   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10385              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10386       
10387       size = AOP_SIZE (right) - 1;
10388       while (size--) emitcode ("lcall","__decdptr");
10389   }
10390   freeAsmop (result, NULL, ic, TRUE);
10391   freeAsmop (right, NULL, ic, TRUE);
10392 }
10393
10394 /*-----------------------------------------------------------------*/
10395 /* genPointerSet - stores the value into a pointer location        */
10396 /*-----------------------------------------------------------------*/
10397 static void
10398 genPointerSet (iCode * ic, iCode *pi)
10399 {
10400   operand *right, *result;
10401   sym_link *type, *etype;
10402   int p_type;
10403
10404   D (emitcode (";", "genPointerSet "););
10405
10406   right = IC_RIGHT (ic);
10407   result = IC_RESULT (ic);
10408
10409   /* depending on the type of pointer we need to
10410      move it to the correct pointer register */
10411   type = operandType (result);
10412   etype = getSpec (type);
10413   /* if left is of type of pointer then it is simple */
10414   if (IS_PTR (type) && !IS_FUNC (type->next))
10415     {
10416       p_type = DCL_TYPE (type);
10417     }
10418   else
10419     {
10420       /* we have to go by the storage class */
10421       p_type = PTR_TYPE (SPEC_OCLS (etype));
10422     }
10423   /* special case when cast remat */
10424   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10425       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10426           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10427           type = operandType (result);
10428           p_type = DCL_TYPE (type);
10429   }
10430
10431   /* now that we have the pointer type we assign
10432      the pointer values */
10433   switch (p_type)
10434     {
10435
10436     case POINTER:
10437     case IPOINTER:
10438       genNearPointerSet (right, result, ic, pi);
10439       break;
10440
10441     case PPOINTER:
10442       genPagedPointerSet (right, result, ic, pi);
10443       break;
10444
10445     case FPOINTER:
10446       genFarPointerSet (right, result, ic, pi);
10447       break;
10448
10449     case GPOINTER:
10450       genGenPointerSet (right, result, ic, pi);
10451       break;
10452
10453     default:
10454       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10455               "genPointerSet: illegal pointer type");
10456     }
10457
10458 }
10459
10460 /*-----------------------------------------------------------------*/
10461 /* genIfx - generate code for Ifx statement                        */
10462 /*-----------------------------------------------------------------*/
10463 static void
10464 genIfx (iCode * ic, iCode * popIc)
10465 {
10466   operand *cond = IC_COND (ic);
10467   int isbit = 0;
10468
10469   D (emitcode (";", "genIfx "););
10470
10471   aopOp (cond, ic, FALSE, FALSE);
10472
10473   /* get the value into acc */
10474   if (AOP_TYPE (cond) != AOP_CRY)
10475     {
10476         toBoolean (cond);
10477     }
10478   else
10479     {
10480         isbit = 1;
10481     }
10482     
10483   /* the result is now in the accumulator */
10484   freeAsmop (cond, NULL, ic, TRUE);
10485
10486   /* if there was something to be popped then do it */
10487   if (popIc)
10488     genIpop (popIc);
10489
10490   /* if the condition is  a bit variable */
10491   if (isbit && IS_ITEMP (cond) &&
10492       SPIL_LOC (cond))
10493     {
10494         genIfxJump (ic, SPIL_LOC (cond)->rname);
10495     }
10496   else if (isbit && !IS_ITEMP (cond))
10497     {
10498         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10499     }
10500   else
10501     {
10502         genIfxJump (ic, "a");
10503     }
10504
10505   ic->generated = 1;
10506 }
10507
10508 /*-----------------------------------------------------------------*/
10509 /* genAddrOf - generates code for address of                       */
10510 /*-----------------------------------------------------------------*/
10511 static void
10512 genAddrOf (iCode * ic)
10513 {
10514   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10515   int size, offset;
10516
10517   D (emitcode (";", "genAddrOf ");
10518     );
10519
10520   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10521
10522   /* if the operand is on the stack then we
10523      need to get the stack offset of this
10524      variable */
10525   if (sym->onStack) {
10526       
10527       /* if 10 bit stack */
10528       if (options.stack10bit) {
10529           char buff[10];
10530           int  offset;
10531           
10532           tsprintf(buff, sizeof(buff), 
10533                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10534           /* if it has an offset then we need to compute it */
10535 /*        emitcode ("subb", "a,#!constbyte", */
10536 /*                  -((sym->stack < 0) ? */
10537 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10538 /*                    ((short) sym->stack)) & 0xff); */
10539 /*        emitcode ("mov","b,a"); */
10540 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10541 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10542 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10543           if (sym->stack) {
10544               emitcode ("mov", "a,_bpx");
10545               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10546                                              ((char) (sym->stack - _G.nRegsSaved)) :
10547                                              ((char) sym->stack )) & 0xff);
10548               emitcode ("mov", "b,a");
10549               emitcode ("mov", "a,_bpx+1");
10550               
10551               offset = (((sym->stack < 0) ? 
10552                          ((short) (sym->stack - _G.nRegsSaved)) :
10553                          ((short) sym->stack )) >> 8) & 0xff;
10554           
10555               emitcode ("addc","a,#!constbyte", offset);
10556
10557               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10558               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10559               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10560           } else {
10561               /* we can just move _bp */
10562               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10563               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10564               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10565           }       
10566       } else {
10567           /* if it has an offset then we need to compute it */
10568           if (sym->stack) {
10569               emitcode ("mov", "a,_bp");
10570               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10571               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10572           } else {
10573               /* we can just move _bp */
10574               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10575           }
10576           /* fill the result with zero */
10577           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10578           
10579           
10580           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10581               fprintf (stderr,
10582                        "*** warning: pointer to stack var truncated.\n");
10583           }
10584
10585           offset = 1;
10586           while (size--) {
10587               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10588           }      
10589       }
10590       goto release;
10591   }
10592
10593   /* object not on stack then we need the name */
10594   size = AOP_SIZE (IC_RESULT (ic));
10595   offset = 0;
10596
10597   while (size--)
10598     {
10599       char s[SDCC_NAME_MAX];
10600       if (offset) {
10601           switch (offset) {
10602           case 1:
10603               tsprintf(s, sizeof(s), "#!his",sym->rname);
10604               break;
10605           case 2:
10606               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10607               break;
10608           case 3:
10609               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10610               break;
10611           default: /* should not need this (just in case) */
10612               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10613                        sym->rname,
10614                        offset * 8);
10615           }
10616       } 
10617       else
10618       {
10619           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10620       }
10621         
10622       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10623     }
10624
10625 release:
10626   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10627
10628 }
10629
10630 #if 0 // obsolete, and buggy for != xdata
10631 /*-----------------------------------------------------------------*/
10632 /* genArrayInit - generates code for address of                       */
10633 /*-----------------------------------------------------------------*/
10634 static void
10635 genArrayInit (iCode * ic)
10636 {
10637     literalList *iLoop;
10638     int         ix, count;
10639     int         elementSize = 0, eIndex;
10640     unsigned    val, lastVal;
10641     sym_link    *type;
10642     operand     *left=IC_LEFT(ic);
10643     
10644     D (emitcode (";", "genArrayInit "););
10645
10646     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10647     
10648     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10649     {
10650         // Load immediate value into DPTR.
10651         emitcode("mov", "dptr, %s",
10652              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10653     }
10654     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10655     {
10656 #if 0
10657       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10658               "Unexpected operand to genArrayInit.\n");
10659       exit(1);
10660 #else
10661       // a regression because of SDCCcse.c:1.52
10662       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10663       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10664       if (options.model == MODEL_FLAT24)
10665         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10666 #endif
10667     }
10668     
10669     type = operandType(IC_LEFT(ic));
10670     
10671     if (type && type->next)
10672     {
10673         elementSize = getSize(type->next);
10674     }
10675     else
10676     {
10677         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10678                                 "can't determine element size in genArrayInit.\n");
10679         exit(1);
10680     }
10681     
10682     iLoop = IC_ARRAYILIST(ic);
10683     lastVal = 0xffff;
10684     
10685     while (iLoop)
10686     {
10687         bool firstpass = TRUE;
10688         
10689         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10690                  iLoop->count, (int)iLoop->literalValue, elementSize);
10691         
10692         ix = iLoop->count;
10693         
10694         while (ix)
10695         {
10696             symbol *tlbl = NULL;
10697             
10698             count = ix > 256 ? 256 : ix;
10699             
10700             if (count > 1)
10701             {
10702                 tlbl = newiTempLabel (NULL);
10703                 if (firstpass || (count & 0xff))
10704                 {
10705                     emitcode("mov", "b, #!constbyte", count & 0xff);
10706                 }
10707                 
10708                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10709             }
10710             
10711             firstpass = FALSE;
10712                 
10713             for (eIndex = 0; eIndex < elementSize; eIndex++)
10714             {
10715                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10716                 if (val != lastVal)
10717                 {
10718                     emitcode("mov", "a, #!constbyte", val);
10719                     lastVal = val;
10720                 }
10721                 
10722                 emitcode("movx", "@dptr, a");
10723                 emitcode("inc", "dptr");
10724             }
10725             
10726             if (count > 1)
10727             {
10728                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10729             }
10730             
10731             ix -= count;
10732         }
10733         
10734         iLoop = iLoop->next;
10735     }
10736     
10737     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10738 }
10739 #endif
10740
10741 /*-----------------------------------------------------------------*/
10742 /* genFarFarAssign - assignment when both are in far space         */
10743 /*-----------------------------------------------------------------*/
10744 static void
10745 genFarFarAssign (operand * result, operand * right, iCode * ic)
10746 {
10747   int size = AOP_SIZE (right);
10748   int offset = 0;
10749   symbol *rSym = NULL;
10750
10751   if (size == 1)
10752   {
10753       /* quick & easy case. */
10754       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10755       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10756       freeAsmop (right, NULL, ic, FALSE);
10757       /* now assign DPTR to result */
10758       _G.accInUse++;
10759       aopOp(result, ic, FALSE, FALSE);
10760       _G.accInUse--;
10761       aopPut(AOP(result), "a", 0);
10762       freeAsmop(result, NULL, ic, FALSE);
10763       return;
10764   }
10765   
10766   /* See if we've got an underlying symbol to abuse. */
10767   if (IS_SYMOP(result) && OP_SYMBOL(result))
10768   {
10769       if (IS_TRUE_SYMOP(result))
10770       {
10771           rSym = OP_SYMBOL(result);
10772       }
10773       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10774       {
10775           rSym = OP_SYMBOL(result)->usl.spillLoc;
10776       }
10777   }
10778              
10779   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10780   {
10781       /* We can use the '390 auto-toggle feature to good effect here. */
10782       
10783       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10784       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10785       emitcode ("mov", "dptr,#%s", rSym->rname); 
10786       /* DP2 = result, DP1 = right, DP1 is current. */
10787       while (size)
10788       {
10789           emitcode("movx", "a,@dptr");
10790           emitcode("movx", "@dptr,a");
10791           if (--size)
10792           {
10793                emitcode("inc", "dptr");
10794                emitcode("inc", "dptr");
10795           }
10796       }
10797       emitcode("mov", "dps,#0");
10798       freeAsmop (right, NULL, ic, FALSE);
10799 #if 0
10800 some alternative code for processors without auto-toggle
10801 no time to test now, so later well put in...kpb
10802         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10803         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10804         emitcode ("mov", "dptr,#%s", rSym->rname); 
10805         /* DP2 = result, DP1 = right, DP1 is current. */
10806         while (size)
10807         {
10808           --size;
10809           emitcode("movx", "a,@dptr");
10810           if (size)
10811             emitcode("inc", "dptr");
10812           emitcode("inc", "dps");
10813           emitcode("movx", "@dptr,a");
10814           if (size)
10815             emitcode("inc", "dptr");
10816           emitcode("inc", "dps");
10817         }
10818         emitcode("mov", "dps,#0");
10819         freeAsmop (right, NULL, ic, FALSE);
10820 #endif
10821   }
10822   else
10823   {
10824       D (emitcode (";", "genFarFarAssign"););
10825       aopOp (result, ic, TRUE, TRUE);
10826
10827       _startLazyDPSEvaluation ();
10828       
10829       while (size--)
10830         {
10831           aopPut (AOP (result),
10832                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10833           offset++;
10834         }
10835       _endLazyDPSEvaluation ();
10836       freeAsmop (result, NULL, ic, FALSE);
10837       freeAsmop (right, NULL, ic, FALSE);
10838   }
10839 }
10840
10841 /*-----------------------------------------------------------------*/
10842 /* genAssign - generate code for assignment                        */
10843 /*-----------------------------------------------------------------*/
10844 static void
10845 genAssign (iCode * ic)
10846 {
10847   operand *result, *right;
10848   int size, offset;
10849   unsigned long lit = 0L;
10850
10851   D (emitcode (";", "genAssign ");
10852     );
10853
10854   result = IC_RESULT (ic);
10855   right = IC_RIGHT (ic);
10856
10857   /* if they are the same */
10858   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10859     return;
10860
10861   aopOp (right, ic, FALSE, FALSE);
10862
10863   emitcode (";", "genAssign: resultIsFar = %s",
10864             isOperandInFarSpace (result) ?
10865             "TRUE" : "FALSE");
10866
10867   /* special case both in far space */
10868   if ((AOP_TYPE (right) == AOP_DPTR ||
10869        AOP_TYPE (right) == AOP_DPTR2) &&
10870   /* IS_TRUE_SYMOP(result)       && */
10871       isOperandInFarSpace (result))
10872     {
10873       genFarFarAssign (result, right, ic);
10874       return;
10875     }
10876
10877   aopOp (result, ic, TRUE, FALSE);
10878
10879   /* if they are the same registers */
10880   if (sameRegs (AOP (right), AOP (result)))
10881     goto release;
10882
10883   /* if the result is a bit */
10884   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10885     {
10886       /* if the right size is a literal then
10887          we know what the value is */
10888       if (AOP_TYPE (right) == AOP_LIT)
10889         {
10890           if (((int) operandLitValue (right)))
10891             aopPut (AOP (result), one, 0);
10892           else
10893             aopPut (AOP (result), zero, 0);
10894           goto release;
10895         }
10896
10897       /* the right is also a bit variable */
10898       if (AOP_TYPE (right) == AOP_CRY)
10899         {
10900           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10901           aopPut (AOP (result), "c", 0);
10902           goto release;
10903         }
10904
10905       /* we need to or */
10906       toBoolean (right);
10907       aopPut (AOP (result), "a", 0);
10908       goto release;
10909     }
10910
10911   /* bit variables done */
10912   /* general case */
10913   size = AOP_SIZE (result);
10914   offset = 0;
10915   if (AOP_TYPE (right) == AOP_LIT)
10916     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10917
10918   if ((size > 1) &&
10919       (AOP_TYPE (result) != AOP_REG) &&
10920       (AOP_TYPE (right) == AOP_LIT) &&
10921       !IS_FLOAT (operandType (right)))
10922     {
10923       _startLazyDPSEvaluation ();
10924       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10925         {
10926           aopPut (AOP (result),
10927                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10928                   offset);
10929           offset++;
10930           size--;
10931         }
10932       /* And now fill the rest with zeros. */
10933       if (size)
10934         {
10935           emitcode ("clr", "a");
10936         }
10937       while (size--)
10938         {
10939           aopPut (AOP (result), "a", offset++);
10940         }
10941       _endLazyDPSEvaluation ();
10942     }
10943   else
10944     {
10945       _startLazyDPSEvaluation ();
10946       while (size--)
10947         {
10948           aopPut (AOP (result),
10949                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10950                   offset);
10951           offset++;
10952         }
10953       _endLazyDPSEvaluation ();
10954     }
10955
10956 release:
10957   freeAsmop (right, NULL, ic, FALSE);
10958   freeAsmop (result, NULL, ic, TRUE);
10959 }
10960
10961 /*-----------------------------------------------------------------*/
10962 /* genJumpTab - generates code for jump table                      */
10963 /*-----------------------------------------------------------------*/
10964 static void
10965 genJumpTab (iCode * ic)
10966 {
10967   symbol *jtab;
10968   char *l;
10969
10970   D (emitcode (";", "genJumpTab ");
10971     );
10972
10973   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10974   /* get the condition into accumulator */
10975   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10976   MOVA (l);
10977   /* multiply by four! */
10978   emitcode ("add", "a,acc");
10979   emitcode ("add", "a,acc");
10980   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10981
10982   jtab = newiTempLabel (NULL);
10983   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10984   emitcode ("jmp", "@a+dptr");
10985   emitcode ("", "!tlabeldef", jtab->key + 100);
10986   /* now generate the jump labels */
10987   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10988        jtab = setNextItem (IC_JTLABELS (ic)))
10989     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10990
10991 }
10992
10993 /*-----------------------------------------------------------------*/
10994 /* genCast - gen code for casting                                  */
10995 /*-----------------------------------------------------------------*/
10996 static void
10997 genCast (iCode * ic)
10998 {
10999   operand *result = IC_RESULT (ic);
11000   sym_link *ctype = operandType (IC_LEFT (ic));
11001   sym_link *rtype = operandType (IC_RIGHT (ic));
11002   operand *right = IC_RIGHT (ic);
11003   int size, offset;
11004
11005   D (emitcode (";", "genCast "););
11006
11007   /* if they are equivalent then do nothing */
11008   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11009     return;
11010
11011   aopOp (right, ic, FALSE, FALSE);
11012   aopOp (result, ic, FALSE, AOP_USESDPTR(right));
11013
11014   /* if the result is a bit */
11015   if (IS_BITVAR (OP_SYMBOL (result)->type)
11016       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11017     {
11018       /* if the right size is a literal then
11019          we know what the value is */
11020       if (AOP_TYPE (right) == AOP_LIT)
11021         {
11022           if (((int) operandLitValue (right)))
11023             aopPut (AOP (result), one, 0);
11024           else
11025             aopPut (AOP (result), zero, 0);
11026
11027           goto release;
11028         }
11029
11030       /* the right is also a bit variable */
11031       if (AOP_TYPE (right) == AOP_CRY)
11032         {
11033           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11034           aopPut (AOP (result), "c", 0);
11035           goto release;
11036         }
11037
11038       /* we need to or */
11039       toBoolean (right);
11040       aopPut (AOP (result), "a", 0);
11041       goto release;
11042     }
11043
11044   /* if they are the same size : or less */
11045   if (AOP_SIZE (result) <= AOP_SIZE (right))
11046     {
11047
11048       /* if they are in the same place */
11049       if (sameRegs (AOP (right), AOP (result)))
11050         goto release;
11051
11052       /* if they in different places then copy */
11053       size = AOP_SIZE (result);
11054       offset = 0;
11055       _startLazyDPSEvaluation ();
11056       while (size--)
11057         {
11058           aopPut (AOP (result),
11059                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11060                   offset);
11061           offset++;
11062         }
11063       _endLazyDPSEvaluation ();
11064       goto release;
11065     }
11066
11067
11068   /* if the result is of type pointer */
11069   if (IS_PTR (ctype))
11070     {
11071
11072       int p_type;
11073       sym_link *type = operandType (right);
11074
11075       /* pointer to generic pointer */
11076       if (IS_GENPTR (ctype))
11077         {
11078           if (IS_PTR (type))
11079             {
11080               p_type = DCL_TYPE (type);
11081             }
11082           else
11083             {
11084 #if OLD_CAST_BEHAVIOR
11085               /* KV: we are converting a non-pointer type to
11086                * a generic pointer. This (ifdef'd out) code
11087                * says that the resulting generic pointer
11088                * should have the same class as the storage
11089                * location of the non-pointer variable.
11090                *
11091                * For example, converting an int (which happens
11092                * to be stored in DATA space) to a pointer results
11093                * in a DATA generic pointer; if the original int
11094                * in XDATA space, so will be the resulting pointer.
11095                *
11096                * I don't like that behavior, and thus this change:
11097                * all such conversions will be forced to XDATA and
11098                * throw a warning. If you want some non-XDATA
11099                * type, or you want to suppress the warning, you
11100                * must go through an intermediate cast, like so:
11101                *
11102                * char _generic *gp = (char _xdata *)(intVar);
11103                */
11104               sym_link *etype = getSpec (type);
11105
11106               /* we have to go by the storage class */
11107               if (SPEC_OCLS (etype) != generic)
11108                 {
11109                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11110                 }
11111               else
11112 #endif
11113                 {
11114                   /* Converting unknown class (i.e. register variable)
11115                    * to generic pointer. This is not good, but
11116                    * we'll make a guess (and throw a warning).
11117                    */
11118                   p_type = FPOINTER;
11119                   werror (W_INT_TO_GEN_PTR_CAST);
11120                 }
11121             }
11122
11123           /* the first two bytes are known */
11124           size = GPTRSIZE - 1;
11125           offset = 0;
11126           _startLazyDPSEvaluation ();
11127           while (size--)
11128             {
11129               aopPut (AOP (result),
11130                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11131                       offset);
11132               offset++;
11133             }
11134           _endLazyDPSEvaluation ();
11135
11136           /* the last byte depending on type */
11137             {
11138                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11139                 char gpValStr[10];
11140             
11141                 if (gpVal == -1)
11142                 {
11143                     // pointerTypeToGPByte will have bitched.
11144                     exit(1);
11145                 }
11146             
11147                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11148                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11149             }
11150           goto release;
11151         }
11152
11153       /* just copy the pointers */
11154       size = AOP_SIZE (result);
11155       offset = 0;
11156       _startLazyDPSEvaluation ();
11157       while (size--)
11158         {
11159           aopPut (AOP (result),
11160                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11161                   offset);
11162           offset++;
11163         }
11164       _endLazyDPSEvaluation ();
11165       goto release;
11166     }
11167
11168   /* so we now know that the size of destination is greater
11169      than the size of the source */
11170   /* we move to result for the size of source */
11171   size = AOP_SIZE (right);
11172   offset = 0;
11173   _startLazyDPSEvaluation ();
11174   while (size--)
11175     {
11176       aopPut (AOP (result),
11177               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11178               offset);
11179       offset++;
11180     }
11181   _endLazyDPSEvaluation ();
11182
11183   /* now depending on the sign of the source && destination */
11184   size = AOP_SIZE (result) - AOP_SIZE (right);
11185   /* if unsigned or not an integral type */
11186   /* also, if the source is a bit, we don't need to sign extend, because
11187    * it can't possibly have set the sign bit.
11188    */
11189   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11190     {
11191       while (size--)
11192         {
11193           aopPut (AOP (result), zero, offset++);
11194         }
11195     }
11196   else
11197     {
11198       /* we need to extend the sign :{ */
11199       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11200                         FALSE, FALSE, NULL));
11201       emitcode ("rlc", "a");
11202       emitcode ("subb", "a,acc");
11203       while (size--)
11204         aopPut (AOP (result), "a", offset++);
11205     }
11206
11207   /* we are done hurray !!!! */
11208
11209 release:
11210   freeAsmop (right, NULL, ic, TRUE);
11211   freeAsmop (result, NULL, ic, TRUE);
11212
11213 }
11214
11215 /*-----------------------------------------------------------------*/
11216 /* genDjnz - generate decrement & jump if not zero instrucion      */
11217 /*-----------------------------------------------------------------*/
11218 static int
11219 genDjnz (iCode * ic, iCode * ifx)
11220 {
11221   symbol *lbl, *lbl1;
11222   if (!ifx)
11223     return 0;
11224
11225   /* if the if condition has a false label
11226      then we cannot save */
11227   if (IC_FALSE (ifx))
11228     return 0;
11229
11230   /* if the minus is not of the form
11231      a = a - 1 */
11232   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11233       !IS_OP_LITERAL (IC_RIGHT (ic)))
11234     return 0;
11235
11236   if (operandLitValue (IC_RIGHT (ic)) != 1)
11237     return 0;
11238
11239   /* if the size of this greater than one then no
11240      saving */
11241   if (getSize (operandType (IC_RESULT (ic))) > 1)
11242     return 0;
11243
11244   /* otherwise we can save BIG */
11245   D(emitcode(";", "genDjnz"););
11246
11247   lbl = newiTempLabel (NULL);
11248   lbl1 = newiTempLabel (NULL);
11249
11250   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11251
11252   if (AOP_NEEDSACC(IC_RESULT(ic)))
11253   {
11254       /* If the result is accessed indirectly via
11255        * the accumulator, we must explicitly write
11256        * it back after the decrement.
11257        */
11258       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11259       
11260       if (strcmp(rByte, "a"))
11261       {
11262            /* Something is hopelessly wrong */
11263            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11264                    __FILE__, __LINE__);
11265            /* We can just give up; the generated code will be inefficient,
11266             * but what the hey.
11267             */
11268            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11269            return 0;
11270       }
11271       emitcode ("dec", "%s", rByte);
11272       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11273       emitcode ("jnz", "!tlabel", lbl->key + 100);
11274   }
11275   else if (IS_AOP_PREG (IC_RESULT (ic)))
11276     {
11277       emitcode ("dec", "%s",
11278                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11279       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11280       emitcode ("jnz", "!tlabel", lbl->key + 100);
11281     }
11282   else
11283     {
11284       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11285                 lbl->key + 100);
11286     }
11287   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11288   emitcode ("", "!tlabeldef", lbl->key + 100);
11289   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11290   emitcode ("", "!tlabeldef", lbl1->key + 100);
11291
11292   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11293   ifx->generated = 1;
11294   return 1;
11295 }
11296
11297 /*-----------------------------------------------------------------*/
11298 /* genReceive - generate code for a receive iCode                  */
11299 /*-----------------------------------------------------------------*/
11300 static void
11301 genReceive (iCode * ic)
11302 {
11303     int size = getSize (operandType (IC_RESULT (ic)));
11304     int offset = 0;
11305     int rb1off ;
11306     
11307     D (emitcode (";", "genReceive "););
11308
11309     if (ic->argreg == 1) 
11310     {
11311         /* first parameter */
11312         if (AOP_IS_STR(IC_RESULT(ic)))
11313         {
11314             /* Nothing to do: it's already in the proper place. */
11315             return;
11316         }
11317         else
11318         {
11319             bool useDp2;
11320             
11321             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11322                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11323                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11324             
11325             _G.accInUse++;
11326             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11327             _G.accInUse--; 
11328             
11329             /* Sanity checking... */
11330             if (AOP_USESDPTR(IC_RESULT(ic)))
11331             {
11332                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11333                         "genReceive got unexpected DPTR.");
11334             }
11335             assignResultValue (IC_RESULT (ic));
11336         }
11337     } 
11338     else 
11339     { 
11340         /* second receive onwards */
11341         /* this gets a little tricky since unused recevies will be
11342          eliminated, we have saved the reg in the type field . and
11343          we use that to figure out which register to use */
11344         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11345         rb1off = ic->argreg;
11346         while (size--) 
11347         {
11348             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11349         }
11350     }
11351     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11352 }
11353
11354 /*-----------------------------------------------------------------*/
11355 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11356 /*-----------------------------------------------------------------*/
11357 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11358 {
11359     operand *from , *to , *count;
11360     symbol *lbl;
11361     bitVect *rsave;
11362     int i;
11363
11364     /* we know it has to be 3 parameters */
11365     assert (nparms == 3);
11366     
11367     rsave = newBitVect(16);
11368     /* save DPTR if it needs to be saved */
11369     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11370             if (bitVectBitValue(ic->rMask,i))
11371                     rsave = bitVectSetBit(rsave,i);
11372     }
11373     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11374                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11375     savermask(rsave);
11376     
11377     to = parms[0];
11378     from = parms[1];
11379     count = parms[2];
11380
11381     aopOp (from, ic->next, FALSE, FALSE);
11382
11383     /* get from into DPTR1 */
11384     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11385     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11386     if (options.model == MODEL_FLAT24) {
11387         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11388     }
11389
11390     freeAsmop (from, NULL, ic, FALSE);
11391     aopOp (to, ic, FALSE, FALSE);
11392     /* get "to" into DPTR */
11393     /* if the operand is already in dptr
11394        then we do nothing else we move the value to dptr */
11395     if (AOP_TYPE (to) != AOP_STR) {
11396         /* if already in DPTR then we need to push */
11397         if (AOP_TYPE(to) == AOP_DPTR) {
11398             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11399             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11400             if (options.model == MODEL_FLAT24)
11401                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11402             emitcode ("pop", "dph");
11403             emitcode ("pop", "dpl");        
11404         } else {
11405             _startLazyDPSEvaluation ();
11406             /* if this is remateriazable */
11407             if (AOP_TYPE (to) == AOP_IMMD) {
11408                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11409             } else {                    /* we need to get it byte by byte */
11410                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11411                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11412                 if (options.model == MODEL_FLAT24) {
11413                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11414                 }
11415             }
11416             _endLazyDPSEvaluation ();
11417         }
11418     }
11419     freeAsmop (to, NULL, ic, FALSE);
11420     _G.dptrInUse = _G.dptr1InUse = 1;
11421     aopOp (count, ic->next->next, FALSE,FALSE);
11422     lbl =newiTempLabel(NULL);
11423
11424     /* now for the actual copy */
11425     if (AOP_TYPE(count) == AOP_LIT && 
11426         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11427         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11428         if (fromc) {
11429             emitcode ("lcall","__bi_memcpyc2x_s");
11430         } else {
11431             emitcode ("lcall","__bi_memcpyx2x_s");
11432         }
11433         freeAsmop (count, NULL, ic, FALSE);
11434     } else {
11435         symbol *lbl1 = newiTempLabel(NULL);
11436         
11437         emitcode (";"," Auto increment but no djnz");
11438         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11439         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11440         freeAsmop (count, NULL, ic, FALSE);
11441         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11442         emitcode ("","!tlabeldef",lbl->key+100);
11443         if (fromc) {
11444             emitcode ("clr","a");
11445             emitcode ("movc", "a,@a+dptr");
11446         } else 
11447             emitcode ("movx", "a,@dptr");
11448         emitcode ("movx", "@dptr,a");
11449         emitcode ("inc", "dptr");
11450         emitcode ("inc", "dptr");
11451         emitcode ("mov","a,b");
11452         emitcode ("orl","a,_ap");
11453         emitcode ("jz","!tlabel",lbl1->key+100);
11454         emitcode ("mov","a,_ap");
11455         emitcode ("add","a,#!constbyte",0xFF);
11456         emitcode ("mov","_ap,a");
11457         emitcode ("mov","a,b");
11458         emitcode ("addc","a,#!constbyte",0xFF);
11459         emitcode ("mov","b,a");
11460         emitcode ("sjmp","!tlabel",lbl->key+100);
11461         emitcode ("","!tlabeldef",lbl1->key+100);
11462     }
11463     emitcode ("mov", "dps,#0"); 
11464     _G.dptrInUse = _G.dptr1InUse = 0;
11465     unsavermask(rsave);
11466
11467 }
11468
11469 /*-----------------------------------------------------------------*/
11470 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11471 /*-----------------------------------------------------------------*/
11472 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11473 {
11474     operand *from , *to , *count;
11475     symbol *lbl,*lbl2;
11476     bitVect *rsave;
11477     int i;
11478
11479     /* we know it has to be 3 parameters */
11480     assert (nparms == 3);
11481     
11482     rsave = newBitVect(16);
11483     /* save DPTR if it needs to be saved */
11484     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11485             if (bitVectBitValue(ic->rMask,i))
11486                     rsave = bitVectSetBit(rsave,i);
11487     }
11488     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11489                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11490     savermask(rsave);
11491     
11492     to = parms[0];
11493     from = parms[1];
11494     count = parms[2];
11495
11496     aopOp (from, ic->next, FALSE, FALSE);
11497
11498     /* get from into DPTR1 */
11499     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11500     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11501     if (options.model == MODEL_FLAT24) {
11502         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11503     }
11504
11505     freeAsmop (from, NULL, ic, FALSE);
11506     aopOp (to, ic, FALSE, FALSE);
11507     /* get "to" into DPTR */
11508     /* if the operand is already in dptr
11509        then we do nothing else we move the value to dptr */
11510     if (AOP_TYPE (to) != AOP_STR) {
11511         /* if already in DPTR then we need to push */
11512         if (AOP_TYPE(to) == AOP_DPTR) {
11513             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11514             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11515             if (options.model == MODEL_FLAT24)
11516                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11517             emitcode ("pop", "dph");
11518             emitcode ("pop", "dpl");        
11519         } else {
11520             _startLazyDPSEvaluation ();
11521             /* if this is remateriazable */
11522             if (AOP_TYPE (to) == AOP_IMMD) {
11523                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11524             } else {                    /* we need to get it byte by byte */
11525                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11526                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11527                 if (options.model == MODEL_FLAT24) {
11528                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11529                 }
11530             }
11531             _endLazyDPSEvaluation ();
11532         }
11533     }
11534     freeAsmop (to, NULL, ic, FALSE);
11535     _G.dptrInUse = _G.dptr1InUse = 1;
11536     aopOp (count, ic->next->next, FALSE,FALSE);
11537     lbl =newiTempLabel(NULL);
11538     lbl2 =newiTempLabel(NULL);
11539
11540     /* now for the actual compare */
11541     if (AOP_TYPE(count) == AOP_LIT && 
11542         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11543         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11544         if (fromc)
11545             emitcode("lcall","__bi_memcmpc2x_s");
11546         else
11547             emitcode("lcall","__bi_memcmpx2x_s");
11548         freeAsmop (count, NULL, ic, FALSE);
11549         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11550         aopPut(AOP(IC_RESULT(ic)),"a",0);
11551         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11552     } else {
11553         symbol *lbl1 = newiTempLabel(NULL);
11554
11555         emitcode("push","ar0");         
11556         emitcode (";"," Auto increment but no djnz");
11557         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11558         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11559         freeAsmop (count, NULL, ic, FALSE);
11560         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11561         emitcode ("","!tlabeldef",lbl->key+100);
11562         if (fromc) {
11563             emitcode ("clr","a");
11564             emitcode ("movc", "a,@a+dptr");
11565         } else 
11566             emitcode ("movx", "a,@dptr");
11567         emitcode ("mov","r0,a");
11568         emitcode ("movx", "a,@dptr");
11569         emitcode ("clr","c");
11570         emitcode ("subb","a,r0");
11571         emitcode ("jnz","!tlabel",lbl2->key+100);
11572         emitcode ("inc", "dptr");
11573         emitcode ("inc", "dptr");
11574         emitcode ("mov","a,b");
11575         emitcode ("orl","a,_ap");
11576         emitcode ("jz","!tlabel",lbl1->key+100);
11577         emitcode ("mov","a,_ap");
11578         emitcode ("add","a,#!constbyte",0xFF);
11579         emitcode ("mov","_ap,a");
11580         emitcode ("mov","a,b");
11581         emitcode ("addc","a,#!constbyte",0xFF);
11582         emitcode ("mov","b,a");
11583         emitcode ("sjmp","!tlabel",lbl->key+100);
11584         emitcode ("","!tlabeldef",lbl1->key+100);
11585         emitcode ("clr","a");
11586         emitcode ("","!tlabeldef",lbl2->key+100);
11587         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11588         aopPut(AOP(IC_RESULT(ic)),"a",0);
11589         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11590         emitcode("pop","ar0");
11591         emitcode ("mov", "dps,#0");      
11592     }
11593     _G.dptrInUse = _G.dptr1InUse = 0;
11594     unsavermask(rsave);
11595
11596 }
11597
11598 /*-----------------------------------------------------------------*/
11599 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11600 /* port, first parameter output area second parameter pointer to   */
11601 /* port third parameter count                                      */
11602 /*-----------------------------------------------------------------*/
11603 static void genInp( iCode *ic, int nparms, operand **parms)
11604 {
11605     operand *from , *to , *count;
11606     symbol *lbl;
11607     bitVect *rsave;
11608     int i;
11609
11610     /* we know it has to be 3 parameters */
11611     assert (nparms == 3);
11612     
11613     rsave = newBitVect(16);
11614     /* save DPTR if it needs to be saved */
11615     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11616             if (bitVectBitValue(ic->rMask,i))
11617                     rsave = bitVectSetBit(rsave,i);
11618     }
11619     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11620                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11621     savermask(rsave);
11622     
11623     to = parms[0];
11624     from = parms[1];
11625     count = parms[2];
11626
11627     aopOp (from, ic->next, FALSE, FALSE);
11628
11629     /* get from into DPTR1 */
11630     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11631     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11632     if (options.model == MODEL_FLAT24) {
11633         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11634     }
11635
11636     freeAsmop (from, NULL, ic, FALSE);
11637     aopOp (to, ic, FALSE, FALSE);
11638     /* get "to" into DPTR */
11639     /* if the operand is already in dptr
11640        then we do nothing else we move the value to dptr */
11641     if (AOP_TYPE (to) != AOP_STR) {
11642         /* if already in DPTR then we need to push */
11643         if (AOP_TYPE(to) == AOP_DPTR) {
11644             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11645             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11646             if (options.model == MODEL_FLAT24)
11647                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11648             emitcode ("pop", "dph");
11649             emitcode ("pop", "dpl");        
11650         } else {
11651             _startLazyDPSEvaluation ();
11652             /* if this is remateriazable */
11653             if (AOP_TYPE (to) == AOP_IMMD) {
11654                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11655             } else {                    /* we need to get it byte by byte */
11656                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11657                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11658                 if (options.model == MODEL_FLAT24) {
11659                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11660                 }
11661             }
11662             _endLazyDPSEvaluation ();
11663         }
11664     }
11665     freeAsmop (to, NULL, ic, FALSE);
11666
11667     _G.dptrInUse = _G.dptr1InUse = 1;
11668     aopOp (count, ic->next->next, FALSE,FALSE);
11669     lbl =newiTempLabel(NULL);
11670
11671     /* now for the actual copy */
11672     if (AOP_TYPE(count) == AOP_LIT && 
11673         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11674         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11675         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11676         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11677         freeAsmop (count, NULL, ic, FALSE);
11678         emitcode ("","!tlabeldef",lbl->key+100);
11679         emitcode ("movx", "a,@dptr");   /* read data from port */
11680         emitcode ("dec","dps");         /* switch to DPTR */
11681         emitcode ("movx", "@dptr,a");   /* save into location */
11682         emitcode ("inc", "dptr");       /* point to next area */
11683         emitcode ("inc","dps");         /* switch to DPTR2 */
11684         emitcode ("djnz","b,!tlabel",lbl->key+100);
11685     } else {
11686         symbol *lbl1 = newiTempLabel(NULL);
11687         
11688         emitcode (";"," Auto increment but no djnz");
11689         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11690         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11691         freeAsmop (count, NULL, ic, FALSE);
11692         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11693         emitcode ("","!tlabeldef",lbl->key+100);
11694         emitcode ("movx", "a,@dptr");
11695         emitcode ("dec","dps");         /* switch to DPTR */
11696         emitcode ("movx", "@dptr,a");
11697         emitcode ("inc", "dptr");
11698         emitcode ("inc","dps");         /* switch to DPTR2 */
11699 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11700 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11701         emitcode ("mov","a,b");
11702         emitcode ("orl","a,_ap");
11703         emitcode ("jz","!tlabel",lbl1->key+100);
11704         emitcode ("mov","a,_ap");
11705         emitcode ("add","a,#!constbyte",0xFF);
11706         emitcode ("mov","_ap,a");
11707         emitcode ("mov","a,b");
11708         emitcode ("addc","a,#!constbyte",0xFF);
11709         emitcode ("mov","b,a");
11710         emitcode ("sjmp","!tlabel",lbl->key+100);
11711         emitcode ("","!tlabeldef",lbl1->key+100);
11712     }
11713     emitcode ("mov", "dps,#0"); 
11714     _G.dptrInUse = _G.dptr1InUse = 0;
11715     unsavermask(rsave);
11716
11717 }
11718
11719 /*-----------------------------------------------------------------*/
11720 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11721 /* port, first parameter output area second parameter pointer to   */
11722 /* port third parameter count                                      */
11723 /*-----------------------------------------------------------------*/
11724 static void genOutp( iCode *ic, int nparms, operand **parms)
11725 {
11726     operand *from , *to , *count;
11727     symbol *lbl;
11728     bitVect *rsave;
11729     int i;
11730
11731     /* we know it has to be 3 parameters */
11732     assert (nparms == 3);
11733     
11734     rsave = newBitVect(16);
11735     /* save DPTR if it needs to be saved */
11736     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11737             if (bitVectBitValue(ic->rMask,i))
11738                     rsave = bitVectSetBit(rsave,i);
11739     }
11740     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11741                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11742     savermask(rsave);
11743     
11744     to = parms[0];
11745     from = parms[1];
11746     count = parms[2];
11747
11748     aopOp (from, ic->next, FALSE, FALSE);
11749
11750     /* get from into DPTR1 */
11751     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11752     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11753     if (options.model == MODEL_FLAT24) {
11754         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11755     }
11756
11757     freeAsmop (from, NULL, ic, FALSE);
11758     aopOp (to, ic, FALSE, FALSE);
11759     /* get "to" into DPTR */
11760     /* if the operand is already in dptr
11761        then we do nothing else we move the value to dptr */
11762     if (AOP_TYPE (to) != AOP_STR) {
11763         /* if already in DPTR then we need to push */
11764         if (AOP_TYPE(to) == AOP_DPTR) {
11765             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11766             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11767             if (options.model == MODEL_FLAT24)
11768                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11769             emitcode ("pop", "dph");
11770             emitcode ("pop", "dpl");        
11771         } else {
11772             _startLazyDPSEvaluation ();
11773             /* if this is remateriazable */
11774             if (AOP_TYPE (to) == AOP_IMMD) {
11775                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11776             } else {                    /* we need to get it byte by byte */
11777                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11778                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11779                 if (options.model == MODEL_FLAT24) {
11780                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11781                 }
11782             }
11783             _endLazyDPSEvaluation ();
11784         }
11785     }
11786     freeAsmop (to, NULL, ic, FALSE);
11787
11788     _G.dptrInUse = _G.dptr1InUse = 1;
11789     aopOp (count, ic->next->next, FALSE,FALSE);
11790     lbl =newiTempLabel(NULL);
11791
11792     /* now for the actual copy */
11793     if (AOP_TYPE(count) == AOP_LIT && 
11794         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11795         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11796         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11797         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11798         emitcode ("","!tlabeldef",lbl->key+100);
11799         emitcode ("movx", "a,@dptr");   /* read data from port */
11800         emitcode ("inc","dps");         /* switch to DPTR2 */
11801         emitcode ("movx", "@dptr,a");   /* save into location */
11802         emitcode ("inc", "dptr");       /* point to next area */
11803         emitcode ("dec","dps");         /* switch to DPTR */
11804         emitcode ("djnz","b,!tlabel",lbl->key+100);
11805         freeAsmop (count, NULL, ic, FALSE);
11806     } else {
11807         symbol *lbl1 = newiTempLabel(NULL);
11808         
11809         emitcode (";"," Auto increment but no djnz");
11810         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11811         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11812         freeAsmop (count, NULL, ic, FALSE);
11813         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11814         emitcode ("","!tlabeldef",lbl->key+100);
11815         emitcode ("movx", "a,@dptr");
11816         emitcode ("inc", "dptr");
11817         emitcode ("inc","dps");         /* switch to DPTR2 */
11818         emitcode ("movx", "@dptr,a");
11819         emitcode ("dec","dps");         /* switch to DPTR */
11820         emitcode ("mov","a,b");
11821         emitcode ("orl","a,_ap");
11822         emitcode ("jz","!tlabel",lbl1->key+100);
11823         emitcode ("mov","a,_ap");
11824         emitcode ("add","a,#!constbyte",0xFF);
11825         emitcode ("mov","_ap,a");
11826         emitcode ("mov","a,b");
11827         emitcode ("addc","a,#!constbyte",0xFF);
11828         emitcode ("mov","b,a");
11829         emitcode ("sjmp","!tlabel",lbl->key+100);
11830         emitcode ("","!tlabeldef",lbl1->key+100);
11831     }
11832     emitcode ("mov", "dps,#0"); 
11833     _G.dptrInUse = _G.dptr1InUse = 0;
11834     unsavermask(rsave);
11835
11836 }
11837
11838 /*-----------------------------------------------------------------*/
11839 /* genSwapW - swap lower & high order bytes                        */
11840 /*-----------------------------------------------------------------*/
11841 static void genSwapW(iCode *ic, int nparms, operand **parms)
11842 {
11843     operand *dest;
11844     operand *src;
11845     assert (nparms==1);
11846
11847     src = parms[0];
11848     dest=IC_RESULT(ic);
11849
11850     assert(getSize(operandType(src))==2);
11851
11852     aopOp (src, ic, FALSE, FALSE);
11853     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11854     _G.accInUse++;
11855     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11856     _G.accInUse--;
11857     freeAsmop (src, NULL, ic, FALSE);
11858     
11859     aopOp (dest,ic, FALSE, FALSE);
11860     aopPut(AOP(dest),"b",0);
11861     aopPut(AOP(dest),"a",1);
11862     freeAsmop (dest, NULL, ic, FALSE);    
11863 }
11864
11865 /*-----------------------------------------------------------------*/
11866 /* genMemsetX - gencode for memSetX data                           */
11867 /*-----------------------------------------------------------------*/
11868 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11869 {
11870     operand *to , *val , *count;
11871     symbol *lbl;
11872     char *l;
11873     int i;
11874     bitVect *rsave;
11875
11876     /* we know it has to be 3 parameters */
11877     assert (nparms == 3);
11878     
11879     to = parms[0];
11880     val = parms[1];
11881     count = parms[2];
11882         
11883     /* save DPTR if it needs to be saved */
11884     rsave = newBitVect(16);
11885     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11886             if (bitVectBitValue(ic->rMask,i))
11887                     rsave = bitVectSetBit(rsave,i);
11888     }
11889     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11890                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11891     savermask(rsave);
11892
11893     aopOp (to, ic, FALSE, FALSE);
11894     /* get "to" into DPTR */
11895     /* if the operand is already in dptr
11896        then we do nothing else we move the value to dptr */
11897     if (AOP_TYPE (to) != AOP_STR) {
11898         /* if already in DPTR then we need to push */
11899         if (AOP_TYPE(to) == AOP_DPTR) {
11900             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11901             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11902             if (options.model == MODEL_FLAT24)
11903                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11904             emitcode ("pop", "dph");
11905             emitcode ("pop", "dpl");        
11906         } else {
11907             _startLazyDPSEvaluation ();
11908             /* if this is remateriazable */
11909             if (AOP_TYPE (to) == AOP_IMMD) {
11910                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11911             } else {                    /* we need to get it byte by byte */
11912                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11913                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11914                 if (options.model == MODEL_FLAT24) {
11915                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11916                 }
11917             }
11918             _endLazyDPSEvaluation ();
11919         }
11920     }
11921     freeAsmop (to, NULL, ic, FALSE);
11922
11923     aopOp (val, ic->next->next, FALSE,FALSE);
11924     aopOp (count, ic->next->next, FALSE,FALSE);    
11925     lbl =newiTempLabel(NULL);
11926     /* now for the actual copy */
11927     if (AOP_TYPE(count) == AOP_LIT && 
11928         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11929         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11930         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11931         MOVA(l);
11932         emitcode ("","!tlabeldef",lbl->key+100);
11933         emitcode ("movx", "@dptr,a");
11934         emitcode ("inc", "dptr");
11935         emitcode ("djnz","b,!tlabel",lbl->key+100);
11936     } else {
11937         symbol *lbl1 = newiTempLabel(NULL);
11938         
11939         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11940         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11941         emitcode ("","!tlabeldef",lbl->key+100);
11942         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11943         emitcode ("movx", "@dptr,a");
11944         emitcode ("inc", "dptr");
11945         emitcode ("mov","a,b");
11946         emitcode ("orl","a,_ap");
11947         emitcode ("jz","!tlabel",lbl1->key+100);
11948         emitcode ("mov","a,_ap");
11949         emitcode ("add","a,#!constbyte",0xFF);
11950         emitcode ("mov","_ap,a");
11951         emitcode ("mov","a,b");
11952         emitcode ("addc","a,#!constbyte",0xFF);
11953         emitcode ("mov","b,a");
11954         emitcode ("sjmp","!tlabel",lbl->key+100);
11955         emitcode ("","!tlabeldef",lbl1->key+100);
11956     }
11957     freeAsmop (count, NULL, ic, FALSE);
11958     unsavermask(rsave);
11959 }
11960
11961 /*-----------------------------------------------------------------*/
11962 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11963 /*-----------------------------------------------------------------*/
11964 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11965 {
11966         bitVect *rsave ;
11967         operand *pnum, *result;
11968         int i;
11969     
11970         assert (nparms==1);
11971         /* save registers that need to be saved */
11972         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11973                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11974     
11975         pnum = parms[0]; 
11976         aopOp (pnum, ic, FALSE, FALSE);
11977         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11978         freeAsmop (pnum, NULL, ic, FALSE);
11979         emitcode ("lcall","NatLib_LoadPrimitive");
11980         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11981         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11982             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11983                 for (i = (size-1) ; i >= 0 ; i-- ) {
11984                         emitcode ("push","a%s",javaRet[i]);
11985                 }
11986                 for (i=0; i < size ; i++ ) {
11987                         emitcode ("pop","a%s",
11988                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11989                 }
11990         } else {
11991                 for (i = 0 ; i < size ; i++ ) {
11992                         aopPut(AOP(result),javaRet[i],i);
11993                 }
11994         }    
11995         freeAsmop (result, NULL, ic, FALSE);
11996         unsavermask(rsave);
11997 }
11998
11999 /*-----------------------------------------------------------------*/
12000 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12001 /*-----------------------------------------------------------------*/
12002 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12003 {
12004         bitVect *rsave ;
12005         operand *pnum, *result;
12006         int size = 3;
12007         int i;
12008     
12009         assert (nparms==1);
12010         /* save registers that need to be saved */
12011         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12012                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12013     
12014         pnum = parms[0]; 
12015         aopOp (pnum, ic, FALSE, FALSE);
12016         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12017         freeAsmop (pnum, NULL, ic, FALSE);
12018         emitcode ("lcall","NatLib_LoadPointer");
12019         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12020         if (AOP_TYPE(result)!=AOP_STR) {
12021                 for (i = 0 ; i < size ; i++ ) {
12022                         aopPut(AOP(result),fReturn[i],i);
12023                 }
12024         }    
12025         freeAsmop (result, NULL, ic, FALSE);
12026         unsavermask(rsave);
12027 }
12028
12029 /*-----------------------------------------------------------------*/
12030 /* genNatLibInstallStateBlock -                                    */
12031 /*-----------------------------------------------------------------*/
12032 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12033                                        operand **parms, const char *name)
12034 {
12035         bitVect *rsave ;
12036         operand *psb, *handle;
12037         assert (nparms==2);
12038
12039         /* save registers that need to be saved */
12040         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12041                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12042         psb = parms[0];
12043         handle = parms[1];
12044
12045         /* put pointer to state block into DPTR1 */
12046         aopOp (psb, ic, FALSE, FALSE);
12047         if (AOP_TYPE (psb) == AOP_IMMD) {
12048                 emitcode ("mov","dps,#1");
12049                 emitcode ("mov", "dptr,%s",
12050                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12051                 emitcode ("mov","dps,#0");
12052         } else {
12053                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12054                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12055                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12056         }
12057         freeAsmop (psb, NULL, ic, FALSE);
12058
12059         /* put libraryID into DPTR */
12060         emitcode ("mov","dptr,#LibraryID");
12061
12062         /* put handle into r3:r2 */
12063         aopOp (handle, ic, FALSE, FALSE);
12064         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12065                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12066                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12067                 emitcode ("pop","ar3");
12068                 emitcode ("pop","ar2");
12069         } else {        
12070                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12071                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12072         }
12073         freeAsmop (psb, NULL, ic, FALSE);
12074
12075         /* make the call */
12076         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12077
12078         /* put return value into place*/
12079         _G.accInUse++;
12080         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12081         _G.accInUse--;
12082         aopPut(AOP(IC_RESULT(ic)),"a",0);
12083         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12084         unsavermask(rsave);
12085 }
12086
12087 /*-----------------------------------------------------------------*/
12088 /* genNatLibRemoveStateBlock -                                     */
12089 /*-----------------------------------------------------------------*/
12090 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12091 {
12092         bitVect *rsave ;
12093
12094         assert(nparms==0);
12095
12096         /* save registers that need to be saved */
12097         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12098                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12099
12100         /* put libraryID into DPTR */
12101         emitcode ("mov","dptr,#LibraryID");
12102         /* make the call */
12103         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12104         unsavermask(rsave);
12105 }
12106
12107 /*-----------------------------------------------------------------*/
12108 /* genNatLibGetStateBlock -                                        */
12109 /*-----------------------------------------------------------------*/
12110 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12111                                    operand **parms,const char *name)
12112 {
12113         bitVect *rsave ;
12114         symbol *lbl = newiTempLabel(NULL);
12115         
12116         assert(nparms==0);
12117         /* save registers that need to be saved */
12118         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12119                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12120
12121         /* put libraryID into DPTR */
12122         emitcode ("mov","dptr,#LibraryID");
12123         /* make the call */
12124         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12125         emitcode ("jnz","!tlabel",lbl->key+100);
12126
12127         /* put return value into place */
12128         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12129         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12130                 emitcode ("push","ar3");
12131                 emitcode ("push","ar2");
12132                 emitcode ("pop","%s",
12133                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12134                 emitcode ("pop","%s",
12135                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12136         } else {
12137                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12138                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12139         }
12140         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12141         emitcode ("","!tlabeldef",lbl->key+100);
12142         unsavermask(rsave);
12143 }
12144
12145 /*-----------------------------------------------------------------*/
12146 /* genMMMalloc -                                                   */
12147 /*-----------------------------------------------------------------*/
12148 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12149                          int size, const char *name)
12150 {
12151         bitVect *rsave ;
12152         operand *bsize;
12153         symbol *rsym;
12154         symbol *lbl = newiTempLabel(NULL);
12155
12156         assert (nparms == 1);
12157         /* save registers that need to be saved */
12158         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12159                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12160         
12161         bsize=parms[0];
12162         aopOp (bsize,ic,FALSE,FALSE);
12163
12164         /* put the size in R4-R2 */
12165         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12166                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12167                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12168                 if (size==3) {
12169                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12170                         emitcode("pop","ar4");
12171                 }
12172                 emitcode("pop","ar3");
12173                 emitcode("pop","ar2");          
12174         } else {
12175                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12176                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12177                 if (size==3) {
12178                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12179                 }
12180         }
12181         freeAsmop (bsize, NULL, ic, FALSE);
12182
12183         /* make the call */
12184         emitcode ("lcall","MM_%s",name);
12185         emitcode ("jz","!tlabel",lbl->key+100);
12186         emitcode ("mov","r2,#!constbyte",0xff);
12187         emitcode ("mov","r3,#!constbyte",0xff);
12188         emitcode ("","!tlabeldef",lbl->key+100);
12189         /* we don't care about the pointer : we just save the handle */
12190         rsym = OP_SYMBOL(IC_RESULT(ic));
12191         if (rsym->liveFrom != rsym->liveTo) {
12192                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12193                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12194                         emitcode ("push","ar3");
12195                         emitcode ("push","ar2");
12196                         emitcode ("pop","%s",
12197                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12198                         emitcode ("pop","%s",
12199                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12200                 } else {
12201                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12202                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12203                 }
12204                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12205         }
12206         unsavermask(rsave);
12207 }
12208
12209 /*-----------------------------------------------------------------*/
12210 /* genMMDeref -                                                    */
12211 /*-----------------------------------------------------------------*/
12212 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12213 {
12214         bitVect *rsave ;
12215         operand *handle;
12216
12217         assert (nparms == 1);
12218         /* save registers that need to be saved */
12219         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12220                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12221         
12222         handle=parms[0];
12223         aopOp (handle,ic,FALSE,FALSE);
12224
12225         /* put the size in R4-R2 */
12226         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12227                 emitcode("push","%s",
12228                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12229                 emitcode("push","%s",
12230                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12231                 emitcode("pop","ar3");
12232                 emitcode("pop","ar2");          
12233         } else {
12234                 emitcode ("mov","r2,%s",
12235                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12236                 emitcode ("mov","r3,%s",
12237                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12238         }
12239         freeAsmop (handle, NULL, ic, FALSE);
12240
12241         /* make the call */
12242         emitcode ("lcall","MM_Deref");
12243         
12244         {
12245                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12246                 if (rsym->liveFrom != rsym->liveTo) {                   
12247                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12248                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12249                             _startLazyDPSEvaluation ();
12250                             
12251                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12252                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12253                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12254
12255                             _endLazyDPSEvaluation ();
12256                             
12257                         }
12258                 }
12259         }
12260         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12261         unsavermask(rsave);
12262 }
12263
12264 /*-----------------------------------------------------------------*/
12265 /* genMMUnrestrictedPersist -                                      */
12266 /*-----------------------------------------------------------------*/
12267 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12268 {
12269         bitVect *rsave ;
12270         operand *handle;
12271
12272         assert (nparms == 1);
12273         /* save registers that need to be saved */
12274         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12275                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12276         
12277         handle=parms[0];
12278         aopOp (handle,ic,FALSE,FALSE);
12279
12280         /* put the size in R3-R2 */
12281         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12282                 emitcode("push","%s",
12283                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12284                 emitcode("push","%s",
12285                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12286                 emitcode("pop","ar3");
12287                 emitcode("pop","ar2");          
12288         } else {
12289                 emitcode ("mov","r2,%s",
12290                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12291                 emitcode ("mov","r3,%s",
12292                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12293         }
12294         freeAsmop (handle, NULL, ic, FALSE);
12295
12296         /* make the call */
12297         emitcode ("lcall","MM_UnrestrictedPersist");
12298
12299         {
12300                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12301                 if (rsym->liveFrom != rsym->liveTo) {   
12302                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12303                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12304                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12305                 }
12306         }
12307         unsavermask(rsave);
12308 }
12309
12310 /*-----------------------------------------------------------------*/
12311 /* genSystemExecJavaProcess -                                      */
12312 /*-----------------------------------------------------------------*/
12313 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12314 {
12315         bitVect *rsave ;
12316         operand *handle, *pp;
12317
12318         assert (nparms==2);
12319         /* save registers that need to be saved */
12320         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12321                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12322         
12323         pp = parms[0];
12324         handle = parms[1];
12325         
12326         /* put the handle in R3-R2 */
12327         aopOp (handle,ic,FALSE,FALSE);
12328         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12329                 emitcode("push","%s",
12330                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12331                 emitcode("push","%s",
12332                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12333                 emitcode("pop","ar3");
12334                 emitcode("pop","ar2");          
12335         } else {
12336                 emitcode ("mov","r2,%s",
12337                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12338                 emitcode ("mov","r3,%s",
12339                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12340         }
12341         freeAsmop (handle, NULL, ic, FALSE);
12342         
12343         /* put pointer in DPTR */
12344         aopOp (pp,ic,FALSE,FALSE);
12345         if (AOP_TYPE(pp) == AOP_IMMD) {
12346                 emitcode ("mov", "dptr,%s",
12347                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12348         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12349                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12350                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12351                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12352         }
12353         freeAsmop (handle, NULL, ic, FALSE);
12354
12355         /* make the call */
12356         emitcode ("lcall","System_ExecJavaProcess");
12357         
12358         /* put result in place */
12359         {
12360                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12361                 if (rsym->liveFrom != rsym->liveTo) {   
12362                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12363                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12364                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12365                 }
12366         }
12367         
12368         unsavermask(rsave);
12369 }
12370
12371 /*-----------------------------------------------------------------*/
12372 /* genSystemRTCRegisters -                                         */
12373 /*-----------------------------------------------------------------*/
12374 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12375                                   char *name)
12376 {
12377         bitVect *rsave ;
12378         operand *pp;
12379
12380         assert (nparms==1);
12381         /* save registers that need to be saved */
12382         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12383                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12384         
12385         pp=parms[0];
12386         /* put pointer in DPTR */
12387         aopOp (pp,ic,FALSE,FALSE);
12388         if (AOP_TYPE (pp) == AOP_IMMD) {
12389                 emitcode ("mov","dps,#1");
12390                 emitcode ("mov", "dptr,%s", 
12391                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12392                 emitcode ("mov","dps,#0");
12393         } else {
12394                 emitcode ("mov","dpl1,%s",
12395                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12396                 emitcode ("mov","dph1,%s",
12397                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12398                 emitcode ("mov","dpx1,%s",
12399                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12400         }
12401         freeAsmop (pp, NULL, ic, FALSE);
12402
12403         /* make the call */
12404         emitcode ("lcall","System_%sRTCRegisters",name);
12405
12406         unsavermask(rsave);
12407 }
12408
12409 /*-----------------------------------------------------------------*/
12410 /* genSystemThreadSleep -                                          */
12411 /*-----------------------------------------------------------------*/
12412 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12413 {
12414         bitVect *rsave ;
12415         operand *to, *s;
12416
12417         assert (nparms==1);
12418         /* save registers that need to be saved */
12419         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12420                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12421
12422         to = parms[0];
12423         aopOp(to,ic,FALSE,FALSE);
12424         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12425             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12426                 emitcode ("push","%s",
12427                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12428                 emitcode ("push","%s",
12429                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12430                 emitcode ("push","%s",
12431                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12432                 emitcode ("push","%s",
12433                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12434                 emitcode ("pop","ar3");
12435                 emitcode ("pop","ar2");
12436                 emitcode ("pop","ar1");
12437                 emitcode ("pop","ar0");
12438         } else {
12439                 emitcode ("mov","r0,%s",
12440                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12441                 emitcode ("mov","r1,%s",
12442                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12443                 emitcode ("mov","r2,%s",
12444                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12445                 emitcode ("mov","r3,%s",
12446                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12447         }
12448         freeAsmop (to, NULL, ic, FALSE);
12449
12450         /* suspend in acc */
12451         s = parms[1];
12452         aopOp(s,ic,FALSE,FALSE);
12453         emitcode ("mov","a,%s",
12454                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12455         freeAsmop (s, NULL, ic, FALSE);
12456
12457         /* make the call */
12458         emitcode ("lcall","System_%s",name);
12459
12460         unsavermask(rsave);
12461 }
12462
12463 /*-----------------------------------------------------------------*/
12464 /* genSystemThreadResume -                                         */
12465 /*-----------------------------------------------------------------*/
12466 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12467 {
12468         bitVect *rsave ;
12469         operand *tid,*pid;
12470
12471         assert (nparms==2);
12472         /* save registers that need to be saved */
12473         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12474                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12475         
12476         tid = parms[0];
12477         pid = parms[1];
12478         
12479         /* PID in R0 */
12480         aopOp(pid,ic,FALSE,FALSE);
12481         emitcode ("mov","r0,%s",
12482                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12483         freeAsmop (pid, NULL, ic, FALSE);
12484         
12485         /* tid into ACC */
12486         aopOp(tid,ic,FALSE,FALSE);
12487         emitcode ("mov","a,%s",
12488                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12489         freeAsmop (tid, NULL, ic, FALSE);
12490         
12491         emitcode ("lcall","System_ThreadResume");
12492
12493         /* put result into place */
12494         {
12495                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12496                 if (rsym->liveFrom != rsym->liveTo) {   
12497                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12498                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12499                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12500                 }
12501         }
12502         unsavermask(rsave);
12503 }
12504
12505 /*-----------------------------------------------------------------*/
12506 /* genSystemProcessResume -                                        */
12507 /*-----------------------------------------------------------------*/
12508 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12509 {
12510         bitVect *rsave ;
12511         operand *pid;
12512
12513         assert (nparms==1);
12514         /* save registers that need to be saved */
12515         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12516                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12517         
12518         pid = parms[0];
12519         
12520         /* pid into ACC */
12521         aopOp(pid,ic,FALSE,FALSE);
12522         emitcode ("mov","a,%s",
12523                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12524         freeAsmop (pid, NULL, ic, FALSE);
12525         
12526         emitcode ("lcall","System_ProcessResume");
12527
12528         unsavermask(rsave);
12529 }
12530
12531 /*-----------------------------------------------------------------*/
12532 /* genSystem -                                                     */
12533 /*-----------------------------------------------------------------*/
12534 static void genSystem (iCode *ic,int nparms,char *name)
12535 {
12536         assert(nparms == 0);
12537
12538         emitcode ("lcall","System_%s",name);
12539 }
12540
12541 /*-----------------------------------------------------------------*/
12542 /* genSystemPoll -                                                  */
12543 /*-----------------------------------------------------------------*/
12544 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12545 {
12546         bitVect *rsave ;
12547         operand *fp;
12548
12549         assert (nparms==1);
12550         /* save registers that need to be saved */
12551         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12552                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12553
12554         fp = parms[0];
12555         aopOp (fp,ic,FALSE,FALSE);
12556         if (AOP_TYPE (fp) == AOP_IMMD) {
12557                 emitcode ("mov", "dptr,%s", 
12558                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12559         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12560                 emitcode ("mov","dpl,%s",
12561                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12562                 emitcode ("mov","dph,%s",
12563                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12564                 emitcode ("mov","dpx,%s",
12565                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12566         }
12567         freeAsmop (fp, NULL, ic, FALSE);
12568
12569         emitcode ("lcall","System_%sPoll",name);
12570
12571         /* put result into place */
12572         {
12573                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12574                 if (rsym->liveFrom != rsym->liveTo) {   
12575                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12576                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12577                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12578                 }
12579         }
12580         unsavermask(rsave);
12581 }
12582
12583 /*-----------------------------------------------------------------*/
12584 /* genSystemGetCurrentID -                                         */
12585 /*-----------------------------------------------------------------*/
12586 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12587 {
12588         assert (nparms==0);
12589
12590         emitcode ("lcall","System_GetCurrent%sId",name);
12591         /* put result into place */
12592         {
12593                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12594                 if (rsym->liveFrom != rsym->liveTo) {   
12595                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12596                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12597                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12598                 }
12599         }
12600 }
12601
12602 /*-----------------------------------------------------------------*/
12603 /* genDummyRead - generate code for dummy read of volatiles        */
12604 /*-----------------------------------------------------------------*/
12605 static void
12606 genDummyRead (iCode * ic)
12607 {
12608   operand *right;
12609   int size, offset;
12610
12611   D(emitcode(";     genDummyRead",""));
12612
12613   right = IC_RIGHT (ic);
12614
12615   aopOp (right, ic, FALSE, FALSE);
12616
12617   /* if the result is a bit */
12618   if (AOP_TYPE (right) == AOP_CRY)
12619     {
12620       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12621       goto release;
12622     }
12623
12624   /* bit variables done */
12625   /* general case */
12626   size = AOP_SIZE (right);
12627   offset = 0;
12628   while (size--)
12629     {
12630       emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12631       offset++;
12632     }
12633
12634 release:
12635   freeAsmop (right, NULL, ic, TRUE);
12636 }
12637
12638 /*-----------------------------------------------------------------*/
12639 /* genBuiltIn - calls the appropriate function to  generating code */
12640 /* for a built in function                                         */
12641 /*-----------------------------------------------------------------*/
12642 static void genBuiltIn (iCode *ic)
12643 {
12644         operand *bi_parms[MAX_BUILTIN_ARGS];
12645         int nbi_parms;
12646         iCode *bi_iCode;
12647         symbol *bif;
12648
12649         /* get all the arguments for a built in function */
12650         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12651
12652         /* which function is it */
12653         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12654         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12655                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12656         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12657                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12658         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12659                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12660         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12661                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12662         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12663                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12664         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12665                 genInp(bi_iCode,nbi_parms,bi_parms);
12666         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12667                 genOutp(bi_iCode,nbi_parms,bi_parms);
12668         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12669                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12670                 /* JavaNative builtIns */               
12671         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12672                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12673         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12674                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12675         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12676                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12677         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12678                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12679         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12680                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12681         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12682                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12683         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12684                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12685         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12686                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12687         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12688                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12689         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12690                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12691         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12692                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12693         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12694                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12695         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12696                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12697         } else if (strcmp(bif->name,"MM_Free")==0) {
12698                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12699         } else if (strcmp(bif->name,"MM_Deref")==0) {
12700                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12701         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12702                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12703         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12704                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12705         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12706                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12707         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12708                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12709         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12710                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12711         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12712                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12713         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12714                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12715         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12716                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12717         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12718                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12719         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12720                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12721         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12722                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12723         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12724                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12725         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12726                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12727         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12728                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12729         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12730                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12731         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12732                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12733         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12734                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12735         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12736                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12737         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12738                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12739         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12740                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12741         } else {
12742                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12743                 return ;
12744         }
12745         return ;    
12746 }
12747
12748 /*-----------------------------------------------------------------*/
12749 /* gen390Code - generate code for Dallas 390 based controllers     */
12750 /*-----------------------------------------------------------------*/
12751 void
12752 gen390Code (iCode * lic)
12753 {
12754   iCode *ic;
12755   int cln = 0;
12756
12757   lineHead = lineCurr = NULL;
12758   dptrn[1][0] = "dpl1";
12759   dptrn[1][1] = "dph1";
12760   dptrn[1][2] = "dpx1";
12761   
12762   if (options.model == MODEL_FLAT24) {
12763     fReturnSizeDS390 = 5;
12764     fReturn = fReturn24;
12765   } else {
12766     fReturnSizeDS390 = 4;
12767     fReturn = fReturn16;
12768     options.stack10bit=0;
12769   }
12770 #if 1
12771   /* print the allocation information */
12772   if (allocInfo && currFunc)
12773     printAllocInfo (currFunc, codeOutFile);
12774 #endif
12775   /* if debug information required */
12776   if (options.debug && currFunc)
12777     {
12778       debugFile->writeFunction(currFunc);
12779       _G.debugLine = 1;
12780       if (IS_STATIC (currFunc->etype))
12781         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12782       else
12783         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12784       _G.debugLine = 0;
12785     }
12786   /* stack pointer name */
12787   if (options.useXstack)
12788     spname = "_spx";
12789   else
12790     spname = "sp";
12791
12792
12793   for (ic = lic; ic; ic = ic->next)
12794     {
12795
12796       if (ic->lineno && cln != ic->lineno)
12797         {
12798           if (options.debug)
12799             {
12800               _G.debugLine = 1;
12801               emitcode ("", "C$%s$%d$%d$%d ==.",
12802                         FileBaseName (ic->filename), ic->lineno,
12803                         ic->level, ic->block);
12804               _G.debugLine = 0;
12805             }
12806           if (!options.noCcodeInAsm) {
12807             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12808                       printCLine(ic->filename, ic->lineno));
12809           }
12810           cln = ic->lineno;
12811         }
12812       if (options.iCodeInAsm) {
12813         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12814       }
12815       /* if the result is marked as
12816          spilt and rematerializable or code for
12817          this has already been generated then
12818          do nothing */
12819       if (resultRemat (ic) || ic->generated)
12820         continue;
12821
12822       /* depending on the operation */
12823       switch (ic->op)
12824         {
12825         case '!':
12826           genNot (ic);
12827           break;
12828
12829         case '~':
12830           genCpl (ic);
12831           break;
12832
12833         case UNARYMINUS:
12834           genUminus (ic);
12835           break;
12836
12837         case IPUSH:
12838           genIpush (ic);
12839           break;
12840
12841         case IPOP:
12842           /* IPOP happens only when trying to restore a
12843              spilt live range, if there is an ifx statement
12844              following this pop then the if statement might
12845              be using some of the registers being popped which
12846              would destory the contents of the register so
12847              we need to check for this condition and handle it */
12848           if (ic->next &&
12849               ic->next->op == IFX &&
12850               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12851             genIfx (ic->next, ic);
12852           else
12853             genIpop (ic);
12854           break;
12855
12856         case CALL:
12857           genCall (ic);
12858           break;
12859
12860         case PCALL:
12861           genPcall (ic);
12862           break;
12863
12864         case FUNCTION:
12865           genFunction (ic);
12866           break;
12867
12868         case ENDFUNCTION:
12869           genEndFunction (ic);
12870           break;
12871
12872         case RETURN:
12873           genRet (ic);
12874           break;
12875
12876         case LABEL:
12877           genLabel (ic);
12878           break;
12879
12880         case GOTO:
12881           genGoto (ic);
12882           break;
12883
12884         case '+':
12885           genPlus (ic);
12886           break;
12887
12888         case '-':
12889           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12890             genMinus (ic);
12891           break;
12892
12893         case '*':
12894           genMult (ic);
12895           break;
12896
12897         case '/':
12898           genDiv (ic);
12899           break;
12900
12901         case '%':
12902           genMod (ic);
12903           break;
12904
12905         case '>':
12906           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12907           break;
12908
12909         case '<':
12910           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12911           break;
12912
12913         case LE_OP:
12914         case GE_OP:
12915         case NE_OP:
12916
12917           /* note these two are xlated by algebraic equivalence
12918              during parsing SDCC.y */
12919           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12920                   "got '>=' or '<=' shouldn't have come here");
12921           break;
12922
12923         case EQ_OP:
12924           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12925           break;
12926
12927         case AND_OP:
12928           genAndOp (ic);
12929           break;
12930
12931         case OR_OP:
12932           genOrOp (ic);
12933           break;
12934
12935         case '^':
12936           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12937           break;
12938
12939         case '|':
12940           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12941           break;
12942
12943         case BITWISEAND:
12944           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12945           break;
12946
12947         case INLINEASM:
12948           genInline (ic);
12949           break;
12950
12951         case RRC:
12952           genRRC (ic);
12953           break;
12954
12955         case RLC:
12956           genRLC (ic);
12957           break;
12958
12959         case GETHBIT:
12960           genGetHbit (ic);
12961           break;
12962
12963         case LEFT_OP:
12964           genLeftShift (ic);
12965           break;
12966
12967         case RIGHT_OP:
12968           genRightShift (ic);
12969           break;
12970
12971         case GET_VALUE_AT_ADDRESS:
12972           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12973           break;
12974
12975         case '=':
12976           if (POINTER_SET (ic))
12977             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12978           else
12979             genAssign (ic);
12980           break;
12981
12982         case IFX:
12983           genIfx (ic, NULL);
12984           break;
12985
12986         case ADDRESS_OF:
12987           genAddrOf (ic);
12988           break;
12989
12990         case JUMPTABLE:
12991           genJumpTab (ic);
12992           break;
12993
12994         case CAST:
12995           genCast (ic);
12996           break;
12997
12998         case RECEIVE:
12999           genReceive (ic);
13000           break;
13001
13002         case SEND:
13003           if (ic->builtinSEND) genBuiltIn(ic);
13004           else addSet (&_G.sendSet, ic);
13005           break;
13006
13007         case DUMMY_READ_VOLATILE:
13008           genDummyRead (ic);
13009           break;
13010
13011 #if 0 // obsolete, and buggy for != xdata
13012         case ARRAYINIT:
13013             genArrayInit(ic);
13014             break;
13015 #endif
13016             
13017         default:
13018           ic = ic;
13019         }
13020     }
13021
13022
13023   /* now we are ready to call the
13024      peep hole optimizer */
13025   if (!options.nopeep)
13026     peepHole (&lineHead);
13027
13028   /* now do the actual printing */
13029   printLine (lineHead, codeOutFile);
13030   return;
13031 }