no comments
[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                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
522                 TR_DPTR("#2");
523                 emitcode ("mov", "dph1,_bpx+1");
524                 emitcode ("mov", "dpl1,_bpx");
525                 emitcode ("mov","dps,#1");
526             } else {
527                 if (options.model == MODEL_FLAT24)
528                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
529                 emitcode ("mov", "dph,_bpx+1");
530                 emitcode ("mov", "dpl,_bpx");
531             }
532             stack_val = -stack_val;
533             while (stack_val--) {
534                 emitcode ("inc","dptr");
535             }
536             if (useDP2) {
537                 emitcode("mov","dps,#0");
538             }
539         }  else {
540             if (_G.accInUse)
541                 emitcode ("push", "acc");
542             
543             if (_G.bInUse)
544                 emitcode ("push", "b");
545         
546             emitcode ("mov", "a,_bpx");
547             emitcode ("clr","c");
548             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
549             emitcode ("mov","b,a");
550             emitcode ("mov","a,_bpx+1");
551             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
552             if (useDP2) {
553                 if (options.model == MODEL_FLAT24)
554                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
555                 TR_DPTR("#2");
556                 emitcode ("mov", "dph1,a");
557                 emitcode ("mov", "dpl1,b");
558             } else {
559                 if (options.model == MODEL_FLAT24)
560                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
561                 emitcode ("mov", "dph,a");
562                 emitcode ("mov", "dpl,b");
563             }
564             
565             if (_G.bInUse)
566                 emitcode ("pop", "b");
567             
568             if (_G.accInUse)
569                 emitcode ("pop", "acc");
570         }
571         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
572         aop->size = getSize (sym->type);
573         return aop;
574     }
575
576   /* if in bit space */
577   if (IN_BITSPACE (space))
578     {
579       sym->aop = aop = newAsmop (AOP_CRY);
580       aop->aopu.aop_dir = sym->rname;
581       aop->size = getSize (sym->type);
582       return aop;
583     }
584   /* if it is in direct space */
585   if (IN_DIRSPACE (space))
586     {
587       sym->aop = aop = newAsmop (AOP_DIR);
588       aop->aopu.aop_dir = sym->rname;
589       aop->size = getSize (sym->type);
590       return aop;
591     }
592
593   /* special case for a function */
594   if (IS_FUNC (sym->type))
595     {
596       sym->aop = aop = newAsmop (AOP_IMMD);
597       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);   
598       aop->size = FPTRSIZE;
599       return aop;
600     }
601   
602   /* only remaining is far space */
603   /* in which case DPTR gets the address */
604   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
605   if (useDP2)
606     {
607       genSetDPTR (1);
608       _flushLazyDPS ();
609       emitcode ("mov", "dptr,#%s", sym->rname);
610       genSetDPTR (0);
611     }
612   else
613     {
614       emitcode ("mov", "dptr,#%s", sym->rname);
615     }
616   aop->size = getSize (sym->type);
617
618   /* if it is in code space */
619   if (IN_CODESPACE (space))
620     aop->code = 1;
621
622   return aop;
623 }
624
625 /*-----------------------------------------------------------------*/
626 /* aopForRemat - rematerialzes an object                           */
627 /*-----------------------------------------------------------------*/
628 static asmop *
629 aopForRemat (symbol * sym)
630 {
631   iCode *ic = sym->rematiCode;
632   asmop *aop = newAsmop (AOP_IMMD);
633   int ptr_type =0;
634   int val = 0;
635
636   for (;;)
637     {
638       if (ic->op == '+')
639         val += (int) operandLitValue (IC_RIGHT (ic));
640       else if (ic->op == '-')
641         val -= (int) operandLitValue (IC_RIGHT (ic));
642       else if (IS_CAST_ICODE(ic)) {
643               sym_link *from_type = operandType(IC_RIGHT(ic));
644               aop->aopu.aop_immd.from_cast_remat = 1;
645               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
646               ptr_type = DCL_TYPE(from_type);
647               if (ptr_type == IPOINTER) {
648                 // bug #481053
649                 ptr_type = POINTER;
650               }
651               continue ;
652       } else break;
653       
654       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
655     }
656
657   if (val)
658   {
659       SNPRINTF (buffer, sizeof(buffer),
660                 "(%s %c 0x%04x)",
661                 OP_SYMBOL (IC_LEFT (ic))->rname,
662                 val >= 0 ? '+' : '-',
663                 abs (val) & 0xffffff);
664   }
665   else 
666   {
667       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
668       {
669           SNPRINTF(buffer, sizeof(buffer), 
670                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
671       }
672       else
673       {
674           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
675       }
676   }
677
678   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
679   /* set immd2 field if required */
680   if (aop->aopu.aop_immd.from_cast_remat) 
681   {
682       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
683       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
684   }
685
686   return aop;
687 }
688
689 /*-----------------------------------------------------------------*/
690 /* aopHasRegs - returns true if aop has regs between from-to       */
691 /*-----------------------------------------------------------------*/
692 static int aopHasRegs(asmop *aop, int from, int to)
693 {
694     int size =0;
695
696     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
697
698     for (; size < aop->size ; size++) {
699         int reg;
700         for (reg = from ; reg <= to ; reg++)
701             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
702     }
703     return 0;
704 }
705
706 /*-----------------------------------------------------------------*/
707 /* regsInCommon - two operands have some registers in common       */
708 /*-----------------------------------------------------------------*/
709 static bool
710 regsInCommon (operand * op1, operand * op2)
711 {
712   symbol *sym1, *sym2;
713   int i;
714
715   /* if they have registers in common */
716   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
717     return FALSE;
718
719   sym1 = OP_SYMBOL (op1);
720   sym2 = OP_SYMBOL (op2);
721
722   if (sym1->nRegs == 0 || sym2->nRegs == 0)
723     return FALSE;
724
725   for (i = 0; i < sym1->nRegs; i++)
726     {
727       int j;
728       if (!sym1->regs[i])
729         continue;
730
731       for (j = 0; j < sym2->nRegs; j++)
732         {
733           if (!sym2->regs[j])
734             continue;
735
736           if (sym2->regs[j] == sym1->regs[i])
737             return TRUE;
738         }
739     }
740
741   return FALSE;
742 }
743
744 /*-----------------------------------------------------------------*/
745 /* operandsEqu - equivalent                                        */
746 /*-----------------------------------------------------------------*/
747 static bool
748 operandsEqu (operand * op1, operand * op2)
749 {
750   symbol *sym1, *sym2;
751
752   /* if they not symbols */
753   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
754     return FALSE;
755
756   sym1 = OP_SYMBOL (op1);
757   sym2 = OP_SYMBOL (op2);
758
759   /* if both are itemps & one is spilt
760      and the other is not then false */
761   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
762       sym1->isspilt != sym2->isspilt)
763     return FALSE;
764
765   /* if they are the same */
766   if (sym1 == sym2)
767     return TRUE;
768
769   if (strcmp (sym1->rname, sym2->rname) == 0)
770     return TRUE;
771
772
773   /* if left is a tmp & right is not */
774   if (IS_ITEMP (op1) &&
775       !IS_ITEMP (op2) &&
776       sym1->isspilt &&
777       (sym1->usl.spillLoc == sym2))
778     return TRUE;
779
780   if (IS_ITEMP (op2) &&
781       !IS_ITEMP (op1) &&
782       sym2->isspilt &&
783       sym1->level > 0 &&
784       (sym2->usl.spillLoc == sym1))
785     return TRUE;
786
787   return FALSE;
788 }
789
790 /*-----------------------------------------------------------------*/
791 /* sameRegs - two asmops have the same registers                   */
792 /*-----------------------------------------------------------------*/
793 static bool
794 sameRegs (asmop * aop1, asmop * aop2)
795 {
796   int i;
797
798   if (aop1 == aop2)
799     {
800       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
801         {
802           return FALSE;
803         }
804       return TRUE;
805     }
806
807   if (aop1->type != AOP_REG ||
808       aop2->type != AOP_REG)
809     return FALSE;
810
811   if (aop1->size != aop2->size)
812     return FALSE;
813
814   for (i = 0; i < aop1->size; i++)
815     if (aop1->aopu.aop_reg[i] !=
816         aop2->aopu.aop_reg[i])
817       return FALSE;
818
819   return TRUE;
820 }
821
822 /*-----------------------------------------------------------------*/
823 /* aopOp - allocates an asmop for an operand  :                    */
824 /*-----------------------------------------------------------------*/
825 static void
826 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
827 {
828   asmop *aop;
829   symbol *sym;
830   int i;
831
832   if (!op)
833     return;
834
835   /* if this a literal */
836   if (IS_OP_LITERAL (op))
837     {
838       op->aop = aop = newAsmop (AOP_LIT);
839       aop->aopu.aop_lit = op->operand.valOperand;
840       aop->size = getSize (operandType (op));
841       return;
842     }
843
844   /* if already has a asmop then continue */
845   if (op->aop)
846     return;
847
848   /* if the underlying symbol has a aop */
849   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
850     {
851       op->aop = OP_SYMBOL (op)->aop;
852       return;
853     }
854
855   /* if this is a true symbol */
856   if (IS_TRUE_SYMOP (op))
857     {
858       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
859       return;
860     }
861
862   /* this is a temporary : this has
863      only four choices :
864      a) register
865      b) spillocation
866      c) rematerialize
867      d) conditional
868      e) can be a return use only */
869
870   sym = OP_SYMBOL (op);
871
872
873   /* if the type is a conditional */
874   if (sym->regType == REG_CND)
875     {
876       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
877       aop->size = 0;
878       return;
879     }
880
881   /* if it is spilt then two situations
882      a) is rematerialize
883      b) has a spill location */
884   if (sym->isspilt || sym->nRegs == 0)
885     {
886
887       /* rematerialize it NOW */
888       if (sym->remat)
889         {
890           sym->aop = op->aop = aop =
891             aopForRemat (sym);
892           aop->size = getSize (sym->type);
893           return;
894         }
895
896       if (sym->accuse)
897         {
898           int i;
899           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
900           aop->size = getSize (sym->type);
901           for (i = 0; i < 2; i++)
902             aop->aopu.aop_str[i] = accUse[i];
903           return;
904         }
905
906       if (sym->ruonly)
907         {
908           int i;
909
910           if (useDP2)
911             {
912               /* a AOP_STR uses DPTR, but DPTR is already in use;
913                * we're just hosed.
914                */
915                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
916             }
917
918           aop = op->aop = sym->aop = newAsmop (AOP_STR);
919           aop->size = getSize (sym->type);
920           for (i = 0; i < (int) fReturnSizeDS390; i++)
921             aop->aopu.aop_str[i] = fReturn[i];
922           return;
923         }
924       
925       if (sym->dptr) { /* has been allocated to a DPTRn */
926           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
927           aop->size = getSize (sym->type);
928           aop->aopu.dptr = sym->dptr;
929           return ;
930       }
931       /* else spill location  */
932       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
933           /* force a new aop if sizes differ */
934           sym->usl.spillLoc->aop = NULL;
935       }
936       sym->aop = op->aop = aop =
937         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
938       aop->size = getSize (sym->type);
939       return;
940     }
941
942   /* must be in a register */
943   sym->aop = op->aop = aop = newAsmop (AOP_REG);
944   aop->size = sym->nRegs;
945   for (i = 0; i < sym->nRegs; i++)
946     aop->aopu.aop_reg[i] = sym->regs[i];
947 }
948
949 /*-----------------------------------------------------------------*/
950 /* freeAsmop - free up the asmop given to an operand               */
951 /*----------------------------------------------------------------*/
952 static void
953 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
954 {
955   asmop *aop;
956
957   if (!op)
958     aop = aaop;
959   else
960     aop = op->aop;
961
962   if (!aop)
963     return;
964
965   if (aop->freed)
966     goto dealloc;
967
968   aop->freed = 1;
969
970   /* depending on the asmop type only three cases need work AOP_RO
971      , AOP_R1 && AOP_STK */
972   switch (aop->type)
973     {
974     case AOP_R0:
975       if (_G.r0Pushed)
976         {
977           if (pop)
978             {
979               emitcode ("pop", "ar0");
980               _G.r0Pushed--;
981             }
982         }
983       bitVectUnSetBit (ic->rUsed, R0_IDX);
984       break;
985
986     case AOP_R1:
987       if (_G.r1Pushed)
988         {
989           if (pop)
990             {
991               emitcode ("pop", "ar1");
992               _G.r1Pushed--;
993             }
994         }
995       bitVectUnSetBit (ic->rUsed, R1_IDX);
996       break;
997
998     case AOP_STK:
999       {
1000         int sz = aop->size;
1001         int stk = aop->aopu.aop_stk + aop->size;
1002         bitVectUnSetBit (ic->rUsed, R0_IDX);
1003         bitVectUnSetBit (ic->rUsed, R1_IDX);
1004
1005         getFreePtr (ic, &aop, FALSE);
1006
1007         if (options.stack10bit)
1008           {
1009             /* I'm not sure what to do here yet... */
1010             /* #STUB */
1011             fprintf (stderr,
1012                      "*** Warning: probably generating bad code for "
1013                      "10 bit stack mode.\n");
1014           }
1015
1016         if (stk)
1017           {
1018             emitcode ("mov", "a,_bp");
1019             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1020             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1021           }
1022         else
1023           {
1024             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1025           }
1026
1027         while (sz--)
1028           {
1029             emitcode ("pop", "acc");
1030             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1031             if (!sz)
1032               break;
1033             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1034           }
1035         op->aop = aop;
1036         freeAsmop (op, NULL, ic, TRUE);
1037         if (_G.r0Pushed)
1038           {
1039             emitcode ("pop", "ar0");
1040             _G.r0Pushed--;
1041           }
1042
1043         if (_G.r1Pushed)
1044           {
1045             emitcode ("pop", "ar1");
1046             _G.r1Pushed--;
1047           }
1048       }
1049     case AOP_DPTR2:
1050         if (_G.dptr1InUse) {
1051             emitcode ("pop","dpx1");
1052             emitcode ("pop","dph1");
1053             emitcode ("pop","dpl1");
1054         }
1055         break;
1056     case AOP_DPTR:
1057         if (_G.dptrInUse) {
1058             emitcode ("pop","dpx");
1059             emitcode ("pop","dph");
1060             emitcode ("pop","dpl");
1061         }
1062         break;
1063     }
1064 dealloc:
1065   /* all other cases just dealloc */
1066   if (op)
1067     {
1068       op->aop = NULL;
1069       if (IS_SYMOP (op))
1070         {
1071           OP_SYMBOL (op)->aop = NULL;
1072           /* if the symbol has a spill */
1073           if (SPIL_LOC (op))
1074             SPIL_LOC (op)->aop = NULL;
1075         }
1076     }
1077 }
1078
1079 #define DEFAULT_ACC_WARNING 0
1080 static int saveAccWarn = DEFAULT_ACC_WARNING;
1081
1082 /*-------------------------------------------------------------------*/
1083 /* aopGet - for fetching value of the aop                            */
1084 /*                                                                   */
1085 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1086 /* in the accumulator. Set it to the name of a free register         */
1087 /* if acc must be preserved; the register will be used to preserve   */
1088 /* acc temporarily and to return the result byte.                    */
1089 /*-------------------------------------------------------------------*/
1090
1091 static char *
1092 aopGet (asmop *aop,
1093         int   offset,
1094         bool  bit16,
1095         bool  dname,
1096         char  *saveAcc)
1097 {
1098   /* offset is greater than
1099      size then zero */
1100   if (offset > (aop->size - 1) &&
1101       aop->type != AOP_LIT)
1102     return zero;
1103
1104   /* depending on type */
1105   switch (aop->type)
1106     {
1107
1108     case AOP_R0:
1109     case AOP_R1:
1110       /* if we need to increment it */
1111       while (offset > aop->coff)
1112         {
1113           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1114           aop->coff++;
1115         }
1116
1117       while (offset < aop->coff)
1118         {
1119           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1120           aop->coff--;
1121         }
1122
1123       aop->coff = offset;
1124       if (aop->paged)
1125         {
1126           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1127           return (dname ? "acc" : "a");
1128         }
1129       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1130       return Safe_strdup(buffer);       
1131
1132     case AOP_DPTRn:
1133         assert(offset <= 3);
1134         return dptrn[aop->aopu.dptr][offset];
1135
1136     case AOP_DPTR:
1137     case AOP_DPTR2:
1138
1139       if (aop->type == AOP_DPTR2)
1140         {
1141           genSetDPTR (1);
1142         }
1143         
1144       if (saveAcc)
1145         {
1146             TR_AP("#1");
1147 //          if (aop->type != AOP_DPTR2)
1148 //          {
1149 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1150 //              emitcode(";", "spanky: saveAcc for DPTR");
1151 //          }
1152             
1153             emitcode ("xch", "a, %s", saveAcc);
1154         }
1155
1156       _flushLazyDPS ();
1157
1158       while (offset > aop->coff)
1159         {
1160           emitcode ("inc", "dptr");
1161           aop->coff++;
1162         }
1163
1164       while (offset < aop->coff)
1165         {
1166           emitcode ("lcall", "__decdptr");
1167           aop->coff--;
1168         }
1169
1170       aop->coff = offset;
1171       if (aop->code)
1172         {
1173           emitcode ("clr", "a");
1174           emitcode ("movc", "a,@a+dptr");
1175         }
1176       else
1177         {
1178           emitcode ("movx", "a,@dptr");
1179         }
1180
1181       if (aop->type == AOP_DPTR2)
1182         {
1183           genSetDPTR (0);
1184         }
1185         
1186         if (saveAcc)
1187         {
1188        TR_AP("#2");
1189               emitcode ("xch", "a, %s", saveAcc);
1190 //            if (strcmp(saveAcc, "_ap"))
1191 //            {
1192 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1193 //            }
1194                   
1195               return saveAcc;
1196         }
1197       return (dname ? "acc" : "a");
1198
1199     case AOP_IMMD:
1200       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1201       {
1202           SNPRINTF(buffer, sizeof(buffer), 
1203                    "%s",aop->aopu.aop_immd.aop_immd2);
1204       } 
1205       else if (bit16)
1206       {
1207          SNPRINTF(buffer, sizeof(buffer), 
1208                   "#%s", aop->aopu.aop_immd.aop_immd1);
1209       }
1210       else if (offset) 
1211       {
1212           switch (offset) {
1213           case 1:
1214               tsprintf(buffer, sizeof(buffer),
1215                        "#!his",aop->aopu.aop_immd.aop_immd1);
1216               break;
1217           case 2:
1218               tsprintf(buffer, sizeof(buffer), 
1219                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1220               break;
1221           case 3:
1222               tsprintf(buffer, sizeof(buffer),
1223                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1224               break;
1225           default: /* should not need this (just in case) */
1226               SNPRINTF (buffer, sizeof(buffer), 
1227                         "#(%s >> %d)",
1228                        aop->aopu.aop_immd.aop_immd1,
1229                        offset * 8);
1230           }
1231       }
1232       else
1233       {
1234         SNPRINTF (buffer, sizeof(buffer), 
1235                   "#%s", aop->aopu.aop_immd.aop_immd1);
1236       }
1237       return Safe_strdup(buffer);       
1238
1239     case AOP_DIR:
1240       if (offset)
1241       {
1242         SNPRINTF (buffer, sizeof(buffer),
1243                   "(%s + %d)",
1244                  aop->aopu.aop_dir,
1245                  offset);
1246       }
1247       else
1248       {
1249         SNPRINTF(buffer, sizeof(buffer), 
1250                  "%s", aop->aopu.aop_dir);
1251       }
1252
1253       return Safe_strdup(buffer);
1254
1255     case AOP_REG:
1256       if (dname)
1257         return aop->aopu.aop_reg[offset]->dname;
1258       else
1259         return aop->aopu.aop_reg[offset]->name;
1260
1261     case AOP_CRY:
1262       emitcode ("clr", "a");
1263       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1264       emitcode ("rlc", "a");
1265       return (dname ? "acc" : "a");
1266
1267     case AOP_ACC:
1268       if (!offset && dname)
1269         return "acc";
1270       return aop->aopu.aop_str[offset];
1271
1272     case AOP_LIT:
1273       return aopLiteral (aop->aopu.aop_lit, offset);
1274
1275     case AOP_STR:
1276       aop->coff = offset;
1277       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1278           dname)
1279         return "acc";
1280
1281       return aop->aopu.aop_str[offset];
1282
1283     }
1284
1285   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1286           "aopget got unsupported aop->type");
1287   exit (1);
1288     
1289   return NULL;  // not reached, but makes compiler happy.
1290 }
1291 /*-----------------------------------------------------------------*/
1292 /* aopPut - puts a string for a aop                                */
1293 /*-----------------------------------------------------------------*/
1294 static void
1295 aopPut (asmop * aop, char *s, int offset)
1296 {
1297   if (aop->size && offset > (aop->size - 1))
1298     {
1299       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1300               "aopPut got offset > aop->size");
1301       exit (1);
1302     }
1303
1304   /* will assign value to value */
1305   /* depending on where it is ofcourse */
1306   switch (aop->type)
1307     {
1308     case AOP_DIR:
1309         if (offset)
1310         {
1311             SNPRINTF (buffer, sizeof(buffer),
1312                       "(%s + %d)",
1313                       aop->aopu.aop_dir, offset);
1314         }
1315         else
1316         {
1317             SNPRINTF (buffer, sizeof(buffer), 
1318                      "%s", aop->aopu.aop_dir);
1319         }
1320         
1321
1322         if (strcmp (buffer, s))
1323         {
1324             emitcode ("mov", "%s,%s", buffer, s);
1325         }
1326       break;
1327
1328     case AOP_REG:
1329       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1330           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1331         {
1332           if (*s == '@' ||
1333               strcmp (s, "r0") == 0 ||
1334               strcmp (s, "r1") == 0 ||
1335               strcmp (s, "r2") == 0 ||
1336               strcmp (s, "r3") == 0 ||
1337               strcmp (s, "r4") == 0 ||
1338               strcmp (s, "r5") == 0 ||
1339               strcmp (s, "r6") == 0 ||
1340               strcmp (s, "r7") == 0)
1341             {
1342                 emitcode ("mov", "%s,%s",
1343                           aop->aopu.aop_reg[offset]->dname, s);
1344             }
1345             else
1346             {
1347                 emitcode ("mov", "%s,%s",
1348                           aop->aopu.aop_reg[offset]->name, s);
1349             }
1350         }
1351       break;
1352
1353     case AOP_DPTRn:
1354         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1355         break;
1356
1357     case AOP_DPTR:
1358     case AOP_DPTR2:
1359
1360       if (aop->type == AOP_DPTR2)
1361         {
1362           genSetDPTR (1);
1363         }
1364       _flushLazyDPS ();
1365
1366       if (aop->code)
1367         {
1368           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1369                   "aopPut writting to code space");
1370           exit (1);
1371         }
1372
1373       while (offset > aop->coff)
1374         {
1375           aop->coff++;
1376           emitcode ("inc", "dptr");
1377         }
1378
1379       while (offset < aop->coff)
1380         {
1381           aop->coff--;
1382           emitcode ("lcall", "__decdptr");
1383         }
1384
1385       aop->coff = offset;
1386
1387       /* if not in accumulater */
1388       MOVA (s);
1389
1390       emitcode ("movx", "@dptr,a");
1391
1392       if (aop->type == AOP_DPTR2)
1393         {
1394           genSetDPTR (0);
1395         }
1396       break;
1397
1398     case AOP_R0:
1399     case AOP_R1:
1400       while (offset > aop->coff)
1401         {
1402           aop->coff++;
1403           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1404         }
1405       while (offset < aop->coff)
1406         {
1407           aop->coff--;
1408           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1409         }
1410       aop->coff = offset;
1411
1412       if (aop->paged)
1413         {
1414           MOVA (s);
1415           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1416
1417         }
1418       else if (*s == '@')
1419         {
1420           MOVA (s);
1421           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1422         }
1423       else if (strcmp (s, "r0") == 0 ||
1424                strcmp (s, "r1") == 0 ||
1425                strcmp (s, "r2") == 0 ||
1426                strcmp (s, "r3") == 0 ||
1427                strcmp (s, "r4") == 0 ||
1428                strcmp (s, "r5") == 0 ||
1429                strcmp (s, "r6") == 0 ||
1430                strcmp (s, "r7") == 0)
1431         {
1432           char buff[10];
1433           SNPRINTF(buff, sizeof(buff), 
1434                    "a%s", s);
1435           emitcode ("mov", "@%s,%s",
1436                     aop->aopu.aop_ptr->name, buff);
1437         }
1438         else
1439         {
1440             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1441         }
1442       break;
1443
1444     case AOP_STK:
1445       if (strcmp (s, "a") == 0)
1446         emitcode ("push", "acc");
1447       else
1448         if (*s=='@') {
1449           MOVA(s);
1450           emitcode ("push", "acc");
1451         } else {
1452           emitcode ("push", s);
1453         }
1454
1455       break;
1456
1457     case AOP_CRY:
1458       /* if bit variable */
1459       if (!aop->aopu.aop_dir)
1460         {
1461           emitcode ("clr", "a");
1462           emitcode ("rlc", "a");
1463         }
1464       else
1465         {
1466           if (s == zero)
1467             emitcode ("clr", "%s", aop->aopu.aop_dir);
1468           else if (s == one)
1469             emitcode ("setb", "%s", aop->aopu.aop_dir);
1470           else if (!strcmp (s, "c"))
1471             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1472           else
1473             {
1474               if (strcmp (s, "a"))
1475                 {
1476                   MOVA (s);
1477                 }
1478               {
1479                 /* set C, if a >= 1 */
1480                 emitcode ("add", "a,#!constbyte",0xff);
1481                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1482               }
1483             }
1484         }
1485       break;
1486
1487     case AOP_STR:
1488       aop->coff = offset;
1489       if (strcmp (aop->aopu.aop_str[offset], s))
1490         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1491       break;
1492
1493     case AOP_ACC:
1494       aop->coff = offset;
1495       if (!offset && (strcmp (s, "acc") == 0))
1496         break;
1497
1498       if (strcmp (aop->aopu.aop_str[offset], s))
1499         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1500       break;
1501
1502     default:
1503       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1504               "aopPut got unsupported aop->type");
1505       exit (1);
1506     }
1507
1508 }
1509
1510
1511 /*--------------------------------------------------------------------*/
1512 /* reAdjustPreg - points a register back to where it should (coff==0) */
1513 /*--------------------------------------------------------------------*/
1514 static void
1515 reAdjustPreg (asmop * aop)
1516 {
1517   if ((aop->coff==0) || (aop->size <= 1)) {
1518     return;
1519   }
1520
1521   switch (aop->type)
1522     {
1523     case AOP_R0:
1524     case AOP_R1:
1525       while (aop->coff--)
1526         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1527       break;
1528     case AOP_DPTR:
1529     case AOP_DPTR2:
1530       if (aop->type == AOP_DPTR2)
1531         {
1532           genSetDPTR (1);
1533           _flushLazyDPS ();
1534         }
1535       while (aop->coff--)
1536         {
1537           emitcode ("lcall", "__decdptr");
1538         }
1539
1540       if (aop->type == AOP_DPTR2)
1541         {
1542           genSetDPTR (0);
1543         }
1544       break;
1545
1546     }
1547   aop->coff=0;
1548 }
1549
1550 #define AOP(op) op->aop
1551 #define AOP_TYPE(op) AOP(op)->type
1552 #define AOP_SIZE(op) AOP(op)->size
1553 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1554                        AOP_TYPE(x) == AOP_R0))
1555
1556 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1557                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1558                          AOP(x)->paged))
1559
1560 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1561                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1562                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1563 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1564 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1565 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1566
1567 // The following two macros can be used even if the aop has not yet been aopOp'd.
1568 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1569 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1570
1571 /* Workaround for DS80C390 bug: div ab may return bogus results
1572  * if A is accessed in instruction immediately before the div.
1573  *
1574  * Will be fixed in B4 rev of processor, Dallas claims.
1575  */
1576
1577 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1578     if (!AOP_NEEDSACC(RIGHT))         \
1579     {               \
1580       /* We can load A first, then B, since     \
1581        * B (the RIGHT operand) won't clobber A,   \
1582        * thus avoiding touching A right before the div. \
1583        */             \
1584       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1585       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1586       MOVA(L);            \
1587       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1588       MOVB(L); \
1589     }               \
1590     else              \
1591     {               \
1592       /* Just stuff in a nop after loading A. */    \
1593       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1594       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1595       MOVA(L);            \
1596       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1597     }
1598
1599 /*-----------------------------------------------------------------*/
1600 /* genNotFloat - generates not for float operations              */
1601 /*-----------------------------------------------------------------*/
1602 static void
1603 genNotFloat (operand * op, operand * res)
1604 {
1605   int size, offset;
1606   symbol *tlbl;
1607
1608   D (emitcode (";", "genNotFloat "););
1609
1610   /* we will put 127 in the first byte of
1611      the result */
1612   aopPut (AOP (res), "#127", 0);
1613   size = AOP_SIZE (op) - 1;
1614   offset = 1;
1615
1616   _startLazyDPSEvaluation ();
1617   MOVA(aopGet(op->aop, offset++, FALSE, FALSE, NULL));
1618
1619   while (size--)
1620     {
1621       emitcode ("orl", "a,%s",
1622                 aopGet (op->aop,
1623                         offset++, FALSE, FALSE,
1624                         DP2_RESULT_REG));
1625     }
1626   _endLazyDPSEvaluation ();
1627
1628   tlbl = newiTempLabel (NULL);
1629   aopPut (res->aop, one, 1);
1630   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1631   aopPut (res->aop, zero, 1);
1632   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1633
1634   size = res->aop->size - 2;
1635   offset = 2;
1636   /* put zeros in the rest */
1637   while (size--)
1638     aopPut (res->aop, zero, offset++);
1639 }
1640
1641 /*-----------------------------------------------------------------*/
1642 /* opIsGptr: returns non-zero if the passed operand is       */
1643 /* a generic pointer type.             */
1644 /*-----------------------------------------------------------------*/
1645 static int
1646 opIsGptr (operand * op)
1647 {
1648   sym_link *type = operandType (op);
1649
1650   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1651     {
1652       return 1;
1653     }
1654   return 0;
1655 }
1656
1657 /*-----------------------------------------------------------------*/
1658 /* getDataSize - get the operand data size                         */
1659 /*-----------------------------------------------------------------*/
1660 static int
1661 getDataSize (operand * op)
1662 {
1663   int size;
1664   size = AOP_SIZE (op);
1665   if (size == GPTRSIZE)
1666     {
1667       sym_link *type = operandType (op);
1668       if (IS_GENPTR (type))
1669         {
1670           /* generic pointer; arithmetic operations
1671            * should ignore the high byte (pointer type).
1672            */
1673           size--;
1674         }
1675     }
1676   return size;
1677 }
1678
1679 /*-----------------------------------------------------------------*/
1680 /* outAcc - output Acc                                             */
1681 /*-----------------------------------------------------------------*/
1682 static void
1683 outAcc (operand * result)
1684 {
1685   int size, offset;
1686   size = getDataSize (result);
1687   if (size)
1688     {
1689       aopPut (AOP (result), "a", 0);
1690       size--;
1691       offset = 1;
1692       /* unsigned or positive */
1693       while (size--)
1694         {
1695           aopPut (AOP (result), zero, offset++);
1696         }
1697     }
1698 }
1699
1700 /*-----------------------------------------------------------------*/
1701 /* outBitC - output a bit C                                        */
1702 /*-----------------------------------------------------------------*/
1703 static void
1704 outBitC (operand * result)
1705 {
1706   /* if the result is bit */
1707   if (AOP_TYPE (result) == AOP_CRY)
1708     {
1709       aopPut (AOP (result), "c", 0);
1710     }
1711   else
1712     {
1713       emitcode ("clr", "a");
1714       emitcode ("rlc", "a");
1715       outAcc (result);
1716     }
1717 }
1718
1719 /*-----------------------------------------------------------------*/
1720 /* toBoolean - emit code for orl a,operator(sizeop)                */
1721 /*-----------------------------------------------------------------*/
1722 static void
1723 toBoolean (operand * oper)
1724 {
1725   int   size = AOP_SIZE (oper) - 1;
1726   int   offset = 1;
1727   bool usedB = FALSE;
1728
1729   /* The generic part of a generic pointer should
1730    * not participate in it's truth value.
1731    *
1732    * i.e. 0x10000000 is zero.
1733    */
1734   if (opIsGptr (oper))
1735     {
1736       D (emitcode (";", "toBoolean: generic ptr special case."););
1737       size--;
1738     }
1739
1740   _startLazyDPSEvaluation ();
1741   if (AOP_NEEDSACC (oper) && size)
1742     {
1743       usedB = TRUE;
1744       if (_G.bInUse)
1745       {
1746           emitcode ("push", "b");
1747       }
1748       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1749     }
1750   else
1751     {
1752       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1753     }
1754     
1755   while (size--)
1756     {
1757       if (usedB)
1758         {
1759           emitcode ("orl", "b,%s",
1760                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1761         }
1762       else
1763         {
1764           emitcode ("orl", "a,%s",
1765                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1766         }
1767     }
1768   _endLazyDPSEvaluation ();
1769
1770   if (usedB)
1771     {
1772       emitcode ("mov", "a,b");
1773       if (_G.bInUse)
1774       {
1775           emitcode ("pop", "b");
1776       }
1777         
1778     }
1779 }
1780
1781
1782 /*-----------------------------------------------------------------*/
1783 /* genNot - generate code for ! operation                          */
1784 /*-----------------------------------------------------------------*/
1785 static void
1786 genNot (iCode * ic)
1787 {
1788   symbol *tlbl;
1789   sym_link *optype = operandType (IC_LEFT (ic));
1790
1791   D (emitcode (";", "genNot "););
1792
1793   /* assign asmOps to operand & result */
1794   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1795   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1796
1797   /* if in bit space then a special case */
1798   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1799     {
1800       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1801       emitcode ("cpl", "c");
1802       outBitC (IC_RESULT (ic));
1803       goto release;
1804     }
1805
1806   /* if type float then do float */
1807   if (IS_FLOAT (optype))
1808     {
1809       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1810       goto release;
1811     }
1812
1813   toBoolean (IC_LEFT (ic));
1814
1815   tlbl = newiTempLabel (NULL);
1816   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1817   emitcode ("", "!tlabeldef", tlbl->key + 100);
1818   outBitC (IC_RESULT (ic));
1819
1820 release:
1821   /* release the aops */
1822   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1823   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1824 }
1825
1826
1827 /*-----------------------------------------------------------------*/
1828 /* genCpl - generate code for complement                           */
1829 /*-----------------------------------------------------------------*/
1830 static void
1831 genCpl (iCode * ic)
1832 {
1833   int offset = 0;
1834   int size;
1835   symbol *tlbl;
1836
1837   D (emitcode (";", "genCpl "););
1838
1839
1840   /* assign asmOps to operand & result */
1841   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1842   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1843
1844   /* special case if in bit space */
1845   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1846     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1847       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1848       emitcode ("cpl", "c");
1849       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1850       goto release;
1851     }
1852     tlbl=newiTempLabel(NULL);
1853     emitcode ("cjne", "%s,#0x01,%05d$", 
1854               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1855     emitcode ("", "%05d$:", tlbl->key+100);
1856     outBitC (IC_RESULT(ic));
1857     goto release;
1858   }
1859
1860   size = AOP_SIZE (IC_RESULT (ic));
1861   _startLazyDPSEvaluation ();
1862   while (size--)
1863     {
1864       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1865       emitcode ("cpl", "a");
1866       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1867     }
1868   _endLazyDPSEvaluation ();
1869
1870
1871 release:
1872   /* release the aops */
1873   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1874   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1875 }
1876
1877 /*-----------------------------------------------------------------*/
1878 /* genUminusFloat - unary minus for floating points                */
1879 /*-----------------------------------------------------------------*/
1880 static void
1881 genUminusFloat (operand * op, operand * result)
1882 {
1883   int size, offset = 0;
1884     
1885   D(emitcode (";", "genUminusFloat"););
1886   
1887   /* for this we just copy and then flip the bit */
1888     
1889   _startLazyDPSEvaluation ();
1890   size = AOP_SIZE (op) - 1;
1891
1892   while (size--)
1893   {
1894       aopPut (AOP (result),
1895               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1896               offset);
1897       offset++;
1898     }
1899   
1900   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1901
1902   emitcode ("cpl", "acc.7");
1903   aopPut (AOP (result), "a", offset);    
1904   _endLazyDPSEvaluation ();
1905 }
1906
1907 /*-----------------------------------------------------------------*/
1908 /* genUminus - unary minus code generation                         */
1909 /*-----------------------------------------------------------------*/
1910 static void
1911 genUminus (iCode * ic)
1912 {
1913   int offset, size;
1914   sym_link *optype;
1915
1916   D (emitcode (";", "genUminus "););
1917
1918   /* assign asmops */
1919   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1920   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1921
1922   /* if both in bit space then special
1923      case */
1924   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1925       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1926     {
1927
1928       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1929       emitcode ("cpl", "c");
1930       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1931       goto release;
1932     }
1933
1934   optype = operandType (IC_LEFT (ic));
1935
1936   /* if float then do float stuff */
1937   if (IS_FLOAT (optype))
1938     {
1939       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1940       goto release;
1941     }
1942
1943   /* otherwise subtract from zero */
1944   size = AOP_SIZE (IC_LEFT (ic));
1945   offset = 0;
1946   _startLazyDPSEvaluation ();
1947   while (size--)
1948     {
1949       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1950       if (!strcmp (l, "a"))
1951         {
1952           if (offset == 0)
1953             SETC;
1954           emitcode ("cpl", "a");
1955           emitcode ("addc", "a,#0");
1956         }
1957       else
1958         {
1959           if (offset == 0)
1960             CLRC;
1961           emitcode ("clr", "a");
1962           emitcode ("subb", "a,%s", l);
1963         }
1964       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1965     }
1966   _endLazyDPSEvaluation ();
1967
1968   /* if any remaining bytes in the result */
1969   /* we just need to propagate the sign   */
1970   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1971     {
1972       emitcode ("rlc", "a");
1973       emitcode ("subb", "a,acc");
1974       while (size--)
1975         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1976     }
1977
1978 release:
1979   /* release the aops */
1980   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1981   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1982 }
1983
1984 /*-----------------------------------------------------------------*/
1985 /* savermask - saves registers in the mask                         */
1986 /*-----------------------------------------------------------------*/
1987 static void savermask(bitVect *rs_mask)
1988 {
1989     int i;
1990     if (options.useXstack) {
1991         if (bitVectBitValue (rs_mask, R0_IDX))
1992             emitcode ("mov", "b,r0");
1993         emitcode ("mov", "r0,%s", spname);
1994         for (i = 0; i < ds390_nRegs; i++) {
1995             if (bitVectBitValue (rs_mask, i)) {
1996                 if (i == R0_IDX)
1997                     emitcode ("mov", "a,b");
1998                 else
1999                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2000                 emitcode ("movx", "@r0,a");
2001                 emitcode ("inc", "r0");
2002             }
2003         }
2004         emitcode ("mov", "%s,r0", spname);
2005         if (bitVectBitValue (rs_mask, R0_IDX))
2006             emitcode ("mov", "r0,b");
2007     } else {
2008         for (i = 0; i < ds390_nRegs; i++) {
2009             if (bitVectBitValue (rs_mask, i))
2010                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2011         }
2012     }
2013 }
2014
2015 /*-----------------------------------------------------------------*/
2016 /* saveRegisters - will look for a call and save the registers     */
2017 /*-----------------------------------------------------------------*/
2018 static void
2019 saveRegisters (iCode * lic)
2020 {
2021   iCode *ic;
2022   bitVect *rsave;
2023
2024   /* look for call */
2025   for (ic = lic; ic; ic = ic->next)
2026     if (ic->op == CALL || ic->op == PCALL)
2027       break;
2028
2029   if (!ic)
2030     {
2031       fprintf (stderr, "found parameter push with no function call\n");
2032       return;
2033     }
2034
2035   /* if the registers have been saved already then
2036      do nothing */
2037   if (ic->regsSaved || 
2038       (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))))
2039     return ;
2040
2041   /* special case if DPTR alive across a function call then must save it 
2042      even though callee saves */
2043   if (IS_SYMOP(IC_LEFT(ic)) &&
2044       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2045       int i;
2046       rsave = newBitVect(ic->rMask->size);
2047       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2048           if (bitVectBitValue(ic->rMask,i))
2049               rsave = bitVectSetBit(rsave,i);
2050       }
2051       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2052   } else {
2053     /* safe the registers in use at this time but skip the
2054        ones for the result */
2055     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2056                            ds390_rUmaskForOp (IC_RESULT(ic)));
2057   }
2058   ic->regsSaved = 1;
2059   savermask(rsave);
2060 }
2061
2062 /*-----------------------------------------------------------------*/
2063 /* usavermask - restore registers with mask                        */
2064 /*-----------------------------------------------------------------*/
2065 static void unsavermask(bitVect *rs_mask)
2066 {
2067     int i;
2068     if (options.useXstack) {
2069         emitcode ("mov", "r0,%s", spname);
2070         for (i = ds390_nRegs; i >= 0; i--) {
2071             if (bitVectBitValue (rs_mask, i)) {
2072                 emitcode ("dec", "r0");
2073                 emitcode ("movx", "a,@r0");
2074                 if (i == R0_IDX)
2075                     emitcode ("mov", "b,a");
2076                 else
2077                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2078             }       
2079         }
2080         emitcode ("mov", "%s,r0", spname);
2081         if (bitVectBitValue (rs_mask, R0_IDX))
2082             emitcode ("mov", "r0,b");
2083     } else {
2084         for (i = ds390_nRegs; i >= 0; i--) {
2085             if (bitVectBitValue (rs_mask, i))
2086                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2087         }
2088     }
2089 }
2090
2091 /*-----------------------------------------------------------------*/
2092 /* unsaveRegisters - pop the pushed registers                      */
2093 /*-----------------------------------------------------------------*/
2094 static void
2095 unsaveRegisters (iCode * ic)
2096 {
2097   bitVect *rsave;
2098
2099   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2100       int i;
2101       rsave = newBitVect(ic->rMask->size);
2102       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2103           if (bitVectBitValue(ic->rMask,i))
2104               rsave = bitVectSetBit(rsave,i);
2105       }
2106       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2107   } else {
2108     /* restore the registers in use at this time but skip the
2109        ones for the result */
2110     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2111                            ds390_rUmaskForOp (IC_RESULT(ic)));
2112   }
2113   unsavermask(rsave);
2114 }
2115
2116
2117 /*-----------------------------------------------------------------*/
2118 /* pushSide -                */
2119 /*-----------------------------------------------------------------*/
2120 static void
2121 pushSide (operand * oper, int size)
2122 {
2123   int offset = 0;
2124   _startLazyDPSEvaluation ();
2125   while (size--)
2126     {
2127       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2128       if (AOP_TYPE (oper) != AOP_REG &&
2129           AOP_TYPE (oper) != AOP_DIR &&
2130           strcmp (l, "a"))
2131         {
2132           emitcode ("mov", "a,%s", l);
2133           emitcode ("push", "acc");
2134         }
2135       else
2136         emitcode ("push", "%s", l);
2137     }
2138   _endLazyDPSEvaluation ();
2139 }
2140
2141 /*-----------------------------------------------------------------*/
2142 /* assignResultValue -               */
2143 /*-----------------------------------------------------------------*/
2144 static void
2145 assignResultValue (operand * oper)
2146 {
2147   int offset = 0;
2148   int size = AOP_SIZE (oper);
2149   bool pushedAcc = FALSE;
2150
2151   if (size == fReturnSizeDS390)
2152   {
2153       /* I don't think this case can ever happen... */
2154       /* ACC is the last part of this. If writing the result
2155        * uses AC, we must preserve it.
2156        */
2157       if (AOP_NEEDSACC(oper))
2158       {
2159           emitcode(";", "assignResultValue special case for ACC.");
2160           emitcode("push", "acc");
2161           pushedAcc = TRUE;
2162           size--;
2163       }
2164   }
2165     
2166     
2167   _startLazyDPSEvaluation ();
2168   while (size--)
2169     {
2170       aopPut (AOP (oper), fReturn[offset], offset);
2171       offset++;
2172     }
2173   _endLazyDPSEvaluation ();
2174     
2175   if (pushedAcc)
2176     {
2177         emitcode("pop", "acc");
2178         aopPut(AOP(oper), "a", offset);
2179     }
2180 }
2181
2182
2183 /*-----------------------------------------------------------------*/
2184 /* genXpush - pushes onto the external stack                       */
2185 /*-----------------------------------------------------------------*/
2186 static void
2187 genXpush (iCode * ic)
2188 {
2189   asmop *aop = newAsmop (0);
2190   regs *r;
2191   int size, offset = 0;
2192
2193   D (emitcode (";", "genXpush ");
2194     );
2195
2196   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2197   r = getFreePtr (ic, &aop, FALSE);
2198
2199
2200   emitcode ("mov", "%s,_spx", r->name);
2201
2202   size = AOP_SIZE (IC_LEFT (ic));
2203   _startLazyDPSEvaluation ();
2204   while (size--)
2205     {
2206
2207       MOVA (aopGet (AOP (IC_LEFT (ic)),
2208                         offset++, FALSE, FALSE, NULL));
2209       emitcode ("movx", "@%s,a", r->name);
2210       emitcode ("inc", "%s", r->name);
2211
2212     }
2213   _endLazyDPSEvaluation ();
2214
2215
2216   emitcode ("mov", "_spx,%s", r->name);
2217
2218   freeAsmop (NULL, aop, ic, TRUE);
2219   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2220 }
2221
2222 /*-----------------------------------------------------------------*/
2223 /* genIpush - generate code for pushing this gets a little complex  */
2224 /*-----------------------------------------------------------------*/
2225 static void
2226 genIpush (iCode * ic)
2227 {
2228   int size, offset = 0;
2229   char *l;
2230
2231   D (emitcode (";", "genIpush ");
2232     );
2233
2234   /* if this is not a parm push : ie. it is spill push
2235      and spill push is always done on the local stack */
2236   if (!ic->parmPush)
2237     {
2238
2239       /* and the item is spilt then do nothing */
2240       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2241         return;
2242
2243       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2244       size = AOP_SIZE (IC_LEFT (ic));
2245       /* push it on the stack */
2246       _startLazyDPSEvaluation ();
2247       while (size--)
2248         {
2249           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2250           if (*l == '#')
2251             {
2252               MOVA (l);
2253               l = "acc";
2254             }
2255           emitcode ("push", "%s", l);
2256         }
2257       _endLazyDPSEvaluation ();
2258       return;
2259     }
2260
2261   /* this is a paramter push: in this case we call
2262      the routine to find the call and save those
2263      registers that need to be saved */
2264   saveRegisters (ic);
2265
2266   /* if use external stack then call the external
2267      stack pushing routine */
2268   if (options.useXstack)
2269     {
2270       genXpush (ic);
2271       return;
2272     }
2273
2274   /* then do the push */
2275   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2276
2277   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2278   size = AOP_SIZE (IC_LEFT (ic));
2279
2280   _startLazyDPSEvaluation ();
2281   while (size--)
2282     {
2283       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2284       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2285           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2286           strcmp (l, "acc"))
2287         {
2288           emitcode ("mov", "a,%s", l);
2289           emitcode ("push", "acc");
2290         }
2291       else
2292         {
2293             emitcode ("push", "%s", l);
2294         }
2295     }
2296   _endLazyDPSEvaluation ();
2297
2298   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2299 }
2300
2301 /*-----------------------------------------------------------------*/
2302 /* genIpop - recover the registers: can happen only for spilling   */
2303 /*-----------------------------------------------------------------*/
2304 static void
2305 genIpop (iCode * ic)
2306 {
2307   int size, offset;
2308
2309   D (emitcode (";", "genIpop ");
2310     );
2311
2312
2313   /* if the temp was not pushed then */
2314   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2315     return;
2316
2317   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2318   size = AOP_SIZE (IC_LEFT (ic));
2319   offset = (size - 1);
2320   _startLazyDPSEvaluation ();
2321   while (size--)
2322     {
2323       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2324                                      FALSE, TRUE, NULL));
2325     }
2326   _endLazyDPSEvaluation ();
2327
2328   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2329 }
2330
2331 /*-----------------------------------------------------------------*/
2332 /* unsaveRBank - restores the resgister bank from stack            */
2333 /*-----------------------------------------------------------------*/
2334 static void
2335 unsaveRBank (int bank, iCode * ic, bool popPsw)
2336 {
2337   int i;
2338   asmop *aop = NULL;
2339   regs *r = NULL;
2340
2341   if (options.useXstack)
2342   {
2343       if (!ic)
2344       {
2345           /* Assume r0 is available for use. */
2346           r = ds390_regWithIdx (R0_IDX);;          
2347       } 
2348       else
2349       {
2350           aop = newAsmop (0);
2351           r = getFreePtr (ic, &aop, FALSE);
2352       }
2353       emitcode ("mov", "%s,_spx", r->name);      
2354   }
2355   
2356   if (popPsw)
2357     {
2358       if (options.useXstack)
2359       {
2360           emitcode ("movx", "a,@%s", r->name);
2361           emitcode ("mov", "psw,a");
2362           emitcode ("dec", "%s", r->name);
2363         }
2364       else
2365       {
2366         emitcode ("pop", "psw");
2367       }
2368     }
2369
2370   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2371     {
2372       if (options.useXstack)
2373         {
2374           emitcode ("movx", "a,@%s", r->name);
2375           emitcode ("mov", "(%s+%d),a",
2376                     regs390[i].base, 8 * bank + regs390[i].offset);
2377           emitcode ("dec", "%s", r->name);
2378
2379         }
2380       else
2381         emitcode ("pop", "(%s+%d)",
2382                   regs390[i].base, 8 * bank + regs390[i].offset);
2383     }
2384
2385   if (options.useXstack)
2386     {
2387       emitcode ("mov", "_spx,%s", r->name);
2388     }
2389     
2390   if (aop)
2391   {
2392       freeAsmop (NULL, aop, ic, TRUE);  
2393   }    
2394 }
2395
2396 /*-----------------------------------------------------------------*/
2397 /* saveRBank - saves an entire register bank on the stack          */
2398 /*-----------------------------------------------------------------*/
2399 static void
2400 saveRBank (int bank, iCode * ic, bool pushPsw)
2401 {
2402   int i;
2403   asmop *aop = NULL;
2404   regs *r = NULL;
2405
2406   if (options.useXstack)
2407     {
2408         if (!ic)
2409         {
2410           /* Assume r0 is available for use. */
2411                   r = ds390_regWithIdx (R0_IDX);;
2412         }
2413         else
2414         {
2415           aop = newAsmop (0);
2416           r = getFreePtr (ic, &aop, FALSE);
2417         }
2418         emitcode ("mov", "%s,_spx", r->name);    
2419     }
2420
2421   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2422     {
2423       if (options.useXstack)
2424         {
2425           emitcode ("inc", "%s", r->name);
2426           emitcode ("mov", "a,(%s+%d)",
2427                     regs390[i].base, 8 * bank + regs390[i].offset);
2428           emitcode ("movx", "@%s,a", r->name);
2429         }
2430       else
2431         emitcode ("push", "(%s+%d)",
2432                   regs390[i].base, 8 * bank + regs390[i].offset);
2433     }
2434
2435   if (pushPsw)
2436     {
2437       if (options.useXstack)
2438         {
2439           emitcode ("mov", "a,psw");
2440           emitcode ("movx", "@%s,a", r->name);
2441           emitcode ("inc", "%s", r->name);
2442           emitcode ("mov", "_spx,%s", r->name);
2443         }
2444       else
2445       {
2446         emitcode ("push", "psw");
2447       }
2448
2449       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2450     }
2451   
2452   if (aop)
2453   {
2454        freeAsmop (NULL, aop, ic, TRUE);
2455   }    
2456     
2457   if (ic)
2458   {  
2459       ic->bankSaved = 1;
2460   }
2461 }
2462
2463 /*-----------------------------------------------------------------*/
2464 /* genSend - gen code for SEND                                     */
2465 /*-----------------------------------------------------------------*/
2466 static void genSend(set *sendSet)
2467 {
2468     iCode *sic;
2469     int sendCount = 0 ;
2470     static int rb1_count = 0;
2471
2472     for (sic = setFirstItem (sendSet); sic;
2473          sic = setNextItem (sendSet)) {     
2474         int size, offset = 0;
2475         
2476         size=getSize(operandType(IC_LEFT(sic)));
2477         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2478         if (sendCount == 0) { /* first parameter */
2479             // we know that dpl(hxb) is the result, so
2480             rb1_count = 0 ;
2481             _startLazyDPSEvaluation ();
2482             if (size>1) {
2483                 aopOp (IC_LEFT (sic), sic, FALSE, 
2484                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2485             } else {
2486                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2487             }
2488             while (size--) {
2489                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2490                                   FALSE, FALSE, NULL);
2491                 if (strcmp (l, fReturn[offset])) {
2492                     emitcode ("mov", "%s,%s",
2493                               fReturn[offset],
2494                               l);
2495                 }
2496                 offset++;
2497             }
2498             _endLazyDPSEvaluation ();
2499             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2500             rb1_count =0;
2501         } else { /* if more parameter in registers */
2502             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2503             while (size--) {
2504                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2505                                                                 FALSE, FALSE, NULL));
2506             }
2507             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2508         }
2509         sendCount++;
2510     }
2511 }
2512
2513 /*-----------------------------------------------------------------*/
2514 /* genCall - generates a call statement                            */
2515 /*-----------------------------------------------------------------*/
2516 static void
2517 genCall (iCode * ic)
2518 {
2519   sym_link *dtype;
2520   bool restoreBank = FALSE;
2521   bool swapBanks = FALSE;
2522
2523   D (emitcode (";", "genCall "););
2524
2525   /* if we are calling a not _naked function that is not using
2526      the same register bank then we need to save the
2527      destination registers on the stack */
2528   dtype = operandType (IC_LEFT (ic));
2529   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2530       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2531       IFFUNC_ISISR (currFunc->type))
2532   {
2533       if (!ic->bankSaved) 
2534       {
2535            /* This is unexpected; the bank should have been saved in
2536             * genFunction.
2537             */
2538            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2539            restoreBank = TRUE;
2540       }
2541       swapBanks = TRUE;
2542   }
2543   
2544     /* if caller saves & we have not saved then */
2545     if (!ic->regsSaved)
2546       saveRegisters (ic);
2547   
2548   /* if send set is not empty the assign */
2549   /* We've saved all the registers we care about;
2550   * therefore, we may clobber any register not used
2551   * in the calling convention (i.e. anything not in
2552   * fReturn.
2553   */
2554   if (_G.sendSet)
2555     {
2556         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2557             genSend(reverseSet(_G.sendSet));
2558         } else {
2559             genSend(_G.sendSet);
2560         }
2561       _G.sendSet = NULL;
2562     }  
2563     
2564   if (swapBanks)
2565   {
2566         emitcode ("mov", "psw,#!constbyte", 
2567            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2568   }
2569
2570   /* make the call */
2571   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2572                             OP_SYMBOL (IC_LEFT (ic))->rname :
2573                             OP_SYMBOL (IC_LEFT (ic))->name));
2574
2575   if (swapBanks)
2576   {
2577        emitcode ("mov", "psw,#!constbyte", 
2578           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2579   }
2580
2581   /* if we need assign a result value */
2582   if ((IS_ITEMP (IC_RESULT (ic)) &&
2583        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2584         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2585         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2586       IS_TRUE_SYMOP (IC_RESULT (ic)))
2587     {
2588       if (isOperandInFarSpace (IC_RESULT (ic))
2589           && getSize (operandType (IC_RESULT (ic))) <= 2)
2590         {
2591           int size = getSize (operandType (IC_RESULT (ic)));
2592
2593           /* Special case for 1 or 2 byte return in far space. */
2594           MOVA (fReturn[0]);
2595           if (size > 1)
2596             {
2597               emitcode ("mov", "b,%s", fReturn[1]);
2598             }
2599
2600           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2601           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2602
2603           if (size > 1)
2604             {
2605               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2606             }
2607           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2608         }
2609       else
2610         {
2611           _G.accInUse++;
2612           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2613           _G.accInUse--;
2614
2615           assignResultValue (IC_RESULT (ic));
2616
2617           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2618         }
2619     }
2620
2621   /* adjust the stack for parameters if
2622      required */
2623   if (ic->parmBytes) {
2624       int i;
2625       if (options.stack10bit) {
2626           if (ic->parmBytes <= 10) {
2627               emitcode(";","stack adjustment for parms");
2628               for (i=0; i < ic->parmBytes ; i++) {
2629                   emitcode("pop","acc");
2630               }
2631           } else {            
2632               PROTECT_SP;
2633               emitcode ("clr","c");
2634               emitcode ("mov","a,sp");
2635               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2636               emitcode ("mov","sp,a");
2637               emitcode ("mov","a,esp");
2638               emitcode ("anl","a,#3");
2639               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2640               emitcode ("mov","esp,a");   
2641               UNPROTECT_SP;
2642           }
2643       } else {
2644           if (ic->parmBytes > 3) {
2645               emitcode ("mov", "a,%s", spname);
2646               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2647               emitcode ("mov", "%s,a", spname);
2648           } else
2649               for (i = 0; i < ic->parmBytes; i++)
2650                   emitcode ("dec", "%s", spname);
2651       }
2652   }
2653
2654   /* if we hade saved some registers then unsave them */
2655   if (ic->regsSaved)
2656     unsaveRegisters (ic);
2657
2658   /* if register bank was saved then pop them */
2659   if (restoreBank)
2660     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2661 }
2662
2663 /*-----------------------------------------------------------------*/
2664 /* genPcall - generates a call by pointer statement                */
2665 /*-----------------------------------------------------------------*/
2666 static void
2667 genPcall (iCode * ic)
2668 {
2669   sym_link *dtype;
2670   symbol *rlbl = newiTempLabel (NULL);
2671   bool restoreBank=FALSE;
2672
2673   D (emitcode (";", "genPcall ");
2674     );
2675
2676
2677   /* if caller saves & we have not saved then */
2678   if (!ic->regsSaved)
2679     saveRegisters (ic);
2680
2681   /* if we are calling a function that is not using
2682      the same register bank then we need to save the
2683      destination registers on the stack */
2684   dtype = operandType (IC_LEFT (ic));
2685   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2686       IFFUNC_ISISR (currFunc->type) &&
2687       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2688     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2689     restoreBank=TRUE;
2690   }
2691
2692   /* push the return address on to the stack */
2693   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2694   emitcode ("push", "acc");
2695   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2696   emitcode ("push", "acc");
2697
2698   if (options.model == MODEL_FLAT24)
2699     {
2700       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2701       emitcode ("push", "acc");
2702     }
2703
2704   /* now push the calling address */
2705   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2706
2707   pushSide (IC_LEFT (ic), FPTRSIZE);
2708
2709   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2710
2711   /* if send set is not empty the assign */
2712   if (_G.sendSet)
2713     {
2714         genSend(reverseSet(_G.sendSet));
2715         _G.sendSet = NULL;
2716     }
2717
2718   emitcode ("ret", "");
2719   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2720
2721
2722   /* if we need assign a result value */
2723   if ((IS_ITEMP (IC_RESULT (ic)) &&
2724        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2725         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2726       IS_TRUE_SYMOP (IC_RESULT (ic)))
2727     {
2728
2729       _G.accInUse++;
2730       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2731       _G.accInUse--;
2732
2733       assignResultValue (IC_RESULT (ic));
2734
2735       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2736     }
2737
2738   /* adjust the stack for parameters if
2739      required */
2740   if (ic->parmBytes)
2741     {
2742       int i;
2743       if (options.stack10bit) {
2744           if (ic->parmBytes <= 10) {
2745               emitcode(";","stack adjustment for parms");
2746               for (i=0; i < ic->parmBytes ; i++) {
2747                   emitcode("pop","acc");
2748               }
2749           } else {            
2750               PROTECT_SP;
2751               emitcode ("clr","c");
2752               emitcode ("mov","a,sp");
2753               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2754               emitcode ("mov","sp,a");
2755               emitcode ("mov","a,esp");
2756               emitcode ("anl","a,#3");
2757               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2758               emitcode ("mov","esp,a");   
2759               UNPROTECT_SP;
2760           }
2761       } else {
2762           if (ic->parmBytes > 3) {
2763               emitcode ("mov", "a,%s", spname);
2764               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2765               emitcode ("mov", "%s,a", spname);
2766           }
2767           else
2768               for (i = 0; i < ic->parmBytes; i++)
2769                   emitcode ("dec", "%s", spname);
2770           
2771       }
2772     }
2773   /* if register bank was saved then unsave them */
2774   if (restoreBank)
2775     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2776   
2777   /* if we hade saved some registers then
2778      unsave them */
2779   if (ic->regsSaved)
2780     unsaveRegisters (ic);
2781
2782 }
2783
2784 /*-----------------------------------------------------------------*/
2785 /* resultRemat - result  is rematerializable                       */
2786 /*-----------------------------------------------------------------*/
2787 static int
2788 resultRemat (iCode * ic)
2789 {
2790   if (SKIP_IC (ic) || ic->op == IFX)
2791     return 0;
2792
2793   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2794     {
2795       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2796       if (sym->remat && !POINTER_SET (ic))
2797         return 1;
2798     }
2799
2800   return 0;
2801 }
2802
2803 #if defined(__BORLANDC__) || defined(_MSC_VER)
2804 #define STRCASECMP stricmp
2805 #else
2806 #define STRCASECMP strcasecmp
2807 #endif
2808
2809 /*-----------------------------------------------------------------*/
2810 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2811 /*-----------------------------------------------------------------*/
2812 static bool
2813 inExcludeList (char *s)
2814 {
2815   int i = 0;
2816
2817   if (options.excludeRegs[i] &&
2818       STRCASECMP (options.excludeRegs[i], "none") == 0)
2819     return FALSE;
2820
2821   for (i = 0; options.excludeRegs[i]; i++)
2822     {
2823       if (options.excludeRegs[i] &&
2824           STRCASECMP (s, options.excludeRegs[i]) == 0)
2825         return TRUE;
2826     }
2827   return FALSE;
2828 }
2829
2830 /*-----------------------------------------------------------------*/
2831 /* genFunction - generated code for function entry                 */
2832 /*-----------------------------------------------------------------*/
2833 static void
2834 genFunction (iCode * ic)
2835 {
2836   symbol *sym;
2837   sym_link *ftype;
2838   bool   switchedPSW = FALSE;
2839
2840   D (emitcode (";", "genFunction "););
2841
2842   _G.nRegsSaved = 0;
2843   /* create the function header */
2844   emitcode (";", "-----------------------------------------");
2845   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2846   emitcode (";", "-----------------------------------------");
2847
2848   emitcode ("", "%s:", sym->rname);
2849   ftype = operandType (IC_LEFT (ic));
2850
2851   if (IFFUNC_ISNAKED(ftype))
2852   {
2853       emitcode(";", "naked function: no prologue.");
2854       return;
2855   }
2856   
2857   if (options.stack_probe) 
2858       emitcode ("lcall","__stack_probe");
2859   /* if critical function then turn interrupts off */
2860   if (IFFUNC_ISCRITICAL (ftype))
2861     emitcode ("clr", "ea");
2862
2863   /* here we need to generate the equates for the
2864      register bank if required */
2865   if (FUNC_REGBANK (ftype) != rbank)
2866     {
2867       int i;
2868
2869       rbank = FUNC_REGBANK (ftype);
2870       for (i = 0; i < ds390_nRegs; i++)
2871         {
2872           if (regs390[i].print) {
2873               if (strcmp (regs390[i].base, "0") == 0)
2874                   emitcode ("", "%s !equ !constbyte",
2875                             regs390[i].dname,
2876                             8 * rbank + regs390[i].offset);
2877               else
2878                   emitcode ("", "%s !equ %s + !constbyte",
2879                             regs390[i].dname,
2880                             regs390[i].base,
2881                             8 * rbank + regs390[i].offset);
2882           }
2883         }
2884     }
2885
2886   /* if this is an interrupt service routine then
2887      save acc, b, dpl, dph  */
2888   if (IFFUNC_ISISR (sym->type))
2889       { /* is ISR */
2890       if (!inExcludeList ("acc"))
2891         emitcode ("push", "acc");
2892       if (!inExcludeList ("b"))
2893         emitcode ("push", "b");
2894       if (!inExcludeList ("dpl"))
2895         emitcode ("push", "dpl");
2896       if (!inExcludeList ("dph"))
2897         emitcode ("push", "dph");
2898       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2899         {
2900           emitcode ("push", "dpx");
2901           /* Make sure we're using standard DPTR */
2902           emitcode ("push", "dps");
2903           emitcode ("mov", "dps,#0");
2904           if (options.stack10bit)
2905             {
2906               /* This ISR could conceivably use DPTR2. Better save it. */
2907               emitcode ("push", "dpl1");
2908               emitcode ("push", "dph1");
2909               emitcode ("push", "dpx1");
2910               emitcode ("push",  DP2_RESULT_REG);
2911             }
2912         }
2913       /* if this isr has no bank i.e. is going to
2914          run with bank 0 , then we need to save more
2915          registers :-) */
2916       if (!FUNC_REGBANK (sym->type))
2917         {
2918             int i;
2919
2920           /* if this function does not call any other
2921              function then we can be economical and
2922              save only those registers that are used */
2923           if (!IFFUNC_HASFCALL(sym->type))
2924             {
2925
2926               /* if any registers used */
2927               if (sym->regsUsed)
2928                 {
2929                   /* save the registers used */
2930                   for (i = 0; i < sym->regsUsed->size; i++)
2931                     {
2932                       if (bitVectBitValue (sym->regsUsed, i) ||
2933                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2934                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2935                     }
2936                 }
2937
2938             }
2939           else
2940             {
2941               /* this function has  a function call cannot
2942                  determines register usage so we will have to push the
2943                  entire bank */
2944               saveRBank (0, ic, FALSE);
2945               if (options.parms_in_bank1) {
2946                   for (i=0; i < 8 ; i++ ) {
2947                       emitcode ("push","%s",rb1regs[i]);
2948                   }
2949               }
2950             }
2951         }
2952         else
2953         {
2954             /* This ISR uses a non-zero bank.
2955              *
2956              * We assume that the bank is available for our
2957              * exclusive use.
2958              *
2959              * However, if this ISR calls a function which uses some
2960              * other bank, we must save that bank entirely.
2961              */
2962             unsigned long banksToSave = 0;
2963             
2964             if (IFFUNC_HASFCALL(sym->type))
2965             {
2966
2967 #define MAX_REGISTER_BANKS 4
2968
2969                 iCode *i;
2970                 int ix;
2971
2972                 for (i = ic; i; i = i->next)
2973                 {
2974                     if (i->op == ENDFUNCTION)
2975                     {
2976                         /* we got to the end OK. */
2977                         break;
2978                     }
2979                     
2980                     if (i->op == CALL)
2981                     {
2982                         sym_link *dtype;
2983                         
2984                         dtype = operandType (IC_LEFT(i));
2985                         if (dtype 
2986                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2987                         {
2988                              /* Mark this bank for saving. */
2989                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2990                              {
2991                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2992                              }
2993                              else
2994                              {
2995                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2996                              }
2997                              
2998                              /* And note that we don't need to do it in 
2999                               * genCall.
3000                               */
3001                              i->bankSaved = 1;
3002                         }
3003                     }
3004                     if (i->op == PCALL)
3005                     {
3006                         /* This is a mess; we have no idea what
3007                          * register bank the called function might
3008                          * use.
3009                          *
3010                          * The only thing I can think of to do is
3011                          * throw a warning and hope.
3012                          */
3013                         werror(W_FUNCPTR_IN_USING_ISR);   
3014                     }
3015                 }
3016
3017                 if (banksToSave && options.useXstack)
3018                 {
3019                     /* Since we aren't passing it an ic, 
3020                      * saveRBank will assume r0 is available to abuse.
3021                      *
3022                      * So switch to our (trashable) bank now, so
3023                      * the caller's R0 isn't trashed.
3024                      */
3025                     emitcode ("push", "psw");
3026                     emitcode ("mov", "psw,#!constbyte", 
3027                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3028                     switchedPSW = TRUE;
3029                 }
3030                 
3031                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3032                 {
3033                      if (banksToSave & (1 << ix))
3034                      {
3035                          saveRBank(ix, NULL, FALSE);
3036                      }
3037                 }
3038             }
3039             // TODO: this needs a closer look
3040             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3041         }
3042     }
3043   else
3044     {
3045       /* if callee-save to be used for this function
3046          then save the registers being used in this function */
3047       if (IFFUNC_CALLEESAVES(sym->type))
3048         {
3049           int i;
3050
3051           /* if any registers used */
3052           if (sym->regsUsed)
3053             {
3054               /* save the registers used */
3055               for (i = 0; i < sym->regsUsed->size; i++)
3056                 {
3057                   if (bitVectBitValue (sym->regsUsed, i) ||
3058                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3059                     {
3060                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3061                       _G.nRegsSaved++;
3062                     }
3063                 }
3064             }
3065         }
3066     }
3067
3068   /* set the register bank to the desired value */
3069   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3070    && !switchedPSW)
3071     {
3072       emitcode ("push", "psw");
3073       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3074     }
3075
3076   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3077        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3078       if (options.stack10bit) {
3079           emitcode ("push","_bpx");
3080           emitcode ("push","_bpx+1");
3081           emitcode ("mov","_bpx,%s",spname);
3082           emitcode ("mov","_bpx+1,esp");
3083           emitcode ("anl","_bpx+1,#3");
3084       } else {
3085           if (options.useXstack) {
3086               emitcode ("mov", "r0,%s", spname);
3087               emitcode ("mov", "a,_bp");
3088               emitcode ("movx", "@r0,a");
3089               emitcode ("inc", "%s", spname);
3090           } else {
3091               /* set up the stack */
3092               emitcode ("push", "_bp"); /* save the callers stack  */
3093           }
3094           emitcode ("mov", "_bp,%s", spname);
3095       }
3096   }
3097
3098   /* adjust the stack for the function */
3099   if (sym->stack) {
3100       int i = sym->stack;
3101       if (options.stack10bit) {
3102           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3103           assert (sym->recvSize <= 4);
3104           if (sym->stack <= 8) {
3105               while (i--) emitcode ("push","acc");
3106           } else {
3107               PROTECT_SP;
3108               emitcode ("mov","a,sp");
3109               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3110               emitcode ("mov","sp,a");
3111               emitcode ("mov","a,esp");
3112               emitcode ("anl","a,#3");
3113               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3114               emitcode ("mov","esp,a");
3115               UNPROTECT_SP;
3116           }
3117       } else {
3118           if (i > 256)
3119               werror (W_STACK_OVERFLOW, sym->name);
3120           
3121           if (i > 3 && sym->recvSize < 4) {
3122               
3123               emitcode ("mov", "a,sp");
3124               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3125               emitcode ("mov", "sp,a");
3126               
3127           } else
3128               while (i--)
3129                   emitcode ("inc", "sp");
3130       }
3131   }
3132
3133   if (sym->xstack)
3134     {
3135
3136       emitcode ("mov", "a,_spx");
3137       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3138       emitcode ("mov", "_spx,a");
3139     }
3140
3141 }
3142
3143 /*-----------------------------------------------------------------*/
3144 /* genEndFunction - generates epilogue for functions               */
3145 /*-----------------------------------------------------------------*/
3146 static void
3147 genEndFunction (iCode * ic)
3148 {
3149   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3150
3151   D (emitcode (";", "genEndFunction "););
3152
3153   if (IFFUNC_ISNAKED(sym->type))
3154   {
3155       emitcode(";", "naked function: no epilogue.");
3156       return;
3157   }
3158
3159   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3160        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3161
3162       if (options.stack10bit) {
3163           PROTECT_SP;     
3164           emitcode ("mov", "sp,_bpx", spname);
3165           emitcode ("mov", "esp,_bpx+1", spname);
3166           UNPROTECT_SP;
3167       } else {
3168           emitcode ("mov", "%s,_bp", spname);
3169       }
3170   }
3171
3172   /* if use external stack but some variables were
3173      added to the local stack then decrement the
3174      local stack */
3175   if (options.useXstack && sym->stack) {
3176       emitcode ("mov", "a,sp");
3177       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3178       emitcode ("mov", "sp,a");
3179   }
3180
3181
3182   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3183        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3184
3185       if (options.useXstack) {
3186           emitcode ("mov", "r0,%s", spname);
3187           emitcode ("movx", "a,@r0");
3188           emitcode ("mov", "_bp,a");
3189           emitcode ("dec", "%s", spname);
3190       } else {
3191           if (options.stack10bit) {
3192               emitcode ("pop", "_bpx+1");
3193               emitcode ("pop", "_bpx");
3194           } else {
3195               emitcode ("pop", "_bp");
3196           }
3197       }
3198   }
3199
3200   /* restore the register bank  */
3201   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3202   {
3203     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3204      || !options.useXstack)
3205     {
3206         /* Special case of ISR using non-zero bank with useXstack
3207          * is handled below.
3208          */
3209         emitcode ("pop", "psw");
3210     }
3211   } 
3212
3213   if (IFFUNC_ISISR (sym->type))
3214       { /* is ISR */  
3215
3216       /* now we need to restore the registers */
3217       /* if this isr has no bank i.e. is going to
3218          run with bank 0 , then we need to save more
3219          registers :-) */
3220       if (!FUNC_REGBANK (sym->type))
3221         {
3222             int i;
3223           /* if this function does not call any other
3224              function then we can be economical and
3225              save only those registers that are used */
3226           if (!IFFUNC_HASFCALL(sym->type))
3227             {
3228
3229               /* if any registers used */
3230               if (sym->regsUsed)
3231                 {
3232                   /* save the registers used */
3233                   for (i = sym->regsUsed->size; i >= 0; i--)
3234                     {
3235                       if (bitVectBitValue (sym->regsUsed, i) ||
3236                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3237                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3238                     }
3239                 }
3240
3241             }
3242           else
3243             {
3244               /* this function has  a function call cannot
3245                  determines register usage so we will have to pop the
3246                  entire bank */
3247               if (options.parms_in_bank1) {
3248                   for (i = 7 ; i >= 0 ; i-- ) {
3249                       emitcode ("pop","%s",rb1regs[i]);
3250                   }
3251               }
3252               unsaveRBank (0, ic, FALSE);
3253             }
3254         }
3255         else
3256         {
3257             /* This ISR uses a non-zero bank.
3258              *
3259              * Restore any register banks saved by genFunction
3260              * in reverse order.
3261              */
3262             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3263             int ix;
3264           
3265             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3266             {
3267                 if (savedBanks & (1 << ix))
3268                 {
3269                     unsaveRBank(ix, NULL, FALSE);
3270                 }
3271             }
3272             
3273             if (options.useXstack)
3274             {
3275                 /* Restore bank AFTER calling unsaveRBank,
3276                  * since it can trash r0.
3277                  */
3278                 emitcode ("pop", "psw");
3279             }
3280         }
3281
3282       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3283         {
3284           if (options.stack10bit)
3285             {
3286               emitcode ("pop", DP2_RESULT_REG);
3287               emitcode ("pop", "dpx1");
3288               emitcode ("pop", "dph1");
3289               emitcode ("pop", "dpl1");
3290             }
3291           emitcode ("pop", "dps");
3292           emitcode ("pop", "dpx");
3293         }
3294       if (!inExcludeList ("dph"))
3295         emitcode ("pop", "dph");
3296       if (!inExcludeList ("dpl"))
3297         emitcode ("pop", "dpl");
3298       if (!inExcludeList ("b"))
3299         emitcode ("pop", "b");
3300       if (!inExcludeList ("acc"))
3301         emitcode ("pop", "acc");
3302
3303       if (IFFUNC_ISCRITICAL (sym->type))
3304         emitcode ("setb", "ea");
3305
3306       /* if debug then send end of function */
3307       if (options.debug && currFunc) {
3308           _G.debugLine = 1;
3309           emitcode ("", "C$%s$%d$%d$%d ==.",
3310                     FileBaseName (ic->filename), currFunc->lastLine,
3311                     ic->level, ic->block);
3312           if (IS_STATIC (currFunc->etype))
3313             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3314           else
3315             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3316           _G.debugLine = 0;
3317         }
3318
3319       emitcode ("reti", "");
3320     }
3321   else
3322     {
3323       if (IFFUNC_ISCRITICAL (sym->type))
3324         emitcode ("setb", "ea");
3325
3326       if (IFFUNC_CALLEESAVES(sym->type))
3327         {
3328           int i;
3329
3330           /* if any registers used */
3331           if (sym->regsUsed)
3332             {
3333               /* save the registers used */
3334               for (i = sym->regsUsed->size; i >= 0; i--)
3335                 {
3336                   if (bitVectBitValue (sym->regsUsed, i) ||
3337                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3338                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3339                 }
3340             }
3341
3342         }
3343
3344       /* if debug then send end of function */
3345       if (options.debug && currFunc)
3346         {
3347           _G.debugLine = 1;
3348           emitcode ("", "C$%s$%d$%d$%d ==.",
3349                     FileBaseName (ic->filename), currFunc->lastLine,
3350                     ic->level, ic->block);
3351           if (IS_STATIC (currFunc->etype))
3352             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3353           else
3354             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3355           _G.debugLine = 0;
3356         }
3357
3358       emitcode ("ret", "");
3359     }
3360
3361 }
3362
3363 /*-----------------------------------------------------------------*/
3364 /* genJavaNativeRet - generate code for return JavaNative          */
3365 /*-----------------------------------------------------------------*/
3366 static void genJavaNativeRet(iCode *ic)
3367 {
3368     int i, size;
3369
3370     aopOp (IC_LEFT (ic), ic, FALSE, 
3371            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3372     size = AOP_SIZE (IC_LEFT (ic));
3373
3374     assert (size <= 4);
3375
3376     /* it is assigned to GPR0-R3 then push them */
3377     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3378         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3379         for (i = 0 ; i < size ; i++ ) {
3380             emitcode ("push","%s",
3381                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3382         }
3383         for (i = (size-1) ; i >= 0 ; i--) {
3384             emitcode ("pop","a%s",javaRet[i]);
3385         }
3386     } else {
3387         for (i = 0 ; i < size ; i++) 
3388             emitcode ("mov","%s,%s",javaRet[i],
3389                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3390     }
3391     for (i = size ; i < 4 ; i++ )
3392             emitcode ("mov","%s,#0",javaRet[i]);
3393     return;
3394 }
3395
3396 /*-----------------------------------------------------------------*/
3397 /* genRet - generate code for return statement                     */
3398 /*-----------------------------------------------------------------*/
3399 static void
3400 genRet (iCode * ic)
3401 {
3402   int size, offset = 0, pushed = 0;
3403
3404   D (emitcode (";", "genRet "););
3405
3406   /* if we have no return value then
3407      just generate the "ret" */
3408   if (!IC_LEFT (ic))
3409     goto jumpret;
3410
3411   /* if this is a JavaNative function then return 
3412      value in different register */
3413   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3414       genJavaNativeRet(ic);
3415       goto jumpret;
3416   }
3417   /* we have something to return then
3418      move the return value into place */
3419   aopOp (IC_LEFT (ic), ic, FALSE, 
3420          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3421   size = AOP_SIZE (IC_LEFT (ic));
3422
3423   _startLazyDPSEvaluation ();
3424   while (size--)
3425     {
3426       char *l;
3427       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3428         {
3429           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3430                       FALSE, TRUE, NULL);
3431           emitcode ("push", "%s", l);
3432           pushed++;
3433         }
3434       else
3435         {
3436           /* Since A is the last element of fReturn,
3437            * is is OK to clobber it in the aopGet.
3438            */
3439           l = aopGet (AOP (IC_LEFT (ic)), offset,
3440                       FALSE, FALSE, NULL);
3441           if (strcmp (fReturn[offset], l))
3442             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3443         }
3444     }
3445   _endLazyDPSEvaluation ();
3446
3447   if (pushed)
3448     {
3449       while (pushed)
3450         {
3451           pushed--;
3452           if (strcmp (fReturn[pushed], "a"))
3453             emitcode ("pop", fReturn[pushed]);
3454           else
3455             emitcode ("pop", "acc");
3456         }
3457     }
3458   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3459
3460 jumpret:
3461   /* generate a jump to the return label
3462      if the next is not the return statement */
3463   if (!(ic->next && ic->next->op == LABEL &&
3464         IC_LABEL (ic->next) == returnLabel))
3465
3466     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3467
3468 }
3469
3470 /*-----------------------------------------------------------------*/
3471 /* genLabel - generates a label                                    */
3472 /*-----------------------------------------------------------------*/
3473 static void
3474 genLabel (iCode * ic)
3475 {
3476   /* special case never generate */
3477   if (IC_LABEL (ic) == entryLabel)
3478     return;
3479
3480   D (emitcode (";", "genLabel ");
3481     );
3482
3483   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3484 }
3485
3486 /*-----------------------------------------------------------------*/
3487 /* genGoto - generates a ljmp                                      */
3488 /*-----------------------------------------------------------------*/
3489 static void
3490 genGoto (iCode * ic)
3491 {
3492   D (emitcode (";", "genGoto ");
3493     );
3494   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3495 }
3496
3497 /*-----------------------------------------------------------------*/
3498 /* findLabelBackwards: walks back through the iCode chain looking  */
3499 /* for the given label. Returns number of iCode instructions     */
3500 /* between that label and given ic.          */
3501 /* Returns zero if label not found.          */
3502 /*-----------------------------------------------------------------*/
3503 static int
3504 findLabelBackwards (iCode * ic, int key)
3505 {
3506   int count = 0;
3507
3508   while (ic->prev)
3509     {
3510       ic = ic->prev;
3511       count++;
3512
3513       /* If we have any pushes or pops, we cannot predict the distance.
3514          I don't like this at all, this should be dealt with in the 
3515          back-end */
3516       if (ic->op == IPUSH || ic->op == IPOP) {
3517         return 0;
3518       }
3519
3520       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3521         {
3522           /* printf("findLabelBackwards = %d\n", count); */
3523           return count;
3524         }
3525     }
3526
3527   return 0;
3528 }
3529
3530 /*-----------------------------------------------------------------*/
3531 /* genPlusIncr :- does addition with increment if possible         */
3532 /*-----------------------------------------------------------------*/
3533 static bool
3534 genPlusIncr (iCode * ic)
3535 {
3536   unsigned int icount;
3537   unsigned int size = getDataSize (IC_RESULT (ic));
3538
3539   /* will try to generate an increment */
3540   /* if the right side is not a literal
3541      we cannot */
3542   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3543     return FALSE;
3544
3545   /* if the literal value of the right hand side
3546      is greater than 4 then it is not worth it */
3547   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3548     return FALSE;
3549
3550   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3551       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3552       while (icount--) {
3553           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3554       }
3555       return TRUE;
3556   }
3557   /* if increment 16 bits in register */
3558   if (
3559        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3560        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3561        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3562        (size > 1) &&
3563        (icount == 1))
3564     {
3565       symbol  *tlbl;
3566       int     emitTlbl;
3567       int     labelRange;
3568       char    *l;
3569
3570       /* If the next instruction is a goto and the goto target
3571        * is <= 5 instructions previous to this, we can generate
3572        * jumps straight to that target.
3573        */
3574       if (ic->next && ic->next->op == GOTO
3575           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3576           && labelRange <= 5)
3577         {
3578           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3579           tlbl = IC_LABEL (ic->next);
3580           emitTlbl = 0;
3581         }
3582       else
3583         {
3584           tlbl = newiTempLabel (NULL);
3585           emitTlbl = 1;
3586         }
3587         
3588       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3589       emitcode ("inc", "%s", l);
3590       
3591       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3592           IS_AOP_PREG (IC_RESULT (ic)))
3593       {   
3594         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3595       }
3596       else
3597       {
3598           emitcode ("clr", "a");
3599           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3600       }
3601
3602       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3603       emitcode ("inc", "%s", l);
3604       if (size > 2)
3605         {
3606             if (!strcmp(l, "acc"))
3607             {
3608                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3609             }
3610             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3611                      IS_AOP_PREG (IC_RESULT (ic)))
3612             {
3613                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3614             }
3615             else
3616             {
3617                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3618             }
3619
3620             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3621             emitcode ("inc", "%s", l);
3622         }
3623       if (size > 3)
3624         {
3625             if (!strcmp(l, "acc"))
3626             {
3627                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3628             }
3629             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3630                      IS_AOP_PREG (IC_RESULT (ic)))
3631             {
3632                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3633             }
3634             else
3635             {
3636                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3637             }
3638
3639             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3640             emitcode ("inc", "%s", l);  }
3641
3642       if (emitTlbl)
3643         {
3644           emitcode ("", "!tlabeldef", tlbl->key + 100);
3645         }
3646       return TRUE;
3647     }
3648
3649   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3650       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3651       options.model == MODEL_FLAT24 ) {
3652
3653       switch (size) {
3654       case 3:
3655           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3656       case 2:
3657           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3658       case 1:
3659           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3660           break;
3661       }
3662       while (icount--) emitcode ("inc","dptr");      
3663       return TRUE;
3664   }
3665
3666   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3667       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3668       icount <= 5 ) {
3669       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3670       while (icount--) emitcode ("inc","dptr");
3671       emitcode ("mov","dps,#0");
3672       return TRUE;
3673   }
3674
3675   /* if the sizes are greater than 1 then we cannot */
3676   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3677       AOP_SIZE (IC_LEFT (ic)) > 1)
3678     return FALSE;
3679
3680   /* we can if the aops of the left & result match or
3681      if they are in registers and the registers are the
3682      same */
3683   if (
3684        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3685        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3686        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3687     {
3688
3689       if (icount > 3)
3690         {
3691           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3692           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3693           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3694         }
3695       else
3696         {
3697
3698           _startLazyDPSEvaluation ();
3699           while (icount--)
3700             {
3701               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3702             }
3703           _endLazyDPSEvaluation ();
3704         }
3705
3706       return TRUE;
3707     }
3708
3709   return FALSE;
3710 }
3711
3712 /*-----------------------------------------------------------------*/
3713 /* outBitAcc - output a bit in acc                                 */
3714 /*-----------------------------------------------------------------*/
3715 static void
3716 outBitAcc (operand * result)
3717 {
3718   symbol *tlbl = newiTempLabel (NULL);
3719   /* if the result is a bit */
3720   if (AOP_TYPE (result) == AOP_CRY)
3721     {
3722       aopPut (AOP (result), "a", 0);
3723     }
3724   else
3725     {
3726       emitcode ("jz", "!tlabel", tlbl->key + 100);
3727       emitcode ("mov", "a,%s", one);
3728       emitcode ("", "!tlabeldef", tlbl->key + 100);
3729       outAcc (result);
3730     }
3731 }
3732
3733 /*-----------------------------------------------------------------*/
3734 /* genPlusBits - generates code for addition of two bits           */
3735 /*-----------------------------------------------------------------*/
3736 static void
3737 genPlusBits (iCode * ic)
3738 {
3739   D (emitcode (";", "genPlusBits "););
3740     
3741   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3742     {
3743       symbol *lbl = newiTempLabel (NULL);
3744       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3745       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3746       emitcode ("cpl", "c");
3747       emitcode ("", "!tlabeldef", (lbl->key + 100));
3748       outBitC (IC_RESULT (ic));
3749     }
3750   else
3751     {
3752       emitcode ("clr", "a");
3753       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3754       emitcode ("rlc", "a");
3755       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3756       emitcode ("addc", "a,#0");
3757       outAcc (IC_RESULT (ic));
3758     }
3759 }
3760
3761 static void
3762 adjustArithmeticResult (iCode * ic)
3763 {
3764   if (opIsGptr (IC_RESULT (ic)) &&
3765       opIsGptr (IC_LEFT (ic)) &&
3766       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3767     {
3768       aopPut (AOP (IC_RESULT (ic)),
3769               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3770               GPTRSIZE - 1);
3771     }
3772
3773   if (opIsGptr (IC_RESULT (ic)) &&
3774       opIsGptr (IC_RIGHT (ic)) &&
3775       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3776     {
3777       aopPut (AOP (IC_RESULT (ic)),
3778             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3779               GPTRSIZE - 1);
3780     }
3781
3782   if (opIsGptr (IC_RESULT (ic)) &&
3783       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3784       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3785       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3786       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3787     {
3788       char buff[5];
3789       SNPRINTF (buff, sizeof(buff), 
3790                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3791       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3792     }
3793 }
3794
3795 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3796 // generates the result if possible. If result is generated, returns TRUE; otherwise
3797 // returns false and caller must deal with fact that result isn't aopOp'd.
3798 bool aopOp3(iCode * ic)
3799 {
3800     bool dp1InUse, dp2InUse;
3801     bool useDp2;
3802     
3803     // First, generate the right opcode. DPTR may be used if neither left nor result are
3804     // of type AOP_STR.
3805     
3806 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3807 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3808 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3809 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3810 //      );
3811 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3812 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3813 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3814 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3815 //      );      
3816
3817     
3818     // Right uses DPTR unless left or result is an AOP_STR.
3819     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
3820     
3821     // if the right used DPTR, left MUST use DPTR2.
3822     // if the right used DPTR2, left MUST use DPTR.
3823     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3824     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3825     // enabling us to assign DPTR to result.
3826      
3827     if (AOP_USESDPTR(IC_RIGHT(ic)))
3828     {
3829         useDp2 = TRUE;
3830     }
3831     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3832     {
3833         useDp2 = FALSE;
3834     }
3835     else
3836     {
3837         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3838         {
3839             useDp2 = TRUE;
3840         }
3841         else
3842         {
3843             useDp2 = FALSE;
3844         }
3845     }
3846
3847     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3848     
3849     // We've op'd the left & right. So, if left or right are the same operand as result, 
3850     // we know aopOp will succeed, and we can just do it & bail.
3851     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3852         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3853     {
3854 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3855         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3856         return TRUE;
3857     }
3858     
3859     // Note which dptrs are currently in use.
3860     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3861     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3862     
3863     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3864     // generate it.
3865     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3866     {
3867         return FALSE;
3868     }
3869     
3870     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3871     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3872     {
3873         return FALSE;
3874     }
3875     
3876     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3877     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3878     {
3879         return FALSE;
3880     }
3881
3882     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3883
3884     // Some sanity checking...
3885     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3886     {
3887         fprintf(stderr,
3888                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3889                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3890         emitcode(";", ">>> unexpected DPTR here.");
3891     }
3892     
3893     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3894     {
3895         fprintf(stderr,
3896                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3897                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3898         emitcode(";", ">>> unexpected DPTR2 here.");
3899     }    
3900     
3901     return TRUE;
3902 }
3903
3904 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3905 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3906 // will be set TRUE. The caller must then handle the case specially, noting
3907 // that the IC_RESULT operand is not aopOp'd.
3908 // 
3909 #define AOP_OP_3_NOFATAL(ic, rc) \
3910             do { rc = !aopOp3(ic); } while (0)
3911
3912 // aopOp the left & right operands of an ic.
3913 #define AOP_OP_2(ic) \
3914     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3915     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3916
3917 // convienience macro.
3918 #define AOP_SET_LOCALS(ic) \
3919     left = IC_LEFT(ic); \
3920     right = IC_RIGHT(ic); \
3921     result = IC_RESULT(ic);
3922
3923
3924 // Given an integer value of pushedSize bytes on the stack,
3925 // adjust it to be resultSize bytes, either by discarding
3926 // the most significant bytes or by zero-padding.
3927 //
3928 // On exit from this macro, pushedSize will have been adjusted to
3929 // equal resultSize, and ACC may be trashed.
3930 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3931       /* If the pushed data is bigger than the result,          \
3932        * simply discard unused bytes. Icky, but works.          \
3933        */                                                       \
3934       while (pushedSize > resultSize)                           \
3935       {                                                         \
3936           D (emitcode (";", "discarding unused result byte."););\
3937           emitcode ("pop", "acc");                              \
3938           pushedSize--;                                         \
3939       }                                                         \
3940       if (pushedSize < resultSize)                              \
3941       {                                                         \
3942           emitcode ("clr", "a");                                \
3943           /* Conversly, we haven't pushed enough here.          \
3944            * just zero-pad, and all is well.                    \
3945            */                                                   \
3946           while (pushedSize < resultSize)                       \
3947           {                                                     \
3948               emitcode("push", "acc");                          \
3949               pushedSize++;                                     \
3950           }                                                     \
3951       }                                                         \
3952       assert(pushedSize == resultSize);
3953
3954 /*-----------------------------------------------------------------*/
3955 /* genPlus - generates code for addition                           */
3956 /*-----------------------------------------------------------------*/
3957 static void
3958 genPlus (iCode * ic)
3959 {
3960   int size, offset = 0;
3961   bool pushResult;
3962   int rSize;
3963
3964   D (emitcode (";", "genPlus "););
3965
3966   /* special cases :- */
3967   if ( AOP_IS_STR(IC_LEFT(ic)) &&
3968       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3969       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3970       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3971       if (size <= 9) {
3972           while (size--) emitcode ("inc","dptr");
3973       } else {
3974           emitcode ("mov","a,dpl");
3975           emitcode ("add","a,#!constbyte",size & 0xff);
3976           emitcode ("mov","dpl,a");
3977           emitcode ("mov","a,dph");
3978           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3979           emitcode ("mov","dph,a");
3980           emitcode ("mov","a,dpx");
3981           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3982           emitcode ("mov","dpx,a");
3983       }
3984       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3985       return ;
3986   }
3987   if ( IS_SYMOP(IC_LEFT(ic)) && 
3988        OP_SYMBOL(IC_LEFT(ic))->remat &&
3989        isOperandInFarSpace(IC_RIGHT(ic))) {
3990       operand *op = IC_RIGHT(ic);
3991       IC_RIGHT(ic) = IC_LEFT(ic);
3992       IC_LEFT(ic) = op;
3993   }
3994                 
3995   AOP_OP_3_NOFATAL (ic, pushResult);
3996     
3997   if (pushResult)
3998     {
3999       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4000     }
4001
4002   if (!pushResult)
4003     {
4004       /* if literal, literal on the right or
4005          if left requires ACC or right is already
4006          in ACC */
4007       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4008        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4009           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4010         {
4011           operand *t = IC_RIGHT (ic);
4012           IC_RIGHT (ic) = IC_LEFT (ic);
4013           IC_LEFT (ic) = t;
4014           emitcode (";", "Swapped plus args.");
4015         }
4016
4017       /* if both left & right are in bit
4018          space */
4019       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4020           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4021         {
4022           genPlusBits (ic);
4023           goto release;
4024         }
4025
4026       /* if left in bit space & right literal */
4027       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4028           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4029         {
4030           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4031           /* if result in bit space */
4032           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4033             {
4034               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4035                 emitcode ("cpl", "c");
4036               outBitC (IC_RESULT (ic));
4037             }
4038           else
4039             {
4040               size = getDataSize (IC_RESULT (ic));
4041               _startLazyDPSEvaluation ();
4042               while (size--)
4043                 {
4044                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4045                   emitcode ("addc", "a,#0");
4046                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4047                 }
4048               _endLazyDPSEvaluation ();
4049             }
4050           goto release;
4051         }
4052
4053       /* if I can do an increment instead
4054          of add then GOOD for ME */
4055       if (genPlusIncr (ic) == TRUE)
4056         {
4057           emitcode (";", "did genPlusIncr");
4058           goto release;
4059         }
4060
4061     }
4062   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4063
4064   _startLazyDPSEvaluation ();
4065   while (size--)
4066     {
4067       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4068         {
4069           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4070           if (offset == 0)
4071             emitcode ("add", "a,%s",
4072                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4073           else
4074             emitcode ("addc", "a,%s",
4075                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4076         }
4077       else
4078         {
4079           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4080           {
4081               /* right is going to use ACC or we would have taken the
4082                * above branch.
4083                */
4084               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4085        TR_AP("#3");
4086               D(emitcode(";", "+ AOP_ACC special case."););
4087               emitcode("xch", "a, %s", DP2_RESULT_REG);
4088           }
4089           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4090           if (offset == 0)
4091           {
4092             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4093             {
4094          TR_AP("#4");
4095                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4096             }
4097             else
4098             {
4099                 emitcode ("add", "a,%s",
4100                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4101                                   DP2_RESULT_REG));
4102             }
4103           }
4104           else
4105           {
4106             emitcode ("addc", "a,%s",
4107                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4108                           DP2_RESULT_REG));
4109           }
4110         }
4111       if (!pushResult)
4112         {
4113           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4114         }
4115       else
4116         {
4117           emitcode ("push", "acc");
4118         }
4119       offset++;
4120     }
4121   _endLazyDPSEvaluation ();
4122
4123   if (pushResult)
4124     {
4125       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4126
4127       size = getDataSize (IC_LEFT (ic));
4128       rSize = getDataSize (IC_RESULT (ic));
4129
4130       ADJUST_PUSHED_RESULT(size, rSize);
4131
4132       _startLazyDPSEvaluation ();
4133       while (size--)
4134         {
4135           emitcode ("pop", "acc");
4136           aopPut (AOP (IC_RESULT (ic)), "a", size);
4137         }
4138       _endLazyDPSEvaluation ();
4139     }
4140
4141   adjustArithmeticResult (ic);
4142
4143 release:
4144   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4145   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4146   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4147 }
4148
4149 /*-----------------------------------------------------------------*/
4150 /* genMinusDec :- does subtraction with deccrement if possible     */
4151 /*-----------------------------------------------------------------*/
4152 static bool
4153 genMinusDec (iCode * ic)
4154 {
4155   unsigned int icount;
4156   unsigned int size = getDataSize (IC_RESULT (ic));
4157
4158   /* will try to generate an increment */
4159   /* if the right side is not a literal
4160      we cannot */
4161   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4162     return FALSE;
4163
4164   /* if the literal value of the right hand side
4165      is greater than 4 then it is not worth it */
4166   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4167     return FALSE;
4168
4169   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4170       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4171       while (icount--) {
4172           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4173       }
4174       return TRUE;
4175   }
4176   /* if decrement 16 bits in register */
4177   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4178       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4179       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4180       (size > 1) &&
4181       (icount == 1))
4182     {
4183       symbol *tlbl;
4184       int    emitTlbl;
4185       int    labelRange;
4186       char   *l;
4187
4188       /* If the next instruction is a goto and the goto target
4189          * is <= 5 instructions previous to this, we can generate
4190          * jumps straight to that target.
4191        */
4192       if (ic->next && ic->next->op == GOTO
4193           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4194           && labelRange <= 5)
4195         {
4196           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4197           tlbl = IC_LABEL (ic->next);
4198           emitTlbl = 0;
4199         }
4200       else
4201         {
4202           tlbl = newiTempLabel (NULL);
4203           emitTlbl = 1;
4204         }
4205
4206       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4207       emitcode ("dec", "%s", l);
4208  
4209       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4210           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4211           IS_AOP_PREG (IC_RESULT (ic)))
4212       {     
4213           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4214       }
4215       else
4216       {
4217           emitcode ("mov", "a,#!constbyte",0xff);
4218           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4219       }
4220       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4221       emitcode ("dec", "%s", l);
4222       if (size > 2)
4223         {
4224             if (!strcmp(l, "acc"))
4225             {
4226                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4227             }
4228             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4229                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4230                      IS_AOP_PREG (IC_RESULT (ic)))
4231             {       
4232                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4233             }
4234             else
4235             {
4236                 emitcode ("mov", "a,#!constbyte",0xff);
4237                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4238             }
4239             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4240             emitcode ("dec", "%s", l);
4241         }
4242       if (size > 3)
4243         {
4244             if (!strcmp(l, "acc"))
4245             {
4246                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4247             }
4248             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4249                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4250                      IS_AOP_PREG (IC_RESULT (ic)))
4251             {       
4252                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4253             }
4254             else
4255             {
4256                 emitcode ("mov", "a,#!constbyte",0xff);
4257                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4258             }       
4259             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4260             emitcode ("dec", "%s", l);
4261         }
4262       if (emitTlbl)
4263         {
4264           emitcode ("", "!tlabeldef", tlbl->key + 100);
4265         }
4266       return TRUE;
4267     }
4268
4269   /* if the sizes are greater than 1 then we cannot */
4270   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4271       AOP_SIZE (IC_LEFT (ic)) > 1)
4272     return FALSE;
4273
4274   /* we can if the aops of the left & result match or
4275      if they are in registers and the registers are the
4276      same */
4277   if (
4278        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4279        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4280        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4281     {
4282
4283       _startLazyDPSEvaluation ();
4284       while (icount--)
4285         {
4286           emitcode ("dec", "%s",
4287                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4288         }
4289       _endLazyDPSEvaluation ();
4290
4291       return TRUE;
4292     }
4293
4294   return FALSE;
4295 }
4296
4297 /*-----------------------------------------------------------------*/
4298 /* addSign - complete with sign                                    */
4299 /*-----------------------------------------------------------------*/
4300 static void
4301 addSign (operand * result, int offset, int sign)
4302 {
4303   int size = (getDataSize (result) - offset);
4304   if (size > 0)
4305     {
4306       _startLazyDPSEvaluation();
4307       if (sign)
4308         {
4309           emitcode ("rlc", "a");
4310           emitcode ("subb", "a,acc");
4311           while (size--)
4312           {
4313             aopPut (AOP (result), "a", offset++);
4314           }
4315         }
4316       else
4317       {
4318         while (size--)
4319         {
4320           aopPut (AOP (result), zero, offset++);
4321         }
4322       }
4323       _endLazyDPSEvaluation();
4324     }
4325 }
4326
4327 /*-----------------------------------------------------------------*/
4328 /* genMinusBits - generates code for subtraction  of two bits      */
4329 /*-----------------------------------------------------------------*/
4330 static void
4331 genMinusBits (iCode * ic)
4332 {
4333   symbol *lbl = newiTempLabel (NULL);
4334
4335   D (emitcode (";", "genMinusBits "););
4336
4337   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4338     {
4339       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4340       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4341       emitcode ("cpl", "c");
4342       emitcode ("", "!tlabeldef", (lbl->key + 100));
4343       outBitC (IC_RESULT (ic));
4344     }
4345   else
4346     {
4347       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4348       emitcode ("subb", "a,acc");
4349       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4350       emitcode ("inc", "a");
4351       emitcode ("", "!tlabeldef", (lbl->key + 100));
4352       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4353       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4354     }
4355 }
4356
4357 /*-----------------------------------------------------------------*/
4358 /* genMinus - generates code for subtraction                       */
4359 /*-----------------------------------------------------------------*/
4360 static void
4361 genMinus (iCode * ic)
4362 {
4363     int size, offset = 0;
4364     int rSize;
4365     long lit = 0L;
4366     bool pushResult;
4367
4368     D (emitcode (";", "genMinus "););
4369
4370     AOP_OP_3_NOFATAL(ic, pushResult);   
4371
4372     if (!pushResult)
4373     {
4374       /* special cases :- */
4375       /* if both left & right are in bit space */
4376       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4377           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4378         {
4379           genMinusBits (ic);
4380           goto release;
4381         }
4382
4383       /* if I can do an decrement instead
4384          of subtract then GOOD for ME */
4385       if (genMinusDec (ic) == TRUE)
4386         goto release;
4387
4388     }
4389
4390   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4391
4392   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4393     {
4394       CLRC;
4395     }
4396   else
4397     {
4398       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4399       lit = -lit;
4400     }
4401
4402
4403   /* if literal, add a,#-lit, else normal subb */
4404   _startLazyDPSEvaluation ();
4405   while (size--) {
4406       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4407           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4408               emitcode ("mov","b,%s",
4409                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4410               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4411               emitcode ("subb","a,b");
4412           } else {
4413               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4414               emitcode ("subb", "a,%s",
4415                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4416                                 DP2_RESULT_REG));
4417           }
4418       } else {
4419           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4420           /* first add without previous c */
4421           if (!offset) {
4422               if (!size && lit==-1) {
4423                   emitcode ("dec", "a");
4424               } else {
4425                   emitcode ("add", "a,#!constbyte",
4426                             (unsigned int) (lit & 0x0FFL));
4427               }
4428           } else {
4429               emitcode ("addc", "a,#!constbyte",
4430                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4431           }
4432       }
4433       
4434       if (pushResult) {
4435           emitcode ("push", "acc");
4436       } else {
4437           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4438       }
4439       offset++;
4440   }
4441   _endLazyDPSEvaluation ();
4442   
4443   if (pushResult)
4444     {
4445       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4446
4447       size = getDataSize (IC_LEFT (ic));
4448       rSize = getDataSize (IC_RESULT (ic));
4449
4450       ADJUST_PUSHED_RESULT(size, rSize);
4451
4452       _startLazyDPSEvaluation ();
4453       while (size--)
4454         {
4455           emitcode ("pop", "acc");
4456           aopPut (AOP (IC_RESULT (ic)), "a", size);
4457         }
4458       _endLazyDPSEvaluation ();
4459     }
4460
4461   adjustArithmeticResult (ic);
4462
4463 release:
4464   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4465   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4466   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4467 }
4468
4469
4470 /*-----------------------------------------------------------------*/
4471 /* genMultbits :- multiplication of bits                           */
4472 /*-----------------------------------------------------------------*/
4473 static void
4474 genMultbits (operand * left,
4475              operand * right,
4476              operand * result,
4477              iCode   * ic)
4478 {
4479   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4480   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4481   aopOp(result, ic, TRUE, FALSE);
4482   outBitC (result);
4483 }
4484
4485
4486 /*-----------------------------------------------------------------*/
4487 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4488 /*-----------------------------------------------------------------*/
4489 static void
4490 genMultOneByte (operand * left,
4491                 operand * right,
4492                 operand * result,
4493                 iCode   * ic)
4494 {
4495   sym_link *opetype = operandType (result);
4496   symbol *lbl;
4497
4498
4499   /* (if two literals: the value is computed before) */
4500   /* if one literal, literal on the right */
4501   if (AOP_TYPE (left) == AOP_LIT)
4502     {
4503       operand *t = right;
4504       right = left;
4505       left = t;
4506       emitcode (";", "swapped left and right");
4507     }
4508
4509   if (SPEC_USIGN(opetype)
4510       // ignore the sign of left and right, what else can we do?
4511       || (SPEC_USIGN(operandType(left)) && 
4512           SPEC_USIGN(operandType(right)))) {
4513     // just an unsigned 8*8=8/16 multiply
4514     //emitcode (";","unsigned");
4515     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4516     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4517     emitcode ("mul", "ab");
4518    
4519     _G.accInUse++; _G.bInUse++;
4520     aopOp(result, ic, TRUE, FALSE);
4521       
4522       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4523       {
4524           // this should never happen
4525           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4526                    AOP_SIZE(result), __FILE__, lineno);
4527           exit (1);
4528       }      
4529       
4530     aopPut (AOP (result), "a", 0);
4531     _G.accInUse--; _G.bInUse--;
4532     if (AOP_SIZE(result)==2) 
4533     {
4534       aopPut (AOP (result), "b", 1);
4535     }
4536     return;
4537   }
4538
4539   // we have to do a signed multiply
4540
4541   emitcode (";", "signed");
4542   emitcode ("clr", "F0"); // reset sign flag
4543   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4544
4545   lbl=newiTempLabel(NULL);
4546   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4547   // left side is negative, 8-bit two's complement, this fails for -128
4548   emitcode ("setb", "F0"); // set sign flag
4549   emitcode ("cpl", "a");
4550   emitcode ("inc", "a");
4551
4552   emitcode ("", "!tlabeldef", lbl->key+100);
4553
4554   /* if literal */
4555   if (AOP_TYPE(right)==AOP_LIT) {
4556     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4557     /* AND literal negative */
4558     if ((int) val < 0) {
4559       emitcode ("cpl", "F0"); // complement sign flag
4560       emitcode ("mov", "b,#!constbyte", -val);
4561     } else {
4562       emitcode ("mov", "b,#!constbyte", val);
4563     }
4564   } else {
4565     lbl=newiTempLabel(NULL);
4566     emitcode ("mov", "b,a");
4567     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4568     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4569     // right side is negative, 8-bit two's complement
4570     emitcode ("cpl", "F0"); // complement sign flag
4571     emitcode ("cpl", "a");
4572     emitcode ("inc", "a");
4573     emitcode ("", "!tlabeldef", lbl->key+100);
4574   }
4575   emitcode ("mul", "ab");
4576     
4577   _G.accInUse++;_G.bInUse++;
4578   aopOp(result, ic, TRUE, FALSE);
4579     
4580   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4581   {
4582     // this should never happen
4583       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4584                AOP_SIZE(result), __FILE__, lineno);
4585       exit (1);
4586   }    
4587     
4588   lbl=newiTempLabel(NULL);
4589   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4590   // only ONE op was negative, we have to do a 8/16-bit two's complement
4591   emitcode ("cpl", "a"); // lsb
4592   if (AOP_SIZE(result)==1) {
4593     emitcode ("inc", "a");
4594   } else {
4595     emitcode ("add", "a,#1");
4596     emitcode ("xch", "a,b");
4597     emitcode ("cpl", "a"); // msb
4598     emitcode ("addc", "a,#0");
4599     emitcode ("xch", "a,b");
4600   }
4601
4602   emitcode ("", "!tlabeldef", lbl->key+100);
4603   aopPut (AOP (result), "a", 0);
4604   _G.accInUse--;_G.bInUse--;
4605   if (AOP_SIZE(result)==2) {
4606     aopPut (AOP (result), "b", 1);
4607   }
4608 }
4609
4610 /*-----------------------------------------------------------------*/
4611 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4612 /*-----------------------------------------------------------------*/
4613 static void genMultTwoByte (operand *left, operand *right, 
4614                             operand *result, iCode *ic)
4615 {
4616         sym_link *retype = getSpec(operandType(right));
4617         sym_link *letype = getSpec(operandType(left));
4618         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4619         symbol *lbl;
4620
4621         if (AOP_TYPE (left) == AOP_LIT) {
4622                 operand *t = right;
4623                 right = left;
4624                 left = t;
4625         }
4626         /* save EA bit in F1 */
4627         lbl = newiTempLabel(NULL);
4628         emitcode ("setb","F1");
4629         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4630         emitcode ("clr","F1");
4631         emitcode("","!tlabeldef",lbl->key+100);
4632
4633         /* load up MB with right */
4634         if (!umult) {
4635                 emitcode("clr","F0");
4636                 if (AOP_TYPE(right) == AOP_LIT) {
4637                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4638                         if (val < 0) {
4639                                 emitcode("setb","F0");
4640                                 val = -val;
4641                         }
4642                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4643                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4644                 } else {
4645                         lbl = newiTempLabel(NULL);
4646                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4647                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4648                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4649                         emitcode ("xch", "a,b");
4650                         emitcode ("cpl","a");
4651                         emitcode ("add", "a,#1");
4652                         emitcode ("xch", "a,b");
4653                         emitcode ("cpl", "a"); // msb
4654                         emitcode ("addc", "a,#0");
4655                         emitcode ("setb","F0");
4656                         emitcode ("","!tlabeldef",lbl->key+100);
4657                         emitcode ("mov","mb,b");
4658                         emitcode ("mov","mb,a");
4659                 }
4660         } else {
4661                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4662                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4663         }
4664         /* load up MA with left */
4665         if (!umult) {
4666                 lbl = newiTempLabel(NULL);
4667                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4668                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4669                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4670                 emitcode ("xch", "a,b");
4671                 emitcode ("cpl","a");
4672                 emitcode ("add", "a,#1");
4673                 emitcode ("xch", "a,b");
4674                 emitcode ("cpl", "a"); // msb
4675                 emitcode ("addc","a,#0");
4676                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4677                 emitcode ("setb","F0");
4678                 emitcode ("","!tlabeldef",lbl->key+100);
4679                 emitcode ("mov","ma,b");
4680                 emitcode ("mov","ma,a");
4681         } else {
4682                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4683                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4684         }
4685         /* wait for multiplication to finish */
4686         lbl = newiTempLabel(NULL);
4687         emitcode("","!tlabeldef", lbl->key+100);
4688         emitcode("mov","a,mcnt1");
4689         emitcode("anl","a,#!constbyte",0x80);
4690         emitcode("jnz","!tlabel",lbl->key+100);
4691         
4692         freeAsmop (left, NULL, ic, TRUE);
4693         freeAsmop (right, NULL, ic,TRUE);
4694         aopOp(result, ic, TRUE, FALSE);
4695
4696         /* if unsigned then simple */   
4697         if (umult) {
4698                 emitcode ("mov","a,ma");
4699                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4700                 emitcode ("mov","a,ma");
4701                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4702                 aopPut(AOP(result),"ma",1);
4703                 aopPut(AOP(result),"ma",0);
4704         } else {
4705                 emitcode("push","ma");
4706                 emitcode("push","ma");
4707                 emitcode("push","ma");
4708                 MOVA("ma");
4709                 /* negate result if needed */
4710                 lbl = newiTempLabel(NULL);      
4711                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4712                 emitcode("cpl","a");
4713                 emitcode("add","a,#1");
4714                 emitcode("","!tlabeldef", lbl->key+100);
4715                 if (AOP_TYPE(result) == AOP_ACC)
4716                 {
4717                     D(emitcode(";", "ACC special case."););
4718                     /* We know result is the only live aop, and 
4719                      * it's obviously not a DPTR2, so AP is available.
4720                      */
4721                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4722                 }
4723                 else
4724                 {
4725                     aopPut(AOP(result),"a",0);
4726                 }
4727             
4728                 emitcode("pop","acc");
4729                 lbl = newiTempLabel(NULL);      
4730                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4731                 emitcode("cpl","a");
4732                 emitcode("addc","a,#0");
4733                 emitcode("","!tlabeldef", lbl->key+100);
4734                 aopPut(AOP(result),"a",1);
4735                 emitcode("pop","acc");
4736                 if (AOP_SIZE(result) >= 3) {
4737                         lbl = newiTempLabel(NULL);      
4738                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4739                         emitcode("cpl","a");
4740                         emitcode("addc","a,#0");                        
4741                         emitcode("","!tlabeldef", lbl->key+100);
4742                         aopPut(AOP(result),"a",2);
4743                 }
4744                 emitcode("pop","acc");
4745                 if (AOP_SIZE(result) >= 4) {
4746                         lbl = newiTempLabel(NULL);      
4747                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4748                         emitcode("cpl","a");
4749                         emitcode("addc","a,#0");                        
4750                         emitcode("","!tlabeldef", lbl->key+100);
4751                         aopPut(AOP(result),"a",3);
4752                 }
4753                 if (AOP_TYPE(result) == AOP_ACC)
4754                 {
4755                     /* We stashed the result away above. */
4756                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4757                 }           
4758                 
4759         }
4760         freeAsmop (result, NULL, ic, TRUE);
4761
4762         /* restore EA bit in F1 */
4763         lbl = newiTempLabel(NULL);
4764         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4765         emitcode ("setb","EA");
4766         emitcode("","!tlabeldef",lbl->key+100);
4767         return ;
4768 }
4769
4770 /*-----------------------------------------------------------------*/
4771 /* genMult - generates code for multiplication                     */
4772 /*-----------------------------------------------------------------*/
4773 static void
4774 genMult (iCode * ic)
4775 {
4776   operand *left = IC_LEFT (ic);
4777   operand *right = IC_RIGHT (ic);
4778   operand *result = IC_RESULT (ic);
4779
4780   D (emitcode (";", "genMult "););
4781
4782   /* assign the amsops */
4783   AOP_OP_2 (ic);
4784
4785   /* special cases first */
4786   /* both are bits */
4787   if (AOP_TYPE (left) == AOP_CRY &&
4788       AOP_TYPE (right) == AOP_CRY)
4789     {
4790       genMultbits (left, right, result, ic);
4791       goto release;
4792     }
4793
4794   /* if both are of size == 1 */
4795   if (AOP_SIZE (left) == 1 &&
4796       AOP_SIZE (right) == 1)
4797     {
4798       genMultOneByte (left, right, result, ic);
4799       goto release;
4800     }
4801
4802   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4803           /* use the ds390 ARITHMETIC accel UNIT */
4804           genMultTwoByte (left, right, result, ic);
4805           return ;
4806   }
4807   /* should have been converted to function call */
4808   assert (0);
4809
4810 release:
4811   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4812   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4813   freeAsmop (result, NULL, ic, TRUE);
4814 }
4815
4816 /*-----------------------------------------------------------------*/
4817 /* genDivbits :- division of bits                                  */
4818 /*-----------------------------------------------------------------*/
4819 static void
4820 genDivbits (operand * left,
4821             operand * right,
4822             operand * result,
4823             iCode   * ic)
4824 {
4825
4826   char *l;
4827
4828   /* the result must be bit */
4829   LOAD_AB_FOR_DIV (left, right, l);
4830   emitcode ("div", "ab");
4831   emitcode ("rrc", "a");
4832   aopOp(result, ic, TRUE, FALSE);
4833     
4834   aopPut (AOP (result), "c", 0);
4835 }
4836
4837 /*-----------------------------------------------------------------*/
4838 /* genDivOneByte : 8 bit division                                  */
4839 /*-----------------------------------------------------------------*/
4840 static void
4841 genDivOneByte (operand * left,
4842                operand * right,
4843                operand * result,
4844                iCode   * ic)
4845 {
4846   sym_link *opetype = operandType (result);
4847   char *l;
4848   symbol *lbl;
4849   int size, offset;
4850
4851   offset = 1;
4852   /* signed or unsigned */
4853   if (SPEC_USIGN (opetype))
4854     {
4855         /* unsigned is easy */
4856         LOAD_AB_FOR_DIV (left, right, l);
4857         emitcode ("div", "ab");
4858
4859         _G.accInUse++;
4860         aopOp(result, ic, TRUE, FALSE);
4861         aopPut (AOP (result), "a", 0);
4862         _G.accInUse--;
4863
4864         size = AOP_SIZE (result) - 1;
4865         
4866         while (size--)
4867         {
4868             aopPut (AOP (result), zero, offset++);
4869         }
4870       return;
4871     }
4872
4873   /* signed is a little bit more difficult */
4874
4875   /* save the signs of the operands */
4876   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4877   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4878   emitcode ("push", "acc");     /* save it on the stack */
4879
4880   /* now sign adjust for both left & right */
4881   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4882   lbl = newiTempLabel (NULL);
4883   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4884   emitcode ("cpl", "a");
4885   emitcode ("inc", "a");
4886   emitcode ("", "!tlabeldef", (lbl->key + 100));
4887   emitcode ("mov", "b,a");
4888
4889   /* sign adjust left side */
4890   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4891
4892   lbl = newiTempLabel (NULL);
4893   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4894   emitcode ("cpl", "a");
4895   emitcode ("inc", "a");
4896   emitcode ("", "!tlabeldef", (lbl->key + 100));
4897
4898   /* now the division */
4899   emitcode ("nop", "; workaround for DS80C390 div bug.");
4900   emitcode ("div", "ab");
4901   /* we are interested in the lower order
4902      only */
4903   emitcode ("mov", "b,a");
4904   lbl = newiTempLabel (NULL);
4905   emitcode ("pop", "acc");
4906   /* if there was an over flow we don't
4907      adjust the sign of the result */
4908   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4909   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4910   CLRC;
4911   emitcode ("clr", "a");
4912   emitcode ("subb", "a,b");
4913   emitcode ("mov", "b,a");
4914   emitcode ("", "!tlabeldef", (lbl->key + 100));
4915
4916   /* now we are done */
4917   _G.accInUse++;     _G.bInUse++;
4918     aopOp(result, ic, TRUE, FALSE);
4919     
4920     aopPut (AOP (result), "b", 0);
4921     
4922     size = AOP_SIZE (result) - 1;
4923     
4924     if (size > 0)
4925     {
4926       emitcode ("mov", "c,b.7");
4927       emitcode ("subb", "a,acc");
4928     }
4929     while (size--)
4930     {
4931         aopPut (AOP (result), "a", offset++);
4932     }
4933     _G.accInUse--;     _G.bInUse--;
4934
4935 }
4936
4937 /*-----------------------------------------------------------------*/
4938 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4939 /*-----------------------------------------------------------------*/
4940 static void genDivTwoByte (operand *left, operand *right, 
4941                             operand *result, iCode *ic)
4942 {
4943         sym_link *retype = getSpec(operandType(right));
4944         sym_link *letype = getSpec(operandType(left));
4945         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4946         symbol *lbl;
4947
4948         /* save EA bit in F1 */
4949         lbl = newiTempLabel(NULL);
4950         emitcode ("setb","F1");
4951         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4952         emitcode ("clr","F1");
4953         emitcode("","!tlabeldef",lbl->key+100);
4954
4955         /* load up MA with left */
4956         if (!umult) {
4957                 emitcode("clr","F0");
4958                 lbl = newiTempLabel(NULL);
4959                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4960                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4961                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4962                 emitcode ("xch", "a,b");
4963                 emitcode ("cpl","a");
4964                 emitcode ("add", "a,#1");
4965                 emitcode ("xch", "a,b");
4966                 emitcode ("cpl", "a"); // msb
4967                 emitcode ("addc","a,#0");
4968                 emitcode ("setb","F0");
4969                 emitcode ("","!tlabeldef",lbl->key+100);
4970                 emitcode ("mov","ma,b");
4971                 emitcode ("mov","ma,a");
4972         } else {
4973                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4974                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4975         }
4976
4977         /* load up MB with right */
4978         if (!umult) {
4979                 if (AOP_TYPE(right) == AOP_LIT) {
4980                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4981                         if (val < 0) {
4982                                 lbl = newiTempLabel(NULL);
4983                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4984                                 emitcode("setb","F0");
4985                                 emitcode ("","!tlabeldef",lbl->key+100);
4986                                 val = -val;
4987                         } 
4988                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4989                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4990                 } else {
4991                         lbl = newiTempLabel(NULL);
4992                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4993                         emitcode ("mov","a,%s",aopGet(AOP(right),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 ("jbc","F0,!tlabel",lbl->key+100);
5002                         emitcode ("setb","F0");
5003                         emitcode ("","!tlabeldef",lbl->key+100);
5004                         emitcode ("mov","mb,b");
5005                         emitcode ("mov","mb,a");
5006                 }
5007         } else {
5008                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5009                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5010         }
5011
5012         /* wait for multiplication to finish */
5013         lbl = newiTempLabel(NULL);
5014         emitcode("","!tlabeldef", lbl->key+100);
5015         emitcode("mov","a,mcnt1");
5016         emitcode("anl","a,#!constbyte",0x80);
5017         emitcode("jnz","!tlabel",lbl->key+100);
5018         
5019         freeAsmop (left, NULL, ic, TRUE);
5020         freeAsmop (right, NULL, ic,TRUE);
5021         aopOp(result, ic, TRUE, FALSE);
5022
5023         /* if unsigned then simple */   
5024         if (umult) {
5025                 aopPut(AOP(result),"ma",1);
5026                 aopPut(AOP(result),"ma",0);
5027         } else {
5028                 emitcode("push","ma");
5029                 MOVA("ma");
5030                 /* negate result if needed */
5031                 lbl = newiTempLabel(NULL);      
5032                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5033                 emitcode("cpl","a");
5034                 emitcode("add","a,#1");
5035                 emitcode("","!tlabeldef", lbl->key+100);
5036                 aopPut(AOP(result),"a",0);
5037                 emitcode("pop","acc");
5038                 lbl = newiTempLabel(NULL);      
5039                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5040                 emitcode("cpl","a");
5041                 emitcode("addc","a,#0");
5042                 emitcode("","!tlabeldef", lbl->key+100);
5043                 aopPut(AOP(result),"a",1);
5044         }
5045         freeAsmop (result, NULL, ic, TRUE);
5046         /* restore EA bit in F1 */
5047         lbl = newiTempLabel(NULL);
5048         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5049         emitcode ("setb","EA");
5050         emitcode("","!tlabeldef",lbl->key+100);
5051         return ;
5052 }
5053
5054 /*-----------------------------------------------------------------*/
5055 /* genDiv - generates code for division                            */
5056 /*-----------------------------------------------------------------*/
5057 static void
5058 genDiv (iCode * ic)
5059 {
5060   operand *left = IC_LEFT (ic);
5061   operand *right = IC_RIGHT (ic);
5062   operand *result = IC_RESULT (ic);
5063
5064   D (emitcode (";", "genDiv "););
5065
5066   /* assign the amsops */
5067   AOP_OP_2 (ic);
5068
5069   /* special cases first */
5070   /* both are bits */
5071   if (AOP_TYPE (left) == AOP_CRY &&
5072       AOP_TYPE (right) == AOP_CRY)
5073     {
5074       genDivbits (left, right, result, ic);
5075       goto release;
5076     }
5077
5078   /* if both are of size == 1 */
5079   if (AOP_SIZE (left) == 1 &&
5080       AOP_SIZE (right) == 1)
5081     {
5082       genDivOneByte (left, right, result, ic);
5083       goto release;
5084     }
5085
5086   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5087           /* use the ds390 ARITHMETIC accel UNIT */
5088           genDivTwoByte (left, right, result, ic);
5089           return ;
5090   }
5091   /* should have been converted to function call */
5092   assert (0);
5093 release:
5094   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5095   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5096   freeAsmop (result, NULL, ic, TRUE);
5097 }
5098
5099 /*-----------------------------------------------------------------*/
5100 /* genModbits :- modulus of bits                                   */
5101 /*-----------------------------------------------------------------*/
5102 static void
5103 genModbits (operand * left,
5104             operand * right,
5105             operand * result,
5106             iCode   * ic)
5107 {
5108
5109   char *l;
5110
5111   /* the result must be bit */
5112   LOAD_AB_FOR_DIV (left, right, l);
5113   emitcode ("div", "ab");
5114   emitcode ("mov", "a,b");
5115   emitcode ("rrc", "a");
5116   aopOp(result, ic, TRUE, FALSE);
5117   aopPut (AOP (result), "c", 0);
5118 }
5119
5120 /*-----------------------------------------------------------------*/
5121 /* genModOneByte : 8 bit modulus                                   */
5122 /*-----------------------------------------------------------------*/
5123 static void
5124 genModOneByte (operand * left,
5125                operand * right,
5126                operand * result,
5127                iCode   * ic)
5128 {
5129   sym_link *opetype = operandType (result);
5130   char *l;
5131   symbol *lbl;
5132
5133   /* signed or unsigned */
5134   if (SPEC_USIGN (opetype))
5135     {
5136       /* unsigned is easy */
5137       LOAD_AB_FOR_DIV (left, right, l);
5138       emitcode ("div", "ab");
5139       aopOp(result, ic, TRUE, FALSE);   
5140       aopPut (AOP (result), "b", 0);
5141       return;
5142     }
5143
5144   /* signed is a little bit more difficult */
5145
5146   /* save the signs of the operands */
5147   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5148
5149   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5150   emitcode ("push", "acc");     /* save it on the stack */
5151
5152   /* now sign adjust for both left & right */
5153   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5154
5155   lbl = newiTempLabel (NULL);
5156   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5157   emitcode ("cpl", "a");
5158   emitcode ("inc", "a");
5159   emitcode ("", "!tlabeldef", (lbl->key + 100));
5160   emitcode ("mov", "b,a");
5161
5162   /* sign adjust left side */
5163   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5164
5165   lbl = newiTempLabel (NULL);
5166   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5167   emitcode ("cpl", "a");
5168   emitcode ("inc", "a");
5169   emitcode ("", "!tlabeldef", (lbl->key + 100));
5170
5171   /* now the multiplication */
5172   emitcode ("nop", "; workaround for DS80C390 div bug.");
5173   emitcode ("div", "ab");
5174   /* we are interested in the lower order
5175      only */
5176   lbl = newiTempLabel (NULL);
5177   emitcode ("pop", "acc");
5178   /* if there was an over flow we don't
5179      adjust the sign of the result */
5180   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5181   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5182   CLRC;
5183   emitcode ("clr", "a");
5184   emitcode ("subb", "a,b");
5185   emitcode ("mov", "b,a");
5186   emitcode ("", "!tlabeldef", (lbl->key + 100));
5187   
5188   _G.bInUse++;
5189   /* now we are done */
5190   aopOp(result, ic, TRUE, FALSE);    
5191   aopPut (AOP (result), "b", 0);
5192   _G.bInUse--;
5193
5194 }
5195
5196 /*-----------------------------------------------------------------*/
5197 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5198 /*-----------------------------------------------------------------*/
5199 static void genModTwoByte (operand *left, operand *right, 
5200                             operand *result, iCode *ic)
5201 {
5202         sym_link *retype = getSpec(operandType(right));
5203         sym_link *letype = getSpec(operandType(left));
5204         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5205         symbol *lbl;
5206
5207         /* load up MA with left */
5208         /* save EA bit in F1 */
5209         lbl = newiTempLabel(NULL);
5210         emitcode ("setb","F1");
5211         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5212         emitcode ("clr","F1");
5213         emitcode("","!tlabeldef",lbl->key+100);
5214
5215         if (!umult) {
5216                 lbl = newiTempLabel(NULL);
5217                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5218                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5219                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5220                 emitcode ("xch", "a,b");
5221                 emitcode ("cpl","a");
5222                 emitcode ("add", "a,#1");
5223                 emitcode ("xch", "a,b");
5224                 emitcode ("cpl", "a"); // msb
5225                 emitcode ("addc","a,#0");
5226                 emitcode ("","!tlabeldef",lbl->key+100);
5227                 emitcode ("mov","ma,b");
5228                 emitcode ("mov","ma,a");
5229         } else {
5230                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5231                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5232         }
5233
5234         /* load up MB with right */
5235         if (!umult) {
5236                 if (AOP_TYPE(right) == AOP_LIT) {
5237                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
5238                         if (val < 0) {
5239                                 val = -val;
5240                         } 
5241                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5242                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5243                 } else {
5244                         lbl = newiTempLabel(NULL);
5245                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5246                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5247                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5248                         emitcode ("xch", "a,b");
5249                         emitcode ("cpl","a");
5250                         emitcode ("add", "a,#1");
5251                         emitcode ("xch", "a,b");
5252                         emitcode ("cpl", "a"); // msb
5253                         emitcode ("addc", "a,#0");
5254                         emitcode ("","!tlabeldef",lbl->key+100);
5255                         emitcode ("mov","mb,b");
5256                         emitcode ("mov","mb,a");
5257                 }
5258         } else {
5259                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5260                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5261         }
5262
5263         /* wait for multiplication to finish */
5264         lbl = newiTempLabel(NULL);
5265         emitcode("","!tlabeldef", lbl->key+100);
5266         emitcode("mov","a,mcnt1");
5267         emitcode("anl","a,#!constbyte",0x80);
5268         emitcode("jnz","!tlabel",lbl->key+100);
5269         
5270         freeAsmop (left, NULL, ic, TRUE);
5271         freeAsmop (right, NULL, ic,TRUE);
5272         aopOp(result, ic, TRUE, FALSE);
5273
5274         aopPut(AOP(result),"mb",1);
5275         aopPut(AOP(result),"mb",0);
5276         freeAsmop (result, NULL, ic, TRUE);
5277
5278         /* restore EA bit in F1 */
5279         lbl = newiTempLabel(NULL);
5280         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5281         emitcode ("setb","EA");
5282         emitcode("","!tlabeldef",lbl->key+100);
5283         return ;
5284 }
5285
5286 /*-----------------------------------------------------------------*/
5287 /* genMod - generates code for division                            */
5288 /*-----------------------------------------------------------------*/
5289 static void
5290 genMod (iCode * ic)
5291 {
5292   operand *left = IC_LEFT (ic);
5293   operand *right = IC_RIGHT (ic);
5294   operand *result = IC_RESULT (ic);
5295
5296   D (emitcode (";", "genMod "); );
5297
5298   /* assign the amsops */
5299   AOP_OP_2 (ic);
5300
5301   /* special cases first */
5302   /* both are bits */
5303   if (AOP_TYPE (left) == AOP_CRY &&
5304       AOP_TYPE (right) == AOP_CRY)
5305     {
5306       genModbits (left, right, result, ic);
5307       goto release;
5308     }
5309
5310   /* if both are of size == 1 */
5311   if (AOP_SIZE (left) == 1 &&
5312       AOP_SIZE (right) == 1)
5313     {
5314       genModOneByte (left, right, result, ic);
5315       goto release;
5316     }
5317
5318   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5319           /* use the ds390 ARITHMETIC accel UNIT */
5320           genModTwoByte (left, right, result, ic);
5321           return ;
5322   }
5323
5324   /* should have been converted to function call */
5325   assert (0);
5326
5327 release:
5328   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5329   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5330   freeAsmop (result, NULL, ic, TRUE);
5331 }
5332
5333 /*-----------------------------------------------------------------*/
5334 /* genIfxJump :- will create a jump depending on the ifx           */
5335 /*-----------------------------------------------------------------*/
5336 static void
5337 genIfxJump (iCode * ic, char *jval)
5338 {
5339   symbol *jlbl;
5340   symbol *tlbl = newiTempLabel (NULL);
5341   char *inst;
5342
5343   D (emitcode (";", "genIfxJump"););
5344
5345   /* if true label then we jump if condition
5346      supplied is true */
5347   if (IC_TRUE (ic))
5348     {
5349       jlbl = IC_TRUE (ic);
5350       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5351                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5352     }
5353   else
5354     {
5355       /* false label is present */
5356       jlbl = IC_FALSE (ic);
5357       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5358                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5359     }
5360   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5361     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5362   else
5363     emitcode (inst, "!tlabel", tlbl->key + 100);
5364   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5365   emitcode ("", "!tlabeldef", tlbl->key + 100);
5366
5367   /* mark the icode as generated */
5368   ic->generated = 1;
5369 }
5370
5371 /*-----------------------------------------------------------------*/
5372 /* genCmp :- greater or less than comparison                       */
5373 /*-----------------------------------------------------------------*/
5374 static void
5375 genCmp (operand * left, operand * right,
5376         iCode * ic, iCode * ifx, int sign)
5377 {
5378   int size, offset = 0;
5379   unsigned long lit = 0L;
5380   operand *result;
5381
5382   D (emitcode (";", "genCmp"););
5383
5384   result = IC_RESULT (ic);
5385
5386   /* if left & right are bit variables */
5387   if (AOP_TYPE (left) == AOP_CRY &&
5388       AOP_TYPE (right) == AOP_CRY)
5389     {
5390       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5391       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5392     }
5393   else
5394     {
5395       /* subtract right from left if at the
5396          end the carry flag is set then we know that
5397          left is greater than right */
5398       size = max (AOP_SIZE (left), AOP_SIZE (right));
5399
5400       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5401       if ((size == 1) && !sign 
5402           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5403         {
5404           symbol *lbl = newiTempLabel (NULL);
5405           emitcode ("cjne", "%s,%s,!tlabel",
5406                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5407                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5408                     lbl->key + 100);
5409           emitcode ("", "!tlabeldef", lbl->key + 100);
5410         }
5411       else
5412         {
5413           if (AOP_TYPE (right) == AOP_LIT)
5414             {
5415               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5416               /* optimize if(x < 0) or if(x >= 0) */
5417               if (lit == 0L)
5418                 {
5419                   if (!sign)
5420                     {
5421                       CLRC;
5422                     }
5423                   else
5424                     {
5425                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5426
5427                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5428                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5429
5430                       aopOp (result, ic, FALSE, FALSE);
5431
5432                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5433                         {
5434                           freeAsmop (result, NULL, ic, TRUE);
5435                           genIfxJump (ifx, "acc.7");
5436                           return;
5437                         }
5438                       else
5439                         {
5440                           emitcode ("rlc", "a");
5441                         }
5442                       goto release_freedLR;
5443                     }
5444                   goto release;
5445                 }
5446             }
5447           CLRC;
5448           while (size--)
5449             {
5450               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5451               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5452               // emitcode (";", "genCmp #2");
5453               if (sign && (size == 0))
5454                 {
5455                   // emitcode (";", "genCmp #3");
5456                   emitcode ("xrl", "a,#!constbyte",0x80);
5457                   if (AOP_TYPE (right) == AOP_LIT)
5458                     {
5459                       unsigned long lit = (unsigned long)
5460                       floatFromVal (AOP (right)->aopu.aop_lit);
5461                       // emitcode (";", "genCmp #3.1");
5462                       emitcode ("subb", "a,#!constbyte",
5463                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5464                     }
5465                   else
5466                     {
5467                       // emitcode (";", "genCmp #3.2");
5468                       saveAccWarn = 0;  
5469                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5470                       saveAccWarn = DEFAULT_ACC_WARNING;
5471                       emitcode ("xrl", "b,#!constbyte",0x80);
5472                       emitcode ("subb", "a,b");
5473                     }
5474                 }
5475               else
5476                 {
5477                   const char *s;
5478
5479                   // emitcode (";", "genCmp #4");
5480                   saveAccWarn = 0;
5481                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5482                   saveAccWarn = DEFAULT_ACC_WARNING;
5483
5484                   emitcode ("subb", "a,%s", s);
5485                 }
5486             }
5487         }
5488     }
5489
5490 release:
5491 /* Don't need the left & right operands any more; do need the result. */
5492   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5493   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5494
5495   aopOp (result, ic, FALSE, FALSE);
5496
5497 release_freedLR:
5498
5499   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5500     {
5501       outBitC (result);
5502     }
5503   else
5504     {
5505       /* if the result is used in the next
5506          ifx conditional branch then generate
5507          code a little differently */
5508       if (ifx)
5509         {
5510           genIfxJump (ifx, "c");
5511         }
5512       else
5513         {
5514           outBitC (result);
5515         }
5516       /* leave the result in acc */
5517     }
5518   freeAsmop (result, NULL, ic, TRUE);
5519 }
5520
5521 /*-----------------------------------------------------------------*/
5522 /* genCmpGt :- greater than comparison                             */
5523 /*-----------------------------------------------------------------*/
5524 static void
5525 genCmpGt (iCode * ic, iCode * ifx)
5526 {
5527   operand *left, *right;
5528   sym_link *letype, *retype;
5529   int sign;
5530
5531   D (emitcode (";", "genCmpGt ");
5532     );
5533
5534   left = IC_LEFT (ic);
5535   right = IC_RIGHT (ic);
5536
5537   letype = getSpec (operandType (left));
5538   retype = getSpec (operandType (right));
5539   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5540
5541   /* assign the left & right amsops */
5542   AOP_OP_2 (ic);
5543
5544   genCmp (right, left, ic, ifx, sign);
5545 }
5546
5547 /*-----------------------------------------------------------------*/
5548 /* genCmpLt - less than comparisons                                */
5549 /*-----------------------------------------------------------------*/
5550 static void
5551 genCmpLt (iCode * ic, iCode * ifx)
5552 {
5553   operand *left, *right;
5554   sym_link *letype, *retype;
5555   int sign;
5556
5557   D (emitcode (";", "genCmpLt "););
5558
5559   left = IC_LEFT (ic);
5560   right = IC_RIGHT (ic);
5561
5562   letype = getSpec (operandType (left));
5563   retype = getSpec (operandType (right));
5564   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5565
5566   /* assign the left & right amsops */
5567   AOP_OP_2 (ic);
5568
5569   genCmp (left, right, ic, ifx, sign);
5570 }
5571
5572 /*-----------------------------------------------------------------*/
5573 /* gencjneshort - compare and jump if not equal                    */
5574 /*-----------------------------------------------------------------*/
5575 static void
5576 gencjneshort (operand * left, operand * right, symbol * lbl)
5577 {
5578   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5579   int offset = 0;
5580   unsigned long lit = 0L;
5581
5582   D (emitcode (";", "gencjneshort");
5583     );
5584
5585   /* if the left side is a literal or
5586      if the right is in a pointer register and left
5587      is not */
5588   if ((AOP_TYPE (left) == AOP_LIT) ||
5589       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5590     {
5591       operand *t = right;
5592       right = left;
5593       left = t;
5594     }
5595
5596   if (AOP_TYPE (right) == AOP_LIT)
5597     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5598
5599   if (opIsGptr (left) || opIsGptr (right))
5600     {
5601       /* We are comparing a generic pointer to something.
5602        * Exclude the generic type byte from the comparison.
5603        */
5604       size--;
5605       D (emitcode (";", "cjneshort: generic ptr special case."););
5606     }
5607
5608
5609   /* if the right side is a literal then anything goes */
5610   if (AOP_TYPE (right) == AOP_LIT &&
5611       AOP_TYPE (left) != AOP_DIR)
5612     {
5613       while (size--)
5614         {
5615           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5616           emitcode ("cjne", "a,%s,!tlabel",
5617                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5618                     lbl->key + 100);
5619           offset++;
5620         }
5621     }
5622
5623   /* if the right side is in a register or in direct space or
5624      if the left is a pointer register & right is not */
5625   else if (AOP_TYPE (right) == AOP_REG ||
5626            AOP_TYPE (right) == AOP_DIR ||
5627            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5628            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5629     {
5630       while (size--)
5631         {
5632           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5633           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5634               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5635             emitcode ("jnz", "!tlabel", lbl->key + 100);
5636           else
5637             emitcode ("cjne", "a,%s,!tlabel",
5638                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5639                       lbl->key + 100);
5640           offset++;
5641         }
5642     }
5643   else
5644     {
5645       /* right is a pointer reg need both a & b */
5646       while (size--)
5647         {
5648           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5649           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5650           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5651           offset++;
5652         }
5653     }
5654 }
5655
5656 /*-----------------------------------------------------------------*/
5657 /* gencjne - compare and jump if not equal                         */
5658 /*-----------------------------------------------------------------*/
5659 static void
5660 gencjne (operand * left, operand * right, symbol * lbl)
5661 {
5662   symbol *tlbl = newiTempLabel (NULL);
5663
5664   D (emitcode (";", "gencjne");
5665     );
5666
5667   gencjneshort (left, right, lbl);
5668
5669   emitcode ("mov", "a,%s", one);
5670   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5671   emitcode ("", "!tlabeldef", lbl->key + 100);
5672   emitcode ("clr", "a");
5673   emitcode ("", "!tlabeldef", tlbl->key + 100);
5674 }
5675
5676 /*-----------------------------------------------------------------*/
5677 /* genCmpEq - generates code for equal to                          */
5678 /*-----------------------------------------------------------------*/
5679 static void
5680 genCmpEq (iCode * ic, iCode * ifx)
5681 {
5682   operand *left, *right, *result;
5683
5684   D (emitcode (";", "genCmpEq ");
5685     );
5686
5687   AOP_OP_2 (ic);
5688   AOP_SET_LOCALS (ic);
5689
5690   /* if literal, literal on the right or
5691      if the right is in a pointer register and left
5692      is not */
5693   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5694       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5695     {
5696       operand *t = IC_RIGHT (ic);
5697       IC_RIGHT (ic) = IC_LEFT (ic);
5698       IC_LEFT (ic) = t;
5699     }
5700
5701   if (ifx &&                    /* !AOP_SIZE(result) */
5702       OP_SYMBOL (result) &&
5703       OP_SYMBOL (result)->regType == REG_CND)
5704     {
5705       symbol *tlbl;
5706       /* if they are both bit variables */
5707       if (AOP_TYPE (left) == AOP_CRY &&
5708           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5709         {
5710           if (AOP_TYPE (right) == AOP_LIT)
5711             {
5712               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5713               if (lit == 0L)
5714                 {
5715                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5716                   emitcode ("cpl", "c");
5717                 }
5718               else if (lit == 1L)
5719                 {
5720                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5721                 }
5722               else
5723                 {
5724                   emitcode ("clr", "c");
5725                 }
5726               /* AOP_TYPE(right) == AOP_CRY */
5727             }
5728           else
5729             {
5730               symbol *lbl = newiTempLabel (NULL);
5731               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5732               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5733               emitcode ("cpl", "c");
5734               emitcode ("", "!tlabeldef", (lbl->key + 100));
5735             }
5736           /* if true label then we jump if condition
5737              supplied is true */
5738           tlbl = newiTempLabel (NULL);
5739           if (IC_TRUE (ifx))
5740             {
5741               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5742               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5743             }
5744           else
5745             {
5746               emitcode ("jc", "!tlabel", tlbl->key + 100);
5747               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5748             }
5749           emitcode ("", "!tlabeldef", tlbl->key + 100);
5750         }
5751       else
5752         {
5753           tlbl = newiTempLabel (NULL);
5754           gencjneshort (left, right, tlbl);
5755           if (IC_TRUE (ifx))
5756             {
5757               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5758               emitcode ("", "!tlabeldef", tlbl->key + 100);
5759             }
5760           else
5761             {
5762               symbol *lbl = newiTempLabel (NULL);
5763               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5764               emitcode ("", "!tlabeldef", tlbl->key + 100);
5765               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5766               emitcode ("", "!tlabeldef", lbl->key + 100);
5767             }
5768         }
5769       /* mark the icode as generated */
5770       ifx->generated = 1;
5771
5772       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5773       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5774       return;
5775     }
5776
5777   /* if they are both bit variables */
5778   if (AOP_TYPE (left) == AOP_CRY &&
5779       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5780     {
5781       if (AOP_TYPE (right) == AOP_LIT)
5782         {
5783           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5784           if (lit == 0L)
5785             {
5786               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5787               emitcode ("cpl", "c");
5788             }
5789           else if (lit == 1L)
5790             {
5791               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5792             }
5793           else
5794             {
5795               emitcode ("clr", "c");
5796             }
5797           /* AOP_TYPE(right) == AOP_CRY */
5798         }
5799       else
5800         {
5801           symbol *lbl = newiTempLabel (NULL);
5802           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5803           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5804           emitcode ("cpl", "c");
5805           emitcode ("", "!tlabeldef", (lbl->key + 100));
5806         }
5807
5808       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5809       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5810
5811       aopOp (result, ic, TRUE, FALSE);
5812
5813       /* c = 1 if egal */
5814       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5815         {
5816           outBitC (result);
5817           goto release;
5818         }
5819       if (ifx)
5820         {
5821           genIfxJump (ifx, "c");
5822           goto release;
5823         }
5824       /* if the result is used in an arithmetic operation
5825          then put the result in place */
5826       outBitC (result);
5827     }
5828   else
5829     {
5830       gencjne (left, right, newiTempLabel (NULL));
5831
5832       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5833       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5834
5835       aopOp (result, ic, TRUE, FALSE);
5836
5837       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5838         {
5839           aopPut (AOP (result), "a", 0);
5840           goto release;
5841         }
5842       if (ifx)
5843         {
5844           genIfxJump (ifx, "a");
5845           goto release;
5846         }
5847       /* if the result is used in an arithmetic operation
5848          then put the result in place */
5849       if (AOP_TYPE (result) != AOP_CRY)
5850         outAcc (result);
5851       /* leave the result in acc */
5852     }
5853
5854 release:
5855   freeAsmop (result, NULL, ic, TRUE);
5856 }
5857
5858 /*-----------------------------------------------------------------*/
5859 /* ifxForOp - returns the icode containing the ifx for operand     */
5860 /*-----------------------------------------------------------------*/
5861 static iCode *
5862 ifxForOp (operand * op, iCode * ic)
5863 {
5864   /* if true symbol then needs to be assigned */
5865   if (IS_TRUE_SYMOP (op))
5866     return NULL;
5867
5868   /* if this has register type condition and
5869      the next instruction is ifx with the same operand
5870      and live to of the operand is upto the ifx only then */
5871   if (ic->next &&
5872       ic->next->op == IFX &&
5873       IC_COND (ic->next)->key == op->key &&
5874       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5875     return ic->next;
5876
5877   return NULL;
5878 }
5879 /*-----------------------------------------------------------------*/
5880 /* hasInc - operand is incremented before any other use            */
5881 /*-----------------------------------------------------------------*/
5882 static iCode *
5883 hasInc (operand *op, iCode *ic, int osize)
5884 {
5885   sym_link *type = operandType(op);
5886   sym_link *retype = getSpec (type);
5887   iCode *lic = ic->next;
5888   int isize ;
5889   
5890   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5891   if (!IS_SYMOP(op)) return NULL;
5892
5893   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5894   if (IS_AGGREGATE(type->next)) return NULL;
5895   if (osize != (isize = getSize(type->next))) return NULL;
5896
5897   while (lic) {
5898       /* if operand of the form op = op + <sizeof *op> */
5899       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5900           isOperandEqual(IC_RESULT(lic),op) && 
5901           isOperandLiteral(IC_RIGHT(lic)) &&
5902           operandLitValue(IC_RIGHT(lic)) == isize) {
5903           return lic;
5904       }
5905       /* if the operand used or deffed */
5906       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5907           return NULL;
5908       }
5909       /* if GOTO or IFX */
5910       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5911       lic = lic->next;
5912   }
5913   return NULL;
5914 }
5915
5916 /*-----------------------------------------------------------------*/
5917 /* genAndOp - for && operation                                     */
5918 /*-----------------------------------------------------------------*/
5919 static void
5920 genAndOp (iCode * ic)
5921 {
5922   operand *left, *right, *result;
5923   symbol *tlbl;
5924
5925   D (emitcode (";", "genAndOp "););
5926
5927   /* note here that && operations that are in an
5928      if statement are taken away by backPatchLabels
5929      only those used in arthmetic operations remain */
5930   AOP_OP_2 (ic);
5931   AOP_SET_LOCALS (ic);
5932
5933   /* if both are bit variables */
5934   if (AOP_TYPE (left) == AOP_CRY &&
5935       AOP_TYPE (right) == AOP_CRY)
5936     {
5937       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5938       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5939       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5940       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5941   
5942       aopOp (result,ic,FALSE, FALSE);
5943       outBitC (result);
5944     }
5945   else
5946     {
5947       tlbl = newiTempLabel (NULL);
5948       toBoolean (left);
5949       emitcode ("jz", "!tlabel", tlbl->key + 100);
5950       toBoolean (right);
5951       emitcode ("", "!tlabeldef", tlbl->key + 100);
5952       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5953       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5954   
5955       aopOp (result,ic,FALSE, FALSE);
5956       outBitAcc (result);
5957     }
5958     freeAsmop (result, NULL, ic, TRUE);
5959 }
5960
5961
5962 /*-----------------------------------------------------------------*/
5963 /* genOrOp - for || operation                                      */
5964 /*-----------------------------------------------------------------*/
5965 static void
5966 genOrOp (iCode * ic)
5967 {
5968   operand *left, *right, *result;
5969   symbol *tlbl;
5970
5971   D (emitcode (";", "genOrOp "););
5972
5973   /* note here that || operations that are in an
5974      if statement are taken away by backPatchLabels
5975      only those used in arthmetic operations remain */
5976   AOP_OP_2 (ic);
5977   AOP_SET_LOCALS (ic);
5978
5979   /* if both are bit variables */
5980   if (AOP_TYPE (left) == AOP_CRY &&
5981       AOP_TYPE (right) == AOP_CRY)
5982     {
5983       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5984       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
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       
5990       outBitC (result);
5991     }
5992   else
5993     {
5994       tlbl = newiTempLabel (NULL);
5995       toBoolean (left);
5996       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5997       toBoolean (right);
5998       emitcode ("", "!tlabeldef", tlbl->key + 100);
5999       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6000       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6001   
6002       aopOp (result,ic,FALSE, FALSE);
6003       
6004       outBitAcc (result);
6005     }
6006
6007   freeAsmop (result, NULL, ic, TRUE);
6008 }
6009
6010 /*-----------------------------------------------------------------*/
6011 /* isLiteralBit - test if lit == 2^n                               */
6012 /*-----------------------------------------------------------------*/
6013 static int
6014 isLiteralBit (unsigned long lit)
6015 {
6016   unsigned long pw[32] =
6017   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6018    0x100L, 0x200L, 0x400L, 0x800L,
6019    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6020    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6021    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6022    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6023    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6024   int idx;
6025
6026   for (idx = 0; idx < 32; idx++)
6027     if (lit == pw[idx])
6028       return idx + 1;
6029   return 0;
6030 }
6031
6032 /*-----------------------------------------------------------------*/
6033 /* continueIfTrue -                                                */
6034 /*-----------------------------------------------------------------*/
6035 static void
6036 continueIfTrue (iCode * ic)
6037 {
6038   if (IC_TRUE (ic))
6039     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6040   ic->generated = 1;
6041 }
6042
6043 /*-----------------------------------------------------------------*/
6044 /* jmpIfTrue -                                                     */
6045 /*-----------------------------------------------------------------*/
6046 static void
6047 jumpIfTrue (iCode * ic)
6048 {
6049   if (!IC_TRUE (ic))
6050     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6051   ic->generated = 1;
6052 }
6053
6054 /*-----------------------------------------------------------------*/
6055 /* jmpTrueOrFalse -                                                */
6056 /*-----------------------------------------------------------------*/
6057 static void
6058 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6059 {
6060   // ugly but optimized by peephole
6061   if (IC_TRUE (ic))
6062     {
6063       symbol *nlbl = newiTempLabel (NULL);
6064       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6065       emitcode ("", "!tlabeldef", tlbl->key + 100);
6066       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6067       emitcode ("", "!tlabeldef", nlbl->key + 100);
6068     }
6069   else
6070     {
6071       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6072       emitcode ("", "!tlabeldef", tlbl->key + 100);
6073     }
6074   ic->generated = 1;
6075 }
6076
6077 // Generate code to perform a bit-wise logic operation
6078 // on two operands in far space (assumed to already have been 
6079 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6080 // in far space. This requires pushing the result on the stack
6081 // then popping it into the result.
6082 static void
6083 genFarFarLogicOp(iCode *ic, char *logicOp)
6084 {
6085       int size, resultSize, compSize;
6086       int offset = 0;
6087       
6088       TR_AP("#5");
6089       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6090       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6091                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6092       
6093       _startLazyDPSEvaluation();
6094       for (size = compSize; (size--); offset++)
6095       {
6096           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6097           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6098           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6099           
6100           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6101           emitcode ("push", "acc");
6102       }
6103       _endLazyDPSEvaluation();
6104      
6105       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6106       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6107       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6108      
6109       resultSize = AOP_SIZE(IC_RESULT(ic));
6110
6111       ADJUST_PUSHED_RESULT(compSize, resultSize);
6112
6113       _startLazyDPSEvaluation();
6114       while (compSize--)
6115       {
6116           emitcode ("pop", "acc");
6117           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6118       }
6119       _endLazyDPSEvaluation();
6120       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6121 }
6122
6123
6124 /*-----------------------------------------------------------------*/
6125 /* genAnd  - code for and                                          */
6126 /*-----------------------------------------------------------------*/
6127 static void
6128 genAnd (iCode * ic, iCode * ifx)
6129 {
6130   operand *left, *right, *result;
6131   int size, offset = 0;
6132   unsigned long lit = 0L;
6133   int bytelit;
6134   char buff[10];
6135   bool pushResult;
6136
6137   D (emitcode (";", "genAnd "););
6138
6139   AOP_OP_3_NOFATAL (ic, pushResult);
6140   AOP_SET_LOCALS (ic);
6141
6142   if (pushResult)
6143   {
6144       genFarFarLogicOp(ic, "anl");
6145       return;
6146   }  
6147
6148 #ifdef DEBUG_TYPE
6149   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6150             AOP_TYPE (result),
6151             AOP_TYPE (left), AOP_TYPE (right));
6152   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6153             AOP_SIZE (result),
6154             AOP_SIZE (left), AOP_SIZE (right));
6155 #endif
6156
6157   /* if left is a literal & right is not then exchange them */
6158   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6159 #ifdef LOGIC_OPS_BROKEN      
6160     ||  AOP_NEEDSACC (left)
6161 #endif
6162     )
6163     {
6164       operand *tmp = right;
6165       right = left;
6166       left = tmp;
6167     }
6168
6169   /* if result = right then exchange them */
6170   if (sameRegs (AOP (result), AOP (right)))
6171     {
6172       operand *tmp = right;
6173       right = left;
6174       left = tmp;
6175     }
6176
6177   /* if right is bit then exchange them */
6178   if (AOP_TYPE (right) == AOP_CRY &&
6179       AOP_TYPE (left) != AOP_CRY)
6180     {
6181       operand *tmp = right;
6182       right = left;
6183       left = tmp;
6184     }
6185   if (AOP_TYPE (right) == AOP_LIT)
6186     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6187
6188   size = AOP_SIZE (result);
6189
6190   // if(bit & yy)
6191   // result = bit & yy;
6192   if (AOP_TYPE (left) == AOP_CRY)
6193     {
6194       // c = bit & literal;
6195       if (AOP_TYPE (right) == AOP_LIT)
6196         {
6197           if (lit & 1)
6198             {
6199               if (size && sameRegs (AOP (result), AOP (left)))
6200                 // no change
6201                 goto release;
6202               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6203             }
6204           else
6205             {
6206               // bit(result) = 0;
6207               if (size && (AOP_TYPE (result) == AOP_CRY))
6208                 {
6209                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6210                   goto release;
6211                 }
6212               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6213                 {
6214                   jumpIfTrue (ifx);
6215                   goto release;
6216                 }
6217               emitcode ("clr", "c");
6218             }
6219         }
6220       else
6221         {
6222           if (AOP_TYPE (right) == AOP_CRY)
6223             {
6224               // c = bit & bit;
6225               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6226               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6227             }
6228           else
6229             {
6230               // c = bit & val;
6231               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6232               // c = lsb
6233               emitcode ("rrc", "a");
6234               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6235             }
6236         }
6237       // bit = c
6238       // val = c
6239       if (size)
6240         outBitC (result);
6241       // if(bit & ...)
6242       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6243         genIfxJump (ifx, "c");
6244       goto release;
6245     }
6246
6247   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6248   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6249   if ((AOP_TYPE (right) == AOP_LIT) &&
6250       (AOP_TYPE (result) == AOP_CRY) &&
6251       (AOP_TYPE (left) != AOP_CRY))
6252     {
6253       int posbit = isLiteralBit (lit);
6254       /* left &  2^n */
6255       if (posbit)
6256         {
6257           posbit--;
6258           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6259           // bit = left & 2^n
6260           if (size)
6261             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6262           // if(left &  2^n)
6263           else
6264             {
6265               if (ifx)
6266                 {
6267                   SNPRINTF (buff, sizeof(buff), 
6268                             "acc.%d", posbit & 0x07);
6269                   genIfxJump (ifx, buff);
6270                 }
6271               else 
6272                   {
6273                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6274                   }
6275               goto release;
6276             }
6277         }
6278       else
6279         {
6280           symbol *tlbl = newiTempLabel (NULL);
6281           int sizel = AOP_SIZE (left);
6282           if (size)
6283             emitcode ("setb", "c");
6284           while (sizel--)
6285             {
6286               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6287                 {
6288                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6289                   // byte ==  2^n ?
6290                   if ((posbit = isLiteralBit (bytelit)) != 0)
6291                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6292                   else
6293                     {
6294                       if (bytelit != 0x0FFL)
6295                         emitcode ("anl", "a,%s",
6296                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6297                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6298                     }
6299                 }
6300               offset++;
6301             }
6302           // bit = left & literal
6303           if (size)
6304             {
6305               emitcode ("clr", "c");
6306               emitcode ("", "!tlabeldef", tlbl->key + 100);
6307             }
6308           // if(left & literal)
6309           else
6310             {
6311               if (ifx)
6312                 jmpTrueOrFalse (ifx, tlbl);
6313               goto release;
6314             }
6315         }
6316       outBitC (result);
6317       goto release;
6318     }
6319
6320   /* if left is same as result */
6321   if (sameRegs (AOP (result), AOP (left)))
6322     {
6323       for (; size--; offset++)
6324         {
6325           if (AOP_TYPE (right) == AOP_LIT)
6326             {
6327               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6328                 continue;
6329               else if (bytelit == 0)
6330                 aopPut (AOP (result), zero, offset);
6331               else if (IS_AOP_PREG (result))
6332                 {
6333                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6334                   emitcode ("anl", "a,%s",
6335                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6336                   aopPut (AOP (result), "a", offset);
6337                 }
6338               else
6339                 emitcode ("anl", "%s,%s",
6340                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6341                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6342             }
6343           else
6344             {
6345               if (AOP_TYPE (left) == AOP_ACC)
6346                 emitcode ("anl", "a,%s",
6347                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6348               else
6349                 {
6350                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6351                   if (IS_AOP_PREG (result))
6352                     {
6353                       emitcode ("anl", "a,%s",
6354                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6355                       aopPut (AOP (result), "a", offset);
6356                     }
6357                   else
6358                     emitcode ("anl", "%s,a",
6359                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6360                 }
6361             }
6362         }
6363     }
6364   else
6365     {
6366       // left & result in different registers
6367       if (AOP_TYPE (result) == AOP_CRY)
6368         {
6369           // result = bit
6370           // if(size), result in bit
6371           // if(!size && ifx), conditional oper: if(left & right)
6372           symbol *tlbl = newiTempLabel (NULL);
6373           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6374           if (size)
6375             emitcode ("setb", "c");
6376           while (sizer--)
6377             {
6378               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6379                 emitcode ("anl", "a,%s",
6380                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6381               } else {
6382                 if (AOP_TYPE(left)==AOP_ACC) {
6383                   emitcode("mov", "b,a");
6384                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6385                   emitcode("anl", "a,b");
6386                 }else {
6387                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6388                   emitcode ("anl", "a,%s",
6389                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6390                 }
6391               }
6392               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6393               offset++;
6394             }
6395           if (size)
6396             {
6397               CLRC;
6398               emitcode ("", "!tlabeldef", tlbl->key + 100);
6399               outBitC (result);
6400             }
6401           else if (ifx)
6402             jmpTrueOrFalse (ifx, tlbl);
6403         }
6404       else
6405         {
6406           for (; (size--); offset++)
6407             {
6408               // normal case
6409               // result = left & right
6410               if (AOP_TYPE (right) == AOP_LIT)
6411                 {
6412                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6413                     {
6414                       aopPut (AOP (result),
6415                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6416                               offset);
6417                       continue;
6418                     }
6419                   else if (bytelit == 0)
6420                     {
6421                       aopPut (AOP (result), zero, offset);
6422                       continue;
6423                     }
6424                   D (emitcode (";", "better literal AND."););
6425                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6426                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6427                                                     FALSE, FALSE, DP2_RESULT_REG));
6428
6429                 }
6430               else
6431                 {
6432                   // faster than result <- left, anl result,right
6433                   // and better if result is SFR
6434                   if (AOP_TYPE (left) == AOP_ACC)
6435                     {
6436                       emitcode ("anl", "a,%s", 
6437                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6438                     }
6439                   else
6440                     {
6441                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6442                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6443                       {
6444                           emitcode("mov", "b,a");
6445                           rOp = "b";
6446                       }
6447                         
6448                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6449                       emitcode ("anl", "a,%s", rOp);
6450                     }                   
6451                 }
6452               aopPut (AOP (result), "a", offset);
6453             }
6454         }
6455     }
6456
6457 release:
6458   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6459   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6460   freeAsmop (result, NULL, ic, TRUE);
6461 }
6462
6463
6464 /*-----------------------------------------------------------------*/
6465 /* genOr  - code for or                                            */
6466 /*-----------------------------------------------------------------*/
6467 static void
6468 genOr (iCode * ic, iCode * ifx)
6469 {
6470   operand *left, *right, *result;
6471   int size, offset = 0;
6472   unsigned long lit = 0L;
6473   bool     pushResult;
6474
6475   D (emitcode (";", "genOr "););
6476
6477   AOP_OP_3_NOFATAL (ic, pushResult);
6478   AOP_SET_LOCALS (ic);
6479
6480   if (pushResult)
6481   {
6482       genFarFarLogicOp(ic, "orl");
6483       return;
6484   }
6485
6486
6487 #ifdef DEBUG_TYPE
6488   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6489             AOP_TYPE (result),
6490             AOP_TYPE (left), AOP_TYPE (right));
6491   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6492             AOP_SIZE (result),
6493             AOP_SIZE (left), AOP_SIZE (right));
6494 #endif
6495
6496   /* if left is a literal & right is not then exchange them */
6497   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6498 #ifdef LOGIC_OPS_BROKEN
6499    || AOP_NEEDSACC (left) // I think this is a net loss now.
6500 #endif      
6501       )
6502     {
6503       operand *tmp = right;
6504       right = left;
6505       left = tmp;
6506     }
6507
6508   /* if result = right then exchange them */
6509   if (sameRegs (AOP (result), AOP (right)))
6510     {
6511       operand *tmp = right;
6512       right = left;
6513       left = tmp;
6514     }
6515
6516   /* if right is bit then exchange them */
6517   if (AOP_TYPE (right) == AOP_CRY &&
6518       AOP_TYPE (left) != AOP_CRY)
6519     {
6520       operand *tmp = right;
6521       right = left;
6522       left = tmp;
6523     }
6524   if (AOP_TYPE (right) == AOP_LIT)
6525     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6526
6527   size = AOP_SIZE (result);
6528
6529   // if(bit | yy)
6530   // xx = bit | yy;
6531   if (AOP_TYPE (left) == AOP_CRY)
6532     {
6533       if (AOP_TYPE (right) == AOP_LIT)
6534         {
6535           // c = bit & literal;
6536           if (lit)
6537             {
6538               // lit != 0 => result = 1
6539               if (AOP_TYPE (result) == AOP_CRY)
6540                 {
6541                   if (size)
6542                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6543                   else if (ifx)
6544                     continueIfTrue (ifx);
6545                   goto release;
6546                 }
6547               emitcode ("setb", "c");
6548             }
6549           else
6550             {
6551               // lit == 0 => result = left
6552               if (size && sameRegs (AOP (result), AOP (left)))
6553                 goto release;
6554               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6555             }
6556         }
6557       else
6558         {
6559           if (AOP_TYPE (right) == AOP_CRY)
6560             {
6561               // c = bit | bit;
6562               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6563               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6564             }
6565           else
6566             {
6567               // c = bit | val;
6568               symbol *tlbl = newiTempLabel (NULL);
6569               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6570                 emitcode ("setb", "c");
6571               emitcode ("jb", "%s,!tlabel",
6572                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6573               toBoolean (right);
6574               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6575               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6576                 {
6577                   jmpTrueOrFalse (ifx, tlbl);
6578                   goto release;
6579                 }
6580               else
6581                 {
6582                   CLRC;
6583                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6584                 }
6585             }
6586         }
6587       // bit = c
6588       // val = c
6589       if (size)
6590         outBitC (result);
6591       // if(bit | ...)
6592       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6593            genIfxJump (ifx, "c");
6594       goto release;
6595     }
6596
6597   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6598   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6599   if ((AOP_TYPE (right) == AOP_LIT) &&
6600       (AOP_TYPE (result) == AOP_CRY) &&
6601       (AOP_TYPE (left) != AOP_CRY))
6602     {
6603       if (lit)
6604         {
6605           // result = 1
6606           if (size)
6607             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6608           else
6609             continueIfTrue (ifx);
6610           goto release;
6611         }
6612       else
6613         {
6614           // lit = 0, result = boolean(left)
6615           if (size)
6616             emitcode ("setb", "c");
6617           toBoolean (right);
6618           if (size)
6619             {
6620               symbol *tlbl = newiTempLabel (NULL);
6621               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6622               CLRC;
6623               emitcode ("", "!tlabeldef", tlbl->key + 100);
6624             }
6625           else
6626             {
6627               genIfxJump (ifx, "a");
6628               goto release;
6629             }
6630         }
6631       outBitC (result);
6632       goto release;
6633     }
6634
6635   /* if left is same as result */
6636   if (sameRegs (AOP (result), AOP (left)))
6637     {
6638       for (; size--; offset++)
6639         {
6640           if (AOP_TYPE (right) == AOP_LIT)
6641             {
6642               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6643                 {
6644                   continue;
6645                 }
6646               else
6647                 {
6648                   if (IS_AOP_PREG (left))
6649                     {
6650                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6651                       emitcode ("orl", "a,%s",
6652                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6653                       aopPut (AOP (result), "a", offset);
6654                     }
6655                   else
6656                     {
6657                       emitcode ("orl", "%s,%s",
6658                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6659                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6660                     }
6661                 }
6662             }
6663           else
6664             {
6665               if (AOP_TYPE (left) == AOP_ACC)
6666                 {
6667                   emitcode ("orl", "a,%s",
6668                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6669                 }
6670               else
6671                 {
6672                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6673                   if (IS_AOP_PREG (left))
6674                     {
6675                       emitcode ("orl", "a,%s", 
6676                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6677                       aopPut (AOP (result), "a", offset);
6678                     }
6679                   else
6680                     {
6681                       emitcode ("orl", "%s,a",
6682                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6683                     }
6684                 }
6685             }
6686         }
6687     }
6688   else
6689     {
6690       // left & result in different registers
6691       if (AOP_TYPE (result) == AOP_CRY)
6692         {
6693           // result = bit
6694           // if(size), result in bit
6695           // if(!size && ifx), conditional oper: if(left | right)
6696           symbol *tlbl = newiTempLabel (NULL);
6697           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6698           if (size)
6699             emitcode ("setb", "c");
6700           while (sizer--)
6701             {
6702               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6703                 emitcode ("orl", "a,%s",
6704                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6705               } else {
6706                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6707                 emitcode ("orl", "a,%s",
6708                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6709               }
6710               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6711               offset++;
6712             }
6713           if (size)
6714             {
6715               CLRC;
6716               emitcode ("", "!tlabeldef", tlbl->key + 100);
6717               outBitC (result);
6718             }
6719           else if (ifx)
6720             jmpTrueOrFalse (ifx, tlbl);
6721         }
6722       else
6723         {
6724             _startLazyDPSEvaluation();
6725           for (; (size--); offset++)
6726             {
6727               // normal case
6728               // result = left & right
6729               if (AOP_TYPE (right) == AOP_LIT)
6730                 {
6731                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6732                     {
6733                       aopPut (AOP (result),
6734                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6735                               offset);
6736                       continue;
6737                     }
6738                   D (emitcode (";", "better literal OR."););
6739                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6740                   emitcode ("orl", "a, %s",
6741                             aopGet (AOP (right), offset,
6742                                     FALSE, FALSE, DP2_RESULT_REG));
6743
6744                 }
6745               else
6746                 {
6747                   // faster than result <- left, anl result,right
6748                   // and better if result is SFR
6749                   if (AOP_TYPE (left) == AOP_ACC)
6750                     {
6751                       emitcode ("orl", "a,%s",
6752                                 aopGet (AOP (right), offset,
6753                                         FALSE, FALSE, DP2_RESULT_REG));
6754                     }
6755                   else
6756                     {
6757                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6758                         
6759                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6760                       {
6761                           emitcode("mov", "b,a");
6762                           rOp = "b";
6763                       }
6764                         
6765                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6766                       emitcode ("orl", "a,%s", rOp);
6767                     }
6768                 }
6769               aopPut (AOP (result), "a", offset);
6770             }
6771             _endLazyDPSEvaluation();
6772         }
6773     }
6774
6775 release:
6776   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6777   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6778   freeAsmop (result, NULL, ic, TRUE);
6779 }
6780
6781 /*-----------------------------------------------------------------*/
6782 /* genXor - code for xclusive or                                   */
6783 /*-----------------------------------------------------------------*/
6784 static void
6785 genXor (iCode * ic, iCode * ifx)
6786 {
6787   operand *left, *right, *result;
6788   int size, offset = 0;
6789   unsigned long lit = 0L;
6790   bool pushResult;
6791
6792   D (emitcode (";", "genXor "););
6793
6794   AOP_OP_3_NOFATAL (ic, pushResult);
6795   AOP_SET_LOCALS (ic);
6796
6797   if (pushResult)
6798   {
6799       genFarFarLogicOp(ic, "xrl");
6800       return;
6801   }  
6802
6803 #ifdef DEBUG_TYPE
6804   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6805             AOP_TYPE (result),
6806             AOP_TYPE (left), AOP_TYPE (right));
6807   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6808             AOP_SIZE (result),
6809             AOP_SIZE (left), AOP_SIZE (right));
6810 #endif
6811
6812   /* if left is a literal & right is not ||
6813      if left needs acc & right does not */
6814   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6815 #ifdef LOGIC_OPS_BROKEN      
6816       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6817 #endif
6818      )
6819     {
6820       operand *tmp = right;
6821       right = left;
6822       left = tmp;
6823     }
6824
6825   /* if result = right then exchange them */
6826   if (sameRegs (AOP (result), AOP (right)))
6827     {
6828       operand *tmp = right;
6829       right = left;
6830       left = tmp;
6831     }
6832
6833   /* if right is bit then exchange them */
6834   if (AOP_TYPE (right) == AOP_CRY &&
6835       AOP_TYPE (left) != AOP_CRY)
6836     {
6837       operand *tmp = right;
6838       right = left;
6839       left = tmp;
6840     }
6841   if (AOP_TYPE (right) == AOP_LIT)
6842     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6843
6844   size = AOP_SIZE (result);
6845
6846   // if(bit ^ yy)
6847   // xx = bit ^ yy;
6848   if (AOP_TYPE (left) == AOP_CRY)
6849     {
6850       if (AOP_TYPE (right) == AOP_LIT)
6851         {
6852           // c = bit & literal;
6853           if (lit >> 1)
6854             {
6855               // lit>>1  != 0 => result = 1
6856               if (AOP_TYPE (result) == AOP_CRY)
6857                 {
6858                   if (size)
6859                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6860                   else if (ifx)
6861                     continueIfTrue (ifx);
6862                   goto release;
6863                 }
6864               emitcode ("setb", "c");
6865             }
6866           else
6867             {
6868               // lit == (0 or 1)
6869               if (lit == 0)
6870                 {
6871                   // lit == 0, result = left
6872                   if (size && sameRegs (AOP (result), AOP (left)))
6873                     goto release;
6874                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6875                 }
6876               else
6877                 {
6878                   // lit == 1, result = not(left)
6879                   if (size && sameRegs (AOP (result), AOP (left)))
6880                     {
6881                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6882                       goto release;
6883                     }
6884                   else
6885                     {
6886                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6887                       emitcode ("cpl", "c");
6888                     }
6889                 }
6890             }
6891
6892         }
6893       else
6894         {
6895           // right != literal
6896           symbol *tlbl = newiTempLabel (NULL);
6897           if (AOP_TYPE (right) == AOP_CRY)
6898             {
6899               // c = bit ^ bit;
6900               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6901             }
6902           else
6903             {
6904               int sizer = AOP_SIZE (right);
6905               // c = bit ^ val
6906               // if val>>1 != 0, result = 1
6907               emitcode ("setb", "c");
6908               while (sizer)
6909                 {
6910                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6911                   if (sizer == 1)
6912                     // test the msb of the lsb
6913                     emitcode ("anl", "a,#!constbyte",0xfe);
6914                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6915                   sizer--;
6916                 }
6917               // val = (0,1)
6918               emitcode ("rrc", "a");
6919             }
6920           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6921           emitcode ("cpl", "c");
6922           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6923         }
6924       // bit = c
6925       // val = c
6926       if (size)
6927         outBitC (result);
6928       // if(bit | ...)
6929       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6930         genIfxJump (ifx, "c");
6931       goto release;
6932     }
6933
6934   if (sameRegs (AOP (result), AOP (left)))
6935     {
6936       /* if left is same as result */
6937       for (; size--; offset++)
6938         {
6939           if (AOP_TYPE (right) == AOP_LIT)
6940             {
6941               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6942                 continue;
6943               else if (IS_AOP_PREG (left))
6944                 {
6945                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6946                   emitcode ("xrl", "a,%s",
6947                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6948                   aopPut (AOP (result), "a", offset);
6949                 }
6950               else
6951                 emitcode ("xrl", "%s,%s",
6952                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6953                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6954             }
6955           else
6956             {
6957               if (AOP_TYPE (left) == AOP_ACC)
6958                 emitcode ("xrl", "a,%s",
6959                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6960               else
6961                 {
6962                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6963                   if (IS_AOP_PREG (left))
6964                     {
6965                       emitcode ("xrl", "a,%s",
6966                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6967                       aopPut (AOP (result), "a", offset);
6968                     }
6969                   else
6970                     emitcode ("xrl", "%s,a",
6971                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6972                 }
6973             }
6974         }
6975     }
6976   else
6977     {
6978       // left & result in different registers
6979       if (AOP_TYPE (result) == AOP_CRY)
6980         {
6981           // result = bit
6982           // if(size), result in bit
6983           // if(!size && ifx), conditional oper: if(left ^ right)
6984           symbol *tlbl = newiTempLabel (NULL);
6985           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6986                   
6987           if (size)
6988             emitcode ("setb", "c");
6989           while (sizer--)
6990             {
6991               if ((AOP_TYPE (right) == AOP_LIT) &&
6992                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6993                 {
6994                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6995                 }
6996               else
6997                 {
6998                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6999                     emitcode ("xrl", "a,%s",
7000                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7001                   } else {
7002                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7003                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7004                       {
7005                           emitcode("mov", "b,a");
7006                           rOp = "b";
7007                       }
7008                         
7009                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7010                       emitcode ("xrl", "a,%s", rOp);                  
7011                   }
7012                 }
7013               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7014               offset++;
7015             }
7016           if (size)
7017             {
7018               CLRC;
7019               emitcode ("", "!tlabeldef", tlbl->key + 100);
7020               outBitC (result);
7021             }
7022           else if (ifx)
7023             jmpTrueOrFalse (ifx, tlbl);
7024         }
7025       else
7026         {
7027         for (; (size--); offset++)
7028           {
7029             // normal case
7030             // result = left & right
7031             if (AOP_TYPE (right) == AOP_LIT)
7032               {
7033                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7034                   {
7035                     aopPut (AOP (result),
7036                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7037                             offset);
7038                     continue;
7039                   }
7040                 D (emitcode (";", "better literal XOR."););
7041                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7042                 emitcode ("xrl", "a, %s",
7043                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7044               }
7045             else
7046               {
7047                 // faster than result <- left, anl result,right
7048                 // and better if result is SFR
7049                 if (AOP_TYPE (left) == AOP_ACC)
7050                   {
7051                     emitcode ("xrl", "a,%s",
7052                               aopGet (AOP (right), offset,
7053                                       FALSE, FALSE, DP2_RESULT_REG));
7054                   }
7055                 else
7056                   {
7057                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7058                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7059                       {
7060                           emitcode("mov", "b,a");
7061                           rOp = "b";
7062                       }
7063                         
7064                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7065                       emitcode ("xrl", "a,%s", rOp);
7066                   }
7067               }
7068             aopPut (AOP (result), "a", offset);
7069           }
7070         }
7071         
7072     }
7073
7074 release:
7075   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7076   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7077   freeAsmop (result, NULL, ic, TRUE);
7078 }
7079
7080 /*-----------------------------------------------------------------*/
7081 /* genInline - write the inline code out                           */
7082 /*-----------------------------------------------------------------*/
7083 static void
7084 genInline (iCode * ic)
7085 {
7086   char *buffer, *bp, *bp1;
7087
7088   D (emitcode (";", "genInline "); );
7089
7090   _G.inLine += (!options.asmpeep);
7091
7092   buffer = Safe_strdup(IC_INLINE(ic));
7093   bp = buffer;
7094   bp1 = buffer;
7095
7096   /* emit each line as a code */
7097   while (*bp)
7098     {
7099       if (*bp == '\n')
7100         {
7101           *bp++ = '\0';
7102           emitcode (bp1, "");
7103           bp1 = bp;
7104         }
7105       else
7106         {
7107           if (*bp == ':')
7108             {
7109               bp++;
7110               *bp = '\0';
7111               bp++;
7112               emitcode (bp1, "");
7113               bp1 = bp;
7114             }
7115           else
7116             bp++;
7117         }
7118     }
7119   if (bp1 != bp)
7120     emitcode (bp1, "");
7121   /*     emitcode("",buffer); */
7122   _G.inLine -= (!options.asmpeep);
7123 }
7124
7125 /*-----------------------------------------------------------------*/
7126 /* genRRC - rotate right with carry                                */
7127 /*-----------------------------------------------------------------*/
7128 static void
7129 genRRC (iCode * ic)
7130 {
7131   operand *left, *result;
7132   int     size, offset;
7133
7134   D (emitcode (";", "genRRC "););
7135
7136   /* rotate right with carry */
7137   left = IC_LEFT (ic);
7138   result = IC_RESULT (ic);
7139   aopOp (left, ic, FALSE, FALSE);
7140   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7141
7142   /* move it to the result */
7143   size = AOP_SIZE (result);
7144   offset = size - 1;
7145   CLRC;
7146
7147   _startLazyDPSEvaluation ();
7148   while (size--)
7149     {
7150       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7151       emitcode ("rrc", "a");
7152       if (AOP_SIZE (result) > 1)
7153         aopPut (AOP (result), "a", offset--);
7154     }
7155   _endLazyDPSEvaluation ();
7156
7157   /* now we need to put the carry into the
7158      highest order byte of the result */
7159   if (AOP_SIZE (result) > 1)
7160     {
7161       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7162     }
7163   emitcode ("mov", "acc.7,c");
7164   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7165   freeAsmop (left, NULL, ic, TRUE);
7166   freeAsmop (result, NULL, ic, TRUE);
7167 }
7168
7169 /*-----------------------------------------------------------------*/
7170 /* genRLC - generate code for rotate left with carry               */
7171 /*-----------------------------------------------------------------*/
7172 static void
7173 genRLC (iCode * ic)
7174 {
7175   operand *left, *result;
7176   int size, offset;
7177   char *l;
7178
7179   D (emitcode (";", "genRLC "););
7180
7181   /* rotate right with carry */
7182   left = IC_LEFT (ic);
7183   result = IC_RESULT (ic);
7184   aopOp (left, ic, FALSE, FALSE);
7185   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7186
7187   /* move it to the result */
7188   size = AOP_SIZE (result);
7189   offset = 0;
7190   if (size--)
7191     {
7192       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7193       MOVA (l);
7194       emitcode ("add", "a,acc");
7195       if (AOP_SIZE (result) > 1)
7196         {
7197           aopPut (AOP (result), "a", offset++);
7198         }
7199
7200       _startLazyDPSEvaluation ();
7201       while (size--)
7202         {
7203           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7204           MOVA (l);
7205           emitcode ("rlc", "a");
7206           if (AOP_SIZE (result) > 1)
7207             aopPut (AOP (result), "a", offset++);
7208         }
7209       _endLazyDPSEvaluation ();
7210     }
7211   /* now we need to put the carry into the
7212      highest order byte of the result */
7213   if (AOP_SIZE (result) > 1)
7214     {
7215       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7216       MOVA (l);
7217     }
7218   emitcode ("mov", "acc.0,c");
7219   aopPut (AOP (result), "a", 0);
7220   freeAsmop (left, NULL, ic, TRUE);
7221   freeAsmop (result, NULL, ic, TRUE);
7222 }
7223
7224 /*-----------------------------------------------------------------*/
7225 /* genGetHbit - generates code get highest order bit               */
7226 /*-----------------------------------------------------------------*/
7227 static void
7228 genGetHbit (iCode * ic)
7229 {
7230   operand *left, *result;
7231   left = IC_LEFT (ic);
7232   result = IC_RESULT (ic);
7233   aopOp (left, ic, FALSE, FALSE);
7234   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7235
7236   D (emitcode (";", "genGetHbit "););
7237
7238   /* get the highest order byte into a */
7239   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7240   if (AOP_TYPE (result) == AOP_CRY)
7241     {
7242       emitcode ("rlc", "a");
7243       outBitC (result);
7244     }
7245   else
7246     {
7247       emitcode ("rl", "a");
7248       emitcode ("anl", "a,#1");
7249       outAcc (result);
7250     }
7251
7252
7253   freeAsmop (left, NULL, ic, TRUE);
7254   freeAsmop (result, NULL, ic, TRUE);
7255 }
7256
7257 /*-----------------------------------------------------------------*/
7258 /* AccRol - rotate left accumulator by known count                 */
7259 /*-----------------------------------------------------------------*/
7260 static void
7261 AccRol (int shCount)
7262 {
7263   shCount &= 0x0007;            // shCount : 0..7
7264
7265   switch (shCount)
7266     {
7267     case 0:
7268       break;
7269     case 1:
7270       emitcode ("rl", "a");
7271       break;
7272     case 2:
7273       emitcode ("rl", "a");
7274       emitcode ("rl", "a");
7275       break;
7276     case 3:
7277       emitcode ("swap", "a");
7278       emitcode ("rr", "a");
7279       break;
7280     case 4:
7281       emitcode ("swap", "a");
7282       break;
7283     case 5:
7284       emitcode ("swap", "a");
7285       emitcode ("rl", "a");
7286       break;
7287     case 6:
7288       emitcode ("rr", "a");
7289       emitcode ("rr", "a");
7290       break;
7291     case 7:
7292       emitcode ("rr", "a");
7293       break;
7294     }
7295 }
7296
7297 /*-----------------------------------------------------------------*/
7298 /* AccLsh - left shift accumulator by known count                  */
7299 /*-----------------------------------------------------------------*/
7300 static void
7301 AccLsh (int shCount)
7302 {
7303   if (shCount != 0)
7304     {
7305       if (shCount == 1)
7306         emitcode ("add", "a,acc");
7307       else if (shCount == 2)
7308         {
7309           emitcode ("add", "a,acc");
7310           emitcode ("add", "a,acc");
7311         }
7312       else
7313         {
7314           /* rotate left accumulator */
7315           AccRol (shCount);
7316           /* and kill the lower order bits */
7317           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7318         }
7319     }
7320 }
7321
7322 /*-----------------------------------------------------------------*/
7323 /* AccRsh - right shift accumulator by known count                 */
7324 /*-----------------------------------------------------------------*/
7325 static void
7326 AccRsh (int shCount)
7327 {
7328   if (shCount != 0)
7329     {
7330       if (shCount == 1)
7331         {
7332           CLRC;
7333           emitcode ("rrc", "a");
7334         }
7335       else
7336         {
7337           /* rotate right accumulator */
7338           AccRol (8 - shCount);
7339           /* and kill the higher order bits */
7340           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7341         }
7342     }
7343 }
7344
7345 #ifdef BETTER_LITERAL_SHIFT
7346 /*-----------------------------------------------------------------*/
7347 /* AccSRsh - signed right shift accumulator by known count                 */
7348 /*-----------------------------------------------------------------*/
7349 static void
7350 AccSRsh (int shCount)
7351 {
7352   symbol *tlbl;
7353   if (shCount != 0)
7354     {
7355       if (shCount == 1)
7356         {
7357           emitcode ("mov", "c,acc.7");
7358           emitcode ("rrc", "a");
7359         }
7360       else if (shCount == 2)
7361         {
7362           emitcode ("mov", "c,acc.7");
7363           emitcode ("rrc", "a");
7364           emitcode ("mov", "c,acc.7");
7365           emitcode ("rrc", "a");
7366         }
7367       else
7368         {
7369           tlbl = newiTempLabel (NULL);
7370           /* rotate right accumulator */
7371           AccRol (8 - shCount);
7372           /* and kill the higher order bits */
7373           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7374           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7375           emitcode ("orl", "a,#!constbyte",
7376                     (unsigned char) ~SRMask[shCount]);
7377           emitcode ("", "!tlabeldef", tlbl->key + 100);
7378         }
7379     }
7380 }
7381 #endif
7382
7383 #ifdef BETTER_LITERAL_SHIFT
7384 /*-----------------------------------------------------------------*/
7385 /* shiftR1Left2Result - shift right one byte from left to result   */
7386 /*-----------------------------------------------------------------*/
7387 static void
7388 shiftR1Left2Result (operand * left, int offl,
7389                     operand * result, int offr,
7390                     int shCount, int sign)
7391 {
7392   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7393   /* shift right accumulator */
7394   if (sign)
7395     AccSRsh (shCount);
7396   else
7397     AccRsh (shCount);
7398   aopPut (AOP (result), "a", offr);
7399 }
7400 #endif
7401
7402 #ifdef BETTER_LITERAL_SHIFT
7403 /*-----------------------------------------------------------------*/
7404 /* shiftL1Left2Result - shift left one byte from left to result    */
7405 /*-----------------------------------------------------------------*/
7406 static void
7407 shiftL1Left2Result (operand * left, int offl,
7408                     operand * result, int offr, int shCount)
7409 {
7410   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7411   /* shift left accumulator */
7412   AccLsh (shCount);
7413   aopPut (AOP (result), "a", offr);
7414 }
7415 #endif
7416
7417 #ifdef BETTER_LITERAL_SHIFT
7418 /*-----------------------------------------------------------------*/
7419 /* movLeft2Result - move byte from left to result                  */
7420 /*-----------------------------------------------------------------*/
7421 static void
7422 movLeft2Result (operand * left, int offl,
7423                 operand * result, int offr, int sign)
7424 {
7425   char *l;
7426   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7427   {
7428       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7429
7430       if (*l == '@' && (IS_AOP_PREG (result)))
7431       {
7432           emitcode ("mov", "a,%s", l);
7433           aopPut (AOP (result), "a", offr);
7434       }
7435       else
7436       {
7437           if (!sign)
7438           {
7439             aopPut (AOP (result), l, offr);
7440           }
7441           else
7442             {
7443               /* MSB sign in acc.7 ! */
7444               if (getDataSize (left) == offl + 1)
7445                 {
7446                   emitcode ("mov", "a,%s", l);
7447                   aopPut (AOP (result), "a", offr);
7448                 }
7449             }
7450       }
7451   }
7452 }
7453 #endif
7454
7455 #ifdef BETTER_LITERAL_SHIFT
7456 /*-----------------------------------------------------------------*/
7457 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7458 /*-----------------------------------------------------------------*/
7459 static void
7460 AccAXRrl1 (char *x)
7461 {
7462   emitcode ("rrc", "a");
7463   emitcode ("xch", "a,%s", x);
7464   emitcode ("rrc", "a");
7465   emitcode ("xch", "a,%s", x);
7466 }
7467 #endif
7468
7469 #ifdef BETTER_LITERAL_SHIFT
7470 //REMOVE ME!!!
7471 /*-----------------------------------------------------------------*/
7472 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7473 /*-----------------------------------------------------------------*/
7474 static void
7475 AccAXLrl1 (char *x)
7476 {
7477   emitcode ("xch", "a,%s", x);
7478   emitcode ("rlc", "a");
7479   emitcode ("xch", "a,%s", x);
7480   emitcode ("rlc", "a");
7481 }
7482 #endif
7483
7484 #ifdef BETTER_LITERAL_SHIFT
7485 /*-----------------------------------------------------------------*/
7486 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7487 /*-----------------------------------------------------------------*/
7488 static void
7489 AccAXLsh1 (char *x)
7490 {
7491   emitcode ("xch", "a,%s", x);
7492   emitcode ("add", "a,acc");
7493   emitcode ("xch", "a,%s", x);
7494   emitcode ("rlc", "a");
7495 }
7496 #endif
7497
7498 #ifdef BETTER_LITERAL_SHIFT
7499 /*-----------------------------------------------------------------*/
7500 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7501 /*-----------------------------------------------------------------*/
7502 static void
7503 AccAXLsh (char *x, int shCount)
7504 {
7505   switch (shCount)
7506     {
7507     case 0:
7508       break;
7509     case 1:
7510       AccAXLsh1 (x);
7511       break;
7512     case 2:
7513       AccAXLsh1 (x);
7514       AccAXLsh1 (x);
7515       break;
7516     case 3:
7517     case 4:
7518     case 5:                     // AAAAABBB:CCCCCDDD
7519
7520       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7521
7522       emitcode ("anl", "a,#!constbyte",
7523                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7524
7525       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7526
7527       AccRol (shCount);         // DDDCCCCC:BBB00000
7528
7529       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7530
7531       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7532
7533       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7534
7535       emitcode ("anl", "a,#!constbyte",
7536                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7537
7538       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7539
7540       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7541
7542       break;
7543     case 6:                     // AAAAAABB:CCCCCCDD
7544       emitcode ("anl", "a,#!constbyte",
7545                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7546       emitcode ("mov", "c,acc.0");      // c = B
7547       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7548 #if 0
7549       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7550       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7551 #else
7552       emitcode("rrc","a"); 
7553       emitcode("xch","a,%s", x); 
7554       emitcode("rrc","a"); 
7555       emitcode("mov","c,acc.0"); //<< get correct bit 
7556       emitcode("xch","a,%s", x); 
7557
7558       emitcode("rrc","a"); 
7559       emitcode("xch","a,%s", x); 
7560       emitcode("rrc","a"); 
7561       emitcode("xch","a,%s", x); 
7562 #endif
7563       break;
7564     case 7:                     // a:x <<= 7
7565
7566       emitcode ("anl", "a,#!constbyte",
7567                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7568
7569       emitcode ("mov", "c,acc.0");      // c = B
7570
7571       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7572
7573       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7574
7575       break;
7576     default:
7577       break;
7578     }
7579 }
7580 #endif
7581
7582 #ifdef BETTER_LITERAL_SHIFT
7583 //REMOVE ME!!!
7584 /*-----------------------------------------------------------------*/
7585 /* AccAXRsh - right shift a:x known count (0..7)                   */
7586 /*-----------------------------------------------------------------*/
7587 static void
7588 AccAXRsh (char *x, int shCount)
7589 {
7590   switch (shCount)
7591     {
7592     case 0:
7593       break;
7594     case 1:
7595       CLRC;
7596       AccAXRrl1 (x);            // 0->a:x
7597
7598       break;
7599     case 2:
7600       CLRC;
7601       AccAXRrl1 (x);            // 0->a:x
7602
7603       CLRC;
7604       AccAXRrl1 (x);            // 0->a:x
7605
7606       break;
7607     case 3:
7608     case 4:
7609     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7610
7611       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7612
7613       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7614
7615       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7616
7617       emitcode ("anl", "a,#!constbyte",
7618                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7619
7620       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7621
7622       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7623
7624       emitcode ("anl", "a,#!constbyte",
7625                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7626
7627       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7628
7629       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7630
7631       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7632
7633       break;
7634     case 6:                     // AABBBBBB:CCDDDDDD
7635
7636       emitcode ("mov", "c,acc.7");
7637       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7638
7639       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7640
7641       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7642
7643       emitcode ("anl", "a,#!constbyte",
7644                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7645
7646       break;
7647     case 7:                     // ABBBBBBB:CDDDDDDD
7648
7649       emitcode ("mov", "c,acc.7");      // c = A
7650
7651       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7652
7653       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7654
7655       emitcode ("anl", "a,#!constbyte",
7656                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7657
7658       break;
7659     default:
7660       break;
7661     }
7662 }
7663 #endif
7664
7665 #ifdef BETTER_LITERAL_SHIFT
7666 /*-----------------------------------------------------------------*/
7667 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7668 /*-----------------------------------------------------------------*/
7669 static void
7670 AccAXRshS (char *x, int shCount)
7671 {
7672   symbol *tlbl;
7673   switch (shCount)
7674     {
7675     case 0:
7676       break;
7677     case 1:
7678       emitcode ("mov", "c,acc.7");
7679       AccAXRrl1 (x);            // s->a:x
7680
7681       break;
7682     case 2:
7683       emitcode ("mov", "c,acc.7");
7684       AccAXRrl1 (x);            // s->a:x
7685
7686       emitcode ("mov", "c,acc.7");
7687       AccAXRrl1 (x);            // s->a:x
7688
7689       break;
7690     case 3:
7691     case 4:
7692     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7693
7694       tlbl = newiTempLabel (NULL);
7695       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7696
7697       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7698
7699       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7700
7701       emitcode ("anl", "a,#!constbyte",
7702                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7703
7704       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7705
7706       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7707
7708       emitcode ("anl", "a,#!constbyte",
7709                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7710
7711       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7712
7713       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7714
7715       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7716
7717       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7718       emitcode ("orl", "a,#!constbyte",
7719                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7720
7721       emitcode ("", "!tlabeldef", tlbl->key + 100);
7722       break;                    // SSSSAAAA:BBBCCCCC
7723
7724     case 6:                     // AABBBBBB:CCDDDDDD
7725
7726       tlbl = newiTempLabel (NULL);
7727       emitcode ("mov", "c,acc.7");
7728       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7729
7730       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7731
7732       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7733
7734       emitcode ("anl", "a,#!constbyte",
7735                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7736
7737       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7738       emitcode ("orl", "a,#!constbyte",
7739                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7740
7741       emitcode ("", "!tlabeldef", tlbl->key + 100);
7742       break;
7743     case 7:                     // ABBBBBBB:CDDDDDDD
7744
7745       tlbl = newiTempLabel (NULL);
7746       emitcode ("mov", "c,acc.7");      // c = A
7747
7748       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7749
7750       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7751
7752       emitcode ("anl", "a,#!constbyte",
7753                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7754
7755       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7756       emitcode ("orl", "a,#!constbyte",
7757                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7758
7759       emitcode ("", "!tlabeldef", tlbl->key + 100);
7760       break;
7761     default:
7762       break;
7763     }
7764 }
7765 #endif
7766
7767 #ifdef BETTER_LITERAL_SHIFT
7768 static void
7769 _loadLeftIntoAx(char    **lsb, 
7770                 operand *left, 
7771                 operand *result,
7772                 int     offl,
7773                 int     offr)
7774 {
7775   // Get the initial value from left into a pair of registers.
7776   // MSB must be in A, LSB can be any register.
7777   //
7778   // If the result is held in registers, it is an optimization
7779   // if the LSB can be held in the register which will hold the,
7780   // result LSB since this saves us from having to copy it into
7781   // the result following AccAXLsh.
7782   //
7783   // If the result is addressed indirectly, this is not a gain.
7784   if (AOP_NEEDSACC(result))
7785   {
7786        char *leftByte;
7787        
7788        _startLazyDPSEvaluation();
7789       if (AOP_TYPE(left) == AOP_DPTR2)
7790        {
7791            // Get MSB in A.
7792            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7793            // get LSB in DP2_RESULT_REG.
7794            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7795            assert(!strcmp(leftByte, DP2_RESULT_REG));
7796        }
7797        else
7798        {
7799            // get LSB into DP2_RESULT_REG
7800            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7801            if (strcmp(leftByte, DP2_RESULT_REG))
7802            {
7803                TR_AP("#7");
7804                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7805            }
7806            // And MSB in A.
7807            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7808            assert(strcmp(leftByte, DP2_RESULT_REG));
7809            MOVA(leftByte);
7810        }
7811        _endLazyDPSEvaluation();
7812        *lsb = DP2_RESULT_REG;
7813   }
7814   else
7815   {
7816       if (sameRegs (AOP (result), AOP (left)) &&
7817         ((offl + MSB16) == offr))
7818       {
7819           /* don't crash result[offr] */
7820           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7821           emitcode ("xch", "a,%s", 
7822                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7823       }
7824       else
7825       {
7826           movLeft2Result (left, offl, result, offr, 0);
7827           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7828       }
7829       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7830       assert(strcmp(*lsb,"a"));      
7831   }
7832 }
7833
7834 static void
7835 _storeAxResults(char    *lsb,
7836                 operand *result,
7837                 int     offr)
7838 {
7839   _startLazyDPSEvaluation();
7840   if (AOP_NEEDSACC(result))
7841   {
7842       /* We have to explicitly update the result LSB.
7843        */
7844       emitcode("xch","a,%s", lsb);
7845       aopPut(AOP(result), "a", offr);
7846       emitcode("mov","a,%s", lsb);
7847   }
7848   if (getDataSize (result) > 1)
7849   {
7850       aopPut (AOP (result), "a", offr + MSB16);
7851   }
7852   _endLazyDPSEvaluation();
7853 }
7854
7855 /*-----------------------------------------------------------------*/
7856 /* shiftL2Left2Result - shift left two bytes from left to result   */
7857 /*-----------------------------------------------------------------*/
7858 static void
7859 shiftL2Left2Result (operand * left, int offl,
7860                     operand * result, int offr, int shCount)
7861 {
7862   char *lsb;
7863
7864   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7865   
7866   AccAXLsh (lsb, shCount);
7867   
7868   _storeAxResults(lsb, result, offr);
7869 }
7870 #endif
7871
7872 #ifdef BETTER_LITERAL_SHIFT
7873 /*-----------------------------------------------------------------*/
7874 /* shiftR2Left2Result - shift right two bytes from left to result  */
7875 /*-----------------------------------------------------------------*/
7876 static void
7877 shiftR2Left2Result (operand * left, int offl,
7878                     operand * result, int offr,
7879                     int shCount, int sign)
7880 {
7881   char *lsb;
7882   
7883   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7884   
7885   /* a:x >> shCount (x = lsb(result)) */
7886   if (sign)
7887   {
7888      AccAXRshS(lsb, shCount);
7889   }
7890   else
7891   {
7892     AccAXRsh(lsb, shCount);
7893   }
7894   
7895   _storeAxResults(lsb, result, offr);
7896 }
7897 #endif
7898
7899 #if 0
7900 //REMOVE ME!!!
7901 /*-----------------------------------------------------------------*/
7902 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7903 /*-----------------------------------------------------------------*/
7904 static void
7905 shiftLLeftOrResult (operand * left, int offl,
7906                     operand * result, int offr, int shCount)
7907 {
7908   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7909   /* shift left accumulator */
7910   AccLsh (shCount);
7911   /* or with result */
7912   emitcode ("orl", "a,%s",
7913             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7914   /* back to result */
7915   aopPut (AOP (result), "a", offr);
7916 }
7917 #endif
7918
7919 #if 0
7920 //REMOVE ME!!!
7921 /*-----------------------------------------------------------------*/
7922 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7923 /*-----------------------------------------------------------------*/
7924 static void
7925 shiftRLeftOrResult (operand * left, int offl,
7926                     operand * result, int offr, int shCount)
7927 {
7928   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7929   /* shift right accumulator */
7930   AccRsh (shCount);
7931   /* or with result */
7932   emitcode ("orl", "a,%s",
7933             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7934   /* back to result */
7935   aopPut (AOP (result), "a", offr);
7936 }
7937 #endif
7938
7939 #ifdef BETTER_LITERAL_SHIFT
7940 /*-----------------------------------------------------------------*/
7941 /* genlshOne - left shift a one byte quantity by known count       */
7942 /*-----------------------------------------------------------------*/
7943 static void
7944 genlshOne (operand * result, operand * left, int shCount)
7945 {
7946   D (emitcode (";", "genlshOne "););
7947   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7948 }
7949 #endif
7950
7951 #ifdef BETTER_LITERAL_SHIFT
7952 /*-----------------------------------------------------------------*/
7953 /* genlshTwo - left shift two bytes by known amount != 0           */
7954 /*-----------------------------------------------------------------*/
7955 static void
7956 genlshTwo (operand * result, operand * left, int shCount)
7957 {
7958   int size;
7959
7960   D (emitcode (";", "genlshTwo "););
7961
7962   size = getDataSize (result);
7963
7964   /* if shCount >= 8 */
7965   if (shCount >= 8)
7966   {
7967       shCount -= 8;
7968
7969       _startLazyDPSEvaluation();
7970
7971       if (size > 1)
7972         {
7973           if (shCount)
7974           {
7975             _endLazyDPSEvaluation();
7976             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7977             aopPut (AOP (result), zero, LSB);       
7978           }
7979           else
7980           {
7981             movLeft2Result (left, LSB, result, MSB16, 0);
7982             aopPut (AOP (result), zero, LSB);
7983             _endLazyDPSEvaluation();
7984           }
7985         }
7986         else
7987         {
7988           aopPut (AOP (result), zero, LSB);
7989           _endLazyDPSEvaluation();
7990         }
7991   }
7992
7993   /*  1 <= shCount <= 7 */
7994   else
7995     {
7996       if (size == 1)
7997       {
7998         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7999       }
8000       else
8001       {
8002         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8003       }
8004     }
8005 }
8006 #endif
8007
8008 #if 0
8009 //REMOVE ME!!!
8010 /*-----------------------------------------------------------------*/
8011 /* shiftLLong - shift left one long from left to result            */
8012 /* offl = LSB or MSB16                                             */
8013 /*-----------------------------------------------------------------*/
8014 static void
8015 shiftLLong (operand * left, operand * result, int offr)
8016 {
8017   char *l;
8018   int size = AOP_SIZE (result);
8019
8020   if (size >= LSB + offr)
8021     {
8022       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8023       MOVA (l);
8024       emitcode ("add", "a,acc");
8025       if (sameRegs (AOP (left), AOP (result)) &&
8026           size >= MSB16 + offr && offr != LSB)
8027         emitcode ("xch", "a,%s",
8028                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8029       else
8030         aopPut (AOP (result), "a", LSB + offr);
8031     }
8032
8033   if (size >= MSB16 + offr)
8034     {
8035       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8036         {
8037           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8038         }
8039       emitcode ("rlc", "a");
8040       if (sameRegs (AOP (left), AOP (result)) &&
8041           size >= MSB24 + offr && offr != LSB)
8042         emitcode ("xch", "a,%s",
8043                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8044       else
8045         aopPut (AOP (result), "a", MSB16 + offr);
8046     }
8047
8048   if (size >= MSB24 + offr)
8049     {
8050       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8051         {
8052           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8053         }
8054       emitcode ("rlc", "a");
8055       if (sameRegs (AOP (left), AOP (result)) &&
8056           size >= MSB32 + offr && offr != LSB)
8057         emitcode ("xch", "a,%s",
8058                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8059       else
8060         aopPut (AOP (result), "a", MSB24 + offr);
8061     }
8062
8063   if (size > MSB32 + offr)
8064     {
8065       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8066         {
8067           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8068         }
8069       emitcode ("rlc", "a");
8070       aopPut (AOP (result), "a", MSB32 + offr);
8071     }
8072   if (offr != LSB)
8073     aopPut (AOP (result), zero, LSB);
8074 }
8075 #endif
8076
8077 #if 0
8078 //REMOVE ME!!!
8079 /*-----------------------------------------------------------------*/
8080 /* genlshFour - shift four byte by a known amount != 0             */
8081 /*-----------------------------------------------------------------*/
8082 static void
8083 genlshFour (operand * result, operand * left, int shCount)
8084 {
8085   int size;
8086
8087   D (emitcode (";", "genlshFour ");
8088     );
8089
8090   size = AOP_SIZE (result);
8091
8092   /* if shifting more that 3 bytes */
8093   if (shCount >= 24)
8094     {
8095       shCount -= 24;
8096       if (shCount)
8097         /* lowest order of left goes to the highest
8098            order of the destination */
8099         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8100       else
8101         movLeft2Result (left, LSB, result, MSB32, 0);
8102       aopPut (AOP (result), zero, LSB);
8103       aopPut (AOP (result), zero, MSB16);
8104       aopPut (AOP (result), zero, MSB24);
8105       return;
8106     }
8107
8108   /* more than two bytes */
8109   else if (shCount >= 16)
8110     {
8111       /* lower order two bytes goes to higher order two bytes */
8112       shCount -= 16;
8113       /* if some more remaining */
8114       if (shCount)
8115         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8116       else
8117         {
8118           movLeft2Result (left, MSB16, result, MSB32, 0);
8119           movLeft2Result (left, LSB, result, MSB24, 0);
8120         }
8121       aopPut (AOP (result), zero, MSB16);
8122       aopPut (AOP (result), zero, LSB);
8123       return;
8124     }
8125
8126   /* if more than 1 byte */
8127   else if (shCount >= 8)
8128     {
8129       /* lower order three bytes goes to higher order  three bytes */
8130       shCount -= 8;
8131       if (size == 2)
8132         {
8133           if (shCount)
8134             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8135           else
8136             movLeft2Result (left, LSB, result, MSB16, 0);
8137         }
8138       else
8139         {                       /* size = 4 */
8140           if (shCount == 0)
8141             {
8142               movLeft2Result (left, MSB24, result, MSB32, 0);
8143               movLeft2Result (left, MSB16, result, MSB24, 0);
8144               movLeft2Result (left, LSB, result, MSB16, 0);
8145               aopPut (AOP (result), zero, LSB);
8146             }
8147           else if (shCount == 1)
8148             shiftLLong (left, result, MSB16);
8149           else
8150             {
8151               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8152               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8153               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8154               aopPut (AOP (result), zero, LSB);
8155             }
8156         }
8157     }
8158
8159   /* 1 <= shCount <= 7 */
8160   else if (shCount <= 2)
8161     {
8162       shiftLLong (left, result, LSB);
8163       if (shCount == 2)
8164         shiftLLong (result, result, LSB);
8165     }
8166   /* 3 <= shCount <= 7, optimize */
8167   else
8168     {
8169       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8170       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8171       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8172     }
8173 }
8174 #endif
8175
8176 #ifdef BETTER_LITERAL_SHIFT
8177 /*-----------------------------------------------------------------*/
8178 /* genLeftShiftLiteral - left shifting by known count              */
8179 /*-----------------------------------------------------------------*/
8180 static bool
8181 genLeftShiftLiteral (operand * left,
8182                      operand * right,
8183                      operand * result,
8184                      iCode * ic)
8185 {
8186   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8187   int size;
8188
8189   size = getSize (operandType (result));
8190
8191   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8192
8193   /* We only handle certain easy cases so far. */
8194   if ((shCount != 0)
8195    && (shCount < (size * 8))
8196    && (size != 1)
8197    && (size != 2))
8198   {
8199       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8200       return FALSE;
8201   }
8202
8203   freeAsmop (right, NULL, ic, TRUE);
8204
8205   aopOp(left, ic, FALSE, FALSE);
8206   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8207
8208 #if 0 // debug spew
8209   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8210   {
8211         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8212         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8213         {
8214            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8215         }
8216   }
8217   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8218   {
8219         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8220         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8221         {
8222            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8223         }       
8224   }  
8225 #endif
8226   
8227 #if VIEW_SIZE
8228   emitcode ("; shift left ", "result %d, left %d", size,
8229             AOP_SIZE (left));
8230 #endif
8231
8232   /* I suppose that the left size >= result size */
8233   if (shCount == 0)
8234   {
8235         _startLazyDPSEvaluation();
8236         while (size--)
8237         {
8238           movLeft2Result (left, size, result, size, 0);
8239         }
8240         _endLazyDPSEvaluation();
8241   }
8242   else if (shCount >= (size * 8))
8243   {
8244     _startLazyDPSEvaluation();
8245     while (size--)
8246     {
8247       aopPut (AOP (result), zero, size);
8248     }
8249     _endLazyDPSEvaluation();
8250   }
8251   else
8252   {
8253       switch (size)
8254         {
8255         case 1:
8256           genlshOne (result, left, shCount);
8257           break;
8258
8259         case 2:
8260           genlshTwo (result, left, shCount);
8261           break;
8262 #if 0
8263         case 4:
8264           genlshFour (result, left, shCount);
8265           break;
8266 #endif
8267         default:
8268           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8269           break;
8270         }
8271     }
8272   freeAsmop (left, NULL, ic, TRUE);
8273   freeAsmop (result, NULL, ic, TRUE);
8274   return TRUE;
8275 }
8276 #endif
8277
8278 /*-----------------------------------------------------------------*/
8279 /* genLeftShift - generates code for left shifting                 */
8280 /*-----------------------------------------------------------------*/
8281 static void
8282 genLeftShift (iCode * ic)
8283 {
8284   operand *left, *right, *result;
8285   int size, offset;
8286   char *l;
8287   symbol *tlbl, *tlbl1;
8288
8289   D (emitcode (";", "genLeftShift "););
8290
8291   right = IC_RIGHT (ic);
8292   left = IC_LEFT (ic);
8293   result = IC_RESULT (ic);
8294
8295   aopOp (right, ic, FALSE, FALSE);
8296
8297
8298 #ifdef BETTER_LITERAL_SHIFT
8299   /* if the shift count is known then do it
8300      as efficiently as possible */
8301   if (AOP_TYPE (right) == AOP_LIT)
8302     {
8303       if (genLeftShiftLiteral (left, right, result, ic))
8304       {
8305         return;
8306       }
8307     }
8308 #endif
8309
8310   /* shift count is unknown then we have to form
8311      a loop get the loop count in B : Note: we take
8312      only the lower order byte since shifting
8313      more that 32 bits make no sense anyway, ( the
8314      largest size of an object can be only 32 bits ) */
8315
8316   if (AOP_TYPE (right) == AOP_LIT)
8317   {
8318       /* Really should be handled by genLeftShiftLiteral,
8319        * but since I'm too lazy to fix that today, at least we can make
8320        * some small improvement.
8321        */
8322        emitcode("mov", "b,#!constbyte",
8323                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8324   }
8325   else
8326   {
8327       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8328       emitcode ("inc", "b");
8329   }
8330   freeAsmop (right, NULL, ic, TRUE);
8331   aopOp (left, ic, FALSE, FALSE);
8332   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8333
8334   /* now move the left to the result if they are not the
8335      same */
8336   if (!sameRegs (AOP (left), AOP (result)) &&
8337       AOP_SIZE (result) > 1)
8338     {
8339
8340       size = AOP_SIZE (result);
8341       offset = 0;
8342       _startLazyDPSEvaluation ();
8343       while (size--)
8344         {
8345           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8346           if (*l == '@' && (IS_AOP_PREG (result)))
8347             {
8348
8349               emitcode ("mov", "a,%s", l);
8350               aopPut (AOP (result), "a", offset);
8351             }
8352           else
8353             aopPut (AOP (result), l, offset);
8354           offset++;
8355         }
8356       _endLazyDPSEvaluation ();
8357     }
8358
8359   tlbl = newiTempLabel (NULL);
8360   size = AOP_SIZE (result);
8361   offset = 0;
8362   tlbl1 = newiTempLabel (NULL);
8363
8364   /* if it is only one byte then */
8365   if (size == 1)
8366     {
8367       symbol *tlbl1 = newiTempLabel (NULL);
8368
8369       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8370       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8371       emitcode ("", "!tlabeldef", tlbl->key + 100);
8372       emitcode ("add", "a,acc");
8373       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8374       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8375       aopPut (AOP (result), "a", 0);
8376       goto release;
8377     }
8378
8379   reAdjustPreg (AOP (result));
8380
8381   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8382   emitcode ("", "!tlabeldef", tlbl->key + 100);
8383   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8384   emitcode ("add", "a,acc");
8385   aopPut (AOP (result), "a", offset++);
8386   _startLazyDPSEvaluation ();
8387   while (--size)
8388     {
8389       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8390       emitcode ("rlc", "a");
8391       aopPut (AOP (result), "a", offset++);
8392     }
8393   _endLazyDPSEvaluation ();
8394   reAdjustPreg (AOP (result));
8395
8396   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8397   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8398 release:
8399   freeAsmop (left, NULL, ic, TRUE);
8400   freeAsmop (result, NULL, ic, TRUE);
8401 }
8402
8403 #ifdef BETTER_LITERAL_SHIFT
8404 /*-----------------------------------------------------------------*/
8405 /* genrshOne - right shift a one byte quantity by known count      */
8406 /*-----------------------------------------------------------------*/
8407 static void
8408 genrshOne (operand * result, operand * left,
8409            int shCount, int sign)
8410 {
8411   D (emitcode (";", "genrshOne"););
8412   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8413 }
8414 #endif
8415
8416 #ifdef BETTER_LITERAL_SHIFT
8417 /*-----------------------------------------------------------------*/
8418 /* genrshTwo - right shift two bytes by known amount != 0          */
8419 /*-----------------------------------------------------------------*/
8420 static void
8421 genrshTwo (operand * result, operand * left,
8422            int shCount, int sign)
8423 {
8424   D (emitcode (";", "genrshTwo"););
8425
8426   /* if shCount >= 8 */
8427   if (shCount >= 8)
8428     {
8429       shCount -= 8;
8430       _startLazyDPSEvaluation();
8431       if (shCount)
8432       {
8433         shiftR1Left2Result (left, MSB16, result, LSB,
8434                             shCount, sign);
8435       }                     
8436       else
8437       {
8438         movLeft2Result (left, MSB16, result, LSB, sign);
8439       }
8440       addSign (result, MSB16, sign);
8441       _endLazyDPSEvaluation();
8442     }
8443
8444   /*  1 <= shCount <= 7 */
8445   else
8446   {
8447     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8448   }
8449 }
8450 #endif
8451
8452 #if 0
8453 //REMOVE ME!!!
8454 /*-----------------------------------------------------------------*/
8455 /* shiftRLong - shift right one long from left to result           */
8456 /* offl = LSB or MSB16                                             */
8457 /*-----------------------------------------------------------------*/
8458 static void
8459 shiftRLong (operand * left, int offl,
8460             operand * result, int sign)
8461 {
8462   int isSameRegs=sameRegs(AOP(left),AOP(result));
8463
8464   if (isSameRegs && offl>1) {
8465     // we are in big trouble, but this shouldn't happen
8466     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8467   }
8468
8469   MOVA (aopGet (AOP (left), MSB32, FALSE, NULL));
8470   
8471   if (offl==MSB16) {
8472     // shift is > 8
8473     if (sign) {
8474       emitcode ("rlc", "a");
8475       emitcode ("subb", "a,acc");
8476       emitcode ("xch", "a,%s",
8477                 aopGet(AOP(left), MSB32, FALSE, DP2_RESULT_REG));
8478     } else {
8479       aopPut (AOP(result), zero, MSB32);
8480     }
8481   }
8482
8483   if (!sign) {
8484     emitcode ("clr", "c");
8485   } else {
8486     emitcode ("mov", "c,acc.7");
8487   }
8488
8489   emitcode ("rrc", "a");
8490
8491   if (isSameRegs && offl==MSB16) {
8492     emitcode ("xch",
8493               "a,%s",aopGet (AOP (left), MSB24, FALSE, DP2_RESULT_REG));
8494   } else {
8495     aopPut (AOP (result), "a", MSB32);
8496     MOVA (aopGet (AOP (left), MSB24, FALSE, NULL));
8497   }
8498
8499   emitcode ("rrc", "a");
8500   if (isSameRegs && offl==1) {
8501     emitcode ("xch", "a,%s",
8502               aopGet (AOP (left), MSB16, FALSE, DP2_RESULT_REG));
8503   } else {
8504     aopPut (AOP (result), "a", MSB24);
8505     MOVA (aopGet (AOP (left), MSB16, FALSE, NULL));
8506   }
8507   emitcode ("rrc", "a");
8508   aopPut (AOP (result), "a", MSB16 - offl);
8509
8510   if (offl == LSB)
8511     {
8512       MOVA (aopGet (AOP (left), LSB, FALSE, NULL));
8513       emitcode ("rrc", "a");
8514       aopPut (AOP (result), "a", LSB);
8515     }
8516 }
8517 #endif
8518
8519 #if 0
8520 //REMOVE ME!!!
8521 /*-----------------------------------------------------------------*/
8522 /* genrshFour - shift four byte by a known amount != 0             */
8523 /*-----------------------------------------------------------------*/
8524 static void
8525 genrshFour (operand * result, operand * left,
8526             int shCount, int sign)
8527 {
8528   D (emitcode (";", "genrshFour");
8529     );
8530
8531   /* if shifting more that 3 bytes */
8532   if (shCount >= 24)
8533     {
8534       shCount -= 24;
8535       if (shCount)
8536         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8537       else
8538         movLeft2Result (left, MSB32, result, LSB, sign);
8539       addSign (result, MSB16, sign);
8540     }
8541   else if (shCount >= 16)
8542     {
8543       shCount -= 16;
8544       if (shCount)
8545         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8546       else
8547         {
8548           movLeft2Result (left, MSB24, result, LSB, 0);
8549           movLeft2Result (left, MSB32, result, MSB16, sign);
8550         }
8551       addSign (result, MSB24, sign);
8552     }
8553   else if (shCount >= 8)
8554     {
8555       shCount -= 8;
8556       if (shCount == 1)
8557         shiftRLong (left, MSB16, result, sign);
8558       else if (shCount == 0)
8559         {
8560           movLeft2Result (left, MSB16, result, LSB, 0);
8561           movLeft2Result (left, MSB24, result, MSB16, 0);
8562           movLeft2Result (left, MSB32, result, MSB24, sign);
8563           addSign (result, MSB32, sign);
8564         }
8565       else
8566         {
8567           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8568           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8569           /* the last shift is signed */
8570           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8571           addSign (result, MSB32, sign);
8572         }
8573     }
8574   else
8575     {                           /* 1 <= shCount <= 7 */
8576       if (shCount <= 2)
8577         {
8578           shiftRLong (left, LSB, result, sign);
8579           if (shCount == 2)
8580             shiftRLong (result, LSB, result, sign);
8581         }
8582       else
8583         {
8584           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8585           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8586           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8587         }
8588     }
8589 }
8590 #endif
8591
8592 #ifdef BETTER_LITERAL_SHIFT
8593 /*-----------------------------------------------------------------*/
8594 /* genRightShiftLiteral - right shifting by known count            */
8595 /*-----------------------------------------------------------------*/
8596 static bool
8597 genRightShiftLiteral (operand * left,
8598                       operand * right,
8599                       operand * result,
8600                       iCode * ic,
8601                       int sign)
8602 {
8603   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8604   int size;
8605
8606   size = getSize (operandType (result));
8607
8608   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8609
8610   /* We only handle certain easy cases so far. */
8611   if ((shCount != 0)
8612    && (shCount < (size * 8))
8613    && (size != 1)
8614    && (size != 2))
8615   {
8616       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8617       return FALSE;
8618   }
8619
8620   freeAsmop (right, NULL, ic, TRUE);
8621
8622   aopOp (left, ic, FALSE, FALSE);
8623   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8624
8625 #if VIEW_SIZE
8626   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8627             AOP_SIZE (left));
8628 #endif
8629
8630   /* test the LEFT size !!! */
8631
8632   /* I suppose that the left size >= result size */
8633   if (shCount == 0)
8634   {
8635       size = getDataSize (result);
8636       _startLazyDPSEvaluation();
8637       while (size--)
8638       {
8639         movLeft2Result (left, size, result, size, 0);
8640       }
8641       _endLazyDPSEvaluation();
8642   }
8643   else if (shCount >= (size * 8))
8644     {
8645       if (sign)
8646       {
8647         /* get sign in acc.7 */
8648         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8649       }
8650       addSign (result, LSB, sign);
8651     }
8652   else
8653     {
8654       switch (size)
8655         {
8656         case 1:
8657           genrshOne (result, left, shCount, sign);
8658           break;
8659
8660         case 2:
8661           genrshTwo (result, left, shCount, sign);
8662           break;
8663 #if 0
8664         case 4:
8665           genrshFour (result, left, shCount, sign);
8666           break;
8667 #endif    
8668         default:
8669           break;
8670         }
8671     }
8672   freeAsmop (left, NULL, ic, TRUE);
8673   freeAsmop (result, NULL, ic, TRUE);
8674   
8675   return TRUE;
8676 }
8677 #endif
8678
8679 /*-----------------------------------------------------------------*/
8680 /* genSignedRightShift - right shift of signed number              */
8681 /*-----------------------------------------------------------------*/
8682 static void
8683 genSignedRightShift (iCode * ic)
8684 {
8685   operand *right, *left, *result;
8686   int size, offset;
8687   char *l;
8688   symbol *tlbl, *tlbl1;
8689
8690   D (emitcode (";", "genSignedRightShift "););
8691
8692   /* we do it the hard way put the shift count in b
8693      and loop thru preserving the sign */
8694
8695   right = IC_RIGHT (ic);
8696   left = IC_LEFT (ic);
8697   result = IC_RESULT (ic);
8698
8699   aopOp (right, ic, FALSE, FALSE);
8700
8701 #ifdef BETTER_LITERAL_SHIFT
8702   if (AOP_TYPE (right) == AOP_LIT)
8703     {
8704       if (genRightShiftLiteral (left, right, result, ic, 1))
8705       {
8706         return;
8707       }
8708     }
8709 #endif
8710   /* shift count is unknown then we have to form
8711      a loop get the loop count in B : Note: we take
8712      only the lower order byte since shifting
8713      more that 32 bits make no sense anyway, ( the
8714      largest size of an object can be only 32 bits ) */
8715
8716   if (AOP_TYPE (right) == AOP_LIT)
8717   {
8718       /* Really should be handled by genRightShiftLiteral,
8719        * but since I'm too lazy to fix that today, at least we can make
8720        * some small improvement.
8721        */
8722        emitcode("mov", "b,#!constbyte",
8723                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8724   }
8725   else
8726   {
8727         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8728         emitcode ("inc", "b");
8729   }
8730   freeAsmop (right, NULL, ic, TRUE);
8731   aopOp (left, ic, FALSE, FALSE);
8732   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8733
8734   /* now move the left to the result if they are not the
8735      same */
8736   if (!sameRegs (AOP (left), AOP (result)) &&
8737       AOP_SIZE (result) > 1)
8738     {
8739
8740       size = AOP_SIZE (result);
8741       offset = 0;
8742       _startLazyDPSEvaluation ();
8743       while (size--)
8744         {
8745           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8746           if (*l == '@' && IS_AOP_PREG (result))
8747             {
8748
8749               emitcode ("mov", "a,%s", l);
8750               aopPut (AOP (result), "a", offset);
8751             }
8752           else
8753             aopPut (AOP (result), l, offset);
8754           offset++;
8755         }
8756       _endLazyDPSEvaluation ();
8757     }
8758
8759   /* mov the highest order bit to OVR */
8760   tlbl = newiTempLabel (NULL);
8761   tlbl1 = newiTempLabel (NULL);
8762
8763   size = AOP_SIZE (result);
8764   offset = size - 1;
8765   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8766   emitcode ("rlc", "a");
8767   emitcode ("mov", "ov,c");
8768   /* if it is only one byte then */
8769   if (size == 1)
8770     {
8771       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8772       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8773       emitcode ("", "!tlabeldef", tlbl->key + 100);
8774       emitcode ("mov", "c,ov");
8775       emitcode ("rrc", "a");
8776       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8777       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8778       aopPut (AOP (result), "a", 0);
8779       goto release;
8780     }
8781
8782   reAdjustPreg (AOP (result));
8783   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8784   emitcode ("", "!tlabeldef", tlbl->key + 100);
8785   emitcode ("mov", "c,ov");
8786   _startLazyDPSEvaluation ();
8787   while (size--)
8788     {
8789       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8790       emitcode ("rrc", "a");
8791       aopPut (AOP (result), "a", offset--);
8792     }
8793   _endLazyDPSEvaluation ();
8794   reAdjustPreg (AOP (result));
8795   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8796   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8797
8798 release:
8799   freeAsmop (left, NULL, ic, TRUE);
8800   freeAsmop (result, NULL, ic, TRUE);
8801 }
8802
8803 /*-----------------------------------------------------------------*/
8804 /* genRightShift - generate code for right shifting                */
8805 /*-----------------------------------------------------------------*/
8806 static void
8807 genRightShift (iCode * ic)
8808 {
8809   operand *right, *left, *result;
8810   sym_link *retype;
8811   int size, offset;
8812   char *l;
8813   symbol *tlbl, *tlbl1;
8814
8815   D (emitcode (";", "genRightShift "););
8816
8817   /* if signed then we do it the hard way preserve the
8818      sign bit moving it inwards */
8819   retype = getSpec (operandType (IC_RESULT (ic)));
8820
8821   if (!SPEC_USIGN (retype))
8822     {
8823       genSignedRightShift (ic);
8824       return;
8825     }
8826
8827   /* signed & unsigned types are treated the same : i.e. the
8828      signed is NOT propagated inwards : quoting from the
8829      ANSI - standard : "for E1 >> E2, is equivalent to division
8830      by 2**E2 if unsigned or if it has a non-negative value,
8831      otherwise the result is implementation defined ", MY definition
8832      is that the sign does not get propagated */
8833
8834   right = IC_RIGHT (ic);
8835   left = IC_LEFT (ic);
8836   result = IC_RESULT (ic);
8837
8838   aopOp (right, ic, FALSE, FALSE);
8839
8840 #ifdef BETTER_LITERAL_SHIFT
8841   /* if the shift count is known then do it
8842      as efficiently as possible */
8843   if (AOP_TYPE (right) == AOP_LIT)
8844     {
8845       if (genRightShiftLiteral (left, right, result, ic, 0))
8846       {
8847         return;
8848       }
8849     }
8850 #endif
8851
8852   /* shift count is unknown then we have to form
8853      a loop get the loop count in B : Note: we take
8854      only the lower order byte since shifting
8855      more that 32 bits make no sense anyway, ( the
8856      largest size of an object can be only 32 bits ) */
8857   
8858   if (AOP_TYPE (right) == AOP_LIT)
8859   {
8860       /* Really should be handled by genRightShiftLiteral,
8861        * but since I'm too lazy to fix that today, at least we can make
8862        * some small improvement.
8863        */
8864        emitcode("mov", "b,#!constbyte",
8865                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8866   }
8867   else
8868   {
8869       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8870       emitcode ("inc", "b");
8871   }
8872   freeAsmop (right, NULL, ic, TRUE);
8873   aopOp (left, ic, FALSE, FALSE);
8874   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8875
8876   /* now move the left to the result if they are not the
8877      same */
8878   if (!sameRegs (AOP (left), AOP (result)) &&
8879       AOP_SIZE (result) > 1)
8880     {
8881
8882       size = AOP_SIZE (result);
8883       offset = 0;
8884       _startLazyDPSEvaluation ();
8885       while (size--)
8886         {
8887           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8888           if (*l == '@' && IS_AOP_PREG (result))
8889             {
8890
8891               emitcode ("mov", "a,%s", l);
8892               aopPut (AOP (result), "a", offset);
8893             }
8894           else
8895             aopPut (AOP (result), l, offset);
8896           offset++;
8897         }
8898       _endLazyDPSEvaluation ();
8899     }
8900
8901   tlbl = newiTempLabel (NULL);
8902   tlbl1 = newiTempLabel (NULL);
8903   size = AOP_SIZE (result);
8904   offset = size - 1;
8905
8906   /* if it is only one byte then */
8907   if (size == 1)
8908     {
8909       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8910       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8911       emitcode ("", "!tlabeldef", tlbl->key + 100);
8912       CLRC;
8913       emitcode ("rrc", "a");
8914       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8915       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8916       aopPut (AOP (result), "a", 0);
8917       goto release;
8918     }
8919
8920   reAdjustPreg (AOP (result));
8921   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8922   emitcode ("", "!tlabeldef", tlbl->key + 100);
8923   CLRC;
8924   _startLazyDPSEvaluation ();
8925   while (size--)
8926     {
8927       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8928       emitcode ("rrc", "a");
8929       aopPut (AOP (result), "a", offset--);
8930     }
8931   _endLazyDPSEvaluation ();
8932   reAdjustPreg (AOP (result));
8933
8934   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8935   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8936
8937 release:
8938   freeAsmop (left, NULL, ic, TRUE);
8939   freeAsmop (result, NULL, ic, TRUE);
8940 }
8941
8942 /*-----------------------------------------------------------------*/
8943 /* genUnpackBits - generates code for unpacking bits               */
8944 /*-----------------------------------------------------------------*/
8945 static void
8946 genUnpackBits (operand * result, char *rname, int ptype)
8947 {
8948   int shCnt;
8949   int rlen;
8950   sym_link *etype;
8951   int offset = 0;
8952
8953   D (emitcode (";", "genUnpackBits "););
8954
8955   etype = getSpec (operandType (result));
8956
8957   /* read the first byte  */
8958   switch (ptype)
8959     {
8960
8961     case POINTER:
8962     case IPOINTER:
8963       emitcode ("mov", "a,@%s", rname);
8964       break;
8965
8966     case PPOINTER:
8967       emitcode ("movx", "a,@%s", rname);
8968       break;
8969
8970     case FPOINTER:
8971       emitcode ("movx", "a,@dptr");
8972       break;
8973
8974     case CPOINTER:
8975       emitcode ("clr", "a");
8976       emitcode ("movc", "a,@a+dptr");
8977       break;
8978
8979     case GPOINTER:
8980       emitcode ("lcall", "__gptrget");
8981       break;
8982     }
8983
8984   /* if we have bitdisplacement then it fits   */
8985   /* into this byte completely or if length is */
8986   /* less than a byte                          */
8987   if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
8988     {
8989
8990       /* shift right acc */
8991       AccRsh (shCnt);
8992
8993       emitcode ("anl", "a,#!constbyte",
8994                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8995       aopPut (AOP (result), "a", offset);
8996       return;
8997     }
8998
8999   /* bit field did not fit in a byte  */
9000   rlen = SPEC_BLEN (etype) - 8;
9001   aopPut (AOP (result), "a", offset++);
9002
9003   while (1)
9004     {
9005
9006       switch (ptype)
9007         {
9008         case POINTER:
9009         case IPOINTER:
9010           emitcode ("inc", "%s", rname);
9011           emitcode ("mov", "a,@%s", rname);
9012           break;
9013
9014         case PPOINTER:
9015           emitcode ("inc", "%s", rname);
9016           emitcode ("movx", "a,@%s", rname);
9017           break;
9018
9019         case FPOINTER:
9020           emitcode ("inc", "dptr");
9021           emitcode ("movx", "a,@dptr");
9022           break;
9023
9024         case CPOINTER:
9025           emitcode ("clr", "a");
9026           emitcode ("inc", "dptr");
9027           emitcode ("movc", "a,@a+dptr");
9028           break;
9029
9030         case GPOINTER:
9031           emitcode ("inc", "dptr");
9032           emitcode ("lcall", "__gptrget");
9033           break;
9034         }
9035
9036       rlen -= 8;
9037       /* if we are done */
9038       if (rlen < 8)
9039         break;
9040
9041       aopPut (AOP (result), "a", offset++);
9042
9043     }
9044
9045   if (rlen)
9046     {
9047       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
9048       aopPut (AOP (result), "a", offset);
9049     }
9050
9051   return;
9052 }
9053
9054
9055 /*-----------------------------------------------------------------*/
9056 /* genDataPointerGet - generates code when ptr offset is known     */
9057 /*-----------------------------------------------------------------*/
9058 static void
9059 genDataPointerGet (operand * left,
9060                    operand * result,
9061                    iCode * ic)
9062 {
9063   char *l;
9064   char buff[256];
9065   int size, offset = 0;
9066   aopOp (result, ic, TRUE, FALSE);
9067
9068   /* get the string representation of the name */
9069   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9070   size = AOP_SIZE (result);
9071   _startLazyDPSEvaluation ();
9072   while (size--)
9073     {
9074         if (offset)
9075         {
9076             SNPRINTF (buff, sizeof(buff), 
9077                       "(%s + %d)", l + 1, offset);
9078         }
9079         else
9080         {
9081             SNPRINTF (buff, sizeof(buff), 
9082                       "%s", l + 1);
9083         }
9084       aopPut (AOP (result), buff, offset++);
9085     }
9086   _endLazyDPSEvaluation ();
9087
9088   freeAsmop (left, NULL, ic, TRUE);
9089   freeAsmop (result, NULL, ic, TRUE);
9090 }
9091
9092 /*-----------------------------------------------------------------*/
9093 /* genNearPointerGet - emitcode for near pointer fetch             */
9094 /*-----------------------------------------------------------------*/
9095 static void
9096 genNearPointerGet (operand * left,
9097                    operand * result,
9098                    iCode * ic,
9099                    iCode *pi)
9100 {
9101   asmop *aop = NULL;
9102   regs *preg;
9103   char *rname;
9104   sym_link *rtype, *retype, *letype;
9105   sym_link *ltype = operandType (left);
9106   char buff[80];
9107
9108   rtype = operandType (result);
9109   retype = getSpec (rtype);
9110   letype = getSpec (ltype);
9111
9112   aopOp (left, ic, FALSE, FALSE);
9113
9114   /* if left is rematerialisable and
9115      result is not bit variable type and
9116      the left is pointer to data space i.e
9117      lower 128 bytes of space */
9118   if (AOP_TYPE (left) == AOP_IMMD &&
9119       !IS_BITVAR (retype) &&
9120       !IS_BITVAR (letype) &&
9121       DCL_TYPE (ltype) == POINTER)
9122     {
9123       genDataPointerGet (left, result, ic);
9124       return;
9125     }
9126
9127   /* if the value is already in a pointer register
9128      then don't need anything more */
9129   if (!AOP_INPREG (AOP (left)))
9130     {
9131       /* otherwise get a free pointer register */
9132       aop = newAsmop (0);
9133       preg = getFreePtr (ic, &aop, FALSE);
9134       emitcode ("mov", "%s,%s",
9135                 preg->name,
9136                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9137       rname = preg->name;
9138     }
9139   else
9140     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9141
9142   freeAsmop (left, NULL, ic, TRUE);
9143   aopOp (result, ic, FALSE, FALSE);
9144
9145   /* if bitfield then unpack the bits */
9146   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9147     genUnpackBits (result, rname, POINTER);
9148   else
9149     {
9150       /* we have can just get the values */
9151       int size = AOP_SIZE (result);
9152       int offset = 0;
9153
9154       while (size--)
9155         {
9156           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9157             {
9158
9159               emitcode ("mov", "a,@%s", rname);
9160               aopPut (AOP (result), "a", offset);
9161             }
9162           else
9163             {
9164               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9165               aopPut (AOP (result), buff, offset);
9166             }
9167           offset++;
9168           if (size || pi)
9169             {
9170                 emitcode ("inc", "%s", rname);
9171             }
9172         }
9173     }
9174
9175   /* now some housekeeping stuff */
9176   if (aop)
9177     {
9178       /* we had to allocate for this iCode */
9179       if (pi) { /* post increment present */
9180         aopPut(AOP ( left ),rname,0);
9181       }
9182       freeAsmop (NULL, aop, ic, TRUE);
9183     }
9184   else
9185     {
9186       /* we did not allocate which means left
9187          already in a pointer register, then
9188          if size > 0 && this could be used again
9189          we have to point it back to where it
9190          belongs */
9191       if (AOP_SIZE (result) > 1 &&
9192           !OP_SYMBOL (left)->remat &&
9193           (OP_SYMBOL (left)->liveTo > ic->seq ||
9194            ic->depth) &&
9195           !pi)
9196         {
9197           int size = AOP_SIZE (result) - 1;
9198           while (size--)
9199             emitcode ("dec", "%s", rname);
9200         }
9201     }
9202
9203   /* done */
9204   freeAsmop (result, NULL, ic, TRUE);
9205   if (pi) pi->generated = 1;
9206 }
9207
9208 /*-----------------------------------------------------------------*/
9209 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9210 /*-----------------------------------------------------------------*/
9211 static void
9212 genPagedPointerGet (operand * left,
9213                     operand * result,
9214                     iCode * ic,
9215                     iCode * pi)
9216 {
9217   asmop *aop = NULL;
9218   regs *preg;
9219   char *rname;
9220   sym_link *rtype, *retype, *letype;
9221
9222   rtype = operandType (result);
9223   retype = getSpec (rtype);
9224   letype = getSpec (operandType (left));
9225   aopOp (left, ic, FALSE, FALSE);
9226
9227   /* if the value is already in a pointer register
9228      then don't need anything more */
9229   if (!AOP_INPREG (AOP (left)))
9230     {
9231       /* otherwise get a free pointer register */
9232       aop = newAsmop (0);
9233       preg = getFreePtr (ic, &aop, FALSE);
9234       emitcode ("mov", "%s,%s",
9235                 preg->name,
9236                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9237       rname = preg->name;
9238     }
9239   else
9240     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9241
9242   freeAsmop (left, NULL, ic, TRUE);
9243   aopOp (result, ic, FALSE, FALSE);
9244
9245   /* if bitfield then unpack the bits */
9246   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9247     genUnpackBits (result, rname, PPOINTER);
9248   else
9249     {
9250       /* we have can just get the values */
9251       int size = AOP_SIZE (result);
9252       int offset = 0;
9253
9254       while (size--)
9255         {
9256
9257           emitcode ("movx", "a,@%s", rname);
9258           aopPut (AOP (result), "a", offset);
9259
9260           offset++;
9261
9262           if (size || pi)
9263             emitcode ("inc", "%s", rname);
9264         }
9265     }
9266
9267   /* now some housekeeping stuff */
9268   if (aop)
9269     {
9270       /* we had to allocate for this iCode */
9271       if (pi) aopPut ( AOP (left), rname, 0);
9272       freeAsmop (NULL, aop, ic, TRUE);
9273     }
9274   else
9275     {
9276       /* we did not allocate which means left
9277          already in a pointer register, then
9278          if size > 0 && this could be used again
9279          we have to point it back to where it
9280          belongs */
9281       if (AOP_SIZE (result) > 1 &&
9282           !OP_SYMBOL (left)->remat &&
9283           (OP_SYMBOL (left)->liveTo > ic->seq ||
9284            ic->depth) &&
9285           !pi)
9286         {
9287           int size = AOP_SIZE (result) - 1;
9288           while (size--)
9289             emitcode ("dec", "%s", rname);
9290         }
9291     }
9292
9293   /* done */
9294   freeAsmop (result, NULL, ic, TRUE);
9295   if (pi) pi->generated = 1;
9296 }
9297
9298 /*-----------------------------------------------------------------*/
9299 /* genFarPointerGet - gget value from far space                    */
9300 /*-----------------------------------------------------------------*/
9301 static void
9302 genFarPointerGet (operand * left,
9303                   operand * result, iCode * ic, iCode *pi)
9304 {
9305     int size, offset, dopi=1;
9306   sym_link *retype = getSpec (operandType (result));
9307   sym_link *letype = getSpec (operandType (left));
9308   D (emitcode (";", "genFarPointerGet"););
9309
9310   aopOp (left, ic, FALSE, FALSE);
9311
9312   /* if the operand is already in dptr
9313      then we do nothing else we move the value to dptr */
9314   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9315     {
9316       /* if this is remateriazable */
9317       if (AOP_TYPE (left) == AOP_IMMD)
9318         {
9319           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9320         }
9321       else
9322         {
9323           /* we need to get it byte by byte */
9324           _startLazyDPSEvaluation ();
9325           if (AOP_TYPE (left) != AOP_DPTR)
9326             {
9327               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9328               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9329               if (options.model == MODEL_FLAT24)
9330                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9331             }
9332           else
9333             {
9334               /* We need to generate a load to DPTR indirect through DPTR. */
9335               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9336               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9337               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9338               if (options.model == MODEL_FLAT24)
9339                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9340               emitcode ("pop", "dph");
9341               emitcode ("pop", "dpl");
9342               dopi =0;
9343             }
9344           _endLazyDPSEvaluation ();
9345         }
9346     }
9347   /* so dptr know contains the address */
9348   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9349
9350   /* if bit then unpack */
9351   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9352       if (AOP_INDPTRn(left)) {
9353           genSetDPTR(AOP(left)->aopu.dptr);
9354       }
9355       genUnpackBits (result, "dptr", FPOINTER);
9356       if (AOP_INDPTRn(left)) {
9357           genSetDPTR(0);
9358       }
9359   } else
9360     {
9361       size = AOP_SIZE (result);
9362       offset = 0;
9363
9364       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9365           while (size--) {
9366               genSetDPTR(AOP(left)->aopu.dptr);
9367               emitcode ("movx", "a,@dptr");
9368               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9369                   emitcode ("inc", "dptr");
9370               genSetDPTR (0);
9371               aopPut (AOP (result), "a", offset++);
9372           }
9373       } else {
9374           _startLazyDPSEvaluation ();
9375           while (size--) {
9376               if (AOP_INDPTRn(left)) {
9377                   genSetDPTR(AOP(left)->aopu.dptr);
9378               } else {
9379                   genSetDPTR (0);
9380               }
9381               _flushLazyDPS ();
9382               
9383               emitcode ("movx", "a,@dptr");
9384               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9385                   emitcode ("inc", "dptr");
9386               
9387               aopPut (AOP (result), "a", offset++);
9388           }
9389           _endLazyDPSEvaluation ();
9390       }
9391     }
9392   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9393       if (!AOP_INDPTRn(left)) {
9394           _startLazyDPSEvaluation ();
9395           aopPut ( AOP (left), "dpl", 0);
9396           aopPut ( AOP (left), "dph", 1);
9397           if (options.model == MODEL_FLAT24)
9398               aopPut ( AOP (left), "dpx", 2);
9399           _endLazyDPSEvaluation ();
9400       }
9401     pi->generated = 1;
9402   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9403              AOP_SIZE(result) > 1 &&
9404              IS_SYMOP(left) &&
9405              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9406       
9407       size = AOP_SIZE (result) - 1;
9408       if (AOP_INDPTRn(left)) {
9409           genSetDPTR(AOP(left)->aopu.dptr);
9410       }
9411       while (size--) emitcode ("lcall","__decdptr");
9412       if (AOP_INDPTRn(left)) {
9413           genSetDPTR(0);
9414       }
9415   }
9416
9417   freeAsmop (left, NULL, ic, TRUE);
9418   freeAsmop (result, NULL, ic, TRUE);
9419 }
9420
9421 /*-----------------------------------------------------------------*/
9422 /* genCodePointerGet - get value from code space                  */
9423 /*-----------------------------------------------------------------*/
9424 static void
9425 genCodePointerGet (operand * left,
9426                     operand * result, iCode * ic, iCode *pi)
9427 {
9428   int size, offset, dopi=1;
9429   sym_link *retype = getSpec (operandType (result));
9430
9431   aopOp (left, ic, FALSE, FALSE);
9432
9433   /* if the operand is already in dptr
9434      then we do nothing else we move the value to dptr */
9435   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9436     {
9437       /* if this is remateriazable */
9438       if (AOP_TYPE (left) == AOP_IMMD)
9439         {
9440           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9441         }
9442       else
9443         {                       /* we need to get it byte by byte */
9444           _startLazyDPSEvaluation ();
9445           if (AOP_TYPE (left) != AOP_DPTR)
9446             {
9447               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9448               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9449               if (options.model == MODEL_FLAT24)
9450                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9451             }
9452           else
9453             {
9454               /* We need to generate a load to DPTR indirect through DPTR. */
9455               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9456               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9457               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9458               if (options.model == MODEL_FLAT24)
9459                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9460               emitcode ("pop", "dph");
9461               emitcode ("pop", "dpl");
9462               dopi=0;
9463             }
9464           _endLazyDPSEvaluation ();
9465         }
9466     }
9467   /* so dptr know contains the address */
9468   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9469
9470   /* if bit then unpack */
9471   if (IS_BITVAR (retype)) {
9472       if (AOP_INDPTRn(left)) {
9473           genSetDPTR(AOP(left)->aopu.dptr);
9474       }
9475       genUnpackBits (result, "dptr", CPOINTER);
9476       if (AOP_INDPTRn(left)) {
9477           genSetDPTR(0);
9478       }
9479   } else
9480     {
9481       size = AOP_SIZE (result);
9482       offset = 0;
9483       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9484           while (size--) {
9485               genSetDPTR(AOP(left)->aopu.dptr);
9486               emitcode ("clr", "a");
9487               emitcode ("movc", "a,@a+dptr");
9488               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9489                   emitcode ("inc", "dptr");
9490               genSetDPTR (0);
9491               aopPut (AOP (result), "a", offset++);
9492           }
9493       } else {
9494           _startLazyDPSEvaluation ();
9495           while (size--)
9496               {
9497                   if (AOP_INDPTRn(left)) {
9498                       genSetDPTR(AOP(left)->aopu.dptr);
9499                   } else {
9500                       genSetDPTR (0);
9501                   }
9502                   _flushLazyDPS ();
9503                   
9504                   emitcode ("clr", "a");
9505                   emitcode ("movc", "a,@a+dptr");
9506                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9507                       emitcode ("inc", "dptr");
9508                   aopPut (AOP (result), "a", offset++);
9509               }
9510           _endLazyDPSEvaluation ();
9511       }
9512     }
9513   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9514       if (!AOP_INDPTRn(left)) {
9515           _startLazyDPSEvaluation ();
9516           
9517           aopPut ( AOP (left), "dpl", 0);
9518           aopPut ( AOP (left), "dph", 1);
9519           if (options.model == MODEL_FLAT24)
9520               aopPut ( AOP (left), "dpx", 2);
9521
9522           _endLazyDPSEvaluation ();
9523       }
9524       pi->generated = 1;
9525   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9526              AOP_SIZE(result) > 1 &&
9527              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9528       
9529       size = AOP_SIZE (result) - 1;
9530       if (AOP_INDPTRn(left)) {
9531           genSetDPTR(AOP(left)->aopu.dptr);
9532       }
9533       while (size--) emitcode ("lcall","__decdptr");
9534       if (AOP_INDPTRn(left)) {
9535           genSetDPTR(0);
9536       }
9537   }
9538   
9539   freeAsmop (left, NULL, ic, TRUE);
9540   freeAsmop (result, NULL, ic, TRUE);
9541 }
9542
9543 /*-----------------------------------------------------------------*/
9544 /* genGenPointerGet - gget value from generic pointer space        */
9545 /*-----------------------------------------------------------------*/
9546 static void
9547 genGenPointerGet (operand * left,
9548                   operand * result, iCode * ic, iCode * pi)
9549 {
9550   int size, offset;
9551   sym_link *retype = getSpec (operandType (result));
9552   sym_link *letype = getSpec (operandType (left));
9553
9554   D (emitcode (";", "genGenPointerGet "); );
9555
9556   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9557
9558   /* if the operand is already in dptr
9559      then we do nothing else we move the value to dptr */
9560   if (AOP_TYPE (left) != AOP_STR)
9561     {
9562       /* if this is remateriazable */
9563       if (AOP_TYPE (left) == AOP_IMMD)
9564         {
9565           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9566           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9567             {
9568                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9569             }
9570             else
9571             {
9572                 emitcode ("mov", "b,#%d", pointerCode (retype));
9573             }
9574         }
9575       else
9576         {                       /* we need to get it byte by byte */
9577             _startLazyDPSEvaluation ();
9578             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9579             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9580             if (options.model == MODEL_FLAT24) {
9581                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9582                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9583             } else {
9584                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9585             }
9586             _endLazyDPSEvaluation ();
9587         }
9588     }
9589
9590   /* so dptr-b now contains the address */
9591   _G.bInUse++;
9592   aopOp (result, ic, FALSE, TRUE);
9593   _G.bInUse--;
9594
9595   /* if bit then unpack */
9596   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9597   {
9598     genUnpackBits (result, "dptr", GPOINTER);
9599   }
9600   else
9601     {
9602         size = AOP_SIZE (result);
9603         offset = 0;
9604
9605         while (size--)
9606         {
9607             if (size)
9608             {
9609                 // Get two bytes at a time, results in _AP & A.
9610                 // dptr will be incremented ONCE by __gptrgetWord.
9611                 //
9612                 // Note: any change here must be coordinated
9613                 // with the implementation of __gptrgetWord
9614                 // in device/lib/_gptrget.c
9615                 emitcode ("lcall", "__gptrgetWord");
9616                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9617                 aopPut (AOP (result), "a", offset++);
9618                 size--;
9619             }
9620             else
9621             {
9622                 // Only one byte to get.
9623                 emitcode ("lcall", "__gptrget");
9624                 aopPut (AOP (result), "a", offset++);
9625             }
9626             
9627             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9628             {
9629                 emitcode ("inc", "dptr");
9630             }
9631         }
9632     }
9633
9634   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9635     _startLazyDPSEvaluation ();
9636       
9637     aopPut ( AOP (left), "dpl", 0);
9638     aopPut ( AOP (left), "dph", 1);
9639     if (options.model == MODEL_FLAT24) {
9640         aopPut ( AOP (left), "dpx", 2);
9641         aopPut ( AOP (left), "b", 3);   
9642     } else  aopPut ( AOP (left), "b", 2);       
9643     
9644     _endLazyDPSEvaluation ();
9645       
9646     pi->generated = 1;
9647   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9648              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9649       
9650       size = AOP_SIZE (result) - 1;
9651       while (size--) emitcode ("lcall","__decdptr");
9652   }
9653
9654   freeAsmop (left, NULL, ic, TRUE);
9655   freeAsmop (result, NULL, ic, TRUE);
9656 }
9657
9658 /*-----------------------------------------------------------------*/
9659 /* genPointerGet - generate code for pointer get                   */
9660 /*-----------------------------------------------------------------*/
9661 static void
9662 genPointerGet (iCode * ic, iCode *pi)
9663 {
9664   operand *left, *result;
9665   sym_link *type, *etype;
9666   int p_type;
9667
9668   D (emitcode (";", "genPointerGet ");
9669     );
9670
9671   left = IC_LEFT (ic);
9672   result = IC_RESULT (ic);
9673
9674   /* depending on the type of pointer we need to
9675      move it to the correct pointer register */
9676   type = operandType (left);
9677   etype = getSpec (type);
9678   /* if left is of type of pointer then it is simple */
9679   if (IS_PTR (type) && !IS_FUNC (type->next))
9680     p_type = DCL_TYPE (type);
9681   else
9682     {
9683       /* we have to go by the storage class */
9684       p_type = PTR_TYPE (SPEC_OCLS (etype));
9685     }
9686   /* special case when cast remat */
9687   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9688       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9689           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9690           type = operandType (left);
9691           p_type = DCL_TYPE (type);
9692   }
9693   /* now that we have the pointer type we assign
9694      the pointer values */
9695   switch (p_type)
9696     {
9697
9698     case POINTER:
9699     case IPOINTER:
9700       genNearPointerGet (left, result, ic, pi);
9701       break;
9702
9703     case PPOINTER:
9704       genPagedPointerGet (left, result, ic, pi);
9705       break;
9706
9707     case FPOINTER:
9708       genFarPointerGet (left, result, ic, pi);
9709       break;
9710
9711     case CPOINTER:
9712       genCodePointerGet (left, result, ic, pi);
9713       break;
9714
9715     case GPOINTER:
9716       genGenPointerGet (left, result, ic, pi);
9717       break;
9718     }
9719
9720 }
9721
9722 /*-----------------------------------------------------------------*/
9723 /* genPackBits - generates code for packed bit storage             */
9724 /*-----------------------------------------------------------------*/
9725 static void
9726 genPackBits (sym_link * etype,
9727              operand * right,
9728              char *rname, int p_type)
9729 {
9730   int offset = 0;
9731   int rLen;
9732   int blen, bstr;
9733   char *l;
9734
9735   blen = SPEC_BLEN (etype);
9736   bstr = SPEC_BSTR (etype);
9737
9738   MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9739
9740   /* if the bit lenth is less than or    */
9741   /* it exactly fits a byte then         */
9742   if (SPEC_BLEN (etype) <= 8)
9743     {
9744       /* shift left acc */
9745       AccLsh (SPEC_BSTR (etype));
9746
9747       if (SPEC_BLEN (etype) < 8)
9748         {                       /* if smaller than a byte */
9749
9750
9751           switch (p_type)
9752             {
9753             case POINTER:
9754               emitcode ("mov", "b,a");
9755               emitcode ("mov", "a,@%s", rname);
9756               break;
9757
9758             case FPOINTER:
9759               emitcode ("mov", "b,a");
9760               emitcode ("movx", "a,@dptr");
9761               break;
9762
9763             case GPOINTER:
9764               emitcode ("push", "b");
9765               emitcode ("push", "acc");
9766               emitcode ("lcall", "__gptrget");
9767               emitcode ("pop", "b");
9768               break;
9769             }
9770
9771           emitcode ("anl", "a,#!constbyte", (unsigned char)
9772                     ((unsigned char) (0xFF << (blen + bstr)) |
9773                      (unsigned char) (0xFF >> (8 - bstr))));
9774           emitcode ("orl", "a,b");
9775           if (p_type == GPOINTER)
9776             emitcode ("pop", "b");
9777         }
9778     }
9779
9780   switch (p_type)
9781     {
9782     case POINTER:
9783       emitcode ("mov", "@%s,a", rname);
9784       break;
9785
9786     case FPOINTER:
9787       emitcode ("movx", "@dptr,a");
9788       break;
9789
9790     case GPOINTER:
9791       emitcode ("lcall", "__gptrput");
9792       break;
9793     }
9794
9795   /* if we r done */
9796   if (SPEC_BLEN (etype) <= 8)
9797     return;
9798
9799   emitcode ("inc", "%s", rname);
9800   rLen = SPEC_BLEN (etype);
9801
9802   /* now generate for lengths greater than one byte */
9803   while (1)
9804     {
9805
9806       l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9807
9808       rLen -= 8;
9809       if (rLen < 8)
9810         break;
9811
9812       switch (p_type)
9813         {
9814         case POINTER:
9815           if (*l == '@')
9816             {
9817               MOVA (l);
9818               emitcode ("mov", "@%s,a", rname);
9819             }
9820           else
9821             emitcode ("mov", "@%s,%s", rname, l);
9822           break;
9823
9824         case FPOINTER:
9825           MOVA (l);
9826           emitcode ("movx", "@dptr,a");
9827           break;
9828
9829         case GPOINTER:
9830           MOVA (l);
9831           emitcode ("lcall", "__gptrput");
9832           break;
9833         }
9834       emitcode ("inc", "%s", rname);
9835     }
9836
9837   MOVA (l);
9838
9839   /* last last was not complete */
9840   if (rLen)
9841     {
9842       /* save the byte & read byte */
9843       switch (p_type)
9844         {
9845         case POINTER:
9846           emitcode ("mov", "b,a");
9847           emitcode ("mov", "a,@%s", rname);
9848           break;
9849
9850         case FPOINTER:
9851           emitcode ("mov", "b,a");
9852           emitcode ("movx", "a,@dptr");
9853           break;
9854
9855         case GPOINTER:
9856           emitcode ("push", "b");
9857           emitcode ("push", "acc");
9858           emitcode ("lcall", "__gptrget");
9859           emitcode ("pop", "b");
9860           break;
9861         }
9862
9863       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9864       emitcode ("orl", "a,b");
9865     }
9866
9867   if (p_type == GPOINTER)
9868     emitcode ("pop", "b");
9869
9870   switch (p_type)
9871     {
9872
9873     case POINTER:
9874       emitcode ("mov", "@%s,a", rname);
9875       break;
9876
9877     case FPOINTER:
9878       emitcode ("movx", "@dptr,a");
9879       break;
9880
9881     case GPOINTER:
9882       emitcode ("lcall", "__gptrput");
9883       break;
9884     }
9885 }
9886 /*-----------------------------------------------------------------*/
9887 /* genDataPointerSet - remat pointer to data space                 */
9888 /*-----------------------------------------------------------------*/
9889 static void
9890 genDataPointerSet (operand * right,
9891                    operand * result,
9892                    iCode * ic)
9893 {
9894   int size, offset = 0;
9895   char *l, buff[256];
9896
9897   aopOp (right, ic, FALSE, FALSE);
9898
9899   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9900   size = AOP_SIZE (right);
9901   while (size--)
9902     {
9903       if (offset)
9904         {
9905             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9906         }
9907       else
9908         {
9909             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9910         }
9911         
9912       emitcode ("mov", "%s,%s", buff,
9913                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9914     }
9915
9916   freeAsmop (right, NULL, ic, TRUE);
9917   freeAsmop (result, NULL, ic, TRUE);
9918 }
9919
9920 /*-----------------------------------------------------------------*/
9921 /* genNearPointerSet - emitcode for near pointer put                */
9922 /*-----------------------------------------------------------------*/
9923 static void
9924 genNearPointerSet (operand * right,
9925                    operand * result,
9926                    iCode * ic,
9927                    iCode * pi)
9928 {
9929   asmop *aop = NULL;
9930   char *rname, *l;
9931   sym_link *retype, *letype;
9932   sym_link *ptype = operandType (result);
9933
9934   retype = getSpec (operandType (right));
9935   letype = getSpec (ptype);
9936
9937   aopOp (result, ic, FALSE, FALSE);
9938
9939   /* if the result is rematerializable &
9940      in data space & not a bit variable */
9941   if (AOP_TYPE (result) == AOP_IMMD &&
9942       DCL_TYPE (ptype) == POINTER &&
9943       !IS_BITVAR (retype) &&
9944       !IS_BITVAR (letype))
9945     {
9946       genDataPointerSet (right, result, ic);
9947       return;
9948     }
9949
9950   /* if the value is already in a pointer register
9951      then don't need anything more */
9952   if (!AOP_INPREG (AOP (result)))
9953     {
9954       /* otherwise get a free pointer register */
9955       regs *preg;
9956         
9957       aop = newAsmop (0);
9958       preg = getFreePtr (ic, &aop, FALSE);
9959       emitcode ("mov", "%s,%s",
9960                 preg->name,
9961                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
9962       rname = preg->name;
9963     }
9964   else
9965     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
9966
9967   aopOp (right, ic, FALSE, FALSE);
9968
9969   /* if bitfield then unpack the bits */
9970   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9971     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9972   else
9973     {
9974       /* we have can just get the values */
9975       int size = AOP_SIZE (right);
9976       int offset = 0;
9977
9978       while (size--)
9979         {
9980           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
9981           if (*l == '@')
9982             {
9983               MOVA (l);
9984               emitcode ("mov", "@%s,a", rname);
9985             }
9986           else
9987             emitcode ("mov", "@%s,%s", rname, l);
9988           if (size || pi)
9989             emitcode ("inc", "%s", rname);
9990           offset++;
9991         }
9992     }
9993
9994   /* now some housekeeping stuff */
9995   if (aop)
9996     {
9997       /* we had to allocate for this iCode */
9998       if (pi) aopPut (AOP (result),rname,0);
9999       freeAsmop (NULL, aop, ic, TRUE);
10000     }
10001   else
10002     {
10003       /* we did not allocate which means left
10004          already in a pointer register, then
10005          if size > 0 && this could be used again
10006          we have to point it back to where it
10007          belongs */
10008       if (AOP_SIZE (right) > 1 &&
10009           !OP_SYMBOL (result)->remat &&
10010           (OP_SYMBOL (result)->liveTo > ic->seq ||
10011            ic->depth) &&
10012           !pi)
10013         {
10014           int size = AOP_SIZE (right) - 1;
10015           while (size--)
10016             emitcode ("dec", "%s", rname);
10017         }
10018     }
10019
10020   /* done */
10021   if (pi) pi->generated = 1;
10022   freeAsmop (result, NULL, ic, TRUE);
10023   freeAsmop (right, NULL, ic, TRUE);
10024
10025
10026 }
10027
10028 /*-----------------------------------------------------------------*/
10029 /* genPagedPointerSet - emitcode for Paged pointer put             */
10030 /*-----------------------------------------------------------------*/
10031 static void
10032 genPagedPointerSet (operand * right,
10033                     operand * result,
10034                     iCode * ic,
10035                     iCode *pi)
10036 {
10037   asmop *aop = NULL;
10038   char *rname;
10039   sym_link *retype, *letype;
10040
10041   retype = getSpec (operandType (right));
10042   letype = getSpec (operandType (result));
10043
10044   aopOp (result, ic, FALSE, FALSE);
10045
10046   /* if the value is already in a pointer register
10047      then don't need anything more */
10048   if (!AOP_INPREG (AOP (result)))
10049     {
10050       /* otherwise get a free pointer register */
10051       regs *preg;
10052         
10053       aop = newAsmop (0);
10054       preg = getFreePtr (ic, &aop, FALSE);
10055       emitcode ("mov", "%s,%s",
10056                 preg->name,
10057                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10058       rname = preg->name;
10059     }
10060   else
10061     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10062
10063   aopOp (right, ic, FALSE, FALSE);
10064
10065   /* if bitfield then unpack the bits */
10066   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10067     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10068   else
10069     {
10070       /* we have can just get the values */
10071       int size = AOP_SIZE (right);
10072       int offset = 0;
10073
10074       while (size--)
10075         {
10076           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10077
10078           emitcode ("movx", "@%s,a", rname);
10079
10080           if (size || pi)
10081             emitcode ("inc", "%s", rname);
10082
10083           offset++;
10084         }
10085     }
10086
10087   /* now some housekeeping stuff */
10088   if (aop)
10089     {
10090       if (pi) aopPut (AOP (result),rname,0);
10091       /* we had to allocate for this iCode */
10092       freeAsmop (NULL, aop, ic, TRUE);
10093     }
10094   else
10095     {
10096       /* we did not allocate which means left
10097          already in a pointer register, then
10098          if size > 0 && this could be used again
10099          we have to point it back to where it
10100          belongs */
10101       if (AOP_SIZE (right) > 1 &&
10102           !OP_SYMBOL (result)->remat &&
10103           (OP_SYMBOL (result)->liveTo > ic->seq ||
10104            ic->depth) &&
10105           !pi)
10106         {
10107           int size = AOP_SIZE (right) - 1;
10108           while (size--)
10109             emitcode ("dec", "%s", rname);
10110         }
10111     }
10112
10113   /* done */
10114   if (pi) pi->generated = 1;
10115   freeAsmop (result, NULL, ic, TRUE);
10116   freeAsmop (right, NULL, ic, TRUE);
10117
10118
10119 }
10120
10121 /*-----------------------------------------------------------------*/
10122 /* genFarPointerSet - set value from far space                     */
10123 /*-----------------------------------------------------------------*/
10124 static void
10125 genFarPointerSet (operand * right,
10126                   operand * result, iCode * ic, iCode *pi)
10127 {
10128   int size, offset, dopi=1;
10129   sym_link *retype = getSpec (operandType (right));
10130   sym_link *letype = getSpec (operandType (result));
10131
10132   aopOp (result, ic, FALSE, FALSE);
10133
10134   /* if the operand is already in dptr
10135      then we do nothing else we move the value to dptr */
10136   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10137     {
10138       /* if this is remateriazable */
10139       if (AOP_TYPE (result) == AOP_IMMD)
10140         emitcode ("mov", "dptr,%s", 
10141                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10142       else
10143         {
10144           /* we need to get it byte by byte */
10145           _startLazyDPSEvaluation ();
10146           if (AOP_TYPE (result) != AOP_DPTR)
10147             {
10148               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10149               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10150               if (options.model == MODEL_FLAT24)
10151                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10152             }
10153           else
10154             {
10155               /* We need to generate a load to DPTR indirect through DPTR. */
10156               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10157                 
10158               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10159               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10160               if (options.model == MODEL_FLAT24)
10161                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10162               emitcode ("pop", "dph");
10163               emitcode ("pop", "dpl");
10164               dopi=0;
10165             }
10166           _endLazyDPSEvaluation ();
10167         }
10168     }
10169   /* so dptr know contains the address */
10170   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10171
10172   /* if bit then unpack */
10173   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10174       if (AOP_INDPTRn(result)) {
10175           genSetDPTR(AOP(result)->aopu.dptr);
10176       }
10177       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10178       if (AOP_INDPTRn(result)) {
10179           genSetDPTR(0);
10180       }
10181   } else {
10182       size = AOP_SIZE (right);
10183       offset = 0;
10184       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10185           while (size--) {
10186               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10187               
10188               genSetDPTR(AOP(result)->aopu.dptr);
10189               emitcode ("movx", "@dptr,a");
10190               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10191                   emitcode ("inc", "dptr");
10192               genSetDPTR (0);
10193           }
10194       } else {
10195           _startLazyDPSEvaluation ();
10196           while (size--) {
10197               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10198               
10199               if (AOP_INDPTRn(result)) {
10200                   genSetDPTR(AOP(result)->aopu.dptr);
10201               } else {
10202                   genSetDPTR (0);
10203               }
10204               _flushLazyDPS ();
10205               
10206               emitcode ("movx", "@dptr,a");
10207               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10208                   emitcode ("inc", "dptr");
10209           }
10210           _endLazyDPSEvaluation ();
10211       }
10212   }
10213   
10214   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10215       if (!AOP_INDPTRn(result)) {
10216           _startLazyDPSEvaluation ();
10217           
10218           aopPut (AOP(result),"dpl",0);
10219           aopPut (AOP(result),"dph",1);
10220           if (options.model == MODEL_FLAT24)
10221               aopPut (AOP(result),"dpx",2);
10222
10223           _endLazyDPSEvaluation ();
10224       }
10225       pi->generated=1;
10226   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10227              AOP_SIZE(right) > 1 &&
10228              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10229       
10230       size = AOP_SIZE (right) - 1;
10231       if (AOP_INDPTRn(result)) {
10232           genSetDPTR(AOP(result)->aopu.dptr);
10233       } 
10234       while (size--) emitcode ("lcall","__decdptr");
10235       if (AOP_INDPTRn(result)) {
10236           genSetDPTR(0);
10237       }
10238   }
10239   freeAsmop (result, NULL, ic, TRUE);
10240   freeAsmop (right, NULL, ic, TRUE);
10241 }
10242
10243 /*-----------------------------------------------------------------*/
10244 /* genGenPointerSet - set value from generic pointer space         */
10245 /*-----------------------------------------------------------------*/
10246 static void
10247 genGenPointerSet (operand * right,
10248                   operand * result, iCode * ic, iCode *pi)
10249 {
10250   int size, offset;
10251   sym_link *retype = getSpec (operandType (right));
10252   sym_link *letype = getSpec (operandType (result));
10253
10254   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10255
10256   /* if the operand is already in dptr
10257      then we do nothing else we move the value to dptr */
10258   if (AOP_TYPE (result) != AOP_STR)
10259     {
10260       _startLazyDPSEvaluation ();
10261       /* if this is remateriazable */
10262       if (AOP_TYPE (result) == AOP_IMMD)
10263         {
10264           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10265           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10266           {
10267               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10268           }
10269           else
10270           {
10271               emitcode ("mov", 
10272                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10273           }
10274         }
10275       else
10276         {                       /* we need to get it byte by byte */
10277           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10278           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10279           if (options.model == MODEL_FLAT24) {
10280             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10281             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10282           } else {
10283             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10284           }
10285         }
10286       _endLazyDPSEvaluation ();
10287     }
10288   /* so dptr + b now contains the address */
10289   _G.bInUse++;
10290   aopOp (right, ic, FALSE, TRUE);
10291   _G.bInUse--;
10292     
10293
10294   /* if bit then unpack */
10295   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10296     {
10297         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10298     }
10299   else
10300     {
10301         size = AOP_SIZE (right);
10302         offset = 0;
10303
10304         _startLazyDPSEvaluation ();
10305         while (size--)
10306         {
10307             if (size)
10308             {
10309                 // Set two bytes at a time, passed in _AP & A.
10310                 // dptr will be incremented ONCE by __gptrputWord.
10311                 //
10312                 // Note: any change here must be coordinated
10313                 // with the implementation of __gptrputWord
10314                 // in device/lib/_gptrput.c
10315                 emitcode("mov", "_ap, %s", 
10316                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10317                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10318                 
10319                 genSetDPTR (0);
10320                 _flushLazyDPS ();
10321                 emitcode ("lcall", "__gptrputWord");
10322                 size--;
10323             }
10324             else
10325             {
10326                 // Only one byte to put.
10327                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10328
10329                 genSetDPTR (0);
10330                 _flushLazyDPS ();               
10331                 emitcode ("lcall", "__gptrput");
10332             }
10333             
10334             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10335             {
10336                 emitcode ("inc", "dptr");
10337             }
10338         }
10339         _endLazyDPSEvaluation ();
10340     }
10341
10342   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10343       _startLazyDPSEvaluation ();
10344       
10345       aopPut (AOP(result),"dpl",0);
10346       aopPut (AOP(result),"dph",1);
10347       if (options.model == MODEL_FLAT24) {
10348           aopPut (AOP(result),"dpx",2);
10349           aopPut (AOP(result),"b",3);
10350       } else {
10351           aopPut (AOP(result),"b",2);
10352       }
10353       _endLazyDPSEvaluation ();
10354       
10355       pi->generated=1;
10356   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10357              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10358       
10359       size = AOP_SIZE (right) - 1;
10360       while (size--) emitcode ("lcall","__decdptr");
10361   }
10362   freeAsmop (result, NULL, ic, TRUE);
10363   freeAsmop (right, NULL, ic, TRUE);
10364 }
10365
10366 /*-----------------------------------------------------------------*/
10367 /* genPointerSet - stores the value into a pointer location        */
10368 /*-----------------------------------------------------------------*/
10369 static void
10370 genPointerSet (iCode * ic, iCode *pi)
10371 {
10372   operand *right, *result;
10373   sym_link *type, *etype;
10374   int p_type;
10375
10376   D (emitcode (";", "genPointerSet "););
10377
10378   right = IC_RIGHT (ic);
10379   result = IC_RESULT (ic);
10380
10381   /* depending on the type of pointer we need to
10382      move it to the correct pointer register */
10383   type = operandType (result);
10384   etype = getSpec (type);
10385   /* if left is of type of pointer then it is simple */
10386   if (IS_PTR (type) && !IS_FUNC (type->next))
10387     {
10388       p_type = DCL_TYPE (type);
10389     }
10390   else
10391     {
10392       /* we have to go by the storage class */
10393       p_type = PTR_TYPE (SPEC_OCLS (etype));
10394     }
10395   /* special case when cast remat */
10396   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10397       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10398           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10399           type = operandType (result);
10400           p_type = DCL_TYPE (type);
10401   }
10402
10403   /* now that we have the pointer type we assign
10404      the pointer values */
10405   switch (p_type)
10406     {
10407
10408     case POINTER:
10409     case IPOINTER:
10410       genNearPointerSet (right, result, ic, pi);
10411       break;
10412
10413     case PPOINTER:
10414       genPagedPointerSet (right, result, ic, pi);
10415       break;
10416
10417     case FPOINTER:
10418       genFarPointerSet (right, result, ic, pi);
10419       break;
10420
10421     case GPOINTER:
10422       genGenPointerSet (right, result, ic, pi);
10423       break;
10424
10425     default:
10426       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10427               "genPointerSet: illegal pointer type");
10428     }
10429
10430 }
10431
10432 /*-----------------------------------------------------------------*/
10433 /* genIfx - generate code for Ifx statement                        */
10434 /*-----------------------------------------------------------------*/
10435 static void
10436 genIfx (iCode * ic, iCode * popIc)
10437 {
10438   operand *cond = IC_COND (ic);
10439   int isbit = 0;
10440
10441   D (emitcode (";", "genIfx "););
10442
10443   aopOp (cond, ic, FALSE, FALSE);
10444
10445   /* get the value into acc */
10446   if (AOP_TYPE (cond) != AOP_CRY)
10447     {
10448         toBoolean (cond);
10449     }
10450   else
10451     {
10452         isbit = 1;
10453     }
10454     
10455   /* the result is now in the accumulator */
10456   freeAsmop (cond, NULL, ic, TRUE);
10457
10458   /* if there was something to be popped then do it */
10459   if (popIc)
10460     genIpop (popIc);
10461
10462   /* if the condition is  a bit variable */
10463   if (isbit && IS_ITEMP (cond) &&
10464       SPIL_LOC (cond))
10465     {
10466         genIfxJump (ic, SPIL_LOC (cond)->rname);
10467     }
10468   else if (isbit && !IS_ITEMP (cond))
10469     {
10470         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10471     }
10472   else
10473     {
10474         genIfxJump (ic, "a");
10475     }
10476
10477   ic->generated = 1;
10478 }
10479
10480 /*-----------------------------------------------------------------*/
10481 /* genAddrOf - generates code for address of                       */
10482 /*-----------------------------------------------------------------*/
10483 static void
10484 genAddrOf (iCode * ic)
10485 {
10486   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10487   int size, offset;
10488
10489   D (emitcode (";", "genAddrOf ");
10490     );
10491
10492   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10493
10494   /* if the operand is on the stack then we
10495      need to get the stack offset of this
10496      variable */
10497   if (sym->onStack) {
10498       
10499       /* if 10 bit stack */
10500       if (options.stack10bit) {
10501           char buff[10];
10502           tsprintf(buff, sizeof(buff), 
10503                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10504           /* if it has an offset then we need to compute it */
10505 /*        emitcode ("subb", "a,#!constbyte", */
10506 /*                  -((sym->stack < 0) ? */
10507 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10508 /*                    ((short) sym->stack)) & 0xff); */
10509 /*        emitcode ("mov","b,a"); */
10510 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10511 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10512 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10513           if (sym->stack) {
10514               emitcode ("mov", "a,_bpx");
10515               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10516                                              ((char) (sym->stack - _G.nRegsSaved)) :
10517                                              ((char) sym->stack )) & 0xff);
10518               emitcode ("mov", "b,a");
10519               emitcode ("mov", "a,_bpx+1");
10520               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10521                                               ((short) (sym->stack - _G.nRegsSaved)) :
10522                                               ((short) sym->stack )) >> 8) & 0xff);
10523               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10524               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10525               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10526           } else {
10527               /* we can just move _bp */
10528               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10529               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10530               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10531           }       
10532       } else {
10533           /* if it has an offset then we need to compute it */
10534           if (sym->stack) {
10535               emitcode ("mov", "a,_bp");
10536               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10537               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10538           } else {
10539               /* we can just move _bp */
10540               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10541           }
10542           /* fill the result with zero */
10543           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10544           
10545           
10546           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10547               fprintf (stderr,
10548                        "*** warning: pointer to stack var truncated.\n");
10549           }
10550
10551           offset = 1;
10552           while (size--) {
10553               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10554           }      
10555       }
10556       goto release;
10557   }
10558
10559   /* object not on stack then we need the name */
10560   size = AOP_SIZE (IC_RESULT (ic));
10561   offset = 0;
10562
10563   while (size--)
10564     {
10565       char s[SDCC_NAME_MAX];
10566       if (offset) {
10567           switch (offset) {
10568           case 1:
10569               tsprintf(s, sizeof(s), "#!his",sym->rname);
10570               break;
10571           case 2:
10572               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10573               break;
10574           case 3:
10575               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10576               break;
10577           default: /* should not need this (just in case) */
10578               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10579                        sym->rname,
10580                        offset * 8);
10581           }
10582       } 
10583       else
10584       {
10585           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10586       }
10587         
10588       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10589     }
10590
10591 release:
10592   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10593
10594 }
10595
10596 /*-----------------------------------------------------------------*/
10597 /* genArrayInit - generates code for address of                       */
10598 /*-----------------------------------------------------------------*/
10599 static void
10600 genArrayInit (iCode * ic)
10601 {
10602     literalList *iLoop;
10603     int         ix, count;
10604     int         elementSize = 0, eIndex;
10605     unsigned    val, lastVal;
10606     sym_link    *type;
10607     operand     *left=IC_LEFT(ic);
10608     
10609     D (emitcode (";", "genArrayInit "););
10610
10611     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10612     
10613     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10614     {
10615         // Load immediate value into DPTR.
10616         emitcode("mov", "dptr, %s",
10617              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10618     }
10619     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10620     {
10621 #if 0
10622       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10623               "Unexpected operand to genArrayInit.\n");
10624       exit(1);
10625 #else
10626       // a regression because of SDCCcse.c:1.52
10627       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10628       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10629       if (options.model == MODEL_FLAT24)
10630         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10631 #endif
10632     }
10633     
10634     type = operandType(IC_LEFT(ic));
10635     
10636     if (type && type->next)
10637     {
10638         elementSize = getSize(type->next);
10639     }
10640     else
10641     {
10642         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10643                                 "can't determine element size in genArrayInit.\n");
10644         exit(1);
10645     }
10646     
10647     iLoop = IC_ARRAYILIST(ic);
10648     lastVal = 0xffff;
10649     
10650     while (iLoop)
10651     {
10652         bool firstpass = TRUE;
10653         
10654         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10655                  iLoop->count, (int)iLoop->literalValue, elementSize);
10656         
10657         ix = iLoop->count;
10658         
10659         while (ix)
10660         {
10661             symbol *tlbl = NULL;
10662             
10663             count = ix > 256 ? 256 : ix;
10664             
10665             if (count > 1)
10666             {
10667                 tlbl = newiTempLabel (NULL);
10668                 if (firstpass || (count & 0xff))
10669                 {
10670                     emitcode("mov", "b, #!constbyte", count & 0xff);
10671                 }
10672                 
10673                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10674             }
10675             
10676             firstpass = FALSE;
10677                 
10678             for (eIndex = 0; eIndex < elementSize; eIndex++)
10679             {
10680                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10681                 if (val != lastVal)
10682                 {
10683                     emitcode("mov", "a, #!constbyte", val);
10684                     lastVal = val;
10685                 }
10686                 
10687                 emitcode("movx", "@dptr, a");
10688                 emitcode("inc", "dptr");
10689             }
10690             
10691             if (count > 1)
10692             {
10693                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10694             }
10695             
10696             ix -= count;
10697         }
10698         
10699         iLoop = iLoop->next;
10700     }
10701     
10702     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10703 }
10704
10705 /*-----------------------------------------------------------------*/
10706 /* genFarFarAssign - assignment when both are in far space         */
10707 /*-----------------------------------------------------------------*/
10708 static void
10709 genFarFarAssign (operand * result, operand * right, iCode * ic)
10710 {
10711   int size = AOP_SIZE (right);
10712   int offset = 0;
10713   symbol *rSym = NULL;
10714
10715   if (size == 1)
10716   {
10717       /* quick & easy case. */
10718       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10719       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10720       freeAsmop (right, NULL, ic, FALSE);
10721       /* now assign DPTR to result */
10722       _G.accInUse++;
10723       aopOp(result, ic, FALSE, FALSE);
10724       _G.accInUse--;
10725       aopPut(AOP(result), "a", 0);
10726       freeAsmop(result, NULL, ic, FALSE);
10727       return;
10728   }
10729   
10730   /* See if we've got an underlying symbol to abuse. */
10731   if (IS_SYMOP(result) && OP_SYMBOL(result))
10732   {
10733       if (IS_TRUE_SYMOP(result))
10734       {
10735           rSym = OP_SYMBOL(result);
10736       }
10737       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10738       {
10739           rSym = OP_SYMBOL(result)->usl.spillLoc;
10740       }
10741   }
10742              
10743   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10744   {
10745       /* We can use the '390 auto-toggle feature to good effect here. */
10746       
10747       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10748       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10749       emitcode ("mov", "dptr,#%s", rSym->rname); 
10750       /* DP2 = result, DP1 = right, DP1 is current. */
10751       while (size)
10752       {
10753           emitcode("movx", "a,@dptr");
10754           emitcode("movx", "@dptr,a");
10755           if (--size)
10756           {
10757                emitcode("inc", "dptr");
10758                emitcode("inc", "dptr");
10759           }
10760       }
10761       emitcode("mov", "dps,#0");
10762       freeAsmop (right, NULL, ic, FALSE);
10763 #if 0
10764 some alternative code for processors without auto-toggle
10765 no time to test now, so later well put in...kpb
10766         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10767         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10768         emitcode ("mov", "dptr,#%s", rSym->rname); 
10769         /* DP2 = result, DP1 = right, DP1 is current. */
10770         while (size)
10771         {
10772           --size;
10773           emitcode("movx", "a,@dptr");
10774           if (size)
10775             emitcode("inc", "dptr");
10776           emitcode("inc", "dps");
10777           emitcode("movx", "@dptr,a");
10778           if (size)
10779             emitcode("inc", "dptr");
10780           emitcode("inc", "dps");
10781         }
10782         emitcode("mov", "dps,#0");
10783         freeAsmop (right, NULL, ic, FALSE);
10784 #endif
10785   }
10786   else
10787   {
10788       D (emitcode (";", "genFarFarAssign"););
10789       aopOp (result, ic, TRUE, TRUE);
10790
10791       _startLazyDPSEvaluation ();
10792       
10793       while (size--)
10794         {
10795           aopPut (AOP (result),
10796                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10797           offset++;
10798         }
10799       _endLazyDPSEvaluation ();
10800       freeAsmop (result, NULL, ic, FALSE);
10801       freeAsmop (right, NULL, ic, FALSE);
10802   }
10803 }
10804
10805 /*-----------------------------------------------------------------*/
10806 /* genAssign - generate code for assignment                        */
10807 /*-----------------------------------------------------------------*/
10808 static void
10809 genAssign (iCode * ic)
10810 {
10811   operand *result, *right;
10812   int size, offset;
10813   unsigned long lit = 0L;
10814
10815   D (emitcode (";", "genAssign ");
10816     );
10817
10818   result = IC_RESULT (ic);
10819   right = IC_RIGHT (ic);
10820
10821   /* if they are the same */
10822   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10823     return;
10824
10825   aopOp (right, ic, FALSE, FALSE);
10826
10827   emitcode (";", "genAssign: resultIsFar = %s",
10828             isOperandInFarSpace (result) ?
10829             "TRUE" : "FALSE");
10830
10831   /* special case both in far space */
10832   if ((AOP_TYPE (right) == AOP_DPTR ||
10833        AOP_TYPE (right) == AOP_DPTR2) &&
10834   /* IS_TRUE_SYMOP(result)       && */
10835       isOperandInFarSpace (result))
10836     {
10837       genFarFarAssign (result, right, ic);
10838       return;
10839     }
10840
10841   aopOp (result, ic, TRUE, FALSE);
10842
10843   /* if they are the same registers */
10844   if (sameRegs (AOP (right), AOP (result)))
10845     goto release;
10846
10847   /* if the result is a bit */
10848   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10849     {
10850       /* if the right size is a literal then
10851          we know what the value is */
10852       if (AOP_TYPE (right) == AOP_LIT)
10853         {
10854           if (((int) operandLitValue (right)))
10855             aopPut (AOP (result), one, 0);
10856           else
10857             aopPut (AOP (result), zero, 0);
10858           goto release;
10859         }
10860
10861       /* the right is also a bit variable */
10862       if (AOP_TYPE (right) == AOP_CRY)
10863         {
10864           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10865           aopPut (AOP (result), "c", 0);
10866           goto release;
10867         }
10868
10869       /* we need to or */
10870       toBoolean (right);
10871       aopPut (AOP (result), "a", 0);
10872       goto release;
10873     }
10874
10875   /* bit variables done */
10876   /* general case */
10877   size = AOP_SIZE (result);
10878   offset = 0;
10879   if (AOP_TYPE (right) == AOP_LIT)
10880     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10881
10882   if ((size > 1) &&
10883       (AOP_TYPE (result) != AOP_REG) &&
10884       (AOP_TYPE (right) == AOP_LIT) &&
10885       !IS_FLOAT (operandType (right)))
10886     {
10887       _startLazyDPSEvaluation ();
10888       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10889         {
10890           aopPut (AOP (result),
10891                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10892                   offset);
10893           offset++;
10894           size--;
10895         }
10896       /* And now fill the rest with zeros. */
10897       if (size)
10898         {
10899           emitcode ("clr", "a");
10900         }
10901       while (size--)
10902         {
10903           aopPut (AOP (result), "a", offset++);
10904         }
10905       _endLazyDPSEvaluation ();
10906     }
10907   else
10908     {
10909       _startLazyDPSEvaluation ();
10910       while (size--)
10911         {
10912           aopPut (AOP (result),
10913                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10914                   offset);
10915           offset++;
10916         }
10917       _endLazyDPSEvaluation ();
10918     }
10919
10920 release:
10921   freeAsmop (right, NULL, ic, FALSE);
10922   freeAsmop (result, NULL, ic, TRUE);
10923 }
10924
10925 /*-----------------------------------------------------------------*/
10926 /* genJumpTab - generates code for jump table                      */
10927 /*-----------------------------------------------------------------*/
10928 static void
10929 genJumpTab (iCode * ic)
10930 {
10931   symbol *jtab;
10932   char *l;
10933
10934   D (emitcode (";", "genJumpTab ");
10935     );
10936
10937   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10938   /* get the condition into accumulator */
10939   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10940   MOVA (l);
10941   /* multiply by four! */
10942   emitcode ("add", "a,acc");
10943   emitcode ("add", "a,acc");
10944   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10945
10946   jtab = newiTempLabel (NULL);
10947   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10948   emitcode ("jmp", "@a+dptr");
10949   emitcode ("", "!tlabeldef", jtab->key + 100);
10950   /* now generate the jump labels */
10951   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10952        jtab = setNextItem (IC_JTLABELS (ic)))
10953     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10954
10955 }
10956
10957 /*-----------------------------------------------------------------*/
10958 /* genCast - gen code for casting                                  */
10959 /*-----------------------------------------------------------------*/
10960 static void
10961 genCast (iCode * ic)
10962 {
10963   operand *result = IC_RESULT (ic);
10964   sym_link *ctype = operandType (IC_LEFT (ic));
10965   sym_link *rtype = operandType (IC_RIGHT (ic));
10966   operand *right = IC_RIGHT (ic);
10967   int size, offset;
10968
10969   D (emitcode (";", "genCast "););
10970
10971   /* if they are equivalent then do nothing */
10972   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10973     return;
10974
10975   aopOp (right, ic, FALSE, FALSE);
10976   aopOp (result, ic, FALSE, AOP_USESDPTR(right));
10977
10978   /* if the result is a bit */
10979   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10980   if (IS_BITVAR(OP_SYMBOL(result)->type))
10981     {
10982       /* if the right size is a literal then
10983          we know what the value is */
10984       if (AOP_TYPE (right) == AOP_LIT)
10985         {
10986           if (((int) operandLitValue (right)))
10987             aopPut (AOP (result), one, 0);
10988           else
10989             aopPut (AOP (result), zero, 0);
10990
10991           goto release;
10992         }
10993
10994       /* the right is also a bit variable */
10995       if (AOP_TYPE (right) == AOP_CRY)
10996         {
10997           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10998           aopPut (AOP (result), "c", 0);
10999           goto release;
11000         }
11001
11002       /* we need to or */
11003       toBoolean (right);
11004       aopPut (AOP (result), "a", 0);
11005       goto release;
11006     }
11007
11008   /* if they are the same size : or less */
11009   if (AOP_SIZE (result) <= AOP_SIZE (right))
11010     {
11011
11012       /* if they are in the same place */
11013       if (sameRegs (AOP (right), AOP (result)))
11014         goto release;
11015
11016       /* if they in different places then copy */
11017       size = AOP_SIZE (result);
11018       offset = 0;
11019       _startLazyDPSEvaluation ();
11020       while (size--)
11021         {
11022           aopPut (AOP (result),
11023                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11024                   offset);
11025           offset++;
11026         }
11027       _endLazyDPSEvaluation ();
11028       goto release;
11029     }
11030
11031
11032   /* if the result is of type pointer */
11033   if (IS_PTR (ctype))
11034     {
11035
11036       int p_type;
11037       sym_link *type = operandType (right);
11038
11039       /* pointer to generic pointer */
11040       if (IS_GENPTR (ctype))
11041         {
11042           if (IS_PTR (type))
11043             {
11044               p_type = DCL_TYPE (type);
11045             }
11046           else
11047             {
11048 #if OLD_CAST_BEHAVIOR
11049               /* KV: we are converting a non-pointer type to
11050                * a generic pointer. This (ifdef'd out) code
11051                * says that the resulting generic pointer
11052                * should have the same class as the storage
11053                * location of the non-pointer variable.
11054                *
11055                * For example, converting an int (which happens
11056                * to be stored in DATA space) to a pointer results
11057                * in a DATA generic pointer; if the original int
11058                * in XDATA space, so will be the resulting pointer.
11059                *
11060                * I don't like that behavior, and thus this change:
11061                * all such conversions will be forced to XDATA and
11062                * throw a warning. If you want some non-XDATA
11063                * type, or you want to suppress the warning, you
11064                * must go through an intermediate cast, like so:
11065                *
11066                * char _generic *gp = (char _xdata *)(intVar);
11067                */
11068               sym_link *etype = getSpec (type);
11069
11070               /* we have to go by the storage class */
11071               if (SPEC_OCLS (etype) != generic)
11072                 {
11073                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11074                 }
11075               else
11076 #endif
11077                 {
11078                   /* Converting unknown class (i.e. register variable)
11079                    * to generic pointer. This is not good, but
11080                    * we'll make a guess (and throw a warning).
11081                    */
11082                   p_type = FPOINTER;
11083                   werror (W_INT_TO_GEN_PTR_CAST);
11084                 }
11085             }
11086
11087           /* the first two bytes are known */
11088           size = GPTRSIZE - 1;
11089           offset = 0;
11090           _startLazyDPSEvaluation ();
11091           while (size--)
11092             {
11093               aopPut (AOP (result),
11094                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11095                       offset);
11096               offset++;
11097             }
11098           _endLazyDPSEvaluation ();
11099
11100           /* the last byte depending on type */
11101             {
11102                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11103                 char gpValStr[10];
11104             
11105                 if (gpVal == -1)
11106                 {
11107                     // pointerTypeToGPByte will have bitched.
11108                     exit(1);
11109                 }
11110             
11111                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11112                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11113             }
11114           goto release;
11115         }
11116
11117       /* just copy the pointers */
11118       size = AOP_SIZE (result);
11119       offset = 0;
11120       _startLazyDPSEvaluation ();
11121       while (size--)
11122         {
11123           aopPut (AOP (result),
11124                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11125                   offset);
11126           offset++;
11127         }
11128       _endLazyDPSEvaluation ();
11129       goto release;
11130     }
11131
11132   /* so we now know that the size of destination is greater
11133      than the size of the source */
11134   /* we move to result for the size of source */
11135   size = AOP_SIZE (right);
11136   offset = 0;
11137   _startLazyDPSEvaluation ();
11138   while (size--)
11139     {
11140       aopPut (AOP (result),
11141               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11142               offset);
11143       offset++;
11144     }
11145   _endLazyDPSEvaluation ();
11146
11147   /* now depending on the sign of the source && destination */
11148   size = AOP_SIZE (result) - AOP_SIZE (right);
11149   /* if unsigned or not an integral type */
11150   /* also, if the source is a bit, we don't need to sign extend, because
11151    * it can't possibly have set the sign bit.
11152    */
11153   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
11154     {
11155       while (size--)
11156         {
11157           aopPut (AOP (result), zero, offset++);
11158         }
11159     }
11160   else
11161     {
11162       /* we need to extend the sign :{ */
11163       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11164                         FALSE, FALSE, NULL));
11165       emitcode ("rlc", "a");
11166       emitcode ("subb", "a,acc");
11167       while (size--)
11168         aopPut (AOP (result), "a", offset++);
11169     }
11170
11171   /* we are done hurray !!!! */
11172
11173 release:
11174   freeAsmop (right, NULL, ic, TRUE);
11175   freeAsmop (result, NULL, ic, TRUE);
11176
11177 }
11178
11179 /*-----------------------------------------------------------------*/
11180 /* genDjnz - generate decrement & jump if not zero instrucion      */
11181 /*-----------------------------------------------------------------*/
11182 static int
11183 genDjnz (iCode * ic, iCode * ifx)
11184 {
11185   symbol *lbl, *lbl1;
11186   if (!ifx)
11187     return 0;
11188
11189   /* if the if condition has a false label
11190      then we cannot save */
11191   if (IC_FALSE (ifx))
11192     return 0;
11193
11194   /* if the minus is not of the form
11195      a = a - 1 */
11196   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11197       !IS_OP_LITERAL (IC_RIGHT (ic)))
11198     return 0;
11199
11200   if (operandLitValue (IC_RIGHT (ic)) != 1)
11201     return 0;
11202
11203   /* if the size of this greater than one then no
11204      saving */
11205   if (getSize (operandType (IC_RESULT (ic))) > 1)
11206     return 0;
11207
11208   /* otherwise we can save BIG */
11209   D(emitcode(";", "genDjnz"););
11210
11211   lbl = newiTempLabel (NULL);
11212   lbl1 = newiTempLabel (NULL);
11213
11214   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11215
11216   if (AOP_NEEDSACC(IC_RESULT(ic)))
11217   {
11218       /* If the result is accessed indirectly via
11219        * the accumulator, we must explicitly write
11220        * it back after the decrement.
11221        */
11222       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11223       
11224       if (strcmp(rByte, "a"))
11225       {
11226            /* Something is hopelessly wrong */
11227            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11228                    __FILE__, __LINE__);
11229            /* We can just give up; the generated code will be inefficient,
11230             * but what the hey.
11231             */
11232            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11233            return 0;
11234       }
11235       emitcode ("dec", "%s", rByte);
11236       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11237       emitcode ("jnz", "!tlabel", lbl->key + 100);
11238   }
11239   else if (IS_AOP_PREG (IC_RESULT (ic)))
11240     {
11241       emitcode ("dec", "%s",
11242                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11243       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11244       emitcode ("jnz", "!tlabel", lbl->key + 100);
11245     }
11246   else
11247     {
11248       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11249                 lbl->key + 100);
11250     }
11251   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11252   emitcode ("", "!tlabeldef", lbl->key + 100);
11253   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11254   emitcode ("", "!tlabeldef", lbl1->key + 100);
11255
11256   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11257   ifx->generated = 1;
11258   return 1;
11259 }
11260
11261 /*-----------------------------------------------------------------*/
11262 /* genReceive - generate code for a receive iCode                  */
11263 /*-----------------------------------------------------------------*/
11264 static void
11265 genReceive (iCode * ic)
11266 {
11267     int size = getSize (operandType (IC_RESULT (ic)));
11268     int offset = 0;
11269     int rb1off ;
11270     
11271     D (emitcode (";", "genReceive "););
11272
11273     if (ic->argreg == 1) 
11274     {
11275         /* first parameter */
11276         if (AOP_IS_STR(IC_RESULT(ic)))
11277         {
11278             /* Nothing to do: it's already in the proper place. */
11279             return;
11280         }
11281         else
11282         {
11283             bool useDp2;
11284             
11285             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11286                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11287                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11288             
11289             _G.accInUse++;
11290             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11291             _G.accInUse--; 
11292             
11293             /* Sanity checking... */
11294             if (AOP_USESDPTR(IC_RESULT(ic)))
11295             {
11296                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11297                         "genReceive got unexpected DPTR.");
11298             }
11299             assignResultValue (IC_RESULT (ic));
11300         }
11301     } 
11302     else 
11303     { 
11304         /* second receive onwards */
11305         /* this gets a little tricky since unused recevies will be
11306          eliminated, we have saved the reg in the type field . and
11307          we use that to figure out which register to use */
11308         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11309         rb1off = ic->argreg;
11310         while (size--) 
11311         {
11312             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11313         }
11314     }
11315     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11316 }
11317
11318 /*-----------------------------------------------------------------*/
11319 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11320 /*-----------------------------------------------------------------*/
11321 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11322 {
11323     operand *from , *to , *count;
11324     symbol *lbl;
11325     bitVect *rsave;
11326     int i;
11327
11328     /* we know it has to be 3 parameters */
11329     assert (nparms == 3);
11330     
11331     rsave = newBitVect(16);
11332     /* save DPTR if it needs to be saved */
11333     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11334             if (bitVectBitValue(ic->rMask,i))
11335                     rsave = bitVectSetBit(rsave,i);
11336     }
11337     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11338                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11339     savermask(rsave);
11340     
11341     to = parms[0];
11342     from = parms[1];
11343     count = parms[2];
11344
11345     aopOp (from, ic->next, FALSE, FALSE);
11346
11347     /* get from into DPTR1 */
11348     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11349     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11350     if (options.model == MODEL_FLAT24) {
11351         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11352     }
11353
11354     freeAsmop (from, NULL, ic, FALSE);
11355     aopOp (to, ic, FALSE, FALSE);
11356     /* get "to" into DPTR */
11357     /* if the operand is already in dptr
11358        then we do nothing else we move the value to dptr */
11359     if (AOP_TYPE (to) != AOP_STR) {
11360         /* if already in DPTR then we need to push */
11361         if (AOP_TYPE(to) == AOP_DPTR) {
11362             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11363             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11364             if (options.model == MODEL_FLAT24)
11365                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11366             emitcode ("pop", "dph");
11367             emitcode ("pop", "dpl");        
11368         } else {
11369             _startLazyDPSEvaluation ();
11370             /* if this is remateriazable */
11371             if (AOP_TYPE (to) == AOP_IMMD) {
11372                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11373             } else {                    /* we need to get it byte by byte */
11374                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11375                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11376                 if (options.model == MODEL_FLAT24) {
11377                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11378                 }
11379             }
11380             _endLazyDPSEvaluation ();
11381         }
11382     }
11383     freeAsmop (to, NULL, ic, FALSE);
11384     _G.dptrInUse = _G.dptr1InUse = 1;
11385     aopOp (count, ic->next->next, FALSE,FALSE);
11386     lbl =newiTempLabel(NULL);
11387
11388     /* now for the actual copy */
11389     if (AOP_TYPE(count) == AOP_LIT && 
11390         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11391         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11392         if (fromc) {
11393             emitcode ("lcall","__bi_memcpyc2x_s");
11394         } else {
11395             emitcode ("lcall","__bi_memcpyx2x_s");
11396         }
11397         freeAsmop (count, NULL, ic, FALSE);
11398     } else {
11399         symbol *lbl1 = newiTempLabel(NULL);
11400         
11401         emitcode (";"," Auto increment but no djnz");
11402         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11403         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11404         freeAsmop (count, NULL, ic, FALSE);
11405         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11406         emitcode ("","!tlabeldef",lbl->key+100);
11407         if (fromc) {
11408             emitcode ("clr","a");
11409             emitcode ("movc", "a,@a+dptr");
11410         } else 
11411             emitcode ("movx", "a,@dptr");
11412         emitcode ("movx", "@dptr,a");
11413         emitcode ("inc", "dptr");
11414         emitcode ("inc", "dptr");
11415         emitcode ("mov","a,b");
11416         emitcode ("orl","a,_ap");
11417         emitcode ("jz","!tlabel",lbl1->key+100);
11418         emitcode ("mov","a,_ap");
11419         emitcode ("add","a,#!constbyte",0xFF);
11420         emitcode ("mov","_ap,a");
11421         emitcode ("mov","a,b");
11422         emitcode ("addc","a,#!constbyte",0xFF);
11423         emitcode ("mov","b,a");
11424         emitcode ("sjmp","!tlabel",lbl->key+100);
11425         emitcode ("","!tlabeldef",lbl1->key+100);
11426     }
11427     emitcode ("mov", "dps,#0"); 
11428     _G.dptrInUse = _G.dptr1InUse = 0;
11429     unsavermask(rsave);
11430
11431 }
11432
11433 /*-----------------------------------------------------------------*/
11434 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11435 /*-----------------------------------------------------------------*/
11436 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11437 {
11438     operand *from , *to , *count;
11439     symbol *lbl,*lbl2;
11440     bitVect *rsave;
11441     int i;
11442
11443     /* we know it has to be 3 parameters */
11444     assert (nparms == 3);
11445     
11446     rsave = newBitVect(16);
11447     /* save DPTR if it needs to be saved */
11448     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11449             if (bitVectBitValue(ic->rMask,i))
11450                     rsave = bitVectSetBit(rsave,i);
11451     }
11452     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11453                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11454     savermask(rsave);
11455     
11456     to = parms[0];
11457     from = parms[1];
11458     count = parms[2];
11459
11460     aopOp (from, ic->next, FALSE, FALSE);
11461
11462     /* get from into DPTR1 */
11463     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11464     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11465     if (options.model == MODEL_FLAT24) {
11466         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11467     }
11468
11469     freeAsmop (from, NULL, ic, FALSE);
11470     aopOp (to, ic, FALSE, FALSE);
11471     /* get "to" into DPTR */
11472     /* if the operand is already in dptr
11473        then we do nothing else we move the value to dptr */
11474     if (AOP_TYPE (to) != AOP_STR) {
11475         /* if already in DPTR then we need to push */
11476         if (AOP_TYPE(to) == AOP_DPTR) {
11477             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11478             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11479             if (options.model == MODEL_FLAT24)
11480                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11481             emitcode ("pop", "dph");
11482             emitcode ("pop", "dpl");        
11483         } else {
11484             _startLazyDPSEvaluation ();
11485             /* if this is remateriazable */
11486             if (AOP_TYPE (to) == AOP_IMMD) {
11487                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11488             } else {                    /* we need to get it byte by byte */
11489                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11490                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11491                 if (options.model == MODEL_FLAT24) {
11492                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11493                 }
11494             }
11495             _endLazyDPSEvaluation ();
11496         }
11497     }
11498     freeAsmop (to, NULL, ic, FALSE);
11499     _G.dptrInUse = _G.dptr1InUse = 1;
11500     aopOp (count, ic->next->next, FALSE,FALSE);
11501     lbl =newiTempLabel(NULL);
11502     lbl2 =newiTempLabel(NULL);
11503
11504     /* now for the actual compare */
11505     if (AOP_TYPE(count) == AOP_LIT && 
11506         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11507         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11508         if (fromc)
11509             emitcode("lcall","__bi_memcmpc2x_s");
11510         else
11511             emitcode("lcall","__bi_memcmpx2x_s");
11512         freeAsmop (count, NULL, ic, FALSE);
11513         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11514         aopPut(AOP(IC_RESULT(ic)),"a",0);
11515         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11516     } else {
11517         symbol *lbl1 = newiTempLabel(NULL);
11518
11519         emitcode("push","ar0");         
11520         emitcode (";"," Auto increment but no djnz");
11521         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11522         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11523         freeAsmop (count, NULL, ic, FALSE);
11524         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11525         emitcode ("","!tlabeldef",lbl->key+100);
11526         if (fromc) {
11527             emitcode ("clr","a");
11528             emitcode ("movc", "a,@a+dptr");
11529         } else 
11530             emitcode ("movx", "a,@dptr");
11531         emitcode ("mov","r0,a");
11532         emitcode ("movx", "a,@dptr");
11533         emitcode ("clr","c");
11534         emitcode ("subb","a,r0");
11535         emitcode ("jnz","!tlabel",lbl2->key+100);
11536         emitcode ("inc", "dptr");
11537         emitcode ("inc", "dptr");
11538         emitcode ("mov","a,b");
11539         emitcode ("orl","a,_ap");
11540         emitcode ("jz","!tlabel",lbl1->key+100);
11541         emitcode ("mov","a,_ap");
11542         emitcode ("add","a,#!constbyte",0xFF);
11543         emitcode ("mov","_ap,a");
11544         emitcode ("mov","a,b");
11545         emitcode ("addc","a,#!constbyte",0xFF);
11546         emitcode ("mov","b,a");
11547         emitcode ("sjmp","!tlabel",lbl->key+100);
11548         emitcode ("","!tlabeldef",lbl1->key+100);
11549         emitcode ("clr","a");
11550         emitcode ("","!tlabeldef",lbl2->key+100);
11551         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11552         aopPut(AOP(IC_RESULT(ic)),"a",0);
11553         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11554         emitcode("pop","ar0");
11555         emitcode ("mov", "dps,#0");      
11556     }
11557     _G.dptrInUse = _G.dptr1InUse = 0;
11558     unsavermask(rsave);
11559
11560 }
11561
11562 /*-----------------------------------------------------------------*/
11563 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11564 /* port, first parameter output area second parameter pointer to   */
11565 /* port third parameter count                                      */
11566 /*-----------------------------------------------------------------*/
11567 static void genInp( iCode *ic, int nparms, operand **parms)
11568 {
11569     operand *from , *to , *count;
11570     symbol *lbl;
11571     bitVect *rsave;
11572     int i;
11573
11574     /* we know it has to be 3 parameters */
11575     assert (nparms == 3);
11576     
11577     rsave = newBitVect(16);
11578     /* save DPTR if it needs to be saved */
11579     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11580             if (bitVectBitValue(ic->rMask,i))
11581                     rsave = bitVectSetBit(rsave,i);
11582     }
11583     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11584                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11585     savermask(rsave);
11586     
11587     to = parms[0];
11588     from = parms[1];
11589     count = parms[2];
11590
11591     aopOp (from, ic->next, FALSE, FALSE);
11592
11593     /* get from into DPTR1 */
11594     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11595     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11596     if (options.model == MODEL_FLAT24) {
11597         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11598     }
11599
11600     freeAsmop (from, NULL, ic, FALSE);
11601     aopOp (to, ic, FALSE, FALSE);
11602     /* get "to" into DPTR */
11603     /* if the operand is already in dptr
11604        then we do nothing else we move the value to dptr */
11605     if (AOP_TYPE (to) != AOP_STR) {
11606         /* if already in DPTR then we need to push */
11607         if (AOP_TYPE(to) == AOP_DPTR) {
11608             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11609             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11610             if (options.model == MODEL_FLAT24)
11611                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11612             emitcode ("pop", "dph");
11613             emitcode ("pop", "dpl");        
11614         } else {
11615             _startLazyDPSEvaluation ();
11616             /* if this is remateriazable */
11617             if (AOP_TYPE (to) == AOP_IMMD) {
11618                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11619             } else {                    /* we need to get it byte by byte */
11620                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11621                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11622                 if (options.model == MODEL_FLAT24) {
11623                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11624                 }
11625             }
11626             _endLazyDPSEvaluation ();
11627         }
11628     }
11629     freeAsmop (to, NULL, ic, FALSE);
11630
11631     _G.dptrInUse = _G.dptr1InUse = 1;
11632     aopOp (count, ic->next->next, FALSE,FALSE);
11633     lbl =newiTempLabel(NULL);
11634
11635     /* now for the actual copy */
11636     if (AOP_TYPE(count) == AOP_LIT && 
11637         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11638         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11639         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11640         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11641         freeAsmop (count, NULL, ic, FALSE);
11642         emitcode ("","!tlabeldef",lbl->key+100);
11643         emitcode ("movx", "a,@dptr");   /* read data from port */
11644         emitcode ("dec","dps");         /* switch to DPTR */
11645         emitcode ("movx", "@dptr,a");   /* save into location */
11646         emitcode ("inc", "dptr");       /* point to next area */
11647         emitcode ("inc","dps");         /* switch to DPTR2 */
11648         emitcode ("djnz","b,!tlabel",lbl->key+100);
11649     } else {
11650         symbol *lbl1 = newiTempLabel(NULL);
11651         
11652         emitcode (";"," Auto increment but no djnz");
11653         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11654         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11655         freeAsmop (count, NULL, ic, FALSE);
11656         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11657         emitcode ("","!tlabeldef",lbl->key+100);
11658         emitcode ("movx", "a,@dptr");
11659         emitcode ("dec","dps");         /* switch to DPTR */
11660         emitcode ("movx", "@dptr,a");
11661         emitcode ("inc", "dptr");
11662         emitcode ("inc","dps");         /* switch to DPTR2 */
11663 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11664 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11665         emitcode ("mov","a,b");
11666         emitcode ("orl","a,_ap");
11667         emitcode ("jz","!tlabel",lbl1->key+100);
11668         emitcode ("mov","a,_ap");
11669         emitcode ("add","a,#!constbyte",0xFF);
11670         emitcode ("mov","_ap,a");
11671         emitcode ("mov","a,b");
11672         emitcode ("addc","a,#!constbyte",0xFF);
11673         emitcode ("mov","b,a");
11674         emitcode ("sjmp","!tlabel",lbl->key+100);
11675         emitcode ("","!tlabeldef",lbl1->key+100);
11676     }
11677     emitcode ("mov", "dps,#0"); 
11678     _G.dptrInUse = _G.dptr1InUse = 0;
11679     unsavermask(rsave);
11680
11681 }
11682
11683 /*-----------------------------------------------------------------*/
11684 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11685 /* port, first parameter output area second parameter pointer to   */
11686 /* port third parameter count                                      */
11687 /*-----------------------------------------------------------------*/
11688 static void genOutp( iCode *ic, int nparms, operand **parms)
11689 {
11690     operand *from , *to , *count;
11691     symbol *lbl;
11692     bitVect *rsave;
11693     int i;
11694
11695     /* we know it has to be 3 parameters */
11696     assert (nparms == 3);
11697     
11698     rsave = newBitVect(16);
11699     /* save DPTR if it needs to be saved */
11700     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11701             if (bitVectBitValue(ic->rMask,i))
11702                     rsave = bitVectSetBit(rsave,i);
11703     }
11704     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11705                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11706     savermask(rsave);
11707     
11708     to = parms[0];
11709     from = parms[1];
11710     count = parms[2];
11711
11712     aopOp (from, ic->next, FALSE, FALSE);
11713
11714     /* get from into DPTR1 */
11715     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11716     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11717     if (options.model == MODEL_FLAT24) {
11718         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11719     }
11720
11721     freeAsmop (from, NULL, ic, FALSE);
11722     aopOp (to, ic, FALSE, FALSE);
11723     /* get "to" into DPTR */
11724     /* if the operand is already in dptr
11725        then we do nothing else we move the value to dptr */
11726     if (AOP_TYPE (to) != AOP_STR) {
11727         /* if already in DPTR then we need to push */
11728         if (AOP_TYPE(to) == AOP_DPTR) {
11729             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11730             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11731             if (options.model == MODEL_FLAT24)
11732                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11733             emitcode ("pop", "dph");
11734             emitcode ("pop", "dpl");        
11735         } else {
11736             _startLazyDPSEvaluation ();
11737             /* if this is remateriazable */
11738             if (AOP_TYPE (to) == AOP_IMMD) {
11739                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11740             } else {                    /* we need to get it byte by byte */
11741                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11742                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11743                 if (options.model == MODEL_FLAT24) {
11744                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11745                 }
11746             }
11747             _endLazyDPSEvaluation ();
11748         }
11749     }
11750     freeAsmop (to, NULL, ic, FALSE);
11751
11752     _G.dptrInUse = _G.dptr1InUse = 1;
11753     aopOp (count, ic->next->next, FALSE,FALSE);
11754     lbl =newiTempLabel(NULL);
11755
11756     /* now for the actual copy */
11757     if (AOP_TYPE(count) == AOP_LIT && 
11758         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11759         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11760         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11761         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11762         emitcode ("","!tlabeldef",lbl->key+100);
11763         emitcode ("movx", "a,@dptr");   /* read data from port */
11764         emitcode ("inc","dps");         /* switch to DPTR2 */
11765         emitcode ("movx", "@dptr,a");   /* save into location */
11766         emitcode ("inc", "dptr");       /* point to next area */
11767         emitcode ("dec","dps");         /* switch to DPTR */
11768         emitcode ("djnz","b,!tlabel",lbl->key+100);
11769         freeAsmop (count, NULL, ic, FALSE);
11770     } else {
11771         symbol *lbl1 = newiTempLabel(NULL);
11772         
11773         emitcode (";"," Auto increment but no djnz");
11774         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11775         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11776         freeAsmop (count, NULL, ic, FALSE);
11777         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11778         emitcode ("","!tlabeldef",lbl->key+100);
11779         emitcode ("movx", "a,@dptr");
11780         emitcode ("inc", "dptr");
11781         emitcode ("inc","dps");         /* switch to DPTR2 */
11782         emitcode ("movx", "@dptr,a");
11783         emitcode ("dec","dps");         /* switch to DPTR */
11784         emitcode ("mov","a,b");
11785         emitcode ("orl","a,_ap");
11786         emitcode ("jz","!tlabel",lbl1->key+100);
11787         emitcode ("mov","a,_ap");
11788         emitcode ("add","a,#!constbyte",0xFF);
11789         emitcode ("mov","_ap,a");
11790         emitcode ("mov","a,b");
11791         emitcode ("addc","a,#!constbyte",0xFF);
11792         emitcode ("mov","b,a");
11793         emitcode ("sjmp","!tlabel",lbl->key+100);
11794         emitcode ("","!tlabeldef",lbl1->key+100);
11795     }
11796     emitcode ("mov", "dps,#0"); 
11797     _G.dptrInUse = _G.dptr1InUse = 0;
11798     unsavermask(rsave);
11799
11800 }
11801
11802 /*-----------------------------------------------------------------*/
11803 /* genSwapW - swap lower & high order bytes                        */
11804 /*-----------------------------------------------------------------*/
11805 static void genSwapW(iCode *ic, int nparms, operand **parms)
11806 {
11807     operand *dest;
11808     operand *src;
11809     assert (nparms==1);
11810
11811     src = parms[0];
11812     dest=IC_RESULT(ic);
11813
11814     assert(getSize(operandType(src))==2);
11815
11816     aopOp (src, ic, FALSE, FALSE);
11817     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11818     _G.accInUse++;
11819     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11820     _G.accInUse--;
11821     freeAsmop (src, NULL, ic, FALSE);
11822     
11823     aopOp (dest,ic, FALSE, FALSE);
11824     aopPut(AOP(dest),"b",0);
11825     aopPut(AOP(dest),"a",1);
11826     freeAsmop (dest, NULL, ic, FALSE);    
11827 }
11828
11829 /*-----------------------------------------------------------------*/
11830 /* genMemsetX - gencode for memSetX data                           */
11831 /*-----------------------------------------------------------------*/
11832 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11833 {
11834     operand *to , *val , *count;
11835     symbol *lbl;
11836     char *l;
11837     int i;
11838     bitVect *rsave;
11839
11840     /* we know it has to be 3 parameters */
11841     assert (nparms == 3);
11842     
11843     to = parms[0];
11844     val = parms[1];
11845     count = parms[2];
11846         
11847     /* save DPTR if it needs to be saved */
11848     rsave = newBitVect(16);
11849     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11850             if (bitVectBitValue(ic->rMask,i))
11851                     rsave = bitVectSetBit(rsave,i);
11852     }
11853     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11854                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11855     savermask(rsave);
11856
11857     aopOp (to, ic, FALSE, FALSE);
11858     /* get "to" into DPTR */
11859     /* if the operand is already in dptr
11860        then we do nothing else we move the value to dptr */
11861     if (AOP_TYPE (to) != AOP_STR) {
11862         /* if already in DPTR then we need to push */
11863         if (AOP_TYPE(to) == AOP_DPTR) {
11864             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11865             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11866             if (options.model == MODEL_FLAT24)
11867                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11868             emitcode ("pop", "dph");
11869             emitcode ("pop", "dpl");        
11870         } else {
11871             _startLazyDPSEvaluation ();
11872             /* if this is remateriazable */
11873             if (AOP_TYPE (to) == AOP_IMMD) {
11874                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11875             } else {                    /* we need to get it byte by byte */
11876                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11877                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11878                 if (options.model == MODEL_FLAT24) {
11879                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11880                 }
11881             }
11882             _endLazyDPSEvaluation ();
11883         }
11884     }
11885     freeAsmop (to, NULL, ic, FALSE);
11886
11887     aopOp (val, ic->next->next, FALSE,FALSE);
11888     aopOp (count, ic->next->next, FALSE,FALSE);    
11889     lbl =newiTempLabel(NULL);
11890     /* now for the actual copy */
11891     if (AOP_TYPE(count) == AOP_LIT && 
11892         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11893         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11894         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11895         MOVA(l);
11896         emitcode ("","!tlabeldef",lbl->key+100);
11897         emitcode ("movx", "@dptr,a");
11898         emitcode ("inc", "dptr");
11899         emitcode ("djnz","b,!tlabel",lbl->key+100);
11900     } else {
11901         symbol *lbl1 = newiTempLabel(NULL);
11902         
11903         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11904         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11905         emitcode ("","!tlabeldef",lbl->key+100);
11906         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11907         emitcode ("movx", "@dptr,a");
11908         emitcode ("inc", "dptr");
11909         emitcode ("mov","a,b");
11910         emitcode ("orl","a,_ap");
11911         emitcode ("jz","!tlabel",lbl1->key+100);
11912         emitcode ("mov","a,_ap");
11913         emitcode ("add","a,#!constbyte",0xFF);
11914         emitcode ("mov","_ap,a");
11915         emitcode ("mov","a,b");
11916         emitcode ("addc","a,#!constbyte",0xFF);
11917         emitcode ("mov","b,a");
11918         emitcode ("sjmp","!tlabel",lbl->key+100);
11919         emitcode ("","!tlabeldef",lbl1->key+100);
11920     }
11921     freeAsmop (count, NULL, ic, FALSE);
11922     unsavermask(rsave);
11923 }
11924
11925 /*-----------------------------------------------------------------*/
11926 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11927 /*-----------------------------------------------------------------*/
11928 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11929 {
11930         bitVect *rsave ;
11931         operand *pnum, *result;
11932         int i;
11933     
11934         assert (nparms==1);
11935         /* save registers that need to be saved */
11936         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11937                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11938     
11939         pnum = parms[0]; 
11940         aopOp (pnum, ic, FALSE, FALSE);
11941         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11942         freeAsmop (pnum, NULL, ic, FALSE);
11943         emitcode ("lcall","NatLib_LoadPrimitive");
11944         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11945         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11946             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11947                 for (i = (size-1) ; i >= 0 ; i-- ) {
11948                         emitcode ("push","a%s",javaRet[i]);
11949                 }
11950                 for (i=0; i < size ; i++ ) {
11951                         emitcode ("pop","a%s",
11952                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
11953                 }
11954         } else {
11955                 for (i = 0 ; i < size ; i++ ) {
11956                         aopPut(AOP(result),javaRet[i],i);
11957                 }
11958         }    
11959         freeAsmop (result, NULL, ic, FALSE);
11960         unsavermask(rsave);
11961 }
11962
11963 /*-----------------------------------------------------------------*/
11964 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11965 /*-----------------------------------------------------------------*/
11966 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11967 {
11968         bitVect *rsave ;
11969         operand *pnum, *result;
11970         int size = 3;
11971         int i;
11972     
11973         assert (nparms==1);
11974         /* save registers that need to be saved */
11975         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11976                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11977     
11978         pnum = parms[0]; 
11979         aopOp (pnum, ic, FALSE, FALSE);
11980         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11981         freeAsmop (pnum, NULL, ic, FALSE);
11982         emitcode ("lcall","NatLib_LoadPointer");
11983         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11984         if (AOP_TYPE(result)!=AOP_STR) {
11985                 for (i = 0 ; i < size ; i++ ) {
11986                         aopPut(AOP(result),fReturn[i],i);
11987                 }
11988         }    
11989         freeAsmop (result, NULL, ic, FALSE);
11990         unsavermask(rsave);
11991 }
11992
11993 /*-----------------------------------------------------------------*/
11994 /* genNatLibInstallStateBlock -                                    */
11995 /*-----------------------------------------------------------------*/
11996 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
11997                                        operand **parms, const char *name)
11998 {
11999         bitVect *rsave ;
12000         operand *psb, *handle;
12001         assert (nparms==2);
12002
12003         /* save registers that need to be saved */
12004         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12005                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12006         psb = parms[0];
12007         handle = parms[1];
12008
12009         /* put pointer to state block into DPTR1 */
12010         aopOp (psb, ic, FALSE, FALSE);
12011         if (AOP_TYPE (psb) == AOP_IMMD) {
12012                 emitcode ("mov","dps,#1");
12013                 emitcode ("mov", "dptr,%s",
12014                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12015                 emitcode ("mov","dps,#0");
12016         } else {
12017                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12018                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12019                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12020         }
12021         freeAsmop (psb, NULL, ic, FALSE);
12022
12023         /* put libraryID into DPTR */
12024         emitcode ("mov","dptr,#LibraryID");
12025
12026         /* put handle into r3:r2 */
12027         aopOp (handle, ic, FALSE, FALSE);
12028         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12029                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12030                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12031                 emitcode ("pop","ar3");
12032                 emitcode ("pop","ar2");
12033         } else {        
12034                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12035                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12036         }
12037         freeAsmop (psb, NULL, ic, FALSE);
12038
12039         /* make the call */
12040         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12041
12042         /* put return value into place*/
12043         _G.accInUse++;
12044         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12045         _G.accInUse--;
12046         aopPut(AOP(IC_RESULT(ic)),"a",0);
12047         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12048         unsavermask(rsave);
12049 }
12050
12051 /*-----------------------------------------------------------------*/
12052 /* genNatLibRemoveStateBlock -                                     */
12053 /*-----------------------------------------------------------------*/
12054 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12055 {
12056         bitVect *rsave ;
12057
12058         assert(nparms==0);
12059
12060         /* save registers that need to be saved */
12061         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12062                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12063
12064         /* put libraryID into DPTR */
12065         emitcode ("mov","dptr,#LibraryID");
12066         /* make the call */
12067         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12068         unsavermask(rsave);
12069 }
12070
12071 /*-----------------------------------------------------------------*/
12072 /* genNatLibGetStateBlock -                                        */
12073 /*-----------------------------------------------------------------*/
12074 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12075                                    operand **parms,const char *name)
12076 {
12077         bitVect *rsave ;
12078         symbol *lbl = newiTempLabel(NULL);
12079         
12080         assert(nparms==0);
12081         /* save registers that need to be saved */
12082         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12083                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12084
12085         /* put libraryID into DPTR */
12086         emitcode ("mov","dptr,#LibraryID");
12087         /* make the call */
12088         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12089         emitcode ("jnz","!tlabel",lbl->key+100);
12090
12091         /* put return value into place */
12092         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12093         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12094                 emitcode ("push","ar3");
12095                 emitcode ("push","ar2");
12096                 emitcode ("pop","%s",
12097                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12098                 emitcode ("pop","%s",
12099                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12100         } else {
12101                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12102                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12103         }
12104         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12105         emitcode ("","!tlabeldef",lbl->key+100);
12106         unsavermask(rsave);
12107 }
12108
12109 /*-----------------------------------------------------------------*/
12110 /* genMMMalloc -                                                   */
12111 /*-----------------------------------------------------------------*/
12112 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12113                          int size, const char *name)
12114 {
12115         bitVect *rsave ;
12116         operand *bsize;
12117         symbol *rsym;
12118         symbol *lbl = newiTempLabel(NULL);
12119
12120         assert (nparms == 1);
12121         /* save registers that need to be saved */
12122         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12123                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12124         
12125         bsize=parms[0];
12126         aopOp (bsize,ic,FALSE,FALSE);
12127
12128         /* put the size in R4-R2 */
12129         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12130                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12131                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12132                 if (size==3) {
12133                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12134                         emitcode("pop","ar4");
12135                 }
12136                 emitcode("pop","ar3");
12137                 emitcode("pop","ar2");          
12138         } else {
12139                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12140                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12141                 if (size==3) {
12142                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12143                 }
12144         }
12145         freeAsmop (bsize, NULL, ic, FALSE);
12146
12147         /* make the call */
12148         emitcode ("lcall","MM_%s",name);
12149         emitcode ("jz","!tlabel",lbl->key+100);
12150         emitcode ("mov","r2,#!constbyte",0xff);
12151         emitcode ("mov","r3,#!constbyte",0xff);
12152         emitcode ("","!tlabeldef",lbl->key+100);
12153         /* we don't care about the pointer : we just save the handle */
12154         rsym = OP_SYMBOL(IC_RESULT(ic));
12155         if (rsym->liveFrom != rsym->liveTo) {
12156                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12157                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12158                         emitcode ("push","ar3");
12159                         emitcode ("push","ar2");
12160                         emitcode ("pop","%s",
12161                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12162                         emitcode ("pop","%s",
12163                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12164                 } else {
12165                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12166                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12167                 }
12168                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12169         }
12170         unsavermask(rsave);
12171 }
12172
12173 /*-----------------------------------------------------------------*/
12174 /* genMMDeref -                                                    */
12175 /*-----------------------------------------------------------------*/
12176 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12177 {
12178         bitVect *rsave ;
12179         operand *handle;
12180
12181         assert (nparms == 1);
12182         /* save registers that need to be saved */
12183         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12184                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12185         
12186         handle=parms[0];
12187         aopOp (handle,ic,FALSE,FALSE);
12188
12189         /* put the size in R4-R2 */
12190         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12191                 emitcode("push","%s",
12192                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12193                 emitcode("push","%s",
12194                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12195                 emitcode("pop","ar3");
12196                 emitcode("pop","ar2");          
12197         } else {
12198                 emitcode ("mov","r2,%s",
12199                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12200                 emitcode ("mov","r3,%s",
12201                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12202         }
12203         freeAsmop (handle, NULL, ic, FALSE);
12204
12205         /* make the call */
12206         emitcode ("lcall","MM_Deref");
12207         
12208         {
12209                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12210                 if (rsym->liveFrom != rsym->liveTo) {                   
12211                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12212                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12213                             _startLazyDPSEvaluation ();
12214                             
12215                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12216                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12217                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12218
12219                             _endLazyDPSEvaluation ();
12220                             
12221                         }
12222                 }
12223         }
12224         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12225         unsavermask(rsave);
12226 }
12227
12228 /*-----------------------------------------------------------------*/
12229 /* genMMUnrestrictedPersist -                                      */
12230 /*-----------------------------------------------------------------*/
12231 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12232 {
12233         bitVect *rsave ;
12234         operand *handle;
12235
12236         assert (nparms == 1);
12237         /* save registers that need to be saved */
12238         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12239                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12240         
12241         handle=parms[0];
12242         aopOp (handle,ic,FALSE,FALSE);
12243
12244         /* put the size in R3-R2 */
12245         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12246                 emitcode("push","%s",
12247                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12248                 emitcode("push","%s",
12249                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12250                 emitcode("pop","ar3");
12251                 emitcode("pop","ar2");          
12252         } else {
12253                 emitcode ("mov","r2,%s",
12254                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12255                 emitcode ("mov","r3,%s",
12256                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12257         }
12258         freeAsmop (handle, NULL, ic, FALSE);
12259
12260         /* make the call */
12261         emitcode ("lcall","MM_UnrestrictedPersist");
12262
12263         {
12264                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12265                 if (rsym->liveFrom != rsym->liveTo) {   
12266                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12267                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12268                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12269                 }
12270         }
12271         unsavermask(rsave);
12272 }
12273
12274 /*-----------------------------------------------------------------*/
12275 /* genSystemExecJavaProcess -                                      */
12276 /*-----------------------------------------------------------------*/
12277 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12278 {
12279         bitVect *rsave ;
12280         operand *handle, *pp;
12281
12282         assert (nparms==2);
12283         /* save registers that need to be saved */
12284         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12285                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12286         
12287         pp = parms[0];
12288         handle = parms[1];
12289         
12290         /* put the handle in R3-R2 */
12291         aopOp (handle,ic,FALSE,FALSE);
12292         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12293                 emitcode("push","%s",
12294                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12295                 emitcode("push","%s",
12296                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12297                 emitcode("pop","ar3");
12298                 emitcode("pop","ar2");          
12299         } else {
12300                 emitcode ("mov","r2,%s",
12301                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12302                 emitcode ("mov","r3,%s",
12303                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12304         }
12305         freeAsmop (handle, NULL, ic, FALSE);
12306         
12307         /* put pointer in DPTR */
12308         aopOp (pp,ic,FALSE,FALSE);
12309         if (AOP_TYPE(pp) == AOP_IMMD) {
12310                 emitcode ("mov", "dptr,%s",
12311                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12312         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12313                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12314                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12315                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12316         }
12317         freeAsmop (handle, NULL, ic, FALSE);
12318
12319         /* make the call */
12320         emitcode ("lcall","System_ExecJavaProcess");
12321         
12322         /* put result in place */
12323         {
12324                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12325                 if (rsym->liveFrom != rsym->liveTo) {   
12326                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12327                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12328                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12329                 }
12330         }
12331         
12332         unsavermask(rsave);
12333 }
12334
12335 /*-----------------------------------------------------------------*/
12336 /* genSystemRTCRegisters -                                         */
12337 /*-----------------------------------------------------------------*/
12338 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12339                                   char *name)
12340 {
12341         bitVect *rsave ;
12342         operand *pp;
12343
12344         assert (nparms==1);
12345         /* save registers that need to be saved */
12346         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12347                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12348         
12349         pp=parms[0];
12350         /* put pointer in DPTR */
12351         aopOp (pp,ic,FALSE,FALSE);
12352         if (AOP_TYPE (pp) == AOP_IMMD) {
12353                 emitcode ("mov","dps,#1");
12354                 emitcode ("mov", "dptr,%s", 
12355                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12356                 emitcode ("mov","dps,#0");
12357         } else {
12358                 emitcode ("mov","dpl1,%s",
12359                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12360                 emitcode ("mov","dph1,%s",
12361                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12362                 emitcode ("mov","dpx1,%s",
12363                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12364         }
12365         freeAsmop (pp, NULL, ic, FALSE);
12366
12367         /* make the call */
12368         emitcode ("lcall","System_%sRTCRegisters",name);
12369
12370         unsavermask(rsave);
12371 }
12372
12373 /*-----------------------------------------------------------------*/
12374 /* genSystemThreadSleep -                                          */
12375 /*-----------------------------------------------------------------*/
12376 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12377 {
12378         bitVect *rsave ;
12379         operand *to, *s;
12380
12381         assert (nparms==1);
12382         /* save registers that need to be saved */
12383         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12384                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12385
12386         to = parms[0];
12387         aopOp(to,ic,FALSE,FALSE);
12388         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12389             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12390                 emitcode ("push","%s",
12391                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12392                 emitcode ("push","%s",
12393                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12394                 emitcode ("push","%s",
12395                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12396                 emitcode ("push","%s",
12397                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12398                 emitcode ("pop","ar3");
12399                 emitcode ("pop","ar2");
12400                 emitcode ("pop","ar1");
12401                 emitcode ("pop","ar0");
12402         } else {
12403                 emitcode ("mov","r0,%s",
12404                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12405                 emitcode ("mov","r1,%s",
12406                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12407                 emitcode ("mov","r2,%s",
12408                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12409                 emitcode ("mov","r3,%s",
12410                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12411         }
12412         freeAsmop (to, NULL, ic, FALSE);
12413
12414         /* suspend in acc */
12415         s = parms[1];
12416         aopOp(s,ic,FALSE,FALSE);
12417         emitcode ("mov","a,%s",
12418                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12419         freeAsmop (s, NULL, ic, FALSE);
12420
12421         /* make the call */
12422         emitcode ("lcall","System_%s",name);
12423
12424         unsavermask(rsave);
12425 }
12426
12427 /*-----------------------------------------------------------------*/
12428 /* genSystemThreadResume -                                         */
12429 /*-----------------------------------------------------------------*/
12430 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12431 {
12432         bitVect *rsave ;
12433         operand *tid,*pid;
12434
12435         assert (nparms==2);
12436         /* save registers that need to be saved */
12437         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12438                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12439         
12440         tid = parms[0];
12441         pid = parms[1];
12442         
12443         /* PID in R0 */
12444         aopOp(pid,ic,FALSE,FALSE);
12445         emitcode ("mov","r0,%s",
12446                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12447         freeAsmop (pid, NULL, ic, FALSE);
12448         
12449         /* tid into ACC */
12450         aopOp(tid,ic,FALSE,FALSE);
12451         emitcode ("mov","a,%s",
12452                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12453         freeAsmop (tid, NULL, ic, FALSE);
12454         
12455         emitcode ("lcall","System_ThreadResume");
12456
12457         /* put result into place */
12458         {
12459                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12460                 if (rsym->liveFrom != rsym->liveTo) {   
12461                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12462                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12463                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12464                 }
12465         }
12466         unsavermask(rsave);
12467 }
12468
12469 /*-----------------------------------------------------------------*/
12470 /* genSystemProcessResume -                                        */
12471 /*-----------------------------------------------------------------*/
12472 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12473 {
12474         bitVect *rsave ;
12475         operand *pid;
12476
12477         assert (nparms==1);
12478         /* save registers that need to be saved */
12479         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12480                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12481         
12482         pid = parms[0];
12483         
12484         /* pid into ACC */
12485         aopOp(pid,ic,FALSE,FALSE);
12486         emitcode ("mov","a,%s",
12487                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12488         freeAsmop (pid, NULL, ic, FALSE);
12489         
12490         emitcode ("lcall","System_ProcessResume");
12491
12492         unsavermask(rsave);
12493 }
12494
12495 /*-----------------------------------------------------------------*/
12496 /* genSystem -                                                     */
12497 /*-----------------------------------------------------------------*/
12498 static void genSystem (iCode *ic,int nparms,char *name)
12499 {
12500         assert(nparms == 0);
12501
12502         emitcode ("lcall","System_%s",name);
12503 }
12504
12505 /*-----------------------------------------------------------------*/
12506 /* genSystemPoll -                                                  */
12507 /*-----------------------------------------------------------------*/
12508 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12509 {
12510         bitVect *rsave ;
12511         operand *fp;
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         fp = parms[0];
12519         aopOp (fp,ic,FALSE,FALSE);
12520         if (AOP_TYPE (fp) == AOP_IMMD) {
12521                 emitcode ("mov", "dptr,%s", 
12522                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12523         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12524                 emitcode ("mov","dpl,%s",
12525                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12526                 emitcode ("mov","dph,%s",
12527                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12528                 emitcode ("mov","dpx,%s",
12529                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12530         }
12531         freeAsmop (fp, NULL, ic, FALSE);
12532
12533         emitcode ("lcall","System_%sPoll",name);
12534
12535         /* put result into place */
12536         {
12537                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12538                 if (rsym->liveFrom != rsym->liveTo) {   
12539                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12540                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12541                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12542                 }
12543         }
12544         unsavermask(rsave);
12545 }
12546
12547 /*-----------------------------------------------------------------*/
12548 /* genSystemGetCurrentID -                                         */
12549 /*-----------------------------------------------------------------*/
12550 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12551 {
12552         assert (nparms==0);
12553
12554         emitcode ("lcall","System_GetCurrent%sId",name);
12555         /* put result into place */
12556         {
12557                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12558                 if (rsym->liveFrom != rsym->liveTo) {   
12559                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12560                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12561                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12562                 }
12563         }
12564 }
12565
12566 /*-----------------------------------------------------------------*/
12567 /* genBuiltIn - calls the appropriate function to  generating code */
12568 /* for a built in function                                         */
12569 /*-----------------------------------------------------------------*/
12570 static void genBuiltIn (iCode *ic)
12571 {
12572         operand *bi_parms[MAX_BUILTIN_ARGS];
12573         int nbi_parms;
12574         iCode *bi_iCode;
12575         symbol *bif;
12576
12577         /* get all the arguments for a built in function */
12578         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12579
12580         /* which function is it */
12581         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12582         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12583                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12584         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12585                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12586         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12587                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12588         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12589                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12590         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12591                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12592         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12593                 genInp(bi_iCode,nbi_parms,bi_parms);
12594         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12595                 genOutp(bi_iCode,nbi_parms,bi_parms);
12596         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12597                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12598                 /* JavaNative builtIns */               
12599         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12600                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12601         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12602                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12603         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12604                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12605         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12606                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12607         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12608                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12609         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12610                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12611         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12612                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12613         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12614                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12615         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12616                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12617         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12618                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12619         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12620                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12621         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12622                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12623         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12624                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12625         } else if (strcmp(bif->name,"MM_Free")==0) {
12626                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12627         } else if (strcmp(bif->name,"MM_Deref")==0) {
12628                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12629         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12630                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12631         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12632                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12633         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12634                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12635         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12636                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12637         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12638                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12639         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12640                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12641         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12642                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12643         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12644                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12645         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12646                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12647         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12648                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12649         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12650                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12651         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12652                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12653         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12654                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12655         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12656                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12657         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12658                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12659         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12660                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12661         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12662                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12663         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12664                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12665         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12666                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12667         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12668                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12669         } else {
12670                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12671                 return ;
12672         }
12673         return ;    
12674 }
12675
12676 /*-----------------------------------------------------------------*/
12677 /* gen390Code - generate code for Dallas 390 based controllers     */
12678 /*-----------------------------------------------------------------*/
12679 void
12680 gen390Code (iCode * lic)
12681 {
12682   iCode *ic;
12683   int cln = 0;
12684
12685   lineHead = lineCurr = NULL;
12686   dptrn[1][0] = "dpl1";
12687   dptrn[1][1] = "dph1";
12688   dptrn[1][2] = "dpx1";
12689   
12690   if (options.model == MODEL_FLAT24) {
12691     fReturnSizeDS390 = 5;
12692     fReturn = fReturn24;
12693   } else {
12694     fReturnSizeDS390 = 4;
12695     fReturn = fReturn16;
12696     options.stack10bit=0;
12697   }
12698 #if 1
12699   /* print the allocation information */
12700   if (allocInfo)
12701     printAllocInfo (currFunc, codeOutFile);
12702 #endif
12703   /* if debug information required */
12704   if (options.debug && currFunc)
12705     {
12706       debugFile->writeFunction(currFunc);
12707       _G.debugLine = 1;
12708       if (IS_STATIC (currFunc->etype))
12709         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12710       else
12711         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12712       _G.debugLine = 0;
12713     }
12714   /* stack pointer name */
12715   if (options.useXstack)
12716     spname = "_spx";
12717   else
12718     spname = "sp";
12719
12720
12721   for (ic = lic; ic; ic = ic->next)
12722     {
12723
12724       if (ic->lineno && cln != ic->lineno)
12725         {
12726           if (options.debug)
12727             {
12728               _G.debugLine = 1;
12729               emitcode ("", "C$%s$%d$%d$%d ==.",
12730                         FileBaseName (ic->filename), ic->lineno,
12731                         ic->level, ic->block);
12732               _G.debugLine = 0;
12733             }
12734           if (!options.noCcodeInAsm) {
12735             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12736                       printCLine(ic->filename, ic->lineno));
12737           }
12738           cln = ic->lineno;
12739         }
12740       if (options.iCodeInAsm) {
12741         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12742       }
12743       /* if the result is marked as
12744          spilt and rematerializable or code for
12745          this has already been generated then
12746          do nothing */
12747       if (resultRemat (ic) || ic->generated)
12748         continue;
12749
12750       /* depending on the operation */
12751       switch (ic->op)
12752         {
12753         case '!':
12754           genNot (ic);
12755           break;
12756
12757         case '~':
12758           genCpl (ic);
12759           break;
12760
12761         case UNARYMINUS:
12762           genUminus (ic);
12763           break;
12764
12765         case IPUSH:
12766           genIpush (ic);
12767           break;
12768
12769         case IPOP:
12770           /* IPOP happens only when trying to restore a
12771              spilt live range, if there is an ifx statement
12772              following this pop then the if statement might
12773              be using some of the registers being popped which
12774              would destory the contents of the register so
12775              we need to check for this condition and handle it */
12776           if (ic->next &&
12777               ic->next->op == IFX &&
12778               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12779             genIfx (ic->next, ic);
12780           else
12781             genIpop (ic);
12782           break;
12783
12784         case CALL:
12785           genCall (ic);
12786           break;
12787
12788         case PCALL:
12789           genPcall (ic);
12790           break;
12791
12792         case FUNCTION:
12793           genFunction (ic);
12794           break;
12795
12796         case ENDFUNCTION:
12797           genEndFunction (ic);
12798           break;
12799
12800         case RETURN:
12801           genRet (ic);
12802           break;
12803
12804         case LABEL:
12805           genLabel (ic);
12806           break;
12807
12808         case GOTO:
12809           genGoto (ic);
12810           break;
12811
12812         case '+':
12813           genPlus (ic);
12814           break;
12815
12816         case '-':
12817           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12818             genMinus (ic);
12819           break;
12820
12821         case '*':
12822           genMult (ic);
12823           break;
12824
12825         case '/':
12826           genDiv (ic);
12827           break;
12828
12829         case '%':
12830           genMod (ic);
12831           break;
12832
12833         case '>':
12834           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12835           break;
12836
12837         case '<':
12838           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12839           break;
12840
12841         case LE_OP:
12842         case GE_OP:
12843         case NE_OP:
12844
12845           /* note these two are xlated by algebraic equivalence
12846              during parsing SDCC.y */
12847           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12848                   "got '>=' or '<=' shouldn't have come here");
12849           break;
12850
12851         case EQ_OP:
12852           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12853           break;
12854
12855         case AND_OP:
12856           genAndOp (ic);
12857           break;
12858
12859         case OR_OP:
12860           genOrOp (ic);
12861           break;
12862
12863         case '^':
12864           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12865           break;
12866
12867         case '|':
12868           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12869           break;
12870
12871         case BITWISEAND:
12872           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12873           break;
12874
12875         case INLINEASM:
12876           genInline (ic);
12877           break;
12878
12879         case RRC:
12880           genRRC (ic);
12881           break;
12882
12883         case RLC:
12884           genRLC (ic);
12885           break;
12886
12887         case GETHBIT:
12888           genGetHbit (ic);
12889           break;
12890
12891         case LEFT_OP:
12892           genLeftShift (ic);
12893           break;
12894
12895         case RIGHT_OP:
12896           genRightShift (ic);
12897           break;
12898
12899         case GET_VALUE_AT_ADDRESS:
12900           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12901           break;
12902
12903         case '=':
12904           if (POINTER_SET (ic))
12905             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12906           else
12907             genAssign (ic);
12908           break;
12909
12910         case IFX:
12911           genIfx (ic, NULL);
12912           break;
12913
12914         case ADDRESS_OF:
12915           genAddrOf (ic);
12916           break;
12917
12918         case JUMPTABLE:
12919           genJumpTab (ic);
12920           break;
12921
12922         case CAST:
12923           genCast (ic);
12924           break;
12925
12926         case RECEIVE:
12927           genReceive (ic);
12928           break;
12929
12930         case SEND:
12931           if (ic->builtinSEND) genBuiltIn(ic);
12932           else addSet (&_G.sendSet, ic);
12933           break;
12934
12935         case ARRAYINIT:
12936             genArrayInit(ic);
12937             break;
12938             
12939         default:
12940           ic = ic;
12941         }
12942     }
12943
12944
12945   /* now we are ready to call the
12946      peep hole optimizer */
12947   if (!options.nopeep)
12948     peepHole (&lineHead);
12949
12950   /* now do the actual printing */
12951   printLine (lineHead, codeOutFile);
12952   return;
12953 }