Replaced the liverange code.
[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 /* leftRightUseAcc - returns size of accumulator use by operands   */
443 /*-----------------------------------------------------------------*/
444 static int
445 leftRightUseAcc(iCode *ic)
446 {
447   operand *op;
448   int size;
449   int accuseSize = 0;
450   int accuse = 0;
451   
452   if (!ic)
453     {
454       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
455               "null iCode pointer");
456       return 0;
457     }
458
459   if (ic->op == IFX)
460     {
461       op = IC_COND (ic);
462       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
463         {
464           accuse = 1;
465           size = getSize (OP_SYMBOL (op)->type);
466           if (size>accuseSize)
467             accuseSize = size;
468         }
469     }
470   else if (ic->op == JUMPTABLE)
471     {
472       op = IC_JTCOND (ic);
473       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
474         {
475           accuse = 1;
476           size = getSize (OP_SYMBOL (op)->type);
477           if (size>accuseSize)
478             accuseSize = size;
479         }
480     }
481   else
482     {
483       op = IC_LEFT (ic);
484       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
485         {
486           accuse = 1;
487           size = getSize (OP_SYMBOL (op)->type);
488           if (size>accuseSize)
489             accuseSize = size;
490         }
491       op = IC_RIGHT (ic);
492       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
493         {
494           accuse = 1;
495           size = getSize (OP_SYMBOL (op)->type);
496           if (size>accuseSize)
497             accuseSize = size;
498         }
499     }
500   
501   if (accuseSize)
502     return accuseSize;
503   else
504     return accuse;
505 }
506
507 /*-----------------------------------------------------------------*/
508 /* aopForSym - for a true symbol                                   */
509 /*-----------------------------------------------------------------*/
510 static asmop *
511 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
512 {
513   asmop *aop;
514   memmap *space = SPEC_OCLS (sym->etype);
515   int accuse = leftRightUseAcc (ic);
516
517   /* if already has one */
518   if (sym->aop)
519     return sym->aop;
520
521   /* assign depending on the storage class */
522   /* if it is on the stack or indirectly addressable */
523   /* space we need to assign either r0 or r1 to it   */
524   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
525     {
526       sym->aop = aop = newAsmop (0);
527       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
528       aop->size = getSize (sym->type);
529
530       /* now assign the address of the variable to
531          the pointer register */
532       if (aop->type != AOP_STK)
533         {
534
535           if (sym->onStack)
536             {
537               if (_G.accInUse || accuse)
538                 emitcode ("push", "acc");
539
540               if (_G.bInUse || (accuse>1))
541                 emitcode ("push", "b");
542
543               emitcode ("mov", "a,_bp");
544               emitcode ("add", "a,#!constbyte",
545                         ((sym->stack < 0) ?
546                          ((char) (sym->stack - _G.nRegsSaved)) :
547                          ((char) sym->stack)) & 0xff);
548               emitcode ("mov", "%s,a",
549                         aop->aopu.aop_ptr->name);
550
551               if (_G.bInUse || (accuse>1))
552                 emitcode ("pop", "b");
553
554               if (_G.accInUse || accuse)
555                 emitcode ("pop", "acc");
556             }
557           else
558             emitcode ("mov", "%s,#%s",
559                       aop->aopu.aop_ptr->name,
560                       sym->rname);
561           aop->paged = space->paged;
562         }
563       else
564         aop->aopu.aop_stk = sym->stack;
565       return aop;
566     }
567
568   if (sym->onStack && options.stack10bit)
569     {
570         short stack_val = -((sym->stack < 0) ?
571                             ((short) (sym->stack - _G.nRegsSaved)) :
572                             ((short) sym->stack)) ;
573         if (useDP2 && _G.dptr1InUse) {
574             emitcode ("push","dpl1");
575             emitcode ("push","dph1");
576             emitcode ("push","dpx1");
577         } else if (_G.dptrInUse ) {
578             emitcode ("push","dpl");
579             emitcode ("push","dph");
580             emitcode ("push","dpx");
581         }
582       /* It's on the 10 bit stack, which is located in
583        * far data space.
584        */           
585         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
586             if (useDP2) {
587                 if (options.model == MODEL_FLAT24)
588                 {
589                     emitcode ("mov", "dpx1,#!constbyte",
590                               (options.stack_loc >> 16) & 0xff);
591                 }
592                 emitcode ("mov", "dph1,_bpx+1");
593                 
594                 emitcode ("mov", "dpl1,_bpx");
595                 emitcode ("mov","dps,#1");
596             } else {
597                 if (options.model == MODEL_FLAT24)
598                 {
599                     emitcode ("mov", "dpx,#!constbyte",
600                               (options.stack_loc >> 16) & 0xff);
601                 }
602                 emitcode ("mov", "dph,_bpx+1");
603                 emitcode ("mov", "dpl,_bpx");
604             }
605             stack_val = -stack_val;
606             while (stack_val--) {
607                 emitcode ("inc","dptr");
608             }
609             if (useDP2) {
610                 emitcode("mov","dps,#0");
611             }
612         }  else {
613             if (_G.accInUse || accuse)
614                 emitcode ("push", "acc");
615             
616             if (_G.bInUse || (accuse>1))
617                 emitcode ("push", "b");
618         
619             emitcode ("mov", "a,_bpx");
620             emitcode ("clr","c");
621             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
622             emitcode ("mov","b,a");
623             emitcode ("mov","a,_bpx+1");
624             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
625             if (useDP2) {
626                 if (options.model == MODEL_FLAT24)
627                 {
628                     emitcode ("mov", "dpx1,#!constbyte",
629                               (options.stack_loc >> 16) & 0xff);
630                 }
631                 emitcode ("mov", "dph1,a");
632                 emitcode ("mov", "dpl1,b");
633             } else {
634                 if (options.model == MODEL_FLAT24)
635                 {
636                     emitcode ("mov", "dpx,#!constbyte",
637                               (options.stack_loc >> 16) & 0xff);
638                 }
639                 emitcode ("mov", "dph,a");
640                 emitcode ("mov", "dpl,b");
641             }
642             
643             if (_G.bInUse || (accuse>1))
644                 emitcode ("pop", "b");
645             
646             if (_G.accInUse || accuse)
647                 emitcode ("pop", "acc");
648         }
649         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
650         aop->size = getSize (sym->type);
651         return aop;
652     }
653
654   /* if in bit space */
655   if (IN_BITSPACE (space))
656     {
657       sym->aop = aop = newAsmop (AOP_CRY);
658       aop->aopu.aop_dir = sym->rname;
659       aop->size = getSize (sym->type);
660       return aop;
661     }
662   /* if it is in direct space */
663   if (IN_DIRSPACE (space))
664     {
665       sym->aop = aop = newAsmop (AOP_DIR);
666       aop->aopu.aop_dir = sym->rname;
667       aop->size = getSize (sym->type);
668       return aop;
669     }
670
671   /* special case for a function */
672   if (IS_FUNC (sym->type) && !(sym->isitmp))
673     {
674       sym->aop = aop = newAsmop (AOP_IMMD);
675       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
676       aop->size = FPTRSIZE;
677       return aop;
678     }
679
680   /* only remaining is far space */
681   /* in which case DPTR gets the address */
682   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
683   if (useDP2)
684     {
685       genSetDPTR (1);
686       _flushLazyDPS ();
687       emitcode ("mov", "dptr,#%s", sym->rname);
688       genSetDPTR (0);
689     }
690   else
691     {
692       emitcode ("mov", "dptr,#%s", sym->rname);
693     }
694   aop->size = getSize (sym->type);
695
696   /* if it is in code space */
697   if (IN_CODESPACE (space))
698     aop->code = 1;
699
700   return aop;
701 }
702
703 /*-----------------------------------------------------------------*/
704 /* aopForRemat - rematerialzes an object                           */
705 /*-----------------------------------------------------------------*/
706 static asmop *
707 aopForRemat (symbol * sym)
708 {
709   iCode *ic = sym->rematiCode;
710   asmop *aop = newAsmop (AOP_IMMD);
711   int ptr_type =0;
712   int val = 0;
713
714   for (;;)
715     {
716       if (ic->op == '+')
717         val += (int) operandLitValue (IC_RIGHT (ic));
718       else if (ic->op == '-')
719         val -= (int) operandLitValue (IC_RIGHT (ic));
720       else if (IS_CAST_ICODE(ic)) {
721               sym_link *from_type = operandType(IC_RIGHT(ic));
722               aop->aopu.aop_immd.from_cast_remat = 1;
723               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
724               ptr_type = DCL_TYPE(from_type);
725               if (ptr_type == IPOINTER) {
726                 // bug #481053
727                 ptr_type = POINTER;
728               }
729               continue ;
730       } else break;
731       
732       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
733     }
734
735   if (val)
736   {
737       SNPRINTF (buffer, sizeof(buffer),
738                 "(%s %c 0x%04x)",
739                 OP_SYMBOL (IC_LEFT (ic))->rname,
740                 val >= 0 ? '+' : '-',
741                 abs (val) & 0xffffff);
742   }
743   else 
744   {
745       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
746       {
747           SNPRINTF(buffer, sizeof(buffer), 
748                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
749       }
750       else
751       {
752           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
753       }
754   }
755
756   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
757   /* set immd2 field if required */
758   if (aop->aopu.aop_immd.from_cast_remat) 
759   {
760       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
761       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
762   }
763
764   return aop;
765 }
766
767 /*-----------------------------------------------------------------*/
768 /* aopHasRegs - returns true if aop has regs between from-to       */
769 /*-----------------------------------------------------------------*/
770 static int aopHasRegs(asmop *aop, int from, int to)
771 {
772     int size =0;
773
774     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
775
776     for (; size < aop->size ; size++) {
777         int reg;
778         for (reg = from ; reg <= to ; reg++)
779             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
780     }
781     return 0;
782 }
783
784 /*-----------------------------------------------------------------*/
785 /* regsInCommon - two operands have some registers in common       */
786 /*-----------------------------------------------------------------*/
787 static bool
788 regsInCommon (operand * op1, operand * op2)
789 {
790   symbol *sym1, *sym2;
791   int i;
792
793   /* if they have registers in common */
794   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
795     return FALSE;
796
797   sym1 = OP_SYMBOL (op1);
798   sym2 = OP_SYMBOL (op2);
799
800   if (sym1->nRegs == 0 || sym2->nRegs == 0)
801     return FALSE;
802
803   for (i = 0; i < sym1->nRegs; i++)
804     {
805       int j;
806       if (!sym1->regs[i])
807         continue;
808
809       for (j = 0; j < sym2->nRegs; j++)
810         {
811           if (!sym2->regs[j])
812             continue;
813
814           if (sym2->regs[j] == sym1->regs[i])
815             return TRUE;
816         }
817     }
818
819   return FALSE;
820 }
821
822 /*-----------------------------------------------------------------*/
823 /* operandsEqu - equivalent                                        */
824 /*-----------------------------------------------------------------*/
825 static bool
826 operandsEqu (operand * op1, operand * op2)
827 {
828   symbol *sym1, *sym2;
829
830   /* if they not symbols */
831   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
832     return FALSE;
833
834   sym1 = OP_SYMBOL (op1);
835   sym2 = OP_SYMBOL (op2);
836
837   /* if both are itemps & one is spilt
838      and the other is not then false */
839   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
840       sym1->isspilt != sym2->isspilt)
841     return FALSE;
842
843   /* if they are the same */
844   if (sym1 == sym2)
845     return TRUE;
846
847   if (strcmp (sym1->rname, sym2->rname) == 0)
848     return TRUE;
849
850
851   /* if left is a tmp & right is not */
852   if (IS_ITEMP (op1) &&
853       !IS_ITEMP (op2) &&
854       sym1->isspilt &&
855       (sym1->usl.spillLoc == sym2))
856     return TRUE;
857
858   if (IS_ITEMP (op2) &&
859       !IS_ITEMP (op1) &&
860       sym2->isspilt &&
861       sym1->level > 0 &&
862       (sym2->usl.spillLoc == sym1))
863     return TRUE;
864
865   return FALSE;
866 }
867
868 /*-----------------------------------------------------------------*/
869 /* sameRegs - two asmops have the same registers                   */
870 /*-----------------------------------------------------------------*/
871 static bool
872 sameRegs (asmop * aop1, asmop * aop2)
873 {
874   int i;
875
876   if (aop1 == aop2)
877     {
878       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
879         {
880           return FALSE;
881         }
882       return TRUE;
883     }
884
885   if (aop1->type != AOP_REG ||
886       aop2->type != AOP_REG)
887     return FALSE;
888
889   if (aop1->size != aop2->size)
890     return FALSE;
891
892   for (i = 0; i < aop1->size; i++)
893     if (aop1->aopu.aop_reg[i] !=
894         aop2->aopu.aop_reg[i])
895       return FALSE;
896
897   return TRUE;
898 }
899
900 /*-----------------------------------------------------------------*/
901 /* aopOp - allocates an asmop for an operand  :                    */
902 /*-----------------------------------------------------------------*/
903 static void
904 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
905 {
906   asmop *aop;
907   symbol *sym;
908   int i;
909
910   if (!op)
911     return;
912
913   /* if this a literal */
914   if (IS_OP_LITERAL (op))
915     {
916       op->aop = aop = newAsmop (AOP_LIT);
917       aop->aopu.aop_lit = op->operand.valOperand;
918       aop->size = getSize (operandType (op));
919       return;
920     }
921
922   /* if already has a asmop then continue */
923   if (op->aop)
924     return;
925
926   /* if the underlying symbol has a aop */
927   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
928     {
929       op->aop = OP_SYMBOL (op)->aop;
930       return;
931     }
932
933   /* if this is a true symbol */
934   if (IS_TRUE_SYMOP (op))
935     {
936       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
937       return;
938     }
939
940   /* this is a temporary : this has
941      only four choices :
942      a) register
943      b) spillocation
944      c) rematerialize
945      d) conditional
946      e) can be a return use only */
947
948   sym = OP_SYMBOL (op);
949
950
951   /* if the type is a conditional */
952   if (sym->regType == REG_CND)
953     {
954       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
955       aop->size = 0;
956       return;
957     }
958
959   /* if it is spilt then two situations
960      a) is rematerialize
961      b) has a spill location */
962   if (sym->isspilt || sym->nRegs == 0)
963     {
964
965       /* rematerialize it NOW */
966       if (sym->remat)
967         {
968           sym->aop = op->aop = aop =
969             aopForRemat (sym);
970           aop->size = getSize (sym->type);
971           return;
972         }
973
974       if (sym->accuse)
975         {
976           int i;
977           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
978           aop->size = getSize (sym->type);
979           for (i = 0; i < 2; i++)
980             aop->aopu.aop_str[i] = accUse[i];
981           return;
982         }
983
984       if (sym->ruonly)
985         {
986           int i;
987
988           if (useDP2)
989             {
990               /* a AOP_STR uses DPTR, but DPTR is already in use;
991                * we're just hosed.
992                */
993                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
994             }
995
996           aop = op->aop = sym->aop = newAsmop (AOP_STR);
997           aop->size = getSize (sym->type);
998           for (i = 0; i < (int) fReturnSizeDS390; i++)
999             aop->aopu.aop_str[i] = fReturn[i];
1000           return;
1001         }
1002       
1003       if (sym->dptr) { /* has been allocated to a DPTRn */
1004           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1005           aop->size = getSize (sym->type);
1006           aop->aopu.dptr = sym->dptr;
1007           return ;
1008       }
1009       
1010       if (sym->usl.spillLoc)
1011         {
1012           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1013             {
1014               /* force a new aop if sizes differ */
1015               sym->usl.spillLoc->aop = NULL;
1016             }
1017           sym->aop = op->aop = aop =
1018                      aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1019           aop->size = getSize (sym->type);
1020           return;
1021         }
1022       
1023       /* else must be a dummy iTemp */
1024       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1025       aop->size = getSize (sym->type);
1026       return;
1027     }
1028
1029   /* must be in a register */
1030   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1031   aop->size = sym->nRegs;
1032   for (i = 0; i < sym->nRegs; i++)
1033     aop->aopu.aop_reg[i] = sym->regs[i];
1034 }
1035
1036 /*-----------------------------------------------------------------*/
1037 /* freeAsmop - free up the asmop given to an operand               */
1038 /*----------------------------------------------------------------*/
1039 static void
1040 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1041 {
1042   asmop *aop;
1043
1044   if (!op)
1045     aop = aaop;
1046   else
1047     aop = op->aop;
1048
1049   if (!aop)
1050     return;
1051
1052   if (aop->freed)
1053     goto dealloc;
1054
1055   aop->freed = 1;
1056
1057   /* depending on the asmop type only three cases need work AOP_RO
1058      , AOP_R1 && AOP_STK */
1059   switch (aop->type)
1060     {
1061     case AOP_R0:
1062       if (_G.r0Pushed)
1063         {
1064           if (pop)
1065             {
1066               emitcode ("pop", "ar0");
1067               _G.r0Pushed--;
1068             }
1069         }
1070       bitVectUnSetBit (ic->rUsed, R0_IDX);
1071       break;
1072
1073     case AOP_R1:
1074       if (_G.r1Pushed)
1075         {
1076           if (pop)
1077             {
1078               emitcode ("pop", "ar1");
1079               _G.r1Pushed--;
1080             }
1081         }
1082       bitVectUnSetBit (ic->rUsed, R1_IDX);
1083       break;
1084
1085     case AOP_STK:
1086       {
1087         int sz = aop->size;
1088         int stk = aop->aopu.aop_stk + aop->size;
1089         bitVectUnSetBit (ic->rUsed, R0_IDX);
1090         bitVectUnSetBit (ic->rUsed, R1_IDX);
1091
1092         getFreePtr (ic, &aop, FALSE);
1093
1094         if (options.stack10bit)
1095           {
1096             /* I'm not sure what to do here yet... */
1097             /* #STUB */
1098             fprintf (stderr,
1099                      "*** Warning: probably generating bad code for "
1100                      "10 bit stack mode.\n");
1101           }
1102
1103         if (stk)
1104           {
1105             emitcode ("mov", "a,_bp");
1106             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1107             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1108           }
1109         else
1110           {
1111             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1112           }
1113
1114         while (sz--)
1115           {
1116             emitcode ("pop", "acc");
1117             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1118             if (!sz)
1119               break;
1120             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1121           }
1122         op->aop = aop;
1123         freeAsmop (op, NULL, ic, TRUE);
1124         if (_G.r0Pushed)
1125           {
1126             emitcode ("pop", "ar0");
1127             _G.r0Pushed--;
1128           }
1129
1130         if (_G.r1Pushed)
1131           {
1132             emitcode ("pop", "ar1");
1133             _G.r1Pushed--;
1134           }
1135       }
1136     case AOP_DPTR2:
1137         if (_G.dptr1InUse) {
1138             emitcode ("pop","dpx1");
1139             emitcode ("pop","dph1");
1140             emitcode ("pop","dpl1");
1141         }
1142         break;
1143     case AOP_DPTR:
1144         if (_G.dptrInUse) {
1145             emitcode ("pop","dpx");
1146             emitcode ("pop","dph");
1147             emitcode ("pop","dpl");
1148         }
1149         break;
1150     }
1151 dealloc:
1152   /* all other cases just dealloc */
1153   if (op)
1154     {
1155       op->aop = NULL;
1156       if (IS_SYMOP (op))
1157         {
1158           OP_SYMBOL (op)->aop = NULL;
1159           /* if the symbol has a spill */
1160           if (SPIL_LOC (op))
1161             SPIL_LOC (op)->aop = NULL;
1162         }
1163     }
1164 }
1165
1166 #define DEFAULT_ACC_WARNING 0
1167 static int saveAccWarn = DEFAULT_ACC_WARNING;
1168
1169 /*-------------------------------------------------------------------*/
1170 /* aopGet - for fetching value of the aop                            */
1171 /*                                                                   */
1172 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1173 /* in the accumulator. Set it to the name of a free register         */
1174 /* if acc must be preserved; the register will be used to preserve   */
1175 /* acc temporarily and to return the result byte.                    */
1176 /*-------------------------------------------------------------------*/
1177
1178 static char *
1179 aopGet (asmop *aop,
1180         int   offset,
1181         bool  bit16,
1182         bool  dname,
1183         char  *saveAcc)
1184 {
1185   /* offset is greater than
1186      size then zero */
1187   if (offset > (aop->size - 1) &&
1188       aop->type != AOP_LIT)
1189     return zero;
1190
1191   /* depending on type */
1192   switch (aop->type)
1193     {
1194     case AOP_DUMMY:
1195       return zero;
1196
1197     case AOP_R0:
1198     case AOP_R1:
1199       /* if we need to increment it */
1200       while (offset > aop->coff)
1201         {
1202           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1203           aop->coff++;
1204         }
1205
1206       while (offset < aop->coff)
1207         {
1208           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1209           aop->coff--;
1210         }
1211
1212       aop->coff = offset;
1213       if (aop->paged)
1214         {
1215           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1216           return (dname ? "acc" : "a");
1217         }
1218       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1219       return Safe_strdup(buffer);       
1220
1221     case AOP_DPTRn:
1222         assert(offset <= 3);
1223         return dptrn[aop->aopu.dptr][offset];
1224
1225     case AOP_DPTR:
1226     case AOP_DPTR2:
1227
1228       if (aop->type == AOP_DPTR2)
1229         {
1230           genSetDPTR (1);
1231         }
1232         
1233       if (saveAcc)
1234         {
1235             TR_AP("#1");
1236 //          if (aop->type != AOP_DPTR2)
1237 //          {
1238 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1239 //              emitcode(";", "spanky: saveAcc for DPTR");
1240 //          }
1241             
1242             emitcode ("xch", "a, %s", saveAcc);
1243         }
1244
1245       _flushLazyDPS ();
1246
1247       while (offset > aop->coff)
1248         {
1249           emitcode ("inc", "dptr");
1250           aop->coff++;
1251         }
1252
1253       while (offset < aop->coff)
1254         {
1255           emitcode ("lcall", "__decdptr");
1256           aop->coff--;
1257         }
1258
1259       aop->coff = offset;
1260       if (aop->code)
1261         {
1262           emitcode ("clr", "a");
1263           emitcode ("movc", "a,@a+dptr");
1264         }
1265       else
1266         {
1267           emitcode ("movx", "a,@dptr");
1268         }
1269
1270       if (aop->type == AOP_DPTR2)
1271         {
1272           genSetDPTR (0);
1273         }
1274         
1275         if (saveAcc)
1276         {
1277        TR_AP("#2");
1278               emitcode ("xch", "a, %s", saveAcc);
1279 //            if (strcmp(saveAcc, "_ap"))
1280 //            {
1281 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1282 //            }
1283                   
1284               return saveAcc;
1285         }
1286       return (dname ? "acc" : "a");
1287
1288     case AOP_IMMD:
1289       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1290       {
1291           SNPRINTF(buffer, sizeof(buffer), 
1292                    "%s",aop->aopu.aop_immd.aop_immd2);
1293       } 
1294       else if (bit16)
1295       {
1296          SNPRINTF(buffer, sizeof(buffer), 
1297                   "#%s", aop->aopu.aop_immd.aop_immd1);
1298       }
1299       else if (offset) 
1300       {
1301           switch (offset) {
1302           case 1:
1303               tsprintf(buffer, sizeof(buffer),
1304                        "#!his",aop->aopu.aop_immd.aop_immd1);
1305               break;
1306           case 2:
1307               tsprintf(buffer, sizeof(buffer), 
1308                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1309               break;
1310           case 3:
1311               tsprintf(buffer, sizeof(buffer),
1312                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1313               break;
1314           default: /* should not need this (just in case) */
1315               SNPRINTF (buffer, sizeof(buffer), 
1316                         "#(%s >> %d)",
1317                        aop->aopu.aop_immd.aop_immd1,
1318                        offset * 8);
1319           }
1320       }
1321       else
1322       {
1323         SNPRINTF (buffer, sizeof(buffer), 
1324                   "#%s", aop->aopu.aop_immd.aop_immd1);
1325       }
1326       return Safe_strdup(buffer);       
1327
1328     case AOP_DIR:
1329       if (offset)
1330       {
1331         SNPRINTF (buffer, sizeof(buffer),
1332                   "(%s + %d)",
1333                  aop->aopu.aop_dir,
1334                  offset);
1335       }
1336       else
1337       {
1338         SNPRINTF(buffer, sizeof(buffer), 
1339                  "%s", aop->aopu.aop_dir);
1340       }
1341
1342       return Safe_strdup(buffer);
1343
1344     case AOP_REG:
1345       if (dname)
1346         return aop->aopu.aop_reg[offset]->dname;
1347       else
1348         return aop->aopu.aop_reg[offset]->name;
1349
1350     case AOP_CRY:
1351       emitcode ("clr", "a");
1352       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1353       emitcode ("rlc", "a");
1354       return (dname ? "acc" : "a");
1355
1356     case AOP_ACC:
1357       if (!offset && dname)
1358         return "acc";
1359       return aop->aopu.aop_str[offset];
1360
1361     case AOP_LIT:
1362       return aopLiteral (aop->aopu.aop_lit, offset);
1363
1364     case AOP_STR:
1365       aop->coff = offset;
1366       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1367           dname)
1368         return "acc";
1369
1370       return aop->aopu.aop_str[offset];
1371
1372     }
1373
1374   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1375           "aopget got unsupported aop->type");
1376   exit (1);
1377     
1378   return NULL;  // not reached, but makes compiler happy.
1379 }
1380 /*-----------------------------------------------------------------*/
1381 /* aopPut - puts a string for a aop                                */
1382 /*-----------------------------------------------------------------*/
1383 static void
1384 aopPut (asmop * aop, char *s, int offset)
1385 {
1386   if (aop->size && offset > (aop->size - 1))
1387     {
1388       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1389               "aopPut got offset > aop->size");
1390       exit (1);
1391     }
1392
1393   /* will assign value to value */
1394   /* depending on where it is ofcourse */
1395   switch (aop->type)
1396     {
1397     case AOP_DUMMY:
1398       MOVA (s);         /* read s in case it was volatile */
1399       break;
1400       
1401     case AOP_DIR:
1402         if (offset)
1403         {
1404             SNPRINTF (buffer, sizeof(buffer),
1405                       "(%s + %d)",
1406                       aop->aopu.aop_dir, offset);
1407         }
1408         else
1409         {
1410             SNPRINTF (buffer, sizeof(buffer), 
1411                      "%s", aop->aopu.aop_dir);
1412         }
1413         
1414
1415         if (strcmp (buffer, s))
1416         {
1417             emitcode ("mov", "%s,%s", buffer, s);
1418         }
1419       break;
1420
1421     case AOP_REG:
1422       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1423           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1424         {
1425           if (*s == '@' ||
1426               strcmp (s, "r0") == 0 ||
1427               strcmp (s, "r1") == 0 ||
1428               strcmp (s, "r2") == 0 ||
1429               strcmp (s, "r3") == 0 ||
1430               strcmp (s, "r4") == 0 ||
1431               strcmp (s, "r5") == 0 ||
1432               strcmp (s, "r6") == 0 ||
1433               strcmp (s, "r7") == 0)
1434             {
1435                 emitcode ("mov", "%s,%s",
1436                           aop->aopu.aop_reg[offset]->dname, s);
1437             }
1438             else
1439             {
1440                 emitcode ("mov", "%s,%s",
1441                           aop->aopu.aop_reg[offset]->name, s);
1442             }
1443         }
1444       break;
1445
1446     case AOP_DPTRn:
1447         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1448         break;
1449
1450     case AOP_DPTR:
1451     case AOP_DPTR2:
1452
1453       if (aop->type == AOP_DPTR2)
1454         {
1455           genSetDPTR (1);
1456         }
1457       _flushLazyDPS ();
1458
1459       if (aop->code)
1460         {
1461           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1462                   "aopPut writting to code space");
1463           exit (1);
1464         }
1465
1466       while (offset > aop->coff)
1467         {
1468           aop->coff++;
1469           emitcode ("inc", "dptr");
1470         }
1471
1472       while (offset < aop->coff)
1473         {
1474           aop->coff--;
1475           emitcode ("lcall", "__decdptr");
1476         }
1477
1478       aop->coff = offset;
1479
1480       /* if not in accumulater */
1481       MOVA (s);
1482
1483       emitcode ("movx", "@dptr,a");
1484
1485       if (aop->type == AOP_DPTR2)
1486         {
1487           genSetDPTR (0);
1488         }
1489       break;
1490
1491     case AOP_R0:
1492     case AOP_R1:
1493       while (offset > aop->coff)
1494         {
1495           aop->coff++;
1496           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1497         }
1498       while (offset < aop->coff)
1499         {
1500           aop->coff--;
1501           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1502         }
1503       aop->coff = offset;
1504
1505       if (aop->paged)
1506         {
1507           MOVA (s);
1508           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1509
1510         }
1511       else if (*s == '@')
1512         {
1513           MOVA (s);
1514           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1515         }
1516       else if (strcmp (s, "r0") == 0 ||
1517                strcmp (s, "r1") == 0 ||
1518                strcmp (s, "r2") == 0 ||
1519                strcmp (s, "r3") == 0 ||
1520                strcmp (s, "r4") == 0 ||
1521                strcmp (s, "r5") == 0 ||
1522                strcmp (s, "r6") == 0 ||
1523                strcmp (s, "r7") == 0)
1524         {
1525           char buff[10];
1526           SNPRINTF(buff, sizeof(buff), 
1527                    "a%s", s);
1528           emitcode ("mov", "@%s,%s",
1529                     aop->aopu.aop_ptr->name, buff);
1530         }
1531         else
1532         {
1533             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1534         }
1535       break;
1536
1537     case AOP_STK:
1538       if (strcmp (s, "a") == 0)
1539         emitcode ("push", "acc");
1540       else
1541         if (*s=='@') {
1542           MOVA(s);
1543           emitcode ("push", "acc");
1544         } else {
1545           emitcode ("push", s);
1546         }
1547
1548       break;
1549
1550     case AOP_CRY:
1551       /* if bit variable */
1552       if (!aop->aopu.aop_dir)
1553         {
1554           emitcode ("clr", "a");
1555           emitcode ("rlc", "a");
1556         }
1557       else
1558         {
1559           if (s == zero)
1560             emitcode ("clr", "%s", aop->aopu.aop_dir);
1561           else if (s == one)
1562             emitcode ("setb", "%s", aop->aopu.aop_dir);
1563           else if (!strcmp (s, "c"))
1564             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1565           else
1566             {
1567               if (strcmp (s, "a"))
1568                 {
1569                   MOVA (s);
1570                 }
1571               {
1572                 /* set C, if a >= 1 */
1573                 emitcode ("add", "a,#!constbyte",0xff);
1574                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1575               }
1576             }
1577         }
1578       break;
1579
1580     case AOP_STR:
1581       aop->coff = offset;
1582       if (strcmp (aop->aopu.aop_str[offset], s))
1583         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1584       break;
1585
1586     case AOP_ACC:
1587       aop->coff = offset;
1588       if (!offset && (strcmp (s, "acc") == 0))
1589         break;
1590
1591       if (strcmp (aop->aopu.aop_str[offset], s))
1592         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1593       break;
1594
1595     default:
1596       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1597               "aopPut got unsupported aop->type");
1598       exit (1);
1599     }
1600
1601 }
1602
1603
1604 /*--------------------------------------------------------------------*/
1605 /* reAdjustPreg - points a register back to where it should (coff==0) */
1606 /*--------------------------------------------------------------------*/
1607 static void
1608 reAdjustPreg (asmop * aop)
1609 {
1610   if ((aop->coff==0) || (aop->size <= 1)) {
1611     return;
1612   }
1613
1614   switch (aop->type)
1615     {
1616     case AOP_R0:
1617     case AOP_R1:
1618       while (aop->coff--)
1619         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1620       break;
1621     case AOP_DPTR:
1622     case AOP_DPTR2:
1623       if (aop->type == AOP_DPTR2)
1624         {
1625           genSetDPTR (1);
1626           _flushLazyDPS ();
1627         }
1628       while (aop->coff--)
1629         {
1630           emitcode ("lcall", "__decdptr");
1631         }
1632
1633       if (aop->type == AOP_DPTR2)
1634         {
1635           genSetDPTR (0);
1636         }
1637       break;
1638
1639     }
1640   aop->coff=0;
1641 }
1642
1643 #define AOP(op) op->aop
1644 #define AOP_TYPE(op) AOP(op)->type
1645 #define AOP_SIZE(op) AOP(op)->size
1646 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1647                        AOP_TYPE(x) == AOP_R0))
1648
1649 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1650                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1651                          AOP(x)->paged))
1652
1653 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1654                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1655                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1656 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1657 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1658 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1659
1660 // The following two macros can be used even if the aop has not yet been aopOp'd.
1661 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1662 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1663
1664 /* Workaround for DS80C390 bug: div ab may return bogus results
1665  * if A is accessed in instruction immediately before the div.
1666  *
1667  * Will be fixed in B4 rev of processor, Dallas claims.
1668  */
1669
1670 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1671     if (!AOP_NEEDSACC(RIGHT))         \
1672     {               \
1673       /* We can load A first, then B, since     \
1674        * B (the RIGHT operand) won't clobber A,   \
1675        * thus avoiding touching A right before the div. \
1676        */             \
1677       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1678       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1679       MOVA(L);            \
1680       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1681       MOVB(L); \
1682     }               \
1683     else              \
1684     {               \
1685       /* Just stuff in a nop after loading A. */    \
1686       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1687       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1688       MOVA(L);            \
1689       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1690     }
1691
1692
1693 /*-----------------------------------------------------------------*/
1694 /* opIsGptr: returns non-zero if the passed operand is       */
1695 /* a generic pointer type.             */
1696 /*-----------------------------------------------------------------*/
1697 static int
1698 opIsGptr (operand * op)
1699 {
1700   sym_link *type = operandType (op);
1701
1702   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1703     {
1704       return 1;
1705     }
1706   return 0;
1707 }
1708
1709 /*-----------------------------------------------------------------*/
1710 /* getDataSize - get the operand data size                         */
1711 /*-----------------------------------------------------------------*/
1712 static int
1713 getDataSize (operand * op)
1714 {
1715   int size;
1716   size = AOP_SIZE (op);
1717   if (size == GPTRSIZE)
1718     {
1719       sym_link *type = operandType (op);
1720       if (IS_GENPTR (type))
1721         {
1722           /* generic pointer; arithmetic operations
1723            * should ignore the high byte (pointer type).
1724            */
1725           size--;
1726         }
1727     }
1728   return size;
1729 }
1730
1731 /*-----------------------------------------------------------------*/
1732 /* outAcc - output Acc                                             */
1733 /*-----------------------------------------------------------------*/
1734 static void
1735 outAcc (operand * result)
1736 {
1737   int size, offset;
1738   size = getDataSize (result);
1739   if (size)
1740     {
1741       aopPut (AOP (result), "a", 0);
1742       size--;
1743       offset = 1;
1744       /* unsigned or positive */
1745       while (size--)
1746         {
1747           aopPut (AOP (result), zero, offset++);
1748         }
1749     }
1750 }
1751
1752 /*-----------------------------------------------------------------*/
1753 /* outBitC - output a bit C                                        */
1754 /*-----------------------------------------------------------------*/
1755 static void
1756 outBitC (operand * result)
1757 {
1758   /* if the result is bit */
1759   if (AOP_TYPE (result) == AOP_CRY)
1760     {
1761       aopPut (AOP (result), "c", 0);
1762     }
1763   else
1764     {
1765       emitcode ("clr", "a");
1766       emitcode ("rlc", "a");
1767       outAcc (result);
1768     }
1769 }
1770
1771 /*-----------------------------------------------------------------*/
1772 /* toBoolean - emit code for orl a,operator(sizeop)                */
1773 /*-----------------------------------------------------------------*/
1774 static void
1775 toBoolean (operand * oper)
1776 {
1777   int   size = AOP_SIZE (oper) - 1;
1778   int   offset = 1;
1779   bool usedB = FALSE;
1780
1781   /* The generic part of a generic pointer should
1782    * not participate in it's truth value.
1783    *
1784    * i.e. 0x10000000 is zero.
1785    */
1786   if (opIsGptr (oper))
1787     {
1788       D (emitcode (";", "toBoolean: generic ptr special case."););
1789       size--;
1790     }
1791
1792   _startLazyDPSEvaluation ();
1793   if (AOP_NEEDSACC (oper) && size)
1794     {
1795       usedB = TRUE;
1796       if (_G.bInUse)
1797       {
1798           emitcode ("push", "b");
1799       }
1800       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1801     }
1802   else
1803     {
1804       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1805     }
1806     
1807   while (size--)
1808     {
1809       if (usedB)
1810         {
1811           emitcode ("orl", "b,%s",
1812                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1813         }
1814       else
1815         {
1816           emitcode ("orl", "a,%s",
1817                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1818         }
1819     }
1820   _endLazyDPSEvaluation ();
1821
1822   if (usedB)
1823     {
1824       emitcode ("mov", "a,b");
1825       if (_G.bInUse)
1826       {
1827           emitcode ("pop", "b");
1828       }
1829         
1830     }
1831 }
1832
1833
1834 /*-----------------------------------------------------------------*/
1835 /* genNot - generate code for ! operation                          */
1836 /*-----------------------------------------------------------------*/
1837 static void
1838 genNot (iCode * ic)
1839 {
1840   symbol *tlbl;
1841
1842   D (emitcode (";", "genNot "););
1843
1844   /* assign asmOps to operand & result */
1845   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1846   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1847
1848   /* if in bit space then a special case */
1849   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1850     {
1851       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1852       emitcode ("cpl", "c");
1853       outBitC (IC_RESULT (ic));
1854       goto release;
1855     }
1856
1857   toBoolean (IC_LEFT (ic));
1858
1859   tlbl = newiTempLabel (NULL);
1860   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1861   emitcode ("", "!tlabeldef", tlbl->key + 100);
1862   outBitC (IC_RESULT (ic));
1863
1864 release:
1865   /* release the aops */
1866   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1867   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1868 }
1869
1870
1871 /*-----------------------------------------------------------------*/
1872 /* genCpl - generate code for complement                           */
1873 /*-----------------------------------------------------------------*/
1874 static void
1875 genCpl (iCode * ic)
1876 {
1877   int offset = 0;
1878   int size;
1879   symbol *tlbl;
1880
1881   D (emitcode (";", "genCpl "););
1882
1883
1884   /* assign asmOps to operand & result */
1885   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1886   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1887
1888   /* special case if in bit space */
1889   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1890     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1891       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1892       emitcode ("cpl", "c");
1893       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1894       goto release;
1895     }
1896     tlbl=newiTempLabel(NULL);
1897     emitcode ("cjne", "%s,#0x01,%05d$", 
1898               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1899     emitcode ("", "%05d$:", tlbl->key+100);
1900     outBitC (IC_RESULT(ic));
1901     goto release;
1902   }
1903
1904   size = AOP_SIZE (IC_RESULT (ic));
1905   _startLazyDPSEvaluation ();
1906   while (size--)
1907     {
1908       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1909       emitcode ("cpl", "a");
1910       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1911     }
1912   _endLazyDPSEvaluation ();
1913
1914
1915 release:
1916   /* release the aops */
1917   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1918   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1919 }
1920
1921 /*-----------------------------------------------------------------*/
1922 /* genUminusFloat - unary minus for floating points                */
1923 /*-----------------------------------------------------------------*/
1924 static void
1925 genUminusFloat (operand * op, operand * result)
1926 {
1927   int size, offset = 0;
1928     
1929   D(emitcode (";", "genUminusFloat"););
1930   
1931   /* for this we just copy and then flip the bit */
1932     
1933   _startLazyDPSEvaluation ();
1934   size = AOP_SIZE (op) - 1;
1935
1936   while (size--)
1937   {
1938       aopPut (AOP (result),
1939               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1940               offset);
1941       offset++;
1942     }
1943   
1944   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1945
1946   emitcode ("cpl", "acc.7");
1947   aopPut (AOP (result), "a", offset);    
1948   _endLazyDPSEvaluation ();
1949 }
1950
1951 /*-----------------------------------------------------------------*/
1952 /* genUminus - unary minus code generation                         */
1953 /*-----------------------------------------------------------------*/
1954 static void
1955 genUminus (iCode * ic)
1956 {
1957   int offset, size;
1958   sym_link *optype;
1959
1960   D (emitcode (";", "genUminus "););
1961
1962   /* assign asmops */
1963   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1964   aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
1965
1966   /* if both in bit space then special
1967      case */
1968   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1969       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1970     {
1971
1972       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1973       emitcode ("cpl", "c");
1974       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1975       goto release;
1976     }
1977
1978   optype = operandType (IC_LEFT (ic));
1979
1980   /* if float then do float stuff */
1981   if (IS_FLOAT (optype))
1982     {
1983       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1984       goto release;
1985     }
1986
1987   /* otherwise subtract from zero */
1988   size = AOP_SIZE (IC_LEFT (ic));
1989   offset = 0;
1990   _startLazyDPSEvaluation ();
1991   while (size--)
1992     {
1993       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1994       if (!strcmp (l, "a"))
1995         {
1996           if (offset == 0)
1997             SETC;
1998           emitcode ("cpl", "a");
1999           emitcode ("addc", "a,#0");
2000         }
2001       else
2002         {
2003           if (offset == 0)
2004             CLRC;
2005           emitcode ("clr", "a");
2006           emitcode ("subb", "a,%s", l);
2007         }
2008       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2009     }
2010   _endLazyDPSEvaluation ();
2011
2012   /* if any remaining bytes in the result */
2013   /* we just need to propagate the sign   */
2014   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2015     {
2016       emitcode ("rlc", "a");
2017       emitcode ("subb", "a,acc");
2018       while (size--)
2019         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2020     }
2021
2022 release:
2023   /* release the aops */
2024   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2025   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2026 }
2027
2028 /*-----------------------------------------------------------------*/
2029 /* savermask - saves registers in the mask                         */
2030 /*-----------------------------------------------------------------*/
2031 static void savermask(bitVect *rs_mask)
2032 {
2033     int i;
2034     if (options.useXstack) {
2035         if (bitVectBitValue (rs_mask, R0_IDX))
2036             emitcode ("mov", "b,r0");
2037         emitcode ("mov", "r0,%s", spname);
2038         for (i = 0; i < ds390_nRegs; i++) {
2039             if (bitVectBitValue (rs_mask, i)) {
2040                 if (i == R0_IDX)
2041                     emitcode ("mov", "a,b");
2042                 else
2043                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2044                 emitcode ("movx", "@r0,a");
2045                 emitcode ("inc", "r0");
2046             }
2047         }
2048         emitcode ("mov", "%s,r0", spname);
2049         if (bitVectBitValue (rs_mask, R0_IDX))
2050             emitcode ("mov", "r0,b");
2051     } else {
2052         for (i = 0; i < ds390_nRegs; i++) {
2053             if (bitVectBitValue (rs_mask, i))
2054                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2055         }
2056     }
2057 }
2058
2059 /*-----------------------------------------------------------------*/
2060 /* saveRegisters - will look for a call and save the registers     */
2061 /*-----------------------------------------------------------------*/
2062 static void
2063 saveRegisters (iCode * lic)
2064 {
2065   iCode *ic;
2066   bitVect *rsave;
2067
2068   /* look for call */
2069   for (ic = lic; ic; ic = ic->next)
2070     if (ic->op == CALL || ic->op == PCALL)
2071       break;
2072
2073   if (!ic)
2074     {
2075       fprintf (stderr, "found parameter push with no function call\n");
2076       return;
2077     }
2078
2079   /* if the registers have been saved already then
2080      do nothing */
2081   if (ic->regsSaved 
2082       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2083     return ;
2084
2085   /* special case if DPTR alive across a function call then must save it 
2086      even though callee saves */
2087   if (IS_SYMOP(IC_LEFT(ic)) &&
2088       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2089       int i;
2090       rsave = newBitVect(ic->rMask->size);
2091       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2092           if (bitVectBitValue(ic->rMask,i))
2093               rsave = bitVectSetBit(rsave,i);
2094       }
2095       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2096   } else {
2097     /* safe the registers in use at this time but skip the
2098        ones for the result */
2099     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2100                            ds390_rUmaskForOp (IC_RESULT(ic)));
2101   }
2102   ic->regsSaved = 1;
2103   savermask(rsave);
2104 }
2105
2106 /*-----------------------------------------------------------------*/
2107 /* usavermask - restore registers with mask                        */
2108 /*-----------------------------------------------------------------*/
2109 static void unsavermask(bitVect *rs_mask)
2110 {
2111     int i;
2112     if (options.useXstack) {
2113         emitcode ("mov", "r0,%s", spname);
2114         for (i = ds390_nRegs; i >= 0; i--) {
2115             if (bitVectBitValue (rs_mask, i)) {
2116                 emitcode ("dec", "r0");
2117                 emitcode ("movx", "a,@r0");
2118                 if (i == R0_IDX)
2119                     emitcode ("mov", "b,a");
2120                 else
2121                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2122             }       
2123         }
2124         emitcode ("mov", "%s,r0", spname);
2125         if (bitVectBitValue (rs_mask, R0_IDX))
2126             emitcode ("mov", "r0,b");
2127     } else {
2128         for (i = ds390_nRegs; i >= 0; i--) {
2129             if (bitVectBitValue (rs_mask, i))
2130                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2131         }
2132     }
2133 }
2134
2135 /*-----------------------------------------------------------------*/
2136 /* unsaveRegisters - pop the pushed registers                      */
2137 /*-----------------------------------------------------------------*/
2138 static void
2139 unsaveRegisters (iCode * ic)
2140 {
2141   bitVect *rsave;
2142
2143   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2144       int i;
2145       rsave = newBitVect(ic->rMask->size);
2146       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2147           if (bitVectBitValue(ic->rMask,i))
2148               rsave = bitVectSetBit(rsave,i);
2149       }
2150       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2151   } else {
2152     /* restore the registers in use at this time but skip the
2153        ones for the result */
2154     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2155                            ds390_rUmaskForOp (IC_RESULT(ic)));
2156   }
2157   unsavermask(rsave);
2158 }
2159
2160
2161 /*-----------------------------------------------------------------*/
2162 /* pushSide -                */
2163 /*-----------------------------------------------------------------*/
2164 static void
2165 pushSide (operand * oper, int size)
2166 {
2167   int offset = 0;
2168   _startLazyDPSEvaluation ();
2169   while (size--)
2170     {
2171       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2172       if (AOP_TYPE (oper) != AOP_REG &&
2173           AOP_TYPE (oper) != AOP_DIR &&
2174           strcmp (l, "a"))
2175         {
2176           emitcode ("mov", "a,%s", l);
2177           emitcode ("push", "acc");
2178         }
2179       else
2180         emitcode ("push", "%s", l);
2181     }
2182   _endLazyDPSEvaluation ();
2183 }
2184
2185 /*-----------------------------------------------------------------*/
2186 /* assignResultValue -               */
2187 /*-----------------------------------------------------------------*/
2188 static void
2189 assignResultValue (operand * oper)
2190 {
2191   int offset = 0;
2192   int size = AOP_SIZE (oper);
2193   bool pushedAcc = FALSE;
2194
2195   if (size == fReturnSizeDS390)
2196   {
2197       /* I don't think this case can ever happen... */
2198       /* ACC is the last part of this. If writing the result
2199        * uses AC, we must preserve it.
2200        */
2201       if (AOP_NEEDSACC(oper))
2202       {
2203           emitcode(";", "assignResultValue special case for ACC.");
2204           emitcode("push", "acc");
2205           pushedAcc = TRUE;
2206           size--;
2207       }
2208   }
2209     
2210     
2211   _startLazyDPSEvaluation ();
2212   while (size--)
2213     {
2214       aopPut (AOP (oper), fReturn[offset], offset);
2215       offset++;
2216     }
2217   _endLazyDPSEvaluation ();
2218     
2219   if (pushedAcc)
2220     {
2221         emitcode("pop", "acc");
2222         aopPut(AOP(oper), "a", offset);
2223     }
2224 }
2225
2226
2227 /*-----------------------------------------------------------------*/
2228 /* genXpush - pushes onto the external stack                       */
2229 /*-----------------------------------------------------------------*/
2230 static void
2231 genXpush (iCode * ic)
2232 {
2233   asmop *aop = newAsmop (0);
2234   regs *r;
2235   int size, offset = 0;
2236
2237   D (emitcode (";", "genXpush ");
2238     );
2239
2240   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2241   r = getFreePtr (ic, &aop, FALSE);
2242
2243
2244   emitcode ("mov", "%s,_spx", r->name);
2245
2246   size = AOP_SIZE (IC_LEFT (ic));
2247   _startLazyDPSEvaluation ();
2248   while (size--)
2249     {
2250
2251       MOVA (aopGet (AOP (IC_LEFT (ic)),
2252                         offset++, FALSE, FALSE, NULL));
2253       emitcode ("movx", "@%s,a", r->name);
2254       emitcode ("inc", "%s", r->name);
2255
2256     }
2257   _endLazyDPSEvaluation ();
2258
2259
2260   emitcode ("mov", "_spx,%s", r->name);
2261
2262   freeAsmop (NULL, aop, ic, TRUE);
2263   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2264 }
2265
2266 /*-----------------------------------------------------------------*/
2267 /* genIpush - generate code for pushing this gets a little complex  */
2268 /*-----------------------------------------------------------------*/
2269 static void
2270 genIpush (iCode * ic)
2271 {
2272   int size, offset = 0;
2273   char *l;
2274
2275   D (emitcode (";", "genIpush ");
2276     );
2277
2278   /* if this is not a parm push : ie. it is spill push
2279      and spill push is always done on the local stack */
2280   if (!ic->parmPush)
2281     {
2282
2283       /* and the item is spilt then do nothing */
2284       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2285         return;
2286
2287       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2288       size = AOP_SIZE (IC_LEFT (ic));
2289       /* push it on the stack */
2290       _startLazyDPSEvaluation ();
2291       while (size--)
2292         {
2293           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2294           if (*l == '#')
2295             {
2296               MOVA (l);
2297               l = "acc";
2298             }
2299           emitcode ("push", "%s", l);
2300         }
2301       _endLazyDPSEvaluation ();
2302       return;
2303     }
2304
2305   /* this is a paramter push: in this case we call
2306      the routine to find the call and save those
2307      registers that need to be saved */
2308   saveRegisters (ic);
2309
2310   /* if use external stack then call the external
2311      stack pushing routine */
2312   if (options.useXstack)
2313     {
2314       genXpush (ic);
2315       return;
2316     }
2317
2318   /* then do the push */
2319   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2320
2321   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2322   size = AOP_SIZE (IC_LEFT (ic));
2323
2324   _startLazyDPSEvaluation ();
2325   while (size--)
2326     {
2327       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2328       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2329           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2330           strcmp (l, "acc"))
2331         {
2332           emitcode ("mov", "a,%s", l);
2333           emitcode ("push", "acc");
2334         }
2335       else
2336         {
2337             emitcode ("push", "%s", l);
2338         }
2339     }
2340   _endLazyDPSEvaluation ();
2341
2342   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2343 }
2344
2345 /*-----------------------------------------------------------------*/
2346 /* genIpop - recover the registers: can happen only for spilling   */
2347 /*-----------------------------------------------------------------*/
2348 static void
2349 genIpop (iCode * ic)
2350 {
2351   int size, offset;
2352
2353   D (emitcode (";", "genIpop ");
2354     );
2355
2356
2357   /* if the temp was not pushed then */
2358   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2359     return;
2360
2361   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2362   size = AOP_SIZE (IC_LEFT (ic));
2363   offset = (size - 1);
2364   _startLazyDPSEvaluation ();
2365   while (size--)
2366     {
2367       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2368                                      FALSE, TRUE, NULL));
2369     }
2370   _endLazyDPSEvaluation ();
2371
2372   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2373 }
2374
2375 /*-----------------------------------------------------------------*/
2376 /* unsaveRBank - restores the resgister bank from stack            */
2377 /*-----------------------------------------------------------------*/
2378 static void
2379 unsaveRBank (int bank, iCode * ic, bool popPsw)
2380 {
2381   int i;
2382   asmop *aop = NULL;
2383   regs *r = NULL;
2384
2385   if (options.useXstack)
2386   {
2387       if (!ic)
2388       {
2389           /* Assume r0 is available for use. */
2390           r = ds390_regWithIdx (R0_IDX);;          
2391       } 
2392       else
2393       {
2394           aop = newAsmop (0);
2395           r = getFreePtr (ic, &aop, FALSE);
2396       }
2397       emitcode ("mov", "%s,_spx", r->name);      
2398   }
2399   
2400   if (popPsw)
2401     {
2402       if (options.useXstack)
2403       {
2404           emitcode ("movx", "a,@%s", r->name);
2405           emitcode ("mov", "psw,a");
2406           emitcode ("dec", "%s", r->name);
2407         }
2408       else
2409       {
2410         emitcode ("pop", "psw");
2411       }
2412     }
2413
2414   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2415     {
2416       if (options.useXstack)
2417         {
2418           emitcode ("movx", "a,@%s", r->name);
2419           emitcode ("mov", "(%s+%d),a",
2420                     regs390[i].base, 8 * bank + regs390[i].offset);
2421           emitcode ("dec", "%s", r->name);
2422
2423         }
2424       else
2425         emitcode ("pop", "(%s+%d)",
2426                   regs390[i].base, 8 * bank + regs390[i].offset);
2427     }
2428
2429   if (options.useXstack)
2430     {
2431       emitcode ("mov", "_spx,%s", r->name);
2432     }
2433     
2434   if (aop)
2435   {
2436       freeAsmop (NULL, aop, ic, TRUE);  
2437   }    
2438 }
2439
2440 /*-----------------------------------------------------------------*/
2441 /* saveRBank - saves an entire register bank on the stack          */
2442 /*-----------------------------------------------------------------*/
2443 static void
2444 saveRBank (int bank, iCode * ic, bool pushPsw)
2445 {
2446   int i;
2447   asmop *aop = NULL;
2448   regs *r = NULL;
2449
2450   if (options.useXstack)
2451     {
2452         if (!ic)
2453         {
2454           /* Assume r0 is available for use. */
2455                   r = ds390_regWithIdx (R0_IDX);;
2456         }
2457         else
2458         {
2459           aop = newAsmop (0);
2460           r = getFreePtr (ic, &aop, FALSE);
2461         }
2462         emitcode ("mov", "%s,_spx", r->name);    
2463     }
2464
2465   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2466     {
2467       if (options.useXstack)
2468         {
2469           emitcode ("inc", "%s", r->name);
2470           emitcode ("mov", "a,(%s+%d)",
2471                     regs390[i].base, 8 * bank + regs390[i].offset);
2472           emitcode ("movx", "@%s,a", r->name);
2473         }
2474       else
2475         emitcode ("push", "(%s+%d)",
2476                   regs390[i].base, 8 * bank + regs390[i].offset);
2477     }
2478
2479   if (pushPsw)
2480     {
2481       if (options.useXstack)
2482         {
2483           emitcode ("mov", "a,psw");
2484           emitcode ("movx", "@%s,a", r->name);
2485           emitcode ("inc", "%s", r->name);
2486           emitcode ("mov", "_spx,%s", r->name);
2487         }
2488       else
2489       {
2490         emitcode ("push", "psw");
2491       }
2492
2493       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2494     }
2495   
2496   if (aop)
2497   {
2498        freeAsmop (NULL, aop, ic, TRUE);
2499   }    
2500     
2501   if (ic)
2502   {  
2503       ic->bankSaved = 1;
2504   }
2505 }
2506
2507 /*-----------------------------------------------------------------*/
2508 /* genSend - gen code for SEND                                     */
2509 /*-----------------------------------------------------------------*/
2510 static void genSend(set *sendSet)
2511 {
2512     iCode *sic;
2513     int sendCount = 0 ;
2514     static int rb1_count = 0;
2515
2516     for (sic = setFirstItem (sendSet); sic;
2517          sic = setNextItem (sendSet)) {     
2518         int size, offset = 0;
2519         
2520         size=getSize(operandType(IC_LEFT(sic)));
2521         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2522         if (sendCount == 0) { /* first parameter */
2523             // we know that dpl(hxb) is the result, so
2524             rb1_count = 0 ;
2525             _startLazyDPSEvaluation ();
2526             if (size>1) {
2527                 aopOp (IC_LEFT (sic), sic, FALSE, 
2528                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2529             } else {
2530                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2531             }
2532             while (size--) {
2533                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2534                                   FALSE, FALSE, NULL);
2535                 if (strcmp (l, fReturn[offset])) {
2536                     emitcode ("mov", "%s,%s",
2537                               fReturn[offset],
2538                               l);
2539                 }
2540                 offset++;
2541             }
2542             _endLazyDPSEvaluation ();
2543             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2544             rb1_count =0;
2545         } else { /* if more parameter in registers */
2546             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2547             while (size--) {
2548                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2549                                                                 FALSE, FALSE, NULL));
2550             }
2551             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2552         }
2553         sendCount++;
2554     }
2555 }
2556
2557 static void
2558 adjustEsp(const char *reg)
2559 {
2560     emitcode ("anl","%s,#3", reg);
2561     if (TARGET_IS_DS400)
2562     {
2563         emitcode ("orl","%s,#!constbyte",
2564                   reg,
2565                   (options.stack_loc >> 8) & 0xff);
2566     }
2567 }
2568
2569 /*-----------------------------------------------------------------*/
2570 /* genCall - generates a call statement                            */
2571 /*-----------------------------------------------------------------*/
2572 static void
2573 genCall (iCode * ic)
2574 {
2575   sym_link *dtype;
2576   bool restoreBank = FALSE;
2577   bool swapBanks = FALSE;
2578
2579   D (emitcode (";", "genCall "););
2580
2581   /* if we are calling a not _naked function that is not using
2582      the same register bank then we need to save the
2583      destination registers on the stack */
2584   dtype = operandType (IC_LEFT (ic));
2585   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2586       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2587       IFFUNC_ISISR (currFunc->type))
2588   {
2589       if (!ic->bankSaved) 
2590       {
2591            /* This is unexpected; the bank should have been saved in
2592             * genFunction.
2593             */
2594            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2595            restoreBank = TRUE;
2596       }
2597       swapBanks = TRUE;
2598   }
2599   
2600     /* if caller saves & we have not saved then */
2601     if (!ic->regsSaved)
2602       saveRegisters (ic);
2603   
2604   /* if send set is not empty the assign */
2605   /* We've saved all the registers we care about;
2606   * therefore, we may clobber any register not used
2607   * in the calling convention (i.e. anything not in
2608   * fReturn.
2609   */
2610   if (_G.sendSet)
2611     {
2612         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2613             genSend(reverseSet(_G.sendSet));
2614         } else {
2615             genSend(_G.sendSet);
2616         }
2617       _G.sendSet = NULL;
2618     }  
2619     
2620   if (swapBanks)
2621   {
2622         emitcode ("mov", "psw,#!constbyte", 
2623            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2624   }
2625
2626   /* make the call */
2627   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2628                             OP_SYMBOL (IC_LEFT (ic))->rname :
2629                             OP_SYMBOL (IC_LEFT (ic))->name));
2630
2631   if (swapBanks)
2632   {
2633        emitcode ("mov", "psw,#!constbyte", 
2634           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2635   }
2636
2637   /* if we need assign a result value */
2638   if ((IS_ITEMP (IC_RESULT (ic)) &&
2639        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2640         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2641         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2642       IS_TRUE_SYMOP (IC_RESULT (ic)))
2643     {
2644       if (isOperandInFarSpace (IC_RESULT (ic))
2645           && getSize (operandType (IC_RESULT (ic))) <= 2)
2646         {
2647           int size = getSize (operandType (IC_RESULT (ic)));
2648
2649           /* Special case for 1 or 2 byte return in far space. */
2650           MOVA (fReturn[0]);
2651           if (size > 1)
2652             {
2653               emitcode ("mov", "b,%s", fReturn[1]);
2654             }
2655
2656           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2657           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2658
2659           if (size > 1)
2660             {
2661               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2662             }
2663           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2664         }
2665       else
2666         {
2667           _G.bInUse++;
2668           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2669           _G.bInUse--;
2670
2671           assignResultValue (IC_RESULT (ic));
2672
2673           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2674         }
2675     }
2676
2677   /* adjust the stack for parameters if
2678      required */
2679   if (ic->parmBytes) {
2680       int i;
2681       if (options.stack10bit) {
2682           if (ic->parmBytes <= 10) {
2683               emitcode(";","stack adjustment for parms");
2684               for (i=0; i < ic->parmBytes ; i++) {
2685                   emitcode("pop","acc");
2686               }
2687           } else {            
2688               PROTECT_SP;
2689               emitcode ("clr","c");
2690               emitcode ("mov","a,sp");
2691               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2692               emitcode ("mov","sp,a");
2693               emitcode ("mov","a,esp");
2694               adjustEsp("a");
2695               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2696               emitcode ("mov","esp,a");   
2697               UNPROTECT_SP;
2698           }
2699       } else {
2700           if (ic->parmBytes > 3) {
2701               emitcode ("mov", "a,%s", spname);
2702               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2703               emitcode ("mov", "%s,a", spname);
2704           } else
2705               for (i = 0; i < ic->parmBytes; i++)
2706                   emitcode ("dec", "%s", spname);
2707       }
2708   }
2709
2710   /* if we hade saved some registers then unsave them */
2711   if (ic->regsSaved)
2712     unsaveRegisters (ic);
2713
2714   /* if register bank was saved then pop them */
2715   if (restoreBank)
2716     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2717 }
2718
2719 /*-----------------------------------------------------------------*/
2720 /* genPcall - generates a call by pointer statement                */
2721 /*-----------------------------------------------------------------*/
2722 static void
2723 genPcall (iCode * ic)
2724 {
2725   sym_link *dtype;
2726   symbol *rlbl = newiTempLabel (NULL);
2727   bool restoreBank=FALSE;
2728
2729   D (emitcode (";", "genPcall ");
2730     );
2731
2732
2733   /* if caller saves & we have not saved then */
2734   if (!ic->regsSaved)
2735     saveRegisters (ic);
2736
2737   /* if we are calling a function that is not using
2738      the same register bank then we need to save the
2739      destination registers on the stack */
2740   dtype = operandType (IC_LEFT (ic));
2741   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2742       IFFUNC_ISISR (currFunc->type) &&
2743       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2744     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2745     restoreBank=TRUE;
2746   }
2747
2748   /* push the return address on to the stack */
2749   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2750   emitcode ("push", "acc");
2751   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2752   emitcode ("push", "acc");
2753
2754   if (options.model == MODEL_FLAT24)
2755     {
2756       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2757       emitcode ("push", "acc");
2758     }
2759
2760   /* now push the calling address */
2761   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2762
2763   pushSide (IC_LEFT (ic), FPTRSIZE);
2764
2765   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2766
2767   /* if send set is not empty the assign */
2768   if (_G.sendSet)
2769     {
2770         genSend(reverseSet(_G.sendSet));
2771         _G.sendSet = NULL;
2772     }
2773
2774   emitcode ("ret", "");
2775   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2776
2777
2778   /* if we need assign a result value */
2779   if ((IS_ITEMP (IC_RESULT (ic)) &&
2780        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2781         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2782       IS_TRUE_SYMOP (IC_RESULT (ic)))
2783     {
2784
2785       _G.accInUse++;
2786       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2787       _G.accInUse--;
2788
2789       assignResultValue (IC_RESULT (ic));
2790
2791       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2792     }
2793
2794   /* adjust the stack for parameters if
2795      required */
2796   if (ic->parmBytes)
2797     {
2798       int i;
2799       if (options.stack10bit) {
2800           if (ic->parmBytes <= 10) {
2801               emitcode(";","stack adjustment for parms");
2802               for (i=0; i < ic->parmBytes ; i++) {
2803                   emitcode("pop","acc");
2804               }
2805           } else {            
2806               PROTECT_SP;
2807               emitcode ("clr","c");
2808               emitcode ("mov","a,sp");
2809               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2810               emitcode ("mov","sp,a");
2811               emitcode ("mov","a,esp");
2812               adjustEsp("a");
2813               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2814               emitcode ("mov","esp,a");   
2815               UNPROTECT_SP;
2816           }
2817       } else {
2818           if (ic->parmBytes > 3) {
2819               emitcode ("mov", "a,%s", spname);
2820               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2821               emitcode ("mov", "%s,a", spname);
2822           }
2823           else
2824               for (i = 0; i < ic->parmBytes; i++)
2825                   emitcode ("dec", "%s", spname);
2826           
2827       }
2828     }
2829   /* if register bank was saved then unsave them */
2830   if (restoreBank)
2831     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2832   
2833   /* if we hade saved some registers then
2834      unsave them */
2835   if (ic->regsSaved)
2836     unsaveRegisters (ic);
2837
2838 }
2839
2840 /*-----------------------------------------------------------------*/
2841 /* resultRemat - result  is rematerializable                       */
2842 /*-----------------------------------------------------------------*/
2843 static int
2844 resultRemat (iCode * ic)
2845 {
2846   if (SKIP_IC (ic) || ic->op == IFX)
2847     return 0;
2848
2849   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2850     {
2851       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2852       if (sym->remat && !POINTER_SET (ic))
2853         return 1;
2854     }
2855
2856   return 0;
2857 }
2858
2859 #if defined(__BORLANDC__) || defined(_MSC_VER)
2860 #define STRCASECMP stricmp
2861 #else
2862 #define STRCASECMP strcasecmp
2863 #endif
2864
2865 /*-----------------------------------------------------------------*/
2866 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2867 /*-----------------------------------------------------------------*/
2868 static int
2869 regsCmp(void *p1, void *p2)
2870 {
2871   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2872 }
2873
2874 static bool
2875 inExcludeList (char *s)
2876 {
2877   const char *p = setFirstItem(options.excludeRegsSet);
2878
2879   if (p == NULL || STRCASECMP(p, "none") == 0)
2880     return FALSE;
2881
2882
2883   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2884 }
2885
2886 /*-----------------------------------------------------------------*/
2887 /* genFunction - generated code for function entry                 */
2888 /*-----------------------------------------------------------------*/
2889 static void
2890 genFunction (iCode * ic)
2891 {
2892   symbol *sym;
2893   sym_link *ftype;
2894   bool   switchedPSW = FALSE;
2895
2896   D (emitcode (";", "genFunction "););
2897
2898   _G.nRegsSaved = 0;
2899   /* create the function header */
2900   emitcode (";", "-----------------------------------------");
2901   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2902   emitcode (";", "-----------------------------------------");
2903
2904   emitcode ("", "%s:", sym->rname);
2905   ftype = operandType (IC_LEFT (ic));
2906
2907   if (IFFUNC_ISNAKED(ftype))
2908   {
2909       emitcode(";", "naked function: no prologue.");
2910       return;
2911   }
2912   
2913   if (options.stack_probe) 
2914       emitcode ("lcall","__stack_probe");
2915
2916   /* here we need to generate the equates for the
2917      register bank if required */
2918   if (FUNC_REGBANK (ftype) != rbank)
2919     {
2920       int i;
2921
2922       rbank = FUNC_REGBANK (ftype);
2923       for (i = 0; i < ds390_nRegs; i++)
2924         {
2925           if (regs390[i].print) {
2926               if (strcmp (regs390[i].base, "0") == 0)
2927                   emitcode ("", "%s !equ !constbyte",
2928                             regs390[i].dname,
2929                             8 * rbank + regs390[i].offset);
2930               else
2931                   emitcode ("", "%s !equ %s + !constbyte",
2932                             regs390[i].dname,
2933                             regs390[i].base,
2934                             8 * rbank + regs390[i].offset);
2935           }
2936         }
2937     }
2938
2939   /* if this is an interrupt service routine then
2940      save acc, b, dpl, dph  */
2941   if (IFFUNC_ISISR (sym->type))
2942       { /* is ISR */
2943       if (!inExcludeList ("acc"))
2944         emitcode ("push", "acc");
2945       if (!inExcludeList ("b"))
2946         emitcode ("push", "b");
2947       if (!inExcludeList ("dpl"))
2948         emitcode ("push", "dpl");
2949       if (!inExcludeList ("dph"))
2950         emitcode ("push", "dph");
2951       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2952         {
2953           emitcode ("push", "dpx");
2954           /* Make sure we're using standard DPTR */
2955           emitcode ("push", "dps");
2956           emitcode ("mov", "dps,#0");
2957           if (options.stack10bit)
2958             {
2959               /* This ISR could conceivably use DPTR2. Better save it. */
2960               emitcode ("push", "dpl1");
2961               emitcode ("push", "dph1");
2962               emitcode ("push", "dpx1");
2963               emitcode ("push",  DP2_RESULT_REG);
2964             }
2965         }
2966       /* if this isr has no bank i.e. is going to
2967          run with bank 0 , then we need to save more
2968          registers :-) */
2969       if (!FUNC_REGBANK (sym->type))
2970         {
2971             int i;
2972
2973           /* if this function does not call any other
2974              function then we can be economical and
2975              save only those registers that are used */
2976           if (!IFFUNC_HASFCALL(sym->type))
2977             {
2978
2979               /* if any registers used */
2980               if (sym->regsUsed)
2981                 {
2982                   /* save the registers used */
2983                   for (i = 0; i < sym->regsUsed->size; i++)
2984                     {
2985                       if (bitVectBitValue (sym->regsUsed, i) ||
2986                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2987                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2988                     }
2989                 }
2990
2991             }
2992           else
2993             {
2994               /* this function has  a function call cannot
2995                  determines register usage so we will have to push the
2996                  entire bank */
2997               saveRBank (0, ic, FALSE);
2998               if (options.parms_in_bank1) {
2999                   for (i=0; i < 8 ; i++ ) {
3000                       emitcode ("push","%s",rb1regs[i]);
3001                   }
3002               }
3003             }
3004         }
3005         else
3006         {
3007             /* This ISR uses a non-zero bank.
3008              *
3009              * We assume that the bank is available for our
3010              * exclusive use.
3011              *
3012              * However, if this ISR calls a function which uses some
3013              * other bank, we must save that bank entirely.
3014              */
3015             unsigned long banksToSave = 0;
3016             
3017             if (IFFUNC_HASFCALL(sym->type))
3018             {
3019
3020 #define MAX_REGISTER_BANKS 4
3021
3022                 iCode *i;
3023                 int ix;
3024
3025                 for (i = ic; i; i = i->next)
3026                 {
3027                     if (i->op == ENDFUNCTION)
3028                     {
3029                         /* we got to the end OK. */
3030                         break;
3031                     }
3032                     
3033                     if (i->op == CALL)
3034                     {
3035                         sym_link *dtype;
3036                         
3037                         dtype = operandType (IC_LEFT(i));
3038                         if (dtype 
3039                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3040                         {
3041                              /* Mark this bank for saving. */
3042                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3043                              {
3044                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3045                              }
3046                              else
3047                              {
3048                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3049                              }
3050                              
3051                              /* And note that we don't need to do it in 
3052                               * genCall.
3053                               */
3054                              i->bankSaved = 1;
3055                         }
3056                     }
3057                     if (i->op == PCALL)
3058                     {
3059                         /* This is a mess; we have no idea what
3060                          * register bank the called function might
3061                          * use.
3062                          *
3063                          * The only thing I can think of to do is
3064                          * throw a warning and hope.
3065                          */
3066                         werror(W_FUNCPTR_IN_USING_ISR);   
3067                     }
3068                 }
3069
3070                 if (banksToSave && options.useXstack)
3071                 {
3072                     /* Since we aren't passing it an ic, 
3073                      * saveRBank will assume r0 is available to abuse.
3074                      *
3075                      * So switch to our (trashable) bank now, so
3076                      * the caller's R0 isn't trashed.
3077                      */
3078                     emitcode ("push", "psw");
3079                     emitcode ("mov", "psw,#!constbyte", 
3080                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3081                     switchedPSW = TRUE;
3082                 }
3083                 
3084                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3085                 {
3086                      if (banksToSave & (1 << ix))
3087                      {
3088                          saveRBank(ix, NULL, FALSE);
3089                      }
3090                 }
3091             }
3092             // TODO: this needs a closer look
3093             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3094         }
3095     }
3096   else
3097     {
3098       /* if callee-save to be used for this function
3099          then save the registers being used in this function */
3100       if (IFFUNC_CALLEESAVES(sym->type))
3101         {
3102           int i;
3103
3104           /* if any registers used */
3105           if (sym->regsUsed)
3106             {
3107               /* save the registers used */
3108               for (i = 0; i < sym->regsUsed->size; i++)
3109                 {
3110                   if (bitVectBitValue (sym->regsUsed, i) ||
3111                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3112                     {
3113                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3114                       _G.nRegsSaved++;
3115                     }
3116                 }
3117             }
3118         }
3119     }
3120
3121   /* set the register bank to the desired value */
3122   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3123    && !switchedPSW)
3124     {
3125       emitcode ("push", "psw");
3126       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3127     }
3128
3129   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3130        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3131       if (options.stack10bit) {
3132           emitcode ("push","_bpx");
3133           emitcode ("push","_bpx+1");
3134           emitcode ("mov","_bpx,%s",spname);
3135           emitcode ("mov","_bpx+1,esp");
3136           adjustEsp("_bpx+1");
3137       } else {
3138           if (options.useXstack) {
3139               emitcode ("mov", "r0,%s", spname);
3140               emitcode ("mov", "a,_bp");
3141               emitcode ("movx", "@r0,a");
3142               emitcode ("inc", "%s", spname);
3143           } else {
3144               /* set up the stack */
3145               emitcode ("push", "_bp"); /* save the callers stack  */
3146           }
3147           emitcode ("mov", "_bp,%s", spname);
3148       }
3149   }
3150
3151   /* adjust the stack for the function */
3152   if (sym->stack) {
3153       int i = sym->stack;
3154       if (options.stack10bit) {
3155           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3156           assert (sym->recvSize <= 4);
3157           if (sym->stack <= 8) {
3158               while (i--) emitcode ("push","acc");
3159           } else {
3160               PROTECT_SP;
3161               emitcode ("mov","a,sp");
3162               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3163               emitcode ("mov","sp,a");
3164               emitcode ("mov","a,esp");
3165               adjustEsp("a");
3166               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3167               emitcode ("mov","esp,a");
3168               UNPROTECT_SP;
3169           }
3170       } else {
3171           if (i > 256)
3172               werror (W_STACK_OVERFLOW, sym->name);
3173           
3174           if (i > 3 && sym->recvSize < 4) {
3175               
3176               emitcode ("mov", "a,sp");
3177               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3178               emitcode ("mov", "sp,a");
3179               
3180           } else
3181               while (i--)
3182                   emitcode ("inc", "sp");
3183       }
3184   }
3185
3186   if (sym->xstack)
3187     {
3188
3189       emitcode ("mov", "a,_spx");
3190       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3191       emitcode ("mov", "_spx,a");
3192     }
3193   
3194   /* if critical function then turn interrupts off */
3195   if (IFFUNC_ISCRITICAL (ftype))
3196     {
3197       symbol *tlbl = newiTempLabel (NULL);
3198       emitcode ("setb", "c");
3199       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3200       emitcode ("clr", "c");
3201       emitcode ("", "%05d$:", (tlbl->key + 100));
3202       emitcode ("push", "psw"); /* save old ea via c in psw */
3203     }
3204
3205 }
3206
3207 /*-----------------------------------------------------------------*/
3208 /* genEndFunction - generates epilogue for functions               */
3209 /*-----------------------------------------------------------------*/
3210 static void
3211 genEndFunction (iCode * ic)
3212 {
3213   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3214
3215   D (emitcode (";", "genEndFunction "););
3216
3217   if (IFFUNC_ISNAKED(sym->type))
3218   {
3219       emitcode(";", "naked function: no epilogue.");
3220       return;
3221   }
3222
3223   if (IFFUNC_ISCRITICAL (sym->type))
3224     {
3225       emitcode ("pop", "psw"); /* restore ea via c in psw */
3226       emitcode ("mov", "ea,c");
3227     }
3228   
3229   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3230        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3231
3232       if (options.stack10bit) {
3233           PROTECT_SP;     
3234           emitcode ("mov", "sp,_bpx", spname);
3235           emitcode ("mov", "esp,_bpx+1", spname);
3236           UNPROTECT_SP;
3237       } else {
3238           emitcode ("mov", "%s,_bp", spname);
3239       }
3240   }
3241
3242   /* if use external stack but some variables were
3243      added to the local stack then decrement the
3244      local stack */
3245   if (options.useXstack && sym->stack) {
3246       emitcode ("mov", "a,sp");
3247       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3248       emitcode ("mov", "sp,a");
3249   }
3250
3251
3252   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3253        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3254
3255       if (options.useXstack) {
3256           emitcode ("mov", "r0,%s", spname);
3257           emitcode ("movx", "a,@r0");
3258           emitcode ("mov", "_bp,a");
3259           emitcode ("dec", "%s", spname);
3260       } else {
3261           if (options.stack10bit) {
3262               emitcode ("pop", "_bpx+1");
3263               emitcode ("pop", "_bpx");
3264           } else {
3265               emitcode ("pop", "_bp");
3266           }
3267       }
3268   }
3269
3270   /* restore the register bank  */
3271   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3272   {
3273     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3274      || !options.useXstack)
3275     {
3276         /* Special case of ISR using non-zero bank with useXstack
3277          * is handled below.
3278          */
3279         emitcode ("pop", "psw");
3280     }
3281   } 
3282
3283   if (IFFUNC_ISISR (sym->type))
3284       { /* is ISR */  
3285
3286       /* now we need to restore the registers */
3287       /* if this isr has no bank i.e. is going to
3288          run with bank 0 , then we need to save more
3289          registers :-) */
3290       if (!FUNC_REGBANK (sym->type))
3291         {
3292             int i;
3293           /* if this function does not call any other
3294              function then we can be economical and
3295              save only those registers that are used */
3296           if (!IFFUNC_HASFCALL(sym->type))
3297             {
3298
3299               /* if any registers used */
3300               if (sym->regsUsed)
3301                 {
3302                   /* save the registers used */
3303                   for (i = sym->regsUsed->size; i >= 0; i--)
3304                     {
3305                       if (bitVectBitValue (sym->regsUsed, i) ||
3306                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3307                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3308                     }
3309                 }
3310
3311             }
3312           else
3313             {
3314               /* this function has  a function call cannot
3315                  determines register usage so we will have to pop the
3316                  entire bank */
3317               if (options.parms_in_bank1) {
3318                   for (i = 7 ; i >= 0 ; i-- ) {
3319                       emitcode ("pop","%s",rb1regs[i]);
3320                   }
3321               }
3322               unsaveRBank (0, ic, FALSE);
3323             }
3324         }
3325         else
3326         {
3327             /* This ISR uses a non-zero bank.
3328              *
3329              * Restore any register banks saved by genFunction
3330              * in reverse order.
3331              */
3332             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3333             int ix;
3334           
3335             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3336             {
3337                 if (savedBanks & (1 << ix))
3338                 {
3339                     unsaveRBank(ix, NULL, FALSE);
3340                 }
3341             }
3342             
3343             if (options.useXstack)
3344             {
3345                 /* Restore bank AFTER calling unsaveRBank,
3346                  * since it can trash r0.
3347                  */
3348                 emitcode ("pop", "psw");
3349             }
3350         }
3351
3352       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3353         {
3354           if (options.stack10bit)
3355             {
3356               emitcode ("pop", DP2_RESULT_REG);
3357               emitcode ("pop", "dpx1");
3358               emitcode ("pop", "dph1");
3359               emitcode ("pop", "dpl1");
3360             }
3361           emitcode ("pop", "dps");
3362           emitcode ("pop", "dpx");
3363         }
3364       if (!inExcludeList ("dph"))
3365         emitcode ("pop", "dph");
3366       if (!inExcludeList ("dpl"))
3367         emitcode ("pop", "dpl");
3368       if (!inExcludeList ("b"))
3369         emitcode ("pop", "b");
3370       if (!inExcludeList ("acc"))
3371         emitcode ("pop", "acc");
3372
3373       /* if debug then send end of function */
3374       if (options.debug && currFunc) {
3375           _G.debugLine = 1;
3376           emitcode ("", "C$%s$%d$%d$%d ==.",
3377                     FileBaseName (ic->filename), currFunc->lastLine,
3378                     ic->level, ic->block);
3379           if (IS_STATIC (currFunc->etype))
3380             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3381           else
3382             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3383           _G.debugLine = 0;
3384         }
3385
3386       emitcode ("reti", "");
3387     }
3388   else
3389     {
3390       if (IFFUNC_CALLEESAVES(sym->type))
3391         {
3392           int i;
3393
3394           /* if any registers used */
3395           if (sym->regsUsed)
3396             {
3397               /* save the registers used */
3398               for (i = sym->regsUsed->size; i >= 0; i--)
3399                 {
3400                   if (bitVectBitValue (sym->regsUsed, i) ||
3401                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3402                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3403                 }
3404             }
3405
3406         }
3407
3408       /* if debug then send end of function */
3409       if (options.debug && currFunc)
3410         {
3411           _G.debugLine = 1;
3412           emitcode ("", "C$%s$%d$%d$%d ==.",
3413                     FileBaseName (ic->filename), currFunc->lastLine,
3414                     ic->level, ic->block);
3415           if (IS_STATIC (currFunc->etype))
3416             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3417           else
3418             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3419           _G.debugLine = 0;
3420         }
3421
3422       emitcode ("ret", "");
3423     }
3424
3425 }
3426
3427 /*-----------------------------------------------------------------*/
3428 /* genJavaNativeRet - generate code for return JavaNative          */
3429 /*-----------------------------------------------------------------*/
3430 static void genJavaNativeRet(iCode *ic)
3431 {
3432     int i, size;
3433
3434     aopOp (IC_LEFT (ic), ic, FALSE, 
3435            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3436     size = AOP_SIZE (IC_LEFT (ic));
3437
3438     assert (size <= 4);
3439
3440     /* it is assigned to GPR0-R3 then push them */
3441     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3442         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3443         for (i = 0 ; i < size ; i++ ) {
3444             emitcode ("push","%s",
3445                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3446         }
3447         for (i = (size-1) ; i >= 0 ; i--) {
3448             emitcode ("pop","a%s",javaRet[i]);
3449         }
3450     } else {
3451         for (i = 0 ; i < size ; i++) 
3452             emitcode ("mov","%s,%s",javaRet[i],
3453                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3454     }
3455     for (i = size ; i < 4 ; i++ )
3456             emitcode ("mov","%s,#0",javaRet[i]);
3457     return;
3458 }
3459
3460 /*-----------------------------------------------------------------*/
3461 /* genRet - generate code for return statement                     */
3462 /*-----------------------------------------------------------------*/
3463 static void
3464 genRet (iCode * ic)
3465 {
3466   int size, offset = 0, pushed = 0;
3467
3468   D (emitcode (";", "genRet "););
3469
3470   /* if we have no return value then
3471      just generate the "ret" */
3472   if (!IC_LEFT (ic))
3473     goto jumpret;
3474
3475   /* if this is a JavaNative function then return 
3476      value in different register */
3477   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3478       genJavaNativeRet(ic);
3479       goto jumpret;
3480   }
3481   /* we have something to return then
3482      move the return value into place */
3483   aopOp (IC_LEFT (ic), ic, FALSE, 
3484          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3485   size = AOP_SIZE (IC_LEFT (ic));
3486
3487   _startLazyDPSEvaluation ();
3488   while (size--)
3489     {
3490       char *l;
3491       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3492         {
3493           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3494                       FALSE, TRUE, NULL);
3495           emitcode ("push", "%s", l);
3496           pushed++;
3497         }
3498       else
3499         {
3500           /* Since A is the last element of fReturn,
3501            * is is OK to clobber it in the aopGet.
3502            */
3503           l = aopGet (AOP (IC_LEFT (ic)), offset,
3504                       FALSE, FALSE, NULL);
3505           if (strcmp (fReturn[offset], l))
3506             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3507         }
3508     }
3509   _endLazyDPSEvaluation ();
3510
3511   if (pushed)
3512     {
3513       while (pushed)
3514         {
3515           pushed--;
3516           if (strcmp (fReturn[pushed], "a"))
3517             emitcode ("pop", fReturn[pushed]);
3518           else
3519             emitcode ("pop", "acc");
3520         }
3521     }
3522   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3523
3524 jumpret:
3525   /* generate a jump to the return label
3526      if the next is not the return statement */
3527   if (!(ic->next && ic->next->op == LABEL &&
3528         IC_LABEL (ic->next) == returnLabel))
3529
3530     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3531
3532 }
3533
3534 /*-----------------------------------------------------------------*/
3535 /* genLabel - generates a label                                    */
3536 /*-----------------------------------------------------------------*/
3537 static void
3538 genLabel (iCode * ic)
3539 {
3540   /* special case never generate */
3541   if (IC_LABEL (ic) == entryLabel)
3542     return;
3543
3544   D (emitcode (";", "genLabel ");
3545     );
3546
3547   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3548 }
3549
3550 /*-----------------------------------------------------------------*/
3551 /* genGoto - generates a ljmp                                      */
3552 /*-----------------------------------------------------------------*/
3553 static void
3554 genGoto (iCode * ic)
3555 {
3556   D (emitcode (";", "genGoto ");
3557     );
3558   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3559 }
3560
3561 /*-----------------------------------------------------------------*/
3562 /* findLabelBackwards: walks back through the iCode chain looking  */
3563 /* for the given label. Returns number of iCode instructions     */
3564 /* between that label and given ic.          */
3565 /* Returns zero if label not found.          */
3566 /*-----------------------------------------------------------------*/
3567 static int
3568 findLabelBackwards (iCode * ic, int key)
3569 {
3570   int count = 0;
3571
3572   while (ic->prev)
3573     {
3574       ic = ic->prev;
3575       count++;
3576
3577       /* If we have any pushes or pops, we cannot predict the distance.
3578          I don't like this at all, this should be dealt with in the 
3579          back-end */
3580       if (ic->op == IPUSH || ic->op == IPOP) {
3581         return 0;
3582       }
3583
3584       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3585         {
3586           /* printf("findLabelBackwards = %d\n", count); */
3587           return count;
3588         }
3589     }
3590
3591   return 0;
3592 }
3593
3594 /*-----------------------------------------------------------------*/
3595 /* genPlusIncr :- does addition with increment if possible         */
3596 /*-----------------------------------------------------------------*/
3597 static bool
3598 genPlusIncr (iCode * ic)
3599 {
3600   unsigned int icount;
3601   unsigned int size = getDataSize (IC_RESULT (ic));
3602
3603   /* will try to generate an increment */
3604   /* if the right side is not a literal
3605      we cannot */
3606   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3607     return FALSE;
3608
3609   /* if the literal value of the right hand side
3610      is greater than 4 then it is not worth it */
3611   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3612     return FALSE;
3613
3614   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3615       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3616       while (icount--) {
3617           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3618       }
3619       return TRUE;
3620   }
3621   /* if increment 16 bits in register */
3622   if (
3623        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3624        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3625        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3626        (size > 1) &&
3627        (icount == 1))
3628     {
3629       symbol  *tlbl;
3630       int     emitTlbl;
3631       int     labelRange;
3632       char    *l;
3633
3634       /* If the next instruction is a goto and the goto target
3635        * is <= 5 instructions previous to this, we can generate
3636        * jumps straight to that target.
3637        */
3638       if (ic->next && ic->next->op == GOTO
3639           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3640           && labelRange <= 5)
3641         {
3642           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3643           tlbl = IC_LABEL (ic->next);
3644           emitTlbl = 0;
3645         }
3646       else
3647         {
3648           tlbl = newiTempLabel (NULL);
3649           emitTlbl = 1;
3650         }
3651         
3652       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3653       emitcode ("inc", "%s", l);
3654       
3655       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3656           IS_AOP_PREG (IC_RESULT (ic)))
3657       {   
3658         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3659       }
3660       else
3661       {
3662           emitcode ("clr", "a");
3663           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3664       }
3665
3666       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3667       emitcode ("inc", "%s", l);
3668       if (size > 2)
3669         {
3670             if (!strcmp(l, "acc"))
3671             {
3672                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3673             }
3674             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3675                      IS_AOP_PREG (IC_RESULT (ic)))
3676             {
3677                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3678             }
3679             else
3680             {
3681                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3682             }
3683
3684             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3685             emitcode ("inc", "%s", l);
3686         }
3687       if (size > 3)
3688         {
3689             if (!strcmp(l, "acc"))
3690             {
3691                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3692             }
3693             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3694                      IS_AOP_PREG (IC_RESULT (ic)))
3695             {
3696                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3697             }
3698             else
3699             {
3700                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3701             }
3702
3703             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3704             emitcode ("inc", "%s", l);  }
3705
3706       if (emitTlbl)
3707         {
3708           emitcode ("", "!tlabeldef", tlbl->key + 100);
3709         }
3710       return TRUE;
3711     }
3712
3713   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3714       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3715       options.model == MODEL_FLAT24 ) {
3716
3717       switch (size) {
3718       case 3:
3719           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3720       case 2:
3721           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3722       case 1:
3723           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3724           break;
3725       }
3726       while (icount--) emitcode ("inc","dptr");      
3727       return TRUE;
3728   }
3729
3730   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3731       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3732       icount <= 5 ) {
3733       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3734       while (icount--) emitcode ("inc","dptr");
3735       emitcode ("mov","dps,#0");
3736       return TRUE;
3737   }
3738
3739   /* if the sizes are greater than 1 then we cannot */
3740   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3741       AOP_SIZE (IC_LEFT (ic)) > 1)
3742     return FALSE;
3743
3744   /* we can if the aops of the left & result match or
3745      if they are in registers and the registers are the
3746      same */
3747   if (
3748        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3749        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3750        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3751     {
3752
3753       if (icount > 3)
3754         {
3755           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3756           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3757           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3758         }
3759       else
3760         {
3761
3762           _startLazyDPSEvaluation ();
3763           while (icount--)
3764             {
3765               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3766             }
3767           _endLazyDPSEvaluation ();
3768         }
3769
3770       return TRUE;
3771     }
3772
3773   return FALSE;
3774 }
3775
3776 /*-----------------------------------------------------------------*/
3777 /* outBitAcc - output a bit in acc                                 */
3778 /*-----------------------------------------------------------------*/
3779 static void
3780 outBitAcc (operand * result)
3781 {
3782   symbol *tlbl = newiTempLabel (NULL);
3783   /* if the result is a bit */
3784   if (AOP_TYPE (result) == AOP_CRY)
3785     {
3786       aopPut (AOP (result), "a", 0);
3787     }
3788   else
3789     {
3790       emitcode ("jz", "!tlabel", tlbl->key + 100);
3791       emitcode ("mov", "a,%s", one);
3792       emitcode ("", "!tlabeldef", tlbl->key + 100);
3793       outAcc (result);
3794     }
3795 }
3796
3797 /*-----------------------------------------------------------------*/
3798 /* genPlusBits - generates code for addition of two bits           */
3799 /*-----------------------------------------------------------------*/
3800 static void
3801 genPlusBits (iCode * ic)
3802 {
3803   D (emitcode (";", "genPlusBits "););
3804     
3805   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3806     {
3807       symbol *lbl = newiTempLabel (NULL);
3808       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3809       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3810       emitcode ("cpl", "c");
3811       emitcode ("", "!tlabeldef", (lbl->key + 100));
3812       outBitC (IC_RESULT (ic));
3813     }
3814   else
3815     {
3816       emitcode ("clr", "a");
3817       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3818       emitcode ("rlc", "a");
3819       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3820       emitcode ("addc", "a,#0");
3821       outAcc (IC_RESULT (ic));
3822     }
3823 }
3824
3825 static void
3826 adjustArithmeticResult (iCode * ic)
3827 {
3828   if (opIsGptr (IC_RESULT (ic)) &&
3829       opIsGptr (IC_LEFT (ic)) &&
3830       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3831     {
3832       aopPut (AOP (IC_RESULT (ic)),
3833               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3834               GPTRSIZE - 1);
3835     }
3836
3837   if (opIsGptr (IC_RESULT (ic)) &&
3838       opIsGptr (IC_RIGHT (ic)) &&
3839       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3840     {
3841       aopPut (AOP (IC_RESULT (ic)),
3842             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3843               GPTRSIZE - 1);
3844     }
3845
3846   if (opIsGptr (IC_RESULT (ic)) &&
3847       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3848       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3849       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3850       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3851     {
3852       char buff[5];
3853       SNPRINTF (buff, sizeof(buff), 
3854                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3855       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3856     }
3857 }
3858
3859 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3860 // generates the result if possible. If result is generated, returns TRUE; otherwise
3861 // returns false and caller must deal with fact that result isn't aopOp'd.
3862 bool aopOp3(iCode * ic)
3863 {
3864     bool dp1InUse, dp2InUse;
3865     bool useDp2;
3866     
3867     // First, generate the right opcode. DPTR may be used if neither left nor result are
3868     // of type AOP_STR.
3869     
3870 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3871 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3872 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3873 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3874 //      );
3875 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3876 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3877 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3878 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3879 //      );
3880     
3881     // Right uses DPTR unless left or result is an AOP_STR; however,
3882     // if right is an AOP_STR, it must use DPTR regardless.
3883     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3884      && !AOP_IS_STR(IC_RIGHT(ic)))
3885     {
3886         useDp2 = TRUE;
3887     }
3888     else
3889     {
3890         useDp2 = FALSE;
3891     }
3892         
3893     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3894     
3895     // if the right used DPTR, left MUST use DPTR2.
3896     // if the right used DPTR2, left MUST use DPTR.
3897     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3898     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3899     // enabling us to assign DPTR to result.
3900      
3901     if (AOP_USESDPTR(IC_RIGHT(ic)))
3902     {
3903         useDp2 = TRUE;
3904     }
3905     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3906     {
3907         useDp2 = FALSE;
3908     }
3909     else
3910     {
3911         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3912         {
3913             useDp2 = TRUE;
3914         }
3915         else
3916         {
3917             useDp2 = FALSE;
3918         }
3919     }
3920
3921     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3922     
3923     // We've op'd the left & right. So, if left or right are the same operand as result, 
3924     // we know aopOp will succeed, and we can just do it & bail.
3925     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3926         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3927     {
3928 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3929         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3930         return TRUE;
3931     }
3932     
3933     // Note which dptrs are currently in use.
3934     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3935     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3936     
3937     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3938     // generate it.
3939     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3940     {
3941         return FALSE;
3942     }
3943     
3944     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3945     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3946     {
3947         return FALSE;
3948     }
3949     
3950     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3951     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3952     {
3953         return FALSE;
3954     }
3955
3956     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3957
3958     // Some sanity checking...
3959     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3960     {
3961         fprintf(stderr,
3962                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3963                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3964         emitcode(";", ">>> unexpected DPTR here.");
3965     }
3966     
3967     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3968     {
3969         fprintf(stderr,
3970                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3971                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3972         emitcode(";", ">>> unexpected DPTR2 here.");
3973     }    
3974     
3975     return TRUE;
3976 }
3977
3978 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3979 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3980 // will be set TRUE. The caller must then handle the case specially, noting
3981 // that the IC_RESULT operand is not aopOp'd.
3982 // 
3983 #define AOP_OP_3_NOFATAL(ic, rc) \
3984             do { rc = !aopOp3(ic); } while (0)
3985
3986 // aopOp the left & right operands of an ic.
3987 #define AOP_OP_2(ic) \
3988     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3989     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3990
3991 // convienience macro.
3992 #define AOP_SET_LOCALS(ic) \
3993     left = IC_LEFT(ic); \
3994     right = IC_RIGHT(ic); \
3995     result = IC_RESULT(ic);
3996
3997
3998 // Given an integer value of pushedSize bytes on the stack,
3999 // adjust it to be resultSize bytes, either by discarding
4000 // the most significant bytes or by zero-padding.
4001 //
4002 // On exit from this macro, pushedSize will have been adjusted to
4003 // equal resultSize, and ACC may be trashed.
4004 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
4005       /* If the pushed data is bigger than the result,          \
4006        * simply discard unused bytes. Icky, but works.          \
4007        */                                                       \
4008       while (pushedSize > resultSize)                           \
4009       {                                                         \
4010           D (emitcode (";", "discarding unused result byte."););\
4011           emitcode ("pop", "acc");                              \
4012           pushedSize--;                                         \
4013       }                                                         \
4014       if (pushedSize < resultSize)                              \
4015       {                                                         \
4016           emitcode ("clr", "a");                                \
4017           /* Conversly, we haven't pushed enough here.          \
4018            * just zero-pad, and all is well.                    \
4019            */                                                   \
4020           while (pushedSize < resultSize)                       \
4021           {                                                     \
4022               emitcode("push", "acc");                          \
4023               pushedSize++;                                     \
4024           }                                                     \
4025       }                                                         \
4026       assert(pushedSize == resultSize);
4027
4028 /*-----------------------------------------------------------------*/
4029 /* genPlus - generates code for addition                           */
4030 /*-----------------------------------------------------------------*/
4031 static void
4032 genPlus (iCode * ic)
4033 {
4034   int size, offset = 0;
4035   bool pushResult;
4036   int rSize;
4037
4038   D (emitcode (";", "genPlus "););
4039
4040   /* special cases :- */
4041   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4042       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4043       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4044       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4045       if (size <= 9) {
4046           while (size--) emitcode ("inc","dptr");
4047       } else {
4048           emitcode ("mov","a,dpl");
4049           emitcode ("add","a,#!constbyte",size & 0xff);
4050           emitcode ("mov","dpl,a");
4051           emitcode ("mov","a,dph");
4052           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4053           emitcode ("mov","dph,a");
4054           emitcode ("mov","a,dpx");
4055           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4056           emitcode ("mov","dpx,a");
4057       }
4058       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4059       return ;
4060   }
4061   if ( IS_SYMOP(IC_LEFT(ic)) && 
4062        OP_SYMBOL(IC_LEFT(ic))->remat &&
4063        isOperandInFarSpace(IC_RIGHT(ic))) {
4064       operand *op = IC_RIGHT(ic);
4065       IC_RIGHT(ic) = IC_LEFT(ic);
4066       IC_LEFT(ic) = op;
4067   }
4068                 
4069   AOP_OP_3_NOFATAL (ic, pushResult);
4070     
4071   if (pushResult)
4072     {
4073       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4074     }
4075
4076   if (!pushResult)
4077     {
4078       /* if literal, literal on the right or
4079          if left requires ACC or right is already
4080          in ACC */
4081       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4082        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4083           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4084         {
4085           operand *t = IC_RIGHT (ic);
4086           IC_RIGHT (ic) = IC_LEFT (ic);
4087           IC_LEFT (ic) = t;
4088           emitcode (";", "Swapped plus args.");
4089         }
4090
4091       /* if both left & right are in bit
4092          space */
4093       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4094           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4095         {
4096           genPlusBits (ic);
4097           goto release;
4098         }
4099
4100       /* if left in bit space & right literal */
4101       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4102           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4103         {
4104           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4105           /* if result in bit space */
4106           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4107             {
4108               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4109                 emitcode ("cpl", "c");
4110               outBitC (IC_RESULT (ic));
4111             }
4112           else
4113             {
4114               size = getDataSize (IC_RESULT (ic));
4115               _startLazyDPSEvaluation ();
4116               while (size--)
4117                 {
4118                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4119                   emitcode ("addc", "a,#0");
4120                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4121                 }
4122               _endLazyDPSEvaluation ();
4123             }
4124           goto release;
4125         }
4126
4127       /* if I can do an increment instead
4128          of add then GOOD for ME */
4129       if (genPlusIncr (ic) == TRUE)
4130         {
4131           emitcode (";", "did genPlusIncr");
4132           goto release;
4133         }
4134
4135     }
4136   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4137
4138   _startLazyDPSEvaluation ();
4139   while (size--)
4140     {
4141       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4142         {
4143           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4144           if (offset == 0)
4145             emitcode ("add", "a,%s",
4146                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4147           else
4148             emitcode ("addc", "a,%s",
4149                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4150         }
4151       else
4152         {
4153           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4154           {
4155               /* right is going to use ACC or we would have taken the
4156                * above branch.
4157                */
4158               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4159        TR_AP("#3");
4160               D(emitcode(";", "+ AOP_ACC special case."););
4161               emitcode("xch", "a, %s", DP2_RESULT_REG);
4162           }
4163           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4164           if (offset == 0)
4165           {
4166             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4167             {
4168          TR_AP("#4");
4169                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4170             }
4171             else
4172             {
4173                 emitcode ("add", "a,%s",
4174                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4175                                   DP2_RESULT_REG));
4176             }
4177           }
4178           else
4179           {
4180             emitcode ("addc", "a,%s",
4181                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4182                           DP2_RESULT_REG));
4183           }
4184         }
4185       if (!pushResult)
4186         {
4187           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4188         }
4189       else
4190         {
4191           emitcode ("push", "acc");
4192         }
4193       offset++;
4194     }
4195   _endLazyDPSEvaluation ();
4196
4197   if (pushResult)
4198     {
4199       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4200
4201       size = getDataSize (IC_LEFT (ic));
4202       rSize = getDataSize (IC_RESULT (ic));
4203
4204       ADJUST_PUSHED_RESULT(size, rSize);
4205
4206       _startLazyDPSEvaluation ();
4207       while (size--)
4208         {
4209           emitcode ("pop", "acc");
4210           aopPut (AOP (IC_RESULT (ic)), "a", size);
4211         }
4212       _endLazyDPSEvaluation ();
4213     }
4214
4215   adjustArithmeticResult (ic);
4216
4217 release:
4218   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4219   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4220   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4221 }
4222
4223 /*-----------------------------------------------------------------*/
4224 /* genMinusDec :- does subtraction with deccrement if possible     */
4225 /*-----------------------------------------------------------------*/
4226 static bool
4227 genMinusDec (iCode * ic)
4228 {
4229   unsigned int icount;
4230   unsigned int size = getDataSize (IC_RESULT (ic));
4231
4232   /* will try to generate an increment */
4233   /* if the right side is not a literal
4234      we cannot */
4235   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4236     return FALSE;
4237
4238   /* if the literal value of the right hand side
4239      is greater than 4 then it is not worth it */
4240   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4241     return FALSE;
4242
4243   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4244       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4245       while (icount--) {
4246           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4247       }
4248       return TRUE;
4249   }
4250   /* if decrement 16 bits in register */
4251   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4252       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4253       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4254       (size > 1) &&
4255       (icount == 1))
4256     {
4257       symbol *tlbl;
4258       int    emitTlbl;
4259       int    labelRange;
4260       char   *l;
4261
4262       /* If the next instruction is a goto and the goto target
4263          * is <= 5 instructions previous to this, we can generate
4264          * jumps straight to that target.
4265        */
4266       if (ic->next && ic->next->op == GOTO
4267           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4268           && labelRange <= 5)
4269         {
4270           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4271           tlbl = IC_LABEL (ic->next);
4272           emitTlbl = 0;
4273         }
4274       else
4275         {
4276           tlbl = newiTempLabel (NULL);
4277           emitTlbl = 1;
4278         }
4279
4280       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4281       emitcode ("dec", "%s", l);
4282  
4283       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4284           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4285           IS_AOP_PREG (IC_RESULT (ic)))
4286       {     
4287           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4288       }
4289       else
4290       {
4291           emitcode ("mov", "a,#!constbyte",0xff);
4292           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4293       }
4294       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4295       emitcode ("dec", "%s", l);
4296       if (size > 2)
4297         {
4298             if (!strcmp(l, "acc"))
4299             {
4300                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4301             }
4302             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4303                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4304                      IS_AOP_PREG (IC_RESULT (ic)))
4305             {       
4306                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4307             }
4308             else
4309             {
4310                 emitcode ("mov", "a,#!constbyte",0xff);
4311                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4312             }
4313             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4314             emitcode ("dec", "%s", l);
4315         }
4316       if (size > 3)
4317         {
4318             if (!strcmp(l, "acc"))
4319             {
4320                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4321             }
4322             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4323                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4324                      IS_AOP_PREG (IC_RESULT (ic)))
4325             {       
4326                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4327             }
4328             else
4329             {
4330                 emitcode ("mov", "a,#!constbyte",0xff);
4331                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4332             }       
4333             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4334             emitcode ("dec", "%s", l);
4335         }
4336       if (emitTlbl)
4337         {
4338           emitcode ("", "!tlabeldef", tlbl->key + 100);
4339         }
4340       return TRUE;
4341     }
4342
4343   /* if the sizes are greater than 1 then we cannot */
4344   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4345       AOP_SIZE (IC_LEFT (ic)) > 1)
4346     return FALSE;
4347
4348   /* we can if the aops of the left & result match or
4349      if they are in registers and the registers are the
4350      same */
4351   if (
4352        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4353        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4354        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4355     {
4356
4357       _startLazyDPSEvaluation ();
4358       while (icount--)
4359         {
4360           emitcode ("dec", "%s",
4361                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4362         }
4363       _endLazyDPSEvaluation ();
4364
4365       return TRUE;
4366     }
4367
4368   return FALSE;
4369 }
4370
4371 /*-----------------------------------------------------------------*/
4372 /* addSign - complete with sign                                    */
4373 /*-----------------------------------------------------------------*/
4374 static void
4375 addSign (operand * result, int offset, int sign)
4376 {
4377   int size = (getDataSize (result) - offset);
4378   if (size > 0)
4379     {
4380       _startLazyDPSEvaluation();
4381       if (sign)
4382         {
4383           emitcode ("rlc", "a");
4384           emitcode ("subb", "a,acc");
4385           while (size--)
4386           {
4387             aopPut (AOP (result), "a", offset++);
4388           }
4389         }
4390       else
4391       {
4392         while (size--)
4393         {
4394           aopPut (AOP (result), zero, offset++);
4395         }
4396       }
4397       _endLazyDPSEvaluation();
4398     }
4399 }
4400
4401 /*-----------------------------------------------------------------*/
4402 /* genMinusBits - generates code for subtraction  of two bits      */
4403 /*-----------------------------------------------------------------*/
4404 static void
4405 genMinusBits (iCode * ic)
4406 {
4407   symbol *lbl = newiTempLabel (NULL);
4408
4409   D (emitcode (";", "genMinusBits "););
4410
4411   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4412     {
4413       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4414       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4415       emitcode ("cpl", "c");
4416       emitcode ("", "!tlabeldef", (lbl->key + 100));
4417       outBitC (IC_RESULT (ic));
4418     }
4419   else
4420     {
4421       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4422       emitcode ("subb", "a,acc");
4423       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4424       emitcode ("inc", "a");
4425       emitcode ("", "!tlabeldef", (lbl->key + 100));
4426       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4427       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4428     }
4429 }
4430
4431 /*-----------------------------------------------------------------*/
4432 /* genMinus - generates code for subtraction                       */
4433 /*-----------------------------------------------------------------*/
4434 static void
4435 genMinus (iCode * ic)
4436 {
4437     int size, offset = 0;
4438     int rSize;
4439     long lit = 0L;
4440     bool pushResult;
4441
4442     D (emitcode (";", "genMinus "););
4443
4444     AOP_OP_3_NOFATAL(ic, pushResult);   
4445
4446     if (!pushResult)
4447     {
4448       /* special cases :- */
4449       /* if both left & right are in bit space */
4450       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4451           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4452         {
4453           genMinusBits (ic);
4454           goto release;
4455         }
4456
4457       /* if I can do an decrement instead
4458          of subtract then GOOD for ME */
4459       if (genMinusDec (ic) == TRUE)
4460         goto release;
4461
4462     }
4463
4464   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4465
4466   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4467     {
4468       CLRC;
4469     }
4470   else
4471     {
4472       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4473       lit = -lit;
4474     }
4475
4476
4477   /* if literal, add a,#-lit, else normal subb */
4478   _startLazyDPSEvaluation ();
4479   while (size--) {
4480       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4481           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4482               emitcode ("mov","b,%s",
4483                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4484               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4485               emitcode ("subb","a,b");
4486           } else {
4487               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4488               emitcode ("subb", "a,%s",
4489                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4490                                 DP2_RESULT_REG));
4491           }
4492       } else {
4493           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4494           /* first add without previous c */
4495           if (!offset) {
4496               if (!size && lit==-1) {
4497                   emitcode ("dec", "a");
4498               } else {
4499                   emitcode ("add", "a,#!constbyte",
4500                             (unsigned int) (lit & 0x0FFL));
4501               }
4502           } else {
4503               emitcode ("addc", "a,#!constbyte",
4504                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4505           }
4506       }
4507       
4508       if (pushResult) {
4509           emitcode ("push", "acc");
4510       } else {
4511           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4512       }
4513       offset++;
4514   }
4515   _endLazyDPSEvaluation ();
4516   
4517   if (pushResult)
4518     {
4519       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4520
4521       size = getDataSize (IC_LEFT (ic));
4522       rSize = getDataSize (IC_RESULT (ic));
4523
4524       ADJUST_PUSHED_RESULT(size, rSize);
4525
4526       _startLazyDPSEvaluation ();
4527       while (size--)
4528         {
4529           emitcode ("pop", "acc");
4530           aopPut (AOP (IC_RESULT (ic)), "a", size);
4531         }
4532       _endLazyDPSEvaluation ();
4533     }
4534
4535   adjustArithmeticResult (ic);
4536
4537 release:
4538   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4539   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4540   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4541 }
4542
4543
4544 /*-----------------------------------------------------------------*/
4545 /* genMultbits :- multiplication of bits                           */
4546 /*-----------------------------------------------------------------*/
4547 static void
4548 genMultbits (operand * left,
4549              operand * right,
4550              operand * result,
4551              iCode   * ic)
4552 {
4553   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4554   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4555   aopOp(result, ic, TRUE, FALSE);
4556   outBitC (result);
4557 }
4558
4559
4560 /*-----------------------------------------------------------------*/
4561 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4562 /*-----------------------------------------------------------------*/
4563 static void
4564 genMultOneByte (operand * left,
4565                 operand * right,
4566                 operand * result,
4567                 iCode   * ic)
4568 {
4569   sym_link *opetype = operandType (result);
4570   symbol *lbl;
4571
4572
4573   /* (if two literals: the value is computed before) */
4574   /* if one literal, literal on the right */
4575   if (AOP_TYPE (left) == AOP_LIT)
4576     {
4577       operand *t = right;
4578       right = left;
4579       left = t;
4580       emitcode (";", "swapped left and right");
4581     }
4582
4583   if (SPEC_USIGN(opetype)
4584       // ignore the sign of left and right, what else can we do?
4585       || (SPEC_USIGN(operandType(left)) && 
4586           SPEC_USIGN(operandType(right)))) {
4587     // just an unsigned 8*8=8/16 multiply
4588     //emitcode (";","unsigned");
4589     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4590     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4591     emitcode ("mul", "ab");
4592    
4593     _G.accInUse++; _G.bInUse++;
4594     aopOp(result, ic, TRUE, FALSE);
4595       
4596       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4597       {
4598           // this should never happen
4599           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4600                    AOP_SIZE(result), __FILE__, lineno);
4601           exit (1);
4602       }      
4603       
4604     aopPut (AOP (result), "a", 0);
4605     _G.accInUse--; _G.bInUse--;
4606     if (AOP_SIZE(result)==2) 
4607     {
4608       aopPut (AOP (result), "b", 1);
4609     }
4610     return;
4611   }
4612
4613   // we have to do a signed multiply
4614
4615   emitcode (";", "signed");
4616   emitcode ("clr", "F0"); // reset sign flag
4617   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4618
4619   lbl=newiTempLabel(NULL);
4620   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4621   // left side is negative, 8-bit two's complement, this fails for -128
4622   emitcode ("setb", "F0"); // set sign flag
4623   emitcode ("cpl", "a");
4624   emitcode ("inc", "a");
4625
4626   emitcode ("", "!tlabeldef", lbl->key+100);
4627
4628   /* if literal */
4629   if (AOP_TYPE(right)==AOP_LIT) {
4630     signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4631     /* AND literal negative */
4632     if ((int) val < 0) {
4633       emitcode ("cpl", "F0"); // complement sign flag
4634       emitcode ("mov", "b,#!constbyte", -val);
4635     } else {
4636       emitcode ("mov", "b,#!constbyte", val);
4637     }
4638   } else {
4639     lbl=newiTempLabel(NULL);
4640     emitcode ("mov", "b,a");
4641     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4642     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4643     // right side is negative, 8-bit two's complement
4644     emitcode ("cpl", "F0"); // complement sign flag
4645     emitcode ("cpl", "a");
4646     emitcode ("inc", "a");
4647     emitcode ("", "!tlabeldef", lbl->key+100);
4648   }
4649   emitcode ("mul", "ab");
4650     
4651   _G.accInUse++;_G.bInUse++;
4652   aopOp(result, ic, TRUE, FALSE);
4653     
4654   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4655   {
4656     // this should never happen
4657       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4658                AOP_SIZE(result), __FILE__, lineno);
4659       exit (1);
4660   }    
4661     
4662   lbl=newiTempLabel(NULL);
4663   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4664   // only ONE op was negative, we have to do a 8/16-bit two's complement
4665   emitcode ("cpl", "a"); // lsb
4666   if (AOP_SIZE(result)==1) {
4667     emitcode ("inc", "a");
4668   } else {
4669     emitcode ("add", "a,#1");
4670     emitcode ("xch", "a,b");
4671     emitcode ("cpl", "a"); // msb
4672     emitcode ("addc", "a,#0");
4673     emitcode ("xch", "a,b");
4674   }
4675
4676   emitcode ("", "!tlabeldef", lbl->key+100);
4677   aopPut (AOP (result), "a", 0);
4678   _G.accInUse--;_G.bInUse--;
4679   if (AOP_SIZE(result)==2) {
4680     aopPut (AOP (result), "b", 1);
4681   }
4682 }
4683
4684 /*-----------------------------------------------------------------*/
4685 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4686 /*-----------------------------------------------------------------*/
4687 static void genMultTwoByte (operand *left, operand *right, 
4688                             operand *result, iCode *ic)
4689 {
4690         sym_link *retype = getSpec(operandType(right));
4691         sym_link *letype = getSpec(operandType(left));
4692         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4693         symbol *lbl;
4694
4695         if (AOP_TYPE (left) == AOP_LIT) {
4696                 operand *t = right;
4697                 right = left;
4698                 left = t;
4699         }
4700         /* save EA bit in F1 */
4701         lbl = newiTempLabel(NULL);
4702         emitcode ("setb","F1");
4703         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4704         emitcode ("clr","F1");
4705         emitcode("","!tlabeldef",lbl->key+100);
4706
4707         /* load up MB with right */
4708         if (!umult) {
4709                 emitcode("clr","F0");
4710                 if (AOP_TYPE(right) == AOP_LIT) {
4711                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4712                         if (val < 0) {
4713                                 emitcode("setb","F0");
4714                                 val = -val;
4715                         }
4716                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4717                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4718                 } else {
4719                         lbl = newiTempLabel(NULL);
4720                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4721                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4722                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4723                         emitcode ("xch", "a,b");
4724                         emitcode ("cpl","a");
4725                         emitcode ("add", "a,#1");
4726                         emitcode ("xch", "a,b");
4727                         emitcode ("cpl", "a"); // msb
4728                         emitcode ("addc", "a,#0");
4729                         emitcode ("setb","F0");
4730                         emitcode ("","!tlabeldef",lbl->key+100);
4731                         emitcode ("mov","mb,b");
4732                         emitcode ("mov","mb,a");
4733                 }
4734         } else {
4735                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4736                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4737         }
4738         /* load up MA with left */
4739         if (!umult) {
4740                 lbl = newiTempLabel(NULL);
4741                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4742                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4743                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4744                 emitcode ("xch", "a,b");
4745                 emitcode ("cpl","a");
4746                 emitcode ("add", "a,#1");
4747                 emitcode ("xch", "a,b");
4748                 emitcode ("cpl", "a"); // msb
4749                 emitcode ("addc","a,#0");
4750                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4751                 emitcode ("setb","F0");
4752                 emitcode ("","!tlabeldef",lbl->key+100);
4753                 emitcode ("mov","ma,b");
4754                 emitcode ("mov","ma,a");
4755         } else {
4756                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4757                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4758         }
4759         /* wait for multiplication to finish */
4760         lbl = newiTempLabel(NULL);
4761         emitcode("","!tlabeldef", lbl->key+100);
4762         emitcode("mov","a,mcnt1");
4763         emitcode("anl","a,#!constbyte",0x80);
4764         emitcode("jnz","!tlabel",lbl->key+100);
4765         
4766         freeAsmop (left, NULL, ic, TRUE);
4767         freeAsmop (right, NULL, ic,TRUE);
4768         aopOp(result, ic, TRUE, FALSE);
4769
4770         /* if unsigned then simple */   
4771         if (umult) {
4772                 emitcode ("mov","a,ma");
4773                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4774                 emitcode ("mov","a,ma");
4775                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4776                 aopPut(AOP(result),"ma",1);
4777                 aopPut(AOP(result),"ma",0);
4778         } else {
4779                 emitcode("push","ma");
4780                 emitcode("push","ma");
4781                 emitcode("push","ma");
4782                 MOVA("ma");
4783                 /* negate result if needed */
4784                 lbl = newiTempLabel(NULL);      
4785                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4786                 emitcode("cpl","a");
4787                 emitcode("add","a,#1");
4788                 emitcode("","!tlabeldef", lbl->key+100);
4789                 if (AOP_TYPE(result) == AOP_ACC)
4790                 {
4791                     D(emitcode(";", "ACC special case."););
4792                     /* We know result is the only live aop, and 
4793                      * it's obviously not a DPTR2, so AP is available.
4794                      */
4795                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4796                 }
4797                 else
4798                 {
4799                     aopPut(AOP(result),"a",0);
4800                 }
4801             
4802                 emitcode("pop","acc");
4803                 lbl = newiTempLabel(NULL);      
4804                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4805                 emitcode("cpl","a");
4806                 emitcode("addc","a,#0");
4807                 emitcode("","!tlabeldef", lbl->key+100);
4808                 aopPut(AOP(result),"a",1);
4809                 emitcode("pop","acc");
4810                 if (AOP_SIZE(result) >= 3) {
4811                         lbl = newiTempLabel(NULL);      
4812                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4813                         emitcode("cpl","a");
4814                         emitcode("addc","a,#0");                        
4815                         emitcode("","!tlabeldef", lbl->key+100);
4816                         aopPut(AOP(result),"a",2);
4817                 }
4818                 emitcode("pop","acc");
4819                 if (AOP_SIZE(result) >= 4) {
4820                         lbl = newiTempLabel(NULL);      
4821                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4822                         emitcode("cpl","a");
4823                         emitcode("addc","a,#0");                        
4824                         emitcode("","!tlabeldef", lbl->key+100);
4825                         aopPut(AOP(result),"a",3);
4826                 }
4827                 if (AOP_TYPE(result) == AOP_ACC)
4828                 {
4829                     /* We stashed the result away above. */
4830                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4831                 }           
4832                 
4833         }
4834         freeAsmop (result, NULL, ic, TRUE);
4835
4836         /* restore EA bit in F1 */
4837         lbl = newiTempLabel(NULL);
4838         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4839         emitcode ("setb","EA");
4840         emitcode("","!tlabeldef",lbl->key+100);
4841         return ;
4842 }
4843
4844 /*-----------------------------------------------------------------*/
4845 /* genMult - generates code for multiplication                     */
4846 /*-----------------------------------------------------------------*/
4847 static void
4848 genMult (iCode * ic)
4849 {
4850   operand *left = IC_LEFT (ic);
4851   operand *right = IC_RIGHT (ic);
4852   operand *result = IC_RESULT (ic);
4853
4854   D (emitcode (";", "genMult "););
4855
4856   /* assign the amsops */
4857   AOP_OP_2 (ic);
4858
4859   /* special cases first */
4860   /* both are bits */
4861   if (AOP_TYPE (left) == AOP_CRY &&
4862       AOP_TYPE (right) == AOP_CRY)
4863     {
4864       genMultbits (left, right, result, ic);
4865       goto release;
4866     }
4867
4868   /* if both are of size == 1 */
4869   if (AOP_SIZE (left) == 1 &&
4870       AOP_SIZE (right) == 1)
4871     {
4872       genMultOneByte (left, right, result, ic);
4873       goto release;
4874     }
4875
4876   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4877           /* use the ds390 ARITHMETIC accel UNIT */
4878           genMultTwoByte (left, right, result, ic);
4879           return ;
4880   }
4881   /* should have been converted to function call */
4882   assert (0);
4883
4884 release:
4885   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4886   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4887   freeAsmop (result, NULL, ic, TRUE);
4888 }
4889
4890 /*-----------------------------------------------------------------*/
4891 /* genDivbits :- division of bits                                  */
4892 /*-----------------------------------------------------------------*/
4893 static void
4894 genDivbits (operand * left,
4895             operand * right,
4896             operand * result,
4897             iCode   * ic)
4898 {
4899
4900   char *l;
4901
4902   /* the result must be bit */
4903   LOAD_AB_FOR_DIV (left, right, l);
4904   emitcode ("div", "ab");
4905   emitcode ("rrc", "a");
4906   aopOp(result, ic, TRUE, FALSE);
4907     
4908   aopPut (AOP (result), "c", 0);
4909 }
4910
4911 /*-----------------------------------------------------------------*/
4912 /* genDivOneByte : 8 bit division                                  */
4913 /*-----------------------------------------------------------------*/
4914 static void
4915 genDivOneByte (operand * left,
4916                operand * right,
4917                operand * result,
4918                iCode   * ic)
4919 {
4920   sym_link *opetype = operandType (result);
4921   char *l;
4922   symbol *lbl;
4923   int size, offset;
4924
4925   offset = 1;
4926   /* signed or unsigned */
4927   if (SPEC_USIGN (opetype))
4928     {
4929         /* unsigned is easy */
4930         LOAD_AB_FOR_DIV (left, right, l);
4931         emitcode ("div", "ab");
4932
4933         _G.accInUse++;
4934         aopOp(result, ic, TRUE, FALSE);
4935         aopPut (AOP (result), "a", 0);
4936         _G.accInUse--;
4937
4938         size = AOP_SIZE (result) - 1;
4939         
4940         while (size--)
4941         {
4942             aopPut (AOP (result), zero, offset++);
4943         }
4944       return;
4945     }
4946
4947   /* signed is a little bit more difficult */
4948
4949   /* save the signs of the operands */
4950   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4951   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4952   emitcode ("push", "acc");     /* save it on the stack */
4953
4954   /* now sign adjust for both left & right */
4955   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4956   lbl = newiTempLabel (NULL);
4957   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4958   emitcode ("cpl", "a");
4959   emitcode ("inc", "a");
4960   emitcode ("", "!tlabeldef", (lbl->key + 100));
4961   emitcode ("mov", "b,a");
4962
4963   /* sign adjust left side */
4964   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4965
4966   lbl = newiTempLabel (NULL);
4967   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4968   emitcode ("cpl", "a");
4969   emitcode ("inc", "a");
4970   emitcode ("", "!tlabeldef", (lbl->key + 100));
4971
4972   /* now the division */
4973   emitcode ("nop", "; workaround for DS80C390 div bug.");
4974   emitcode ("div", "ab");
4975   /* we are interested in the lower order
4976      only */
4977   emitcode ("mov", "b,a");
4978   lbl = newiTempLabel (NULL);
4979   emitcode ("pop", "acc");
4980   /* if there was an over flow we don't
4981      adjust the sign of the result */
4982   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4983   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4984   CLRC;
4985   emitcode ("clr", "a");
4986   emitcode ("subb", "a,b");
4987   emitcode ("mov", "b,a");
4988   emitcode ("", "!tlabeldef", (lbl->key + 100));
4989
4990   /* now we are done */
4991   _G.accInUse++;     _G.bInUse++;
4992     aopOp(result, ic, TRUE, FALSE);
4993     
4994     aopPut (AOP (result), "b", 0);
4995     
4996     size = AOP_SIZE (result) - 1;
4997     
4998     if (size > 0)
4999     {
5000       emitcode ("mov", "c,b.7");
5001       emitcode ("subb", "a,acc");
5002     }
5003     while (size--)
5004     {
5005         aopPut (AOP (result), "a", offset++);
5006     }
5007     _G.accInUse--;     _G.bInUse--;
5008
5009 }
5010
5011 /*-----------------------------------------------------------------*/
5012 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
5013 /*-----------------------------------------------------------------*/
5014 static void genDivTwoByte (operand *left, operand *right, 
5015                             operand *result, iCode *ic)
5016 {
5017         sym_link *retype = getSpec(operandType(right));
5018         sym_link *letype = getSpec(operandType(left));
5019         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5020         symbol *lbl;
5021
5022         /* save EA bit in F1 */
5023         lbl = newiTempLabel(NULL);
5024         emitcode ("setb","F1");
5025         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5026         emitcode ("clr","F1");
5027         emitcode("","!tlabeldef",lbl->key+100);
5028
5029         /* load up MA with left */
5030         if (!umult) {
5031                 emitcode("clr","F0");
5032                 lbl = newiTempLabel(NULL);
5033                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5034                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5035                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5036                 emitcode ("xch", "a,b");
5037                 emitcode ("cpl","a");
5038                 emitcode ("add", "a,#1");
5039                 emitcode ("xch", "a,b");
5040                 emitcode ("cpl", "a"); // msb
5041                 emitcode ("addc","a,#0");
5042                 emitcode ("setb","F0");
5043                 emitcode ("","!tlabeldef",lbl->key+100);
5044                 emitcode ("mov","ma,b");
5045                 emitcode ("mov","ma,a");
5046         } else {
5047                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5048                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5049         }
5050
5051         /* load up MB with right */
5052         if (!umult) {
5053                 if (AOP_TYPE(right) == AOP_LIT) {
5054                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5055                         if (val < 0) {
5056                                 lbl = newiTempLabel(NULL);
5057                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5058                                 emitcode("setb","F0");
5059                                 emitcode ("","!tlabeldef",lbl->key+100);
5060                                 val = -val;
5061                         } 
5062                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5063                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5064                 } else {
5065                         lbl = newiTempLabel(NULL);
5066                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5067                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5068                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5069                         emitcode ("xch", "a,b");
5070                         emitcode ("cpl","a");
5071                         emitcode ("add", "a,#1");
5072                         emitcode ("xch", "a,b");
5073                         emitcode ("cpl", "a"); // msb
5074                         emitcode ("addc", "a,#0");
5075                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5076                         emitcode ("setb","F0");
5077                         emitcode ("","!tlabeldef",lbl->key+100);
5078                         emitcode ("mov","mb,b");
5079                         emitcode ("mov","mb,a");
5080                 }
5081         } else {
5082                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5083                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5084         }
5085
5086         /* wait for multiplication to finish */
5087         lbl = newiTempLabel(NULL);
5088         emitcode("","!tlabeldef", lbl->key+100);
5089         emitcode("mov","a,mcnt1");
5090         emitcode("anl","a,#!constbyte",0x80);
5091         emitcode("jnz","!tlabel",lbl->key+100);
5092         
5093         freeAsmop (left, NULL, ic, TRUE);
5094         freeAsmop (right, NULL, ic,TRUE);
5095         aopOp(result, ic, TRUE, FALSE);
5096
5097         /* if unsigned then simple */   
5098         if (umult) {
5099                 aopPut(AOP(result),"ma",1);
5100                 aopPut(AOP(result),"ma",0);
5101         } else {
5102                 emitcode("push","ma");
5103                 MOVA("ma");
5104                 /* negate result if needed */
5105                 lbl = newiTempLabel(NULL);      
5106                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5107                 emitcode("cpl","a");
5108                 emitcode("add","a,#1");
5109                 emitcode("","!tlabeldef", lbl->key+100);
5110                 aopPut(AOP(result),"a",0);
5111                 emitcode("pop","acc");
5112                 lbl = newiTempLabel(NULL);      
5113                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5114                 emitcode("cpl","a");
5115                 emitcode("addc","a,#0");
5116                 emitcode("","!tlabeldef", lbl->key+100);
5117                 aopPut(AOP(result),"a",1);
5118         }
5119         freeAsmop (result, NULL, ic, TRUE);
5120         /* restore EA bit in F1 */
5121         lbl = newiTempLabel(NULL);
5122         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5123         emitcode ("setb","EA");
5124         emitcode("","!tlabeldef",lbl->key+100);
5125         return ;
5126 }
5127
5128 /*-----------------------------------------------------------------*/
5129 /* genDiv - generates code for division                            */
5130 /*-----------------------------------------------------------------*/
5131 static void
5132 genDiv (iCode * ic)
5133 {
5134   operand *left = IC_LEFT (ic);
5135   operand *right = IC_RIGHT (ic);
5136   operand *result = IC_RESULT (ic);
5137
5138   D (emitcode (";", "genDiv "););
5139
5140   /* assign the amsops */
5141   AOP_OP_2 (ic);
5142
5143   /* special cases first */
5144   /* both are bits */
5145   if (AOP_TYPE (left) == AOP_CRY &&
5146       AOP_TYPE (right) == AOP_CRY)
5147     {
5148       genDivbits (left, right, result, ic);
5149       goto release;
5150     }
5151
5152   /* if both are of size == 1 */
5153   if (AOP_SIZE (left) == 1 &&
5154       AOP_SIZE (right) == 1)
5155     {
5156       genDivOneByte (left, right, result, ic);
5157       goto release;
5158     }
5159
5160   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5161           /* use the ds390 ARITHMETIC accel UNIT */
5162           genDivTwoByte (left, right, result, ic);
5163           return ;
5164   }
5165   /* should have been converted to function call */
5166   assert (0);
5167 release:
5168   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5169   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5170   freeAsmop (result, NULL, ic, TRUE);
5171 }
5172
5173 /*-----------------------------------------------------------------*/
5174 /* genModbits :- modulus of bits                                   */
5175 /*-----------------------------------------------------------------*/
5176 static void
5177 genModbits (operand * left,
5178             operand * right,
5179             operand * result,
5180             iCode   * ic)
5181 {
5182
5183   char *l;
5184
5185   /* the result must be bit */
5186   LOAD_AB_FOR_DIV (left, right, l);
5187   emitcode ("div", "ab");
5188   emitcode ("mov", "a,b");
5189   emitcode ("rrc", "a");
5190   aopOp(result, ic, TRUE, FALSE);
5191   aopPut (AOP (result), "c", 0);
5192 }
5193
5194 /*-----------------------------------------------------------------*/
5195 /* genModOneByte : 8 bit modulus                                   */
5196 /*-----------------------------------------------------------------*/
5197 static void
5198 genModOneByte (operand * left,
5199                operand * right,
5200                operand * result,
5201                iCode   * ic)
5202 {
5203   sym_link *opetype = operandType (result);
5204   char *l;
5205   symbol *lbl;
5206
5207   /* signed or unsigned */
5208   if (SPEC_USIGN (opetype))
5209     {
5210       /* unsigned is easy */
5211       LOAD_AB_FOR_DIV (left, right, l);
5212       emitcode ("div", "ab");
5213       aopOp(result, ic, TRUE, FALSE);   
5214       aopPut (AOP (result), "b", 0);
5215       return;
5216     }
5217
5218   /* signed is a little bit more difficult */
5219
5220   /* save the signs of the operands */
5221   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5222
5223   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5224   emitcode ("push", "acc");     /* save it on the stack */
5225
5226   /* now sign adjust for both left & right */
5227   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5228
5229   lbl = newiTempLabel (NULL);
5230   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5231   emitcode ("cpl", "a");
5232   emitcode ("inc", "a");
5233   emitcode ("", "!tlabeldef", (lbl->key + 100));
5234   emitcode ("mov", "b,a");
5235
5236   /* sign adjust left side */
5237   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5238
5239   lbl = newiTempLabel (NULL);
5240   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5241   emitcode ("cpl", "a");
5242   emitcode ("inc", "a");
5243   emitcode ("", "!tlabeldef", (lbl->key + 100));
5244
5245   /* now the multiplication */
5246   emitcode ("nop", "; workaround for DS80C390 div bug.");
5247   emitcode ("div", "ab");
5248   /* we are interested in the lower order
5249      only */
5250   lbl = newiTempLabel (NULL);
5251   emitcode ("pop", "acc");
5252   /* if there was an over flow we don't
5253      adjust the sign of the result */
5254   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5255   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5256   CLRC;
5257   emitcode ("clr", "a");
5258   emitcode ("subb", "a,b");
5259   emitcode ("mov", "b,a");
5260   emitcode ("", "!tlabeldef", (lbl->key + 100));
5261   
5262   _G.bInUse++;
5263   /* now we are done */
5264   aopOp(result, ic, TRUE, FALSE);    
5265   aopPut (AOP (result), "b", 0);
5266   _G.bInUse--;
5267
5268 }
5269
5270 /*-----------------------------------------------------------------*/
5271 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5272 /*-----------------------------------------------------------------*/
5273 static void genModTwoByte (operand *left, operand *right, 
5274                             operand *result, iCode *ic)
5275 {
5276         sym_link *retype = getSpec(operandType(right));
5277         sym_link *letype = getSpec(operandType(left));
5278         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5279         symbol *lbl;
5280
5281         /* load up MA with left */
5282         /* save EA bit in F1 */
5283         lbl = newiTempLabel(NULL);
5284         emitcode ("setb","F1");
5285         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5286         emitcode ("clr","F1");
5287         emitcode("","!tlabeldef",lbl->key+100);
5288
5289         if (!umult) {
5290                 lbl = newiTempLabel(NULL);
5291                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5292                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5293                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5294                 emitcode ("xch", "a,b");
5295                 emitcode ("cpl","a");
5296                 emitcode ("add", "a,#1");
5297                 emitcode ("xch", "a,b");
5298                 emitcode ("cpl", "a"); // msb
5299                 emitcode ("addc","a,#0");
5300                 emitcode ("","!tlabeldef",lbl->key+100);
5301                 emitcode ("mov","ma,b");
5302                 emitcode ("mov","ma,a");
5303         } else {
5304                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5305                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5306         }
5307
5308         /* load up MB with right */
5309         if (!umult) {
5310                 if (AOP_TYPE(right) == AOP_LIT) {
5311                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5312                         if (val < 0) {
5313                                 val = -val;
5314                         } 
5315                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5316                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5317                 } else {
5318                         lbl = newiTempLabel(NULL);
5319                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5320                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5321                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5322                         emitcode ("xch", "a,b");
5323                         emitcode ("cpl","a");
5324                         emitcode ("add", "a,#1");
5325                         emitcode ("xch", "a,b");
5326                         emitcode ("cpl", "a"); // msb
5327                         emitcode ("addc", "a,#0");
5328                         emitcode ("","!tlabeldef",lbl->key+100);
5329                         emitcode ("mov","mb,b");
5330                         emitcode ("mov","mb,a");
5331                 }
5332         } else {
5333                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5334                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5335         }
5336
5337         /* wait for multiplication to finish */
5338         lbl = newiTempLabel(NULL);
5339         emitcode("","!tlabeldef", lbl->key+100);
5340         emitcode("mov","a,mcnt1");
5341         emitcode("anl","a,#!constbyte",0x80);
5342         emitcode("jnz","!tlabel",lbl->key+100);
5343         
5344         freeAsmop (left, NULL, ic, TRUE);
5345         freeAsmop (right, NULL, ic,TRUE);
5346         aopOp(result, ic, TRUE, FALSE);
5347
5348         aopPut(AOP(result),"mb",1);
5349         aopPut(AOP(result),"mb",0);
5350         freeAsmop (result, NULL, ic, TRUE);
5351
5352         /* restore EA bit in F1 */
5353         lbl = newiTempLabel(NULL);
5354         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5355         emitcode ("setb","EA");
5356         emitcode("","!tlabeldef",lbl->key+100);
5357         return ;
5358 }
5359
5360 /*-----------------------------------------------------------------*/
5361 /* genMod - generates code for division                            */
5362 /*-----------------------------------------------------------------*/
5363 static void
5364 genMod (iCode * ic)
5365 {
5366   operand *left = IC_LEFT (ic);
5367   operand *right = IC_RIGHT (ic);
5368   operand *result = IC_RESULT (ic);
5369
5370   D (emitcode (";", "genMod "); );
5371
5372   /* assign the amsops */
5373   AOP_OP_2 (ic);
5374
5375   /* special cases first */
5376   /* both are bits */
5377   if (AOP_TYPE (left) == AOP_CRY &&
5378       AOP_TYPE (right) == AOP_CRY)
5379     {
5380       genModbits (left, right, result, ic);
5381       goto release;
5382     }
5383
5384   /* if both are of size == 1 */
5385   if (AOP_SIZE (left) == 1 &&
5386       AOP_SIZE (right) == 1)
5387     {
5388       genModOneByte (left, right, result, ic);
5389       goto release;
5390     }
5391
5392   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5393           /* use the ds390 ARITHMETIC accel UNIT */
5394           genModTwoByte (left, right, result, ic);
5395           return ;
5396   }
5397
5398   /* should have been converted to function call */
5399   assert (0);
5400
5401 release:
5402   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5403   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5404   freeAsmop (result, NULL, ic, TRUE);
5405 }
5406
5407 /*-----------------------------------------------------------------*/
5408 /* genIfxJump :- will create a jump depending on the ifx           */
5409 /*-----------------------------------------------------------------*/
5410 static void
5411 genIfxJump (iCode * ic, char *jval)
5412 {
5413   symbol *jlbl;
5414   symbol *tlbl = newiTempLabel (NULL);
5415   char *inst;
5416
5417   D (emitcode (";", "genIfxJump"););
5418
5419   /* if true label then we jump if condition
5420      supplied is true */
5421   if (IC_TRUE (ic))
5422     {
5423       jlbl = IC_TRUE (ic);
5424       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5425                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5426     }
5427   else
5428     {
5429       /* false label is present */
5430       jlbl = IC_FALSE (ic);
5431       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5432                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5433     }
5434   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5435     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5436   else
5437     emitcode (inst, "!tlabel", tlbl->key + 100);
5438   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5439   emitcode ("", "!tlabeldef", tlbl->key + 100);
5440
5441   /* mark the icode as generated */
5442   ic->generated = 1;
5443 }
5444
5445 /*-----------------------------------------------------------------*/
5446 /* genCmp :- greater or less than comparison                       */
5447 /*-----------------------------------------------------------------*/
5448 static void
5449 genCmp (operand * left, operand * right,
5450         iCode * ic, iCode * ifx, int sign)
5451 {
5452   int size, offset = 0;
5453   unsigned long lit = 0L;
5454   operand *result;
5455
5456   D (emitcode (";", "genCmp"););
5457
5458   result = IC_RESULT (ic);
5459
5460   /* if left & right are bit variables */
5461   if (AOP_TYPE (left) == AOP_CRY &&
5462       AOP_TYPE (right) == AOP_CRY)
5463     {
5464       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5465       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5466     }
5467   else
5468     {
5469       /* subtract right from left if at the
5470          end the carry flag is set then we know that
5471          left is greater than right */
5472       size = max (AOP_SIZE (left), AOP_SIZE (right));
5473
5474       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5475       if ((size == 1) && !sign 
5476           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5477         {
5478           symbol *lbl = newiTempLabel (NULL);
5479           emitcode ("cjne", "%s,%s,!tlabel",
5480                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5481                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5482                     lbl->key + 100);
5483           emitcode ("", "!tlabeldef", lbl->key + 100);
5484         }
5485       else
5486         {
5487           if (AOP_TYPE (right) == AOP_LIT)
5488             {
5489               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5490               /* optimize if(x < 0) or if(x >= 0) */
5491               if (lit == 0L)
5492                 {
5493                   if (!sign)
5494                     {
5495                       CLRC;
5496                     }
5497                   else
5498                     {
5499                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5500
5501                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5502                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5503
5504                       aopOp (result, ic, FALSE, FALSE);
5505
5506                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5507                         {
5508                           freeAsmop (result, NULL, ic, TRUE);
5509                           genIfxJump (ifx, "acc.7");
5510                           return;
5511                         }
5512                       else
5513                         {
5514                           emitcode ("rlc", "a");
5515                         }
5516                       goto release_freedLR;
5517                     }
5518                   goto release;
5519                 }
5520             }
5521           CLRC;
5522           while (size--)
5523             {
5524               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5525               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5526               // emitcode (";", "genCmp #2");
5527               if (sign && (size == 0))
5528                 {
5529                   // emitcode (";", "genCmp #3");
5530                   emitcode ("xrl", "a,#!constbyte",0x80);
5531                   if (AOP_TYPE (right) == AOP_LIT)
5532                     {
5533                       unsigned long lit = (unsigned long)
5534                       floatFromVal (AOP (right)->aopu.aop_lit);
5535                       // emitcode (";", "genCmp #3.1");
5536                       emitcode ("subb", "a,#!constbyte",
5537                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5538                     }
5539                   else
5540                     {
5541                       // emitcode (";", "genCmp #3.2");
5542                       saveAccWarn = 0;  
5543                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5544                       saveAccWarn = DEFAULT_ACC_WARNING;
5545                       emitcode ("xrl", "b,#!constbyte",0x80);
5546                       emitcode ("subb", "a,b");
5547                     }
5548                 }
5549               else
5550                 {
5551                   const char *s;
5552
5553                   // emitcode (";", "genCmp #4");
5554                   saveAccWarn = 0;
5555                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5556                   saveAccWarn = DEFAULT_ACC_WARNING;
5557
5558                   emitcode ("subb", "a,%s", s);
5559                 }
5560             }
5561         }
5562     }
5563
5564 release:
5565 /* Don't need the left & right operands any more; do need the result. */
5566   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5567   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5568
5569   aopOp (result, ic, FALSE, FALSE);
5570
5571 release_freedLR:
5572
5573   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5574     {
5575       outBitC (result);
5576     }
5577   else
5578     {
5579       /* if the result is used in the next
5580          ifx conditional branch then generate
5581          code a little differently */
5582       if (ifx)
5583         {
5584           genIfxJump (ifx, "c");
5585         }
5586       else
5587         {
5588           outBitC (result);
5589         }
5590       /* leave the result in acc */
5591     }
5592   freeAsmop (result, NULL, ic, TRUE);
5593 }
5594
5595 /*-----------------------------------------------------------------*/
5596 /* genCmpGt :- greater than comparison                             */
5597 /*-----------------------------------------------------------------*/
5598 static void
5599 genCmpGt (iCode * ic, iCode * ifx)
5600 {
5601   operand *left, *right;
5602   sym_link *letype, *retype;
5603   int sign;
5604
5605   D (emitcode (";", "genCmpGt ");
5606     );
5607
5608   left = IC_LEFT (ic);
5609   right = IC_RIGHT (ic);
5610
5611   letype = getSpec (operandType (left));
5612   retype = getSpec (operandType (right));
5613   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5614
5615   /* assign the left & right amsops */
5616   AOP_OP_2 (ic);
5617
5618   genCmp (right, left, ic, ifx, sign);
5619 }
5620
5621 /*-----------------------------------------------------------------*/
5622 /* genCmpLt - less than comparisons                                */
5623 /*-----------------------------------------------------------------*/
5624 static void
5625 genCmpLt (iCode * ic, iCode * ifx)
5626 {
5627   operand *left, *right;
5628   sym_link *letype, *retype;
5629   int sign;
5630
5631   D (emitcode (";", "genCmpLt "););
5632
5633   left = IC_LEFT (ic);
5634   right = IC_RIGHT (ic);
5635
5636   letype = getSpec (operandType (left));
5637   retype = getSpec (operandType (right));
5638   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5639
5640   /* assign the left & right amsops */
5641   AOP_OP_2 (ic);
5642
5643   genCmp (left, right, ic, ifx, sign);
5644 }
5645
5646 /*-----------------------------------------------------------------*/
5647 /* gencjneshort - compare and jump if not equal                    */
5648 /*-----------------------------------------------------------------*/
5649 static void
5650 gencjneshort (operand * left, operand * right, symbol * lbl)
5651 {
5652   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5653   int offset = 0;
5654   unsigned long lit = 0L;
5655
5656   D (emitcode (";", "gencjneshort");
5657     );
5658
5659   /* if the left side is a literal or
5660      if the right is in a pointer register and left
5661      is not */
5662   if ((AOP_TYPE (left) == AOP_LIT) ||
5663       (AOP_TYPE (left) == AOP_IMMD) ||
5664       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5665     {
5666       operand *t = right;
5667       right = left;
5668       left = t;
5669     }
5670
5671   if (AOP_TYPE (right) == AOP_LIT)
5672     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5673
5674   if (opIsGptr (left) || opIsGptr (right))
5675     {
5676       /* We are comparing a generic pointer to something.
5677        * Exclude the generic type byte from the comparison.
5678        */
5679       size--;
5680       D (emitcode (";", "cjneshort: generic ptr special case."););
5681     }
5682
5683
5684   /* if the right side is a literal then anything goes */
5685   if (AOP_TYPE (right) == AOP_LIT &&
5686       AOP_TYPE (left) != AOP_DIR)
5687     {
5688       while (size--)
5689         {
5690           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5691           emitcode ("cjne", "a,%s,!tlabel",
5692                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5693                     lbl->key + 100);
5694           offset++;
5695         }
5696     }
5697
5698   /* if the right side is in a register or in direct space or
5699      if the left is a pointer register & right is not */
5700   else if (AOP_TYPE (right) == AOP_REG ||
5701            AOP_TYPE (right) == AOP_DIR ||
5702            AOP_TYPE (right) == AOP_LIT ||
5703            AOP_TYPE (right) == AOP_IMMD ||
5704            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5705            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5706     {
5707       while (size--)
5708         {
5709           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5710           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5711               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5712             emitcode ("jnz", "!tlabel", lbl->key + 100);
5713           else
5714             emitcode ("cjne", "a,%s,!tlabel",
5715                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5716                       lbl->key + 100);
5717           offset++;
5718         }
5719     }
5720   else
5721     {
5722       /* right is a pointer reg need both a & b */
5723       while (size--)
5724         {
5725           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5726           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5727           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5728           offset++;
5729         }
5730     }
5731 }
5732
5733 /*-----------------------------------------------------------------*/
5734 /* gencjne - compare and jump if not equal                         */
5735 /*-----------------------------------------------------------------*/
5736 static void
5737 gencjne (operand * left, operand * right, symbol * lbl)
5738 {
5739   symbol *tlbl = newiTempLabel (NULL);
5740
5741   D (emitcode (";", "gencjne");
5742     );
5743
5744   gencjneshort (left, right, lbl);
5745
5746   emitcode ("mov", "a,%s", one);
5747   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5748   emitcode ("", "!tlabeldef", lbl->key + 100);
5749   emitcode ("clr", "a");
5750   emitcode ("", "!tlabeldef", tlbl->key + 100);
5751 }
5752
5753 /*-----------------------------------------------------------------*/
5754 /* genCmpEq - generates code for equal to                          */
5755 /*-----------------------------------------------------------------*/
5756 static void
5757 genCmpEq (iCode * ic, iCode * ifx)
5758 {
5759   operand *left, *right, *result;
5760
5761   D (emitcode (";", "genCmpEq ");
5762     );
5763
5764   AOP_OP_2 (ic);
5765   AOP_SET_LOCALS (ic);
5766
5767   /* if literal, literal on the right or
5768      if the right is in a pointer register and left
5769      is not */
5770   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5771       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5772     {
5773       operand *t = IC_RIGHT (ic);
5774       IC_RIGHT (ic) = IC_LEFT (ic);
5775       IC_LEFT (ic) = t;
5776     }
5777
5778   if (ifx &&                    /* !AOP_SIZE(result) */
5779       OP_SYMBOL (result) &&
5780       OP_SYMBOL (result)->regType == REG_CND)
5781     {
5782       symbol *tlbl;
5783       /* if they are both bit variables */
5784       if (AOP_TYPE (left) == AOP_CRY &&
5785           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5786         {
5787           if (AOP_TYPE (right) == AOP_LIT)
5788             {
5789               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5790               if (lit == 0L)
5791                 {
5792                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5793                   emitcode ("cpl", "c");
5794                 }
5795               else if (lit == 1L)
5796                 {
5797                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5798                 }
5799               else
5800                 {
5801                   emitcode ("clr", "c");
5802                 }
5803               /* AOP_TYPE(right) == AOP_CRY */
5804             }
5805           else
5806             {
5807               symbol *lbl = newiTempLabel (NULL);
5808               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5809               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5810               emitcode ("cpl", "c");
5811               emitcode ("", "!tlabeldef", (lbl->key + 100));
5812             }
5813           /* if true label then we jump if condition
5814              supplied is true */
5815           tlbl = newiTempLabel (NULL);
5816           if (IC_TRUE (ifx))
5817             {
5818               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5819               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5820             }
5821           else
5822             {
5823               emitcode ("jc", "!tlabel", tlbl->key + 100);
5824               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5825             }
5826           emitcode ("", "!tlabeldef", tlbl->key + 100);
5827         }
5828       else
5829         {
5830           tlbl = newiTempLabel (NULL);
5831           gencjneshort (left, right, tlbl);
5832           if (IC_TRUE (ifx))
5833             {
5834               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5835               emitcode ("", "!tlabeldef", tlbl->key + 100);
5836             }
5837           else
5838             {
5839               symbol *lbl = newiTempLabel (NULL);
5840               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5841               emitcode ("", "!tlabeldef", tlbl->key + 100);
5842               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5843               emitcode ("", "!tlabeldef", lbl->key + 100);
5844             }
5845         }
5846       /* mark the icode as generated */
5847       ifx->generated = 1;
5848
5849       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5850       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5851       return;
5852     }
5853
5854   /* if they are both bit variables */
5855   if (AOP_TYPE (left) == AOP_CRY &&
5856       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5857     {
5858       if (AOP_TYPE (right) == AOP_LIT)
5859         {
5860           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5861           if (lit == 0L)
5862             {
5863               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5864               emitcode ("cpl", "c");
5865             }
5866           else if (lit == 1L)
5867             {
5868               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5869             }
5870           else
5871             {
5872               emitcode ("clr", "c");
5873             }
5874           /* AOP_TYPE(right) == AOP_CRY */
5875         }
5876       else
5877         {
5878           symbol *lbl = newiTempLabel (NULL);
5879           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5880           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5881           emitcode ("cpl", "c");
5882           emitcode ("", "!tlabeldef", (lbl->key + 100));
5883         }
5884
5885       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5886       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5887
5888       aopOp (result, ic, TRUE, FALSE);
5889
5890       /* c = 1 if egal */
5891       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5892         {
5893           outBitC (result);
5894           goto release;
5895         }
5896       if (ifx)
5897         {
5898           genIfxJump (ifx, "c");
5899           goto release;
5900         }
5901       /* if the result is used in an arithmetic operation
5902          then put the result in place */
5903       outBitC (result);
5904     }
5905   else
5906     {
5907       gencjne (left, right, newiTempLabel (NULL));
5908
5909       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5910       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5911
5912       aopOp (result, ic, TRUE, FALSE);
5913
5914       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5915         {
5916           aopPut (AOP (result), "a", 0);
5917           goto release;
5918         }
5919       if (ifx)
5920         {
5921           genIfxJump (ifx, "a");
5922           goto release;
5923         }
5924       /* if the result is used in an arithmetic operation
5925          then put the result in place */
5926       if (AOP_TYPE (result) != AOP_CRY)
5927         outAcc (result);
5928       /* leave the result in acc */
5929     }
5930
5931 release:
5932   freeAsmop (result, NULL, ic, TRUE);
5933 }
5934
5935 /*-----------------------------------------------------------------*/
5936 /* ifxForOp - returns the icode containing the ifx for operand     */
5937 /*-----------------------------------------------------------------*/
5938 static iCode *
5939 ifxForOp (operand * op, iCode * ic)
5940 {
5941   /* if true symbol then needs to be assigned */
5942   if (IS_TRUE_SYMOP (op))
5943     return NULL;
5944
5945   /* if this has register type condition and
5946      the next instruction is ifx with the same operand
5947      and live to of the operand is upto the ifx only then */
5948   if (ic->next &&
5949       ic->next->op == IFX &&
5950       IC_COND (ic->next)->key == op->key &&
5951       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5952     return ic->next;
5953
5954   return NULL;
5955 }
5956 /*-----------------------------------------------------------------*/
5957 /* hasInc - operand is incremented before any other use            */
5958 /*-----------------------------------------------------------------*/
5959 static iCode *
5960 hasInc (operand *op, iCode *ic, int osize)
5961 {
5962   sym_link *type = operandType(op);
5963   sym_link *retype = getSpec (type);
5964   iCode *lic = ic->next;
5965   int isize ;
5966   
5967   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5968   if (!IS_SYMOP(op)) return NULL;
5969
5970   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5971   if (IS_AGGREGATE(type->next)) return NULL;
5972   if (osize != (isize = getSize(type->next))) return NULL;
5973
5974   while (lic) {
5975       /* if operand of the form op = op + <sizeof *op> */
5976       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5977           isOperandEqual(IC_RESULT(lic),op) && 
5978           isOperandLiteral(IC_RIGHT(lic)) &&
5979           operandLitValue(IC_RIGHT(lic)) == isize) {
5980           return lic;
5981       }
5982       /* if the operand used or deffed */
5983       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5984           return NULL;
5985       }
5986       /* if GOTO or IFX */
5987       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5988       lic = lic->next;
5989   }
5990   return NULL;
5991 }
5992
5993 /*-----------------------------------------------------------------*/
5994 /* genAndOp - for && operation                                     */
5995 /*-----------------------------------------------------------------*/
5996 static void
5997 genAndOp (iCode * ic)
5998 {
5999   operand *left, *right, *result;
6000   symbol *tlbl;
6001
6002   D (emitcode (";", "genAndOp "););
6003
6004   /* note here that && operations that are in an
6005      if statement are taken away by backPatchLabels
6006      only those used in arthmetic operations remain */
6007   AOP_OP_2 (ic);
6008   AOP_SET_LOCALS (ic);
6009
6010   /* if both are bit variables */
6011   if (AOP_TYPE (left) == AOP_CRY &&
6012       AOP_TYPE (right) == AOP_CRY)
6013     {
6014       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6015       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6016       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6017       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6018   
6019       aopOp (result,ic,FALSE, FALSE);
6020       outBitC (result);
6021     }
6022   else
6023     {
6024       tlbl = newiTempLabel (NULL);
6025       toBoolean (left);
6026       emitcode ("jz", "!tlabel", tlbl->key + 100);
6027       toBoolean (right);
6028       emitcode ("", "!tlabeldef", tlbl->key + 100);
6029       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6030       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6031   
6032       aopOp (result,ic,FALSE, FALSE);
6033       outBitAcc (result);
6034     }
6035     freeAsmop (result, NULL, ic, TRUE);
6036 }
6037
6038
6039 /*-----------------------------------------------------------------*/
6040 /* genOrOp - for || operation                                      */
6041 /*-----------------------------------------------------------------*/
6042 static void
6043 genOrOp (iCode * ic)
6044 {
6045   operand *left, *right, *result;
6046   symbol *tlbl;
6047
6048   D (emitcode (";", "genOrOp "););
6049
6050   /* note here that || operations that are in an
6051      if statement are taken away by backPatchLabels
6052      only those used in arthmetic operations remain */
6053   AOP_OP_2 (ic);
6054   AOP_SET_LOCALS (ic);
6055
6056   /* if both are bit variables */
6057   if (AOP_TYPE (left) == AOP_CRY &&
6058       AOP_TYPE (right) == AOP_CRY)
6059     {
6060       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6061       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6062       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6063       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6064   
6065       aopOp (result,ic,FALSE, FALSE);
6066       
6067       outBitC (result);
6068     }
6069   else
6070     {
6071       tlbl = newiTempLabel (NULL);
6072       toBoolean (left);
6073       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6074       toBoolean (right);
6075       emitcode ("", "!tlabeldef", tlbl->key + 100);
6076       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6077       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6078   
6079       aopOp (result,ic,FALSE, FALSE);
6080       
6081       outBitAcc (result);
6082     }
6083
6084   freeAsmop (result, NULL, ic, TRUE);
6085 }
6086
6087 /*-----------------------------------------------------------------*/
6088 /* isLiteralBit - test if lit == 2^n                               */
6089 /*-----------------------------------------------------------------*/
6090 static int
6091 isLiteralBit (unsigned long lit)
6092 {
6093   unsigned long pw[32] =
6094   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6095    0x100L, 0x200L, 0x400L, 0x800L,
6096    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6097    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6098    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6099    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6100    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6101   int idx;
6102
6103   for (idx = 0; idx < 32; idx++)
6104     if (lit == pw[idx])
6105       return idx + 1;
6106   return 0;
6107 }
6108
6109 /*-----------------------------------------------------------------*/
6110 /* continueIfTrue -                                                */
6111 /*-----------------------------------------------------------------*/
6112 static void
6113 continueIfTrue (iCode * ic)
6114 {
6115   if (IC_TRUE (ic))
6116     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6117   ic->generated = 1;
6118 }
6119
6120 /*-----------------------------------------------------------------*/
6121 /* jmpIfTrue -                                                     */
6122 /*-----------------------------------------------------------------*/
6123 static void
6124 jumpIfTrue (iCode * ic)
6125 {
6126   if (!IC_TRUE (ic))
6127     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6128   ic->generated = 1;
6129 }
6130
6131 /*-----------------------------------------------------------------*/
6132 /* jmpTrueOrFalse -                                                */
6133 /*-----------------------------------------------------------------*/
6134 static void
6135 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6136 {
6137   // ugly but optimized by peephole
6138   if (IC_TRUE (ic))
6139     {
6140       symbol *nlbl = newiTempLabel (NULL);
6141       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6142       emitcode ("", "!tlabeldef", tlbl->key + 100);
6143       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6144       emitcode ("", "!tlabeldef", nlbl->key + 100);
6145     }
6146   else
6147     {
6148       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6149       emitcode ("", "!tlabeldef", tlbl->key + 100);
6150     }
6151   ic->generated = 1;
6152 }
6153
6154 // Generate code to perform a bit-wise logic operation
6155 // on two operands in far space (assumed to already have been 
6156 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6157 // in far space. This requires pushing the result on the stack
6158 // then popping it into the result.
6159 static void
6160 genFarFarLogicOp(iCode *ic, char *logicOp)
6161 {
6162       int size, resultSize, compSize;
6163       int offset = 0;
6164       
6165       TR_AP("#5");
6166       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6167       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6168                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6169       
6170       _startLazyDPSEvaluation();
6171       for (size = compSize; (size--); offset++)
6172       {
6173           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6174           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6175           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6176           
6177           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6178           emitcode ("push", "acc");
6179       }
6180       _endLazyDPSEvaluation();
6181      
6182       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6183       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6184       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6185      
6186       resultSize = AOP_SIZE(IC_RESULT(ic));
6187
6188       ADJUST_PUSHED_RESULT(compSize, resultSize);
6189
6190       _startLazyDPSEvaluation();
6191       while (compSize--)
6192       {
6193           emitcode ("pop", "acc");
6194           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6195       }
6196       _endLazyDPSEvaluation();
6197       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6198 }
6199
6200
6201 /*-----------------------------------------------------------------*/
6202 /* genAnd  - code for and                                          */
6203 /*-----------------------------------------------------------------*/
6204 static void
6205 genAnd (iCode * ic, iCode * ifx)
6206 {
6207   operand *left, *right, *result;
6208   int size, offset = 0;
6209   unsigned long lit = 0L;
6210   int bytelit;
6211   char buff[10];
6212   bool pushResult;
6213
6214   D (emitcode (";", "genAnd "););
6215
6216   AOP_OP_3_NOFATAL (ic, pushResult);
6217   AOP_SET_LOCALS (ic);
6218
6219   if (pushResult)
6220   {
6221       genFarFarLogicOp(ic, "anl");
6222       return;
6223   }  
6224
6225 #ifdef DEBUG_TYPE
6226   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6227             AOP_TYPE (result),
6228             AOP_TYPE (left), AOP_TYPE (right));
6229   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6230             AOP_SIZE (result),
6231             AOP_SIZE (left), AOP_SIZE (right));
6232 #endif
6233
6234   /* if left is a literal & right is not then exchange them */
6235   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6236 #ifdef LOGIC_OPS_BROKEN      
6237     ||  AOP_NEEDSACC (left)
6238 #endif
6239     )
6240     {
6241       operand *tmp = right;
6242       right = left;
6243       left = tmp;
6244     }
6245
6246   /* if result = right then exchange them */
6247   if (sameRegs (AOP (result), AOP (right)))
6248     {
6249       operand *tmp = right;
6250       right = left;
6251       left = tmp;
6252     }
6253
6254   /* if right is bit then exchange them */
6255   if (AOP_TYPE (right) == AOP_CRY &&
6256       AOP_TYPE (left) != AOP_CRY)
6257     {
6258       operand *tmp = right;
6259       right = left;
6260       left = tmp;
6261     }
6262   if (AOP_TYPE (right) == AOP_LIT)
6263     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6264
6265   size = AOP_SIZE (result);
6266
6267   // if(bit & yy)
6268   // result = bit & yy;
6269   if (AOP_TYPE (left) == AOP_CRY)
6270     {
6271       // c = bit & literal;
6272       if (AOP_TYPE (right) == AOP_LIT)
6273         {
6274           if (lit & 1)
6275             {
6276               if (size && sameRegs (AOP (result), AOP (left)))
6277                 // no change
6278                 goto release;
6279               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6280             }
6281           else
6282             {
6283               // bit(result) = 0;
6284               if (size && (AOP_TYPE (result) == AOP_CRY))
6285                 {
6286                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6287                   goto release;
6288                 }
6289               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6290                 {
6291                   jumpIfTrue (ifx);
6292                   goto release;
6293                 }
6294               emitcode ("clr", "c");
6295             }
6296         }
6297       else
6298         {
6299           if (AOP_TYPE (right) == AOP_CRY)
6300             {
6301               // c = bit & bit;
6302               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6303               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6304             }
6305           else
6306             {
6307               // c = bit & val;
6308               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6309               // c = lsb
6310               emitcode ("rrc", "a");
6311               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6312             }
6313         }
6314       // bit = c
6315       // val = c
6316       if (size)
6317         outBitC (result);
6318       // if(bit & ...)
6319       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6320         genIfxJump (ifx, "c");
6321       goto release;
6322     }
6323
6324   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6325   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6326   if ((AOP_TYPE (right) == AOP_LIT) &&
6327       (AOP_TYPE (result) == AOP_CRY) &&
6328       (AOP_TYPE (left) != AOP_CRY))
6329     {
6330       int posbit = isLiteralBit (lit);
6331       /* left &  2^n */
6332       if (posbit)
6333         {
6334           posbit--;
6335           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6336           // bit = left & 2^n
6337           if (size)
6338             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6339           // if(left &  2^n)
6340           else
6341             {
6342               if (ifx)
6343                 {
6344                   SNPRINTF (buff, sizeof(buff), 
6345                             "acc.%d", posbit & 0x07);
6346                   genIfxJump (ifx, buff);
6347                 }
6348               else 
6349                   {
6350                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6351                   }
6352               goto release;
6353             }
6354         }
6355       else
6356         {
6357           symbol *tlbl = newiTempLabel (NULL);
6358           int sizel = AOP_SIZE (left);
6359           if (size)
6360             emitcode ("setb", "c");
6361           while (sizel--)
6362             {
6363               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6364                 {
6365                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6366                   // byte ==  2^n ?
6367                   if ((posbit = isLiteralBit (bytelit)) != 0)
6368                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6369                   else
6370                     {
6371                       if (bytelit != 0x0FFL)
6372                         emitcode ("anl", "a,%s",
6373                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6374                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6375                     }
6376                 }
6377               offset++;
6378             }
6379           // bit = left & literal
6380           if (size)
6381             {
6382               emitcode ("clr", "c");
6383               emitcode ("", "!tlabeldef", tlbl->key + 100);
6384             }
6385           // if(left & literal)
6386           else
6387             {
6388               if (ifx)
6389                 jmpTrueOrFalse (ifx, tlbl);
6390               goto release;
6391             }
6392         }
6393       outBitC (result);
6394       goto release;
6395     }
6396
6397   /* if left is same as result */
6398   if (sameRegs (AOP (result), AOP (left)))
6399     {
6400       for (; size--; offset++)
6401         {
6402           if (AOP_TYPE (right) == AOP_LIT)
6403             {
6404               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6405                 continue;
6406               else if (bytelit == 0)
6407                 aopPut (AOP (result), zero, offset);
6408               else if (IS_AOP_PREG (result))
6409                 {
6410                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6411                   emitcode ("anl", "a,%s",
6412                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6413                   aopPut (AOP (result), "a", offset);
6414                 }
6415               else
6416                 emitcode ("anl", "%s,%s",
6417                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6418                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6419             }
6420           else
6421             {
6422               if (AOP_TYPE (left) == AOP_ACC)
6423                 emitcode ("anl", "a,%s",
6424                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6425               else
6426                 {
6427                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6428                   if (IS_AOP_PREG (result))
6429                     {
6430                       emitcode ("anl", "a,%s",
6431                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6432                       aopPut (AOP (result), "a", offset);
6433                     }
6434                   else
6435                     emitcode ("anl", "%s,a",
6436                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6437                 }
6438             }
6439         }
6440     }
6441   else
6442     {
6443       // left & result in different registers
6444       if (AOP_TYPE (result) == AOP_CRY)
6445         {
6446           // result = bit
6447           // if(size), result in bit
6448           // if(!size && ifx), conditional oper: if(left & right)
6449           symbol *tlbl = newiTempLabel (NULL);
6450           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6451           if (size)
6452             emitcode ("setb", "c");
6453           while (sizer--)
6454             {
6455               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6456                 emitcode ("anl", "a,%s",
6457                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6458               } else {
6459                 if (AOP_TYPE(left)==AOP_ACC) {
6460                   emitcode("mov", "b,a");
6461                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6462                   emitcode("anl", "a,b");
6463                 }else {
6464                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6465                   emitcode ("anl", "a,%s",
6466                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6467                 }
6468               }
6469               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6470               offset++;
6471             }
6472           if (size)
6473             {
6474               CLRC;
6475               emitcode ("", "!tlabeldef", tlbl->key + 100);
6476               outBitC (result);
6477             }
6478           else if (ifx)
6479             jmpTrueOrFalse (ifx, tlbl);
6480         }
6481       else
6482         {
6483           for (; (size--); offset++)
6484             {
6485               // normal case
6486               // result = left & right
6487               if (AOP_TYPE (right) == AOP_LIT)
6488                 {
6489                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6490                     {
6491                       aopPut (AOP (result),
6492                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6493                               offset);
6494                       continue;
6495                     }
6496                   else if (bytelit == 0)
6497                     {
6498                       aopPut (AOP (result), zero, offset);
6499                       continue;
6500                     }
6501                   D (emitcode (";", "better literal AND."););
6502                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6503                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6504                                                     FALSE, FALSE, DP2_RESULT_REG));
6505
6506                 }
6507               else
6508                 {
6509                   // faster than result <- left, anl result,right
6510                   // and better if result is SFR
6511                   if (AOP_TYPE (left) == AOP_ACC)
6512                     {
6513                       emitcode ("anl", "a,%s", 
6514                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6515                     }
6516                   else
6517                     {
6518                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6519                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6520                       {
6521                           emitcode("mov", "b,a");
6522                           rOp = "b";
6523                       }
6524                         
6525                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6526                       emitcode ("anl", "a,%s", rOp);
6527                     }                   
6528                 }
6529               aopPut (AOP (result), "a", offset);
6530             }
6531         }
6532     }
6533
6534 release:
6535   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6536   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6537   freeAsmop (result, NULL, ic, TRUE);
6538 }
6539
6540
6541 /*-----------------------------------------------------------------*/
6542 /* genOr  - code for or                                            */
6543 /*-----------------------------------------------------------------*/
6544 static void
6545 genOr (iCode * ic, iCode * ifx)
6546 {
6547   operand *left, *right, *result;
6548   int size, offset = 0;
6549   unsigned long lit = 0L;
6550   bool     pushResult;
6551
6552   D (emitcode (";", "genOr "););
6553
6554   AOP_OP_3_NOFATAL (ic, pushResult);
6555   AOP_SET_LOCALS (ic);
6556
6557   if (pushResult)
6558   {
6559       genFarFarLogicOp(ic, "orl");
6560       return;
6561   }
6562
6563
6564 #ifdef DEBUG_TYPE
6565   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6566             AOP_TYPE (result),
6567             AOP_TYPE (left), AOP_TYPE (right));
6568   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6569             AOP_SIZE (result),
6570             AOP_SIZE (left), AOP_SIZE (right));
6571 #endif
6572
6573   /* if left is a literal & right is not then exchange them */
6574   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6575 #ifdef LOGIC_OPS_BROKEN
6576    || AOP_NEEDSACC (left) // I think this is a net loss now.
6577 #endif      
6578       )
6579     {
6580       operand *tmp = right;
6581       right = left;
6582       left = tmp;
6583     }
6584
6585   /* if result = right then exchange them */
6586   if (sameRegs (AOP (result), AOP (right)))
6587     {
6588       operand *tmp = right;
6589       right = left;
6590       left = tmp;
6591     }
6592
6593   /* if right is bit then exchange them */
6594   if (AOP_TYPE (right) == AOP_CRY &&
6595       AOP_TYPE (left) != AOP_CRY)
6596     {
6597       operand *tmp = right;
6598       right = left;
6599       left = tmp;
6600     }
6601   if (AOP_TYPE (right) == AOP_LIT)
6602     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6603
6604   size = AOP_SIZE (result);
6605
6606   // if(bit | yy)
6607   // xx = bit | yy;
6608   if (AOP_TYPE (left) == AOP_CRY)
6609     {
6610       if (AOP_TYPE (right) == AOP_LIT)
6611         {
6612           // c = bit & literal;
6613           if (lit)
6614             {
6615               // lit != 0 => result = 1
6616               if (AOP_TYPE (result) == AOP_CRY)
6617                 {
6618                   if (size)
6619                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6620                   else if (ifx)
6621                     continueIfTrue (ifx);
6622                   goto release;
6623                 }
6624               emitcode ("setb", "c");
6625             }
6626           else
6627             {
6628               // lit == 0 => result = left
6629               if (size && sameRegs (AOP (result), AOP (left)))
6630                 goto release;
6631               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6632             }
6633         }
6634       else
6635         {
6636           if (AOP_TYPE (right) == AOP_CRY)
6637             {
6638               // c = bit | bit;
6639               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6640               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6641             }
6642           else
6643             {
6644               // c = bit | val;
6645               symbol *tlbl = newiTempLabel (NULL);
6646               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6647                 emitcode ("setb", "c");
6648               emitcode ("jb", "%s,!tlabel",
6649                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6650               toBoolean (right);
6651               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6652               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6653                 {
6654                   jmpTrueOrFalse (ifx, tlbl);
6655                   goto release;
6656                 }
6657               else
6658                 {
6659                   CLRC;
6660                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6661                 }
6662             }
6663         }
6664       // bit = c
6665       // val = c
6666       if (size)
6667         outBitC (result);
6668       // if(bit | ...)
6669       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6670            genIfxJump (ifx, "c");
6671       goto release;
6672     }
6673
6674   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6675   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6676   if ((AOP_TYPE (right) == AOP_LIT) &&
6677       (AOP_TYPE (result) == AOP_CRY) &&
6678       (AOP_TYPE (left) != AOP_CRY))
6679     {
6680       if (lit)
6681         {
6682           // result = 1
6683           if (size)
6684             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6685           else
6686             continueIfTrue (ifx);
6687           goto release;
6688         }
6689       else
6690         {
6691           // lit = 0, result = boolean(left)
6692           if (size)
6693             emitcode ("setb", "c");
6694           toBoolean (right);
6695           if (size)
6696             {
6697               symbol *tlbl = newiTempLabel (NULL);
6698               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6699               CLRC;
6700               emitcode ("", "!tlabeldef", tlbl->key + 100);
6701             }
6702           else
6703             {
6704               genIfxJump (ifx, "a");
6705               goto release;
6706             }
6707         }
6708       outBitC (result);
6709       goto release;
6710     }
6711
6712   /* if left is same as result */
6713   if (sameRegs (AOP (result), AOP (left)))
6714     {
6715       for (; size--; offset++)
6716         {
6717           if (AOP_TYPE (right) == AOP_LIT)
6718             {
6719               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6720                 {
6721                   continue;
6722                 }
6723               else
6724                 {
6725                   if (IS_AOP_PREG (left))
6726                     {
6727                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6728                       emitcode ("orl", "a,%s",
6729                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6730                       aopPut (AOP (result), "a", offset);
6731                     }
6732                   else
6733                     {
6734                       emitcode ("orl", "%s,%s",
6735                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6736                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6737                     }
6738                 }
6739             }
6740           else
6741             {
6742               if (AOP_TYPE (left) == AOP_ACC)
6743                 {
6744                   emitcode ("orl", "a,%s",
6745                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6746                 }
6747               else
6748                 {
6749                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6750                   if (IS_AOP_PREG (left))
6751                     {
6752                       emitcode ("orl", "a,%s", 
6753                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6754                       aopPut (AOP (result), "a", offset);
6755                     }
6756                   else
6757                     {
6758                       emitcode ("orl", "%s,a",
6759                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6760                     }
6761                 }
6762             }
6763         }
6764     }
6765   else
6766     {
6767       // left & result in different registers
6768       if (AOP_TYPE (result) == AOP_CRY)
6769         {
6770           // result = bit
6771           // if(size), result in bit
6772           // if(!size && ifx), conditional oper: if(left | right)
6773           symbol *tlbl = newiTempLabel (NULL);
6774           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6775           if (size)
6776             emitcode ("setb", "c");
6777           while (sizer--)
6778             {
6779               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6780                 emitcode ("orl", "a,%s",
6781                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6782               } else {
6783                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6784                 emitcode ("orl", "a,%s",
6785                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6786               }
6787               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6788               offset++;
6789             }
6790           if (size)
6791             {
6792               CLRC;
6793               emitcode ("", "!tlabeldef", tlbl->key + 100);
6794               outBitC (result);
6795             }
6796           else if (ifx)
6797             jmpTrueOrFalse (ifx, tlbl);
6798         }
6799       else
6800         {
6801             _startLazyDPSEvaluation();
6802           for (; (size--); offset++)
6803             {
6804               // normal case
6805               // result = left & right
6806               if (AOP_TYPE (right) == AOP_LIT)
6807                 {
6808                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6809                     {
6810                       aopPut (AOP (result),
6811                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6812                               offset);
6813                       continue;
6814                     }
6815                   D (emitcode (";", "better literal OR."););
6816                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6817                   emitcode ("orl", "a, %s",
6818                             aopGet (AOP (right), offset,
6819                                     FALSE, FALSE, DP2_RESULT_REG));
6820
6821                 }
6822               else
6823                 {
6824                   // faster than result <- left, anl result,right
6825                   // and better if result is SFR
6826                   if (AOP_TYPE (left) == AOP_ACC)
6827                     {
6828                       emitcode ("orl", "a,%s",
6829                                 aopGet (AOP (right), offset,
6830                                         FALSE, FALSE, DP2_RESULT_REG));
6831                     }
6832                   else
6833                     {
6834                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6835                         
6836                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6837                       {
6838                           emitcode("mov", "b,a");
6839                           rOp = "b";
6840                       }
6841                         
6842                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6843                       emitcode ("orl", "a,%s", rOp);
6844                     }
6845                 }
6846               aopPut (AOP (result), "a", offset);
6847             }
6848             _endLazyDPSEvaluation();
6849         }
6850     }
6851
6852 release:
6853   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6854   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6855   freeAsmop (result, NULL, ic, TRUE);
6856 }
6857
6858 /*-----------------------------------------------------------------*/
6859 /* genXor - code for xclusive or                                   */
6860 /*-----------------------------------------------------------------*/
6861 static void
6862 genXor (iCode * ic, iCode * ifx)
6863 {
6864   operand *left, *right, *result;
6865   int size, offset = 0;
6866   unsigned long lit = 0L;
6867   bool pushResult;
6868
6869   D (emitcode (";", "genXor "););
6870
6871   AOP_OP_3_NOFATAL (ic, pushResult);
6872   AOP_SET_LOCALS (ic);
6873
6874   if (pushResult)
6875   {
6876       genFarFarLogicOp(ic, "xrl");
6877       return;
6878   }  
6879
6880 #ifdef DEBUG_TYPE
6881   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6882             AOP_TYPE (result),
6883             AOP_TYPE (left), AOP_TYPE (right));
6884   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6885             AOP_SIZE (result),
6886             AOP_SIZE (left), AOP_SIZE (right));
6887 #endif
6888
6889   /* if left is a literal & right is not ||
6890      if left needs acc & right does not */
6891   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6892 #ifdef LOGIC_OPS_BROKEN      
6893       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6894 #endif
6895      )
6896     {
6897       operand *tmp = right;
6898       right = left;
6899       left = tmp;
6900     }
6901
6902   /* if result = right then exchange them */
6903   if (sameRegs (AOP (result), AOP (right)))
6904     {
6905       operand *tmp = right;
6906       right = left;
6907       left = tmp;
6908     }
6909
6910   /* if right is bit then exchange them */
6911   if (AOP_TYPE (right) == AOP_CRY &&
6912       AOP_TYPE (left) != AOP_CRY)
6913     {
6914       operand *tmp = right;
6915       right = left;
6916       left = tmp;
6917     }
6918   if (AOP_TYPE (right) == AOP_LIT)
6919     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6920
6921   size = AOP_SIZE (result);
6922
6923   // if(bit ^ yy)
6924   // xx = bit ^ yy;
6925   if (AOP_TYPE (left) == AOP_CRY)
6926     {
6927       if (AOP_TYPE (right) == AOP_LIT)
6928         {
6929           // c = bit & literal;
6930           if (lit >> 1)
6931             {
6932               // lit>>1  != 0 => result = 1
6933               if (AOP_TYPE (result) == AOP_CRY)
6934                 {
6935                   if (size)
6936                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6937                   else if (ifx)
6938                     continueIfTrue (ifx);
6939                   goto release;
6940                 }
6941               emitcode ("setb", "c");
6942             }
6943           else
6944             {
6945               // lit == (0 or 1)
6946               if (lit == 0)
6947                 {
6948                   // lit == 0, result = left
6949                   if (size && sameRegs (AOP (result), AOP (left)))
6950                     goto release;
6951                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6952                 }
6953               else
6954                 {
6955                   // lit == 1, result = not(left)
6956                   if (size && sameRegs (AOP (result), AOP (left)))
6957                     {
6958                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6959                       goto release;
6960                     }
6961                   else
6962                     {
6963                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6964                       emitcode ("cpl", "c");
6965                     }
6966                 }
6967             }
6968
6969         }
6970       else
6971         {
6972           // right != literal
6973           symbol *tlbl = newiTempLabel (NULL);
6974           if (AOP_TYPE (right) == AOP_CRY)
6975             {
6976               // c = bit ^ bit;
6977               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6978             }
6979           else
6980             {
6981               int sizer = AOP_SIZE (right);
6982               // c = bit ^ val
6983               // if val>>1 != 0, result = 1
6984               emitcode ("setb", "c");
6985               while (sizer)
6986                 {
6987                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6988                   if (sizer == 1)
6989                     // test the msb of the lsb
6990                     emitcode ("anl", "a,#!constbyte",0xfe);
6991                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6992                   sizer--;
6993                 }
6994               // val = (0,1)
6995               emitcode ("rrc", "a");
6996             }
6997           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6998           emitcode ("cpl", "c");
6999           emitcode ("", "!tlabeldef", (tlbl->key + 100));
7000         }
7001       // bit = c
7002       // val = c
7003       if (size)
7004         outBitC (result);
7005       // if(bit | ...)
7006       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7007         genIfxJump (ifx, "c");
7008       goto release;
7009     }
7010
7011   if (sameRegs (AOP (result), AOP (left)))
7012     {
7013       /* if left is same as result */
7014       for (; size--; offset++)
7015         {
7016           if (AOP_TYPE (right) == AOP_LIT)
7017             {
7018               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7019                 continue;
7020               else if (IS_AOP_PREG (left))
7021                 {
7022                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7023                   emitcode ("xrl", "a,%s",
7024                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7025                   aopPut (AOP (result), "a", offset);
7026                 }
7027               else
7028                 emitcode ("xrl", "%s,%s",
7029                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7030                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7031             }
7032           else
7033             {
7034               if (AOP_TYPE (left) == AOP_ACC)
7035                 emitcode ("xrl", "a,%s",
7036                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7037               else
7038                 {
7039                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7040                   if (IS_AOP_PREG (left))
7041                     {
7042                       emitcode ("xrl", "a,%s",
7043                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7044                       aopPut (AOP (result), "a", offset);
7045                     }
7046                   else
7047                     emitcode ("xrl", "%s,a",
7048                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7049                 }
7050             }
7051         }
7052     }
7053   else
7054     {
7055       // left & result in different registers
7056       if (AOP_TYPE (result) == AOP_CRY)
7057         {
7058           // result = bit
7059           // if(size), result in bit
7060           // if(!size && ifx), conditional oper: if(left ^ right)
7061           symbol *tlbl = newiTempLabel (NULL);
7062           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7063                   
7064           if (size)
7065             emitcode ("setb", "c");
7066           while (sizer--)
7067             {
7068               if ((AOP_TYPE (right) == AOP_LIT) &&
7069                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7070                 {
7071                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7072                 }
7073               else
7074                 {
7075                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7076                     emitcode ("xrl", "a,%s",
7077                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7078                   } else {
7079                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7080                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7081                       {
7082                           emitcode("mov", "b,a");
7083                           rOp = "b";
7084                       }
7085                         
7086                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7087                       emitcode ("xrl", "a,%s", rOp);                  
7088                   }
7089                 }
7090               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7091               offset++;
7092             }
7093           if (size)
7094             {
7095               CLRC;
7096               emitcode ("", "!tlabeldef", tlbl->key + 100);
7097               outBitC (result);
7098             }
7099           else if (ifx)
7100             jmpTrueOrFalse (ifx, tlbl);
7101         }
7102       else
7103         {
7104         for (; (size--); offset++)
7105           {
7106             // normal case
7107             // result = left & right
7108             if (AOP_TYPE (right) == AOP_LIT)
7109               {
7110                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7111                   {
7112                     aopPut (AOP (result),
7113                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7114                             offset);
7115                     continue;
7116                   }
7117                 D (emitcode (";", "better literal XOR."););
7118                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7119                 emitcode ("xrl", "a, %s",
7120                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7121               }
7122             else
7123               {
7124                 // faster than result <- left, anl result,right
7125                 // and better if result is SFR
7126                 if (AOP_TYPE (left) == AOP_ACC)
7127                   {
7128                     emitcode ("xrl", "a,%s",
7129                               aopGet (AOP (right), offset,
7130                                       FALSE, FALSE, DP2_RESULT_REG));
7131                   }
7132                 else
7133                   {
7134                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7135                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7136                       {
7137                           emitcode("mov", "b,a");
7138                           rOp = "b";
7139                       }
7140                         
7141                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7142                       emitcode ("xrl", "a,%s", rOp);
7143                   }
7144               }
7145             aopPut (AOP (result), "a", offset);
7146           }
7147         }
7148         
7149     }
7150
7151 release:
7152   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7153   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7154   freeAsmop (result, NULL, ic, TRUE);
7155 }
7156
7157 /*-----------------------------------------------------------------*/
7158 /* genInline - write the inline code out                           */
7159 /*-----------------------------------------------------------------*/
7160 static void
7161 genInline (iCode * ic)
7162 {
7163   char *buffer, *bp, *bp1;
7164
7165   D (emitcode (";", "genInline "); );
7166
7167   _G.inLine += (!options.asmpeep);
7168
7169   buffer = Safe_strdup(IC_INLINE(ic));
7170   bp = buffer;
7171   bp1 = buffer;
7172
7173   /* emit each line as a code */
7174   while (*bp)
7175     {
7176       if (*bp == '\n')
7177         {
7178           *bp++ = '\0';
7179           emitcode (bp1, "");
7180           bp1 = bp;
7181         }
7182       else
7183         {
7184           if (*bp == ':')
7185             {
7186               bp++;
7187               *bp = '\0';
7188               bp++;
7189               emitcode (bp1, "");
7190               bp1 = bp;
7191             }
7192           else
7193             bp++;
7194         }
7195     }
7196   if (bp1 != bp)
7197     emitcode (bp1, "");
7198   /*     emitcode("",buffer); */
7199   _G.inLine -= (!options.asmpeep);
7200 }
7201
7202 /*-----------------------------------------------------------------*/
7203 /* genRRC - rotate right with carry                                */
7204 /*-----------------------------------------------------------------*/
7205 static void
7206 genRRC (iCode * ic)
7207 {
7208   operand *left, *result;
7209   int     size, offset;
7210
7211   D (emitcode (";", "genRRC "););
7212
7213   /* rotate right with carry */
7214   left = IC_LEFT (ic);
7215   result = IC_RESULT (ic);
7216   aopOp (left, ic, FALSE, FALSE);
7217   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7218
7219   /* move it to the result */
7220   size = AOP_SIZE (result);
7221   offset = size - 1;
7222   CLRC;
7223
7224   _startLazyDPSEvaluation ();
7225   while (size--)
7226     {
7227       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7228       emitcode ("rrc", "a");
7229       if (AOP_SIZE (result) > 1)
7230         aopPut (AOP (result), "a", offset--);
7231     }
7232   _endLazyDPSEvaluation ();
7233
7234   /* now we need to put the carry into the
7235      highest order byte of the result */
7236   if (AOP_SIZE (result) > 1)
7237     {
7238       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7239     }
7240   emitcode ("mov", "acc.7,c");
7241   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7242   freeAsmop (left, NULL, ic, TRUE);
7243   freeAsmop (result, NULL, ic, TRUE);
7244 }
7245
7246 /*-----------------------------------------------------------------*/
7247 /* genRLC - generate code for rotate left with carry               */
7248 /*-----------------------------------------------------------------*/
7249 static void
7250 genRLC (iCode * ic)
7251 {
7252   operand *left, *result;
7253   int size, offset;
7254   char *l;
7255
7256   D (emitcode (";", "genRLC "););
7257
7258   /* rotate right with carry */
7259   left = IC_LEFT (ic);
7260   result = IC_RESULT (ic);
7261   aopOp (left, ic, FALSE, FALSE);
7262   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7263
7264   /* move it to the result */
7265   size = AOP_SIZE (result);
7266   offset = 0;
7267   if (size--)
7268     {
7269       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7270       MOVA (l);
7271       emitcode ("add", "a,acc");
7272       if (AOP_SIZE (result) > 1)
7273         {
7274           aopPut (AOP (result), "a", offset++);
7275         }
7276
7277       _startLazyDPSEvaluation ();
7278       while (size--)
7279         {
7280           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7281           MOVA (l);
7282           emitcode ("rlc", "a");
7283           if (AOP_SIZE (result) > 1)
7284             aopPut (AOP (result), "a", offset++);
7285         }
7286       _endLazyDPSEvaluation ();
7287     }
7288   /* now we need to put the carry into the
7289      highest order byte of the result */
7290   if (AOP_SIZE (result) > 1)
7291     {
7292       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7293       MOVA (l);
7294     }
7295   emitcode ("mov", "acc.0,c");
7296   aopPut (AOP (result), "a", 0);
7297   freeAsmop (left, NULL, ic, TRUE);
7298   freeAsmop (result, NULL, ic, TRUE);
7299 }
7300
7301 /*-----------------------------------------------------------------*/
7302 /* genGetHbit - generates code get highest order bit               */
7303 /*-----------------------------------------------------------------*/
7304 static void
7305 genGetHbit (iCode * ic)
7306 {
7307   operand *left, *result;
7308   left = IC_LEFT (ic);
7309   result = IC_RESULT (ic);
7310   aopOp (left, ic, FALSE, FALSE);
7311   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7312
7313   D (emitcode (";", "genGetHbit "););
7314
7315   /* get the highest order byte into a */
7316   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7317   if (AOP_TYPE (result) == AOP_CRY)
7318     {
7319       emitcode ("rlc", "a");
7320       outBitC (result);
7321     }
7322   else
7323     {
7324       emitcode ("rl", "a");
7325       emitcode ("anl", "a,#1");
7326       outAcc (result);
7327     }
7328
7329
7330   freeAsmop (left, NULL, ic, TRUE);
7331   freeAsmop (result, NULL, ic, TRUE);
7332 }
7333
7334 /*-----------------------------------------------------------------*/
7335 /* AccRol - rotate left accumulator by known count                 */
7336 /*-----------------------------------------------------------------*/
7337 static void
7338 AccRol (int shCount)
7339 {
7340   shCount &= 0x0007;            // shCount : 0..7
7341
7342   switch (shCount)
7343     {
7344     case 0:
7345       break;
7346     case 1:
7347       emitcode ("rl", "a");
7348       break;
7349     case 2:
7350       emitcode ("rl", "a");
7351       emitcode ("rl", "a");
7352       break;
7353     case 3:
7354       emitcode ("swap", "a");
7355       emitcode ("rr", "a");
7356       break;
7357     case 4:
7358       emitcode ("swap", "a");
7359       break;
7360     case 5:
7361       emitcode ("swap", "a");
7362       emitcode ("rl", "a");
7363       break;
7364     case 6:
7365       emitcode ("rr", "a");
7366       emitcode ("rr", "a");
7367       break;
7368     case 7:
7369       emitcode ("rr", "a");
7370       break;
7371     }
7372 }
7373
7374 /*-----------------------------------------------------------------*/
7375 /* AccLsh - left shift accumulator by known count                  */
7376 /*-----------------------------------------------------------------*/
7377 static void
7378 AccLsh (int shCount)
7379 {
7380   if (shCount != 0)
7381     {
7382       if (shCount == 1)
7383         emitcode ("add", "a,acc");
7384       else if (shCount == 2)
7385         {
7386           emitcode ("add", "a,acc");
7387           emitcode ("add", "a,acc");
7388         }
7389       else
7390         {
7391           /* rotate left accumulator */
7392           AccRol (shCount);
7393           /* and kill the lower order bits */
7394           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7395         }
7396     }
7397 }
7398
7399 /*-----------------------------------------------------------------*/
7400 /* AccRsh - right shift accumulator by known count                 */
7401 /*-----------------------------------------------------------------*/
7402 static void
7403 AccRsh (int shCount)
7404 {
7405   if (shCount != 0)
7406     {
7407       if (shCount == 1)
7408         {
7409           CLRC;
7410           emitcode ("rrc", "a");
7411         }
7412       else
7413         {
7414           /* rotate right accumulator */
7415           AccRol (8 - shCount);
7416           /* and kill the higher order bits */
7417           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7418         }
7419     }
7420 }
7421
7422 #ifdef BETTER_LITERAL_SHIFT
7423 /*-----------------------------------------------------------------*/
7424 /* AccSRsh - signed right shift accumulator by known count                 */
7425 /*-----------------------------------------------------------------*/
7426 static void
7427 AccSRsh (int shCount)
7428 {
7429   symbol *tlbl;
7430   if (shCount != 0)
7431     {
7432       if (shCount == 1)
7433         {
7434           emitcode ("mov", "c,acc.7");
7435           emitcode ("rrc", "a");
7436         }
7437       else if (shCount == 2)
7438         {
7439           emitcode ("mov", "c,acc.7");
7440           emitcode ("rrc", "a");
7441           emitcode ("mov", "c,acc.7");
7442           emitcode ("rrc", "a");
7443         }
7444       else
7445         {
7446           tlbl = newiTempLabel (NULL);
7447           /* rotate right accumulator */
7448           AccRol (8 - shCount);
7449           /* and kill the higher order bits */
7450           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7451           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7452           emitcode ("orl", "a,#!constbyte",
7453                     (unsigned char) ~SRMask[shCount]);
7454           emitcode ("", "!tlabeldef", tlbl->key + 100);
7455         }
7456     }
7457 }
7458 #endif
7459
7460 #ifdef BETTER_LITERAL_SHIFT
7461 /*-----------------------------------------------------------------*/
7462 /* shiftR1Left2Result - shift right one byte from left to result   */
7463 /*-----------------------------------------------------------------*/
7464 static void
7465 shiftR1Left2Result (operand * left, int offl,
7466                     operand * result, int offr,
7467                     int shCount, int sign)
7468 {
7469   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7470   /* shift right accumulator */
7471   if (sign)
7472     AccSRsh (shCount);
7473   else
7474     AccRsh (shCount);
7475   aopPut (AOP (result), "a", offr);
7476 }
7477 #endif
7478
7479 #ifdef BETTER_LITERAL_SHIFT
7480 /*-----------------------------------------------------------------*/
7481 /* shiftL1Left2Result - shift left one byte from left to result    */
7482 /*-----------------------------------------------------------------*/
7483 static void
7484 shiftL1Left2Result (operand * left, int offl,
7485                     operand * result, int offr, int shCount)
7486 {
7487   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7488   /* shift left accumulator */
7489   AccLsh (shCount);
7490   aopPut (AOP (result), "a", offr);
7491 }
7492 #endif
7493
7494 #ifdef BETTER_LITERAL_SHIFT
7495 /*-----------------------------------------------------------------*/
7496 /* movLeft2Result - move byte from left to result                  */
7497 /*-----------------------------------------------------------------*/
7498 static void
7499 movLeft2Result (operand * left, int offl,
7500                 operand * result, int offr, int sign)
7501 {
7502   char *l;
7503   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7504   {
7505       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7506
7507       if (*l == '@' && (IS_AOP_PREG (result)))
7508       {
7509           emitcode ("mov", "a,%s", l);
7510           aopPut (AOP (result), "a", offr);
7511       }
7512       else
7513       {
7514           if (!sign)
7515           {
7516             aopPut (AOP (result), l, offr);
7517           }
7518           else
7519             {
7520               /* MSB sign in acc.7 ! */
7521               if (getDataSize (left) == offl + 1)
7522                 {
7523                   emitcode ("mov", "a,%s", l);
7524                   aopPut (AOP (result), "a", offr);
7525                 }
7526             }
7527       }
7528   }
7529 }
7530 #endif
7531
7532 #ifdef BETTER_LITERAL_SHIFT
7533 /*-----------------------------------------------------------------*/
7534 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7535 /*-----------------------------------------------------------------*/
7536 static void
7537 AccAXRrl1 (char *x)
7538 {
7539   emitcode ("rrc", "a");
7540   emitcode ("xch", "a,%s", x);
7541   emitcode ("rrc", "a");
7542   emitcode ("xch", "a,%s", x);
7543 }
7544 #endif
7545
7546 #ifdef BETTER_LITERAL_SHIFT
7547 //REMOVE ME!!!
7548 /*-----------------------------------------------------------------*/
7549 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7550 /*-----------------------------------------------------------------*/
7551 static void
7552 AccAXLrl1 (char *x)
7553 {
7554   emitcode ("xch", "a,%s", x);
7555   emitcode ("rlc", "a");
7556   emitcode ("xch", "a,%s", x);
7557   emitcode ("rlc", "a");
7558 }
7559 #endif
7560
7561 #ifdef BETTER_LITERAL_SHIFT
7562 /*-----------------------------------------------------------------*/
7563 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7564 /*-----------------------------------------------------------------*/
7565 static void
7566 AccAXLsh1 (char *x)
7567 {
7568   emitcode ("xch", "a,%s", x);
7569   emitcode ("add", "a,acc");
7570   emitcode ("xch", "a,%s", x);
7571   emitcode ("rlc", "a");
7572 }
7573 #endif
7574
7575 #ifdef BETTER_LITERAL_SHIFT
7576 /*-----------------------------------------------------------------*/
7577 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7578 /*-----------------------------------------------------------------*/
7579 static void
7580 AccAXLsh (char *x, int shCount)
7581 {
7582   switch (shCount)
7583     {
7584     case 0:
7585       break;
7586     case 1:
7587       AccAXLsh1 (x);
7588       break;
7589     case 2:
7590       AccAXLsh1 (x);
7591       AccAXLsh1 (x);
7592       break;
7593     case 3:
7594     case 4:
7595     case 5:                     // AAAAABBB:CCCCCDDD
7596
7597       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7598
7599       emitcode ("anl", "a,#!constbyte",
7600                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7601
7602       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7603
7604       AccRol (shCount);         // DDDCCCCC:BBB00000
7605
7606       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7607
7608       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7609
7610       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7611
7612       emitcode ("anl", "a,#!constbyte",
7613                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7614
7615       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7616
7617       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7618
7619       break;
7620     case 6:                     // AAAAAABB:CCCCCCDD
7621       emitcode ("anl", "a,#!constbyte",
7622                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7623       emitcode ("mov", "c,acc.0");      // c = B
7624       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7625 #if 0
7626       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7627       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7628 #else
7629       emitcode("rrc","a"); 
7630       emitcode("xch","a,%s", x); 
7631       emitcode("rrc","a"); 
7632       emitcode("mov","c,acc.0"); //<< get correct bit 
7633       emitcode("xch","a,%s", x); 
7634
7635       emitcode("rrc","a"); 
7636       emitcode("xch","a,%s", x); 
7637       emitcode("rrc","a"); 
7638       emitcode("xch","a,%s", x); 
7639 #endif
7640       break;
7641     case 7:                     // a:x <<= 7
7642
7643       emitcode ("anl", "a,#!constbyte",
7644                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7645
7646       emitcode ("mov", "c,acc.0");      // c = B
7647
7648       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7649
7650       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7651
7652       break;
7653     default:
7654       break;
7655     }
7656 }
7657 #endif
7658
7659 #ifdef BETTER_LITERAL_SHIFT
7660 //REMOVE ME!!!
7661 /*-----------------------------------------------------------------*/
7662 /* AccAXRsh - right shift a:x known count (0..7)                   */
7663 /*-----------------------------------------------------------------*/
7664 static void
7665 AccAXRsh (char *x, int shCount)
7666 {
7667   switch (shCount)
7668     {
7669     case 0:
7670       break;
7671     case 1:
7672       CLRC;
7673       AccAXRrl1 (x);            // 0->a:x
7674
7675       break;
7676     case 2:
7677       CLRC;
7678       AccAXRrl1 (x);            // 0->a:x
7679
7680       CLRC;
7681       AccAXRrl1 (x);            // 0->a:x
7682
7683       break;
7684     case 3:
7685     case 4:
7686     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7687
7688       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7689
7690       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7691
7692       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7693
7694       emitcode ("anl", "a,#!constbyte",
7695                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7696
7697       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7698
7699       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7700
7701       emitcode ("anl", "a,#!constbyte",
7702                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7703
7704       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7705
7706       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7707
7708       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7709
7710       break;
7711     case 6:                     // AABBBBBB:CCDDDDDD
7712
7713       emitcode ("mov", "c,acc.7");
7714       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7715
7716       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7717
7718       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7719
7720       emitcode ("anl", "a,#!constbyte",
7721                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7722
7723       break;
7724     case 7:                     // ABBBBBBB:CDDDDDDD
7725
7726       emitcode ("mov", "c,acc.7");      // c = A
7727
7728       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7729
7730       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7731
7732       emitcode ("anl", "a,#!constbyte",
7733                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7734
7735       break;
7736     default:
7737       break;
7738     }
7739 }
7740 #endif
7741
7742 #ifdef BETTER_LITERAL_SHIFT
7743 /*-----------------------------------------------------------------*/
7744 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7745 /*-----------------------------------------------------------------*/
7746 static void
7747 AccAXRshS (char *x, int shCount)
7748 {
7749   symbol *tlbl;
7750   switch (shCount)
7751     {
7752     case 0:
7753       break;
7754     case 1:
7755       emitcode ("mov", "c,acc.7");
7756       AccAXRrl1 (x);            // s->a:x
7757
7758       break;
7759     case 2:
7760       emitcode ("mov", "c,acc.7");
7761       AccAXRrl1 (x);            // s->a:x
7762
7763       emitcode ("mov", "c,acc.7");
7764       AccAXRrl1 (x);            // s->a:x
7765
7766       break;
7767     case 3:
7768     case 4:
7769     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7770
7771       tlbl = newiTempLabel (NULL);
7772       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7773
7774       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7775
7776       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7777
7778       emitcode ("anl", "a,#!constbyte",
7779                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7780
7781       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7782
7783       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7784
7785       emitcode ("anl", "a,#!constbyte",
7786                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7787
7788       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7789
7790       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7791
7792       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7793
7794       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7795       emitcode ("orl", "a,#!constbyte",
7796                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7797
7798       emitcode ("", "!tlabeldef", tlbl->key + 100);
7799       break;                    // SSSSAAAA:BBBCCCCC
7800
7801     case 6:                     // AABBBBBB:CCDDDDDD
7802
7803       tlbl = newiTempLabel (NULL);
7804       emitcode ("mov", "c,acc.7");
7805       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7806
7807       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7808
7809       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7810
7811       emitcode ("anl", "a,#!constbyte",
7812                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7813
7814       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7815       emitcode ("orl", "a,#!constbyte",
7816                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7817
7818       emitcode ("", "!tlabeldef", tlbl->key + 100);
7819       break;
7820     case 7:                     // ABBBBBBB:CDDDDDDD
7821
7822       tlbl = newiTempLabel (NULL);
7823       emitcode ("mov", "c,acc.7");      // c = A
7824
7825       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7826
7827       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7828
7829       emitcode ("anl", "a,#!constbyte",
7830                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7831
7832       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7833       emitcode ("orl", "a,#!constbyte",
7834                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7835
7836       emitcode ("", "!tlabeldef", tlbl->key + 100);
7837       break;
7838     default:
7839       break;
7840     }
7841 }
7842 #endif
7843
7844 #ifdef BETTER_LITERAL_SHIFT
7845 static void
7846 _loadLeftIntoAx(char    **lsb, 
7847                 operand *left, 
7848                 operand *result,
7849                 int     offl,
7850                 int     offr)
7851 {
7852   // Get the initial value from left into a pair of registers.
7853   // MSB must be in A, LSB can be any register.
7854   //
7855   // If the result is held in registers, it is an optimization
7856   // if the LSB can be held in the register which will hold the,
7857   // result LSB since this saves us from having to copy it into
7858   // the result following AccAXLsh.
7859   //
7860   // If the result is addressed indirectly, this is not a gain.
7861   if (AOP_NEEDSACC(result))
7862   {
7863        char *leftByte;
7864        
7865        _startLazyDPSEvaluation();
7866       if (AOP_TYPE(left) == AOP_DPTR2)
7867        {
7868            // Get MSB in A.
7869            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7870            // get LSB in DP2_RESULT_REG.
7871            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7872            assert(!strcmp(leftByte, DP2_RESULT_REG));
7873        }
7874        else
7875        {
7876            // get LSB into DP2_RESULT_REG
7877            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7878            if (strcmp(leftByte, DP2_RESULT_REG))
7879            {
7880                TR_AP("#7");
7881                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7882            }
7883            // And MSB in A.
7884            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7885            assert(strcmp(leftByte, DP2_RESULT_REG));
7886            MOVA(leftByte);
7887        }
7888        _endLazyDPSEvaluation();
7889        *lsb = DP2_RESULT_REG;
7890   }
7891   else
7892   {
7893       if (sameRegs (AOP (result), AOP (left)) &&
7894         ((offl + MSB16) == offr))
7895       {
7896           /* don't crash result[offr] */
7897           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7898           emitcode ("xch", "a,%s", 
7899                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7900       }
7901       else
7902       {
7903           movLeft2Result (left, offl, result, offr, 0);
7904           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7905       }
7906       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7907       assert(strcmp(*lsb,"a"));      
7908   }
7909 }
7910
7911 static void
7912 _storeAxResults(char    *lsb,
7913                 operand *result,
7914                 int     offr)
7915 {
7916   _startLazyDPSEvaluation();
7917   if (AOP_NEEDSACC(result))
7918   {
7919       /* We have to explicitly update the result LSB.
7920        */
7921       emitcode("xch","a,%s", lsb);
7922       aopPut(AOP(result), "a", offr);
7923       emitcode("mov","a,%s", lsb);
7924   }
7925   if (getDataSize (result) > 1)
7926   {
7927       aopPut (AOP (result), "a", offr + MSB16);
7928   }
7929   _endLazyDPSEvaluation();
7930 }
7931
7932 /*-----------------------------------------------------------------*/
7933 /* shiftL2Left2Result - shift left two bytes from left to result   */
7934 /*-----------------------------------------------------------------*/
7935 static void
7936 shiftL2Left2Result (operand * left, int offl,
7937                     operand * result, int offr, int shCount)
7938 {
7939   char *lsb;
7940
7941   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7942   
7943   AccAXLsh (lsb, shCount);
7944   
7945   _storeAxResults(lsb, result, offr);
7946 }
7947 #endif
7948
7949 #ifdef BETTER_LITERAL_SHIFT
7950 /*-----------------------------------------------------------------*/
7951 /* shiftR2Left2Result - shift right two bytes from left to result  */
7952 /*-----------------------------------------------------------------*/
7953 static void
7954 shiftR2Left2Result (operand * left, int offl,
7955                     operand * result, int offr,
7956                     int shCount, int sign)
7957 {
7958   char *lsb;
7959   
7960   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7961   
7962   /* a:x >> shCount (x = lsb(result)) */
7963   if (sign)
7964   {
7965      AccAXRshS(lsb, shCount);
7966   }
7967   else
7968   {
7969     AccAXRsh(lsb, shCount);
7970   }
7971   
7972   _storeAxResults(lsb, result, offr);
7973 }
7974 #endif
7975
7976 /*-----------------------------------------------------------------*/
7977 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7978 /*-----------------------------------------------------------------*/
7979 static void
7980 shiftLLeftOrResult (operand * left, int offl,
7981                     operand * result, int offr, int shCount)
7982 {
7983   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7984   /* shift left accumulator */
7985   AccLsh (shCount);
7986   /* or with result */
7987   emitcode ("orl", "a,%s",
7988             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7989   /* back to result */
7990   aopPut (AOP (result), "a", offr);
7991 }
7992
7993 #if 0
7994 //REMOVE ME!!!
7995 /*-----------------------------------------------------------------*/
7996 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7997 /*-----------------------------------------------------------------*/
7998 static void
7999 shiftRLeftOrResult (operand * left, int offl,
8000                     operand * result, int offr, int shCount)
8001 {
8002   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8003   /* shift right accumulator */
8004   AccRsh (shCount);
8005   /* or with result */
8006   emitcode ("orl", "a,%s",
8007             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8008   /* back to result */
8009   aopPut (AOP (result), "a", offr);
8010 }
8011 #endif
8012
8013 #ifdef BETTER_LITERAL_SHIFT
8014 /*-----------------------------------------------------------------*/
8015 /* genlshOne - left shift a one byte quantity by known count       */
8016 /*-----------------------------------------------------------------*/
8017 static void
8018 genlshOne (operand * result, operand * left, int shCount)
8019 {
8020   D (emitcode (";", "genlshOne "););
8021   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8022 }
8023 #endif
8024
8025 #ifdef BETTER_LITERAL_SHIFT
8026 /*-----------------------------------------------------------------*/
8027 /* genlshTwo - left shift two bytes by known amount != 0           */
8028 /*-----------------------------------------------------------------*/
8029 static void
8030 genlshTwo (operand * result, operand * left, int shCount)
8031 {
8032   int size;
8033
8034   D (emitcode (";", "genlshTwo "););
8035
8036   size = getDataSize (result);
8037
8038   /* if shCount >= 8 */
8039   if (shCount >= 8)
8040   {
8041       shCount -= 8;
8042
8043       _startLazyDPSEvaluation();
8044
8045       if (size > 1)
8046         {
8047           if (shCount)
8048           {
8049             _endLazyDPSEvaluation();
8050             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8051             aopPut (AOP (result), zero, LSB);       
8052           }
8053           else
8054           {
8055             movLeft2Result (left, LSB, result, MSB16, 0);
8056             aopPut (AOP (result), zero, LSB);
8057             _endLazyDPSEvaluation();
8058           }
8059         }
8060         else
8061         {
8062           aopPut (AOP (result), zero, LSB);
8063           _endLazyDPSEvaluation();
8064         }
8065   }
8066
8067   /*  1 <= shCount <= 7 */
8068   else
8069     {
8070       if (size == 1)
8071       {
8072         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8073       }
8074       else
8075       {
8076         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8077       }
8078     }
8079 }
8080 #endif
8081
8082 #if 0
8083 //REMOVE ME!!!
8084 /*-----------------------------------------------------------------*/
8085 /* shiftLLong - shift left one long from left to result            */
8086 /* offl = LSB or MSB16                                             */
8087 /*-----------------------------------------------------------------*/
8088 static void
8089 shiftLLong (operand * left, operand * result, int offr)
8090 {
8091   char *l;
8092   int size = AOP_SIZE (result);
8093
8094   if (size >= LSB + offr)
8095     {
8096       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8097       MOVA (l);
8098       emitcode ("add", "a,acc");
8099       if (sameRegs (AOP (left), AOP (result)) &&
8100           size >= MSB16 + offr && offr != LSB)
8101         emitcode ("xch", "a,%s",
8102                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8103       else
8104         aopPut (AOP (result), "a", LSB + offr);
8105     }
8106
8107   if (size >= MSB16 + offr)
8108     {
8109       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8110         {
8111           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8112         }
8113       emitcode ("rlc", "a");
8114       if (sameRegs (AOP (left), AOP (result)) &&
8115           size >= MSB24 + offr && offr != LSB)
8116         emitcode ("xch", "a,%s",
8117                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8118       else
8119         aopPut (AOP (result), "a", MSB16 + offr);
8120     }
8121
8122   if (size >= MSB24 + offr)
8123     {
8124       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8125         {
8126           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8127         }
8128       emitcode ("rlc", "a");
8129       if (sameRegs (AOP (left), AOP (result)) &&
8130           size >= MSB32 + offr && offr != LSB)
8131         emitcode ("xch", "a,%s",
8132                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8133       else
8134         aopPut (AOP (result), "a", MSB24 + offr);
8135     }
8136
8137   if (size > MSB32 + offr)
8138     {
8139       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8140         {
8141           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8142         }
8143       emitcode ("rlc", "a");
8144       aopPut (AOP (result), "a", MSB32 + offr);
8145     }
8146   if (offr != LSB)
8147     aopPut (AOP (result), zero, LSB);
8148 }
8149 #endif
8150
8151 #if 0
8152 //REMOVE ME!!!
8153 /*-----------------------------------------------------------------*/
8154 /* genlshFour - shift four byte by a known amount != 0             */
8155 /*-----------------------------------------------------------------*/
8156 static void
8157 genlshFour (operand * result, operand * left, int shCount)
8158 {
8159   int size;
8160
8161   D (emitcode (";", "genlshFour ");
8162     );
8163
8164   size = AOP_SIZE (result);
8165
8166   /* if shifting more that 3 bytes */
8167   if (shCount >= 24)
8168     {
8169       shCount -= 24;
8170       if (shCount)
8171         /* lowest order of left goes to the highest
8172            order of the destination */
8173         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8174       else
8175         movLeft2Result (left, LSB, result, MSB32, 0);
8176       aopPut (AOP (result), zero, LSB);
8177       aopPut (AOP (result), zero, MSB16);
8178       aopPut (AOP (result), zero, MSB24);
8179       return;
8180     }
8181
8182   /* more than two bytes */
8183   else if (shCount >= 16)
8184     {
8185       /* lower order two bytes goes to higher order two bytes */
8186       shCount -= 16;
8187       /* if some more remaining */
8188       if (shCount)
8189         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8190       else
8191         {
8192           movLeft2Result (left, MSB16, result, MSB32, 0);
8193           movLeft2Result (left, LSB, result, MSB24, 0);
8194         }
8195       aopPut (AOP (result), zero, MSB16);
8196       aopPut (AOP (result), zero, LSB);
8197       return;
8198     }
8199
8200   /* if more than 1 byte */
8201   else if (shCount >= 8)
8202     {
8203       /* lower order three bytes goes to higher order  three bytes */
8204       shCount -= 8;
8205       if (size == 2)
8206         {
8207           if (shCount)
8208             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8209           else
8210             movLeft2Result (left, LSB, result, MSB16, 0);
8211         }
8212       else
8213         {                       /* size = 4 */
8214           if (shCount == 0)
8215             {
8216               movLeft2Result (left, MSB24, result, MSB32, 0);
8217               movLeft2Result (left, MSB16, result, MSB24, 0);
8218               movLeft2Result (left, LSB, result, MSB16, 0);
8219               aopPut (AOP (result), zero, LSB);
8220             }
8221           else if (shCount == 1)
8222             shiftLLong (left, result, MSB16);
8223           else
8224             {
8225               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8226               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8227               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8228               aopPut (AOP (result), zero, LSB);
8229             }
8230         }
8231     }
8232
8233   /* 1 <= shCount <= 7 */
8234   else if (shCount <= 2)
8235     {
8236       shiftLLong (left, result, LSB);
8237       if (shCount == 2)
8238         shiftLLong (result, result, LSB);
8239     }
8240   /* 3 <= shCount <= 7, optimize */
8241   else
8242     {
8243       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8244       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8245       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8246     }
8247 }
8248 #endif
8249
8250 #ifdef BETTER_LITERAL_SHIFT
8251 /*-----------------------------------------------------------------*/
8252 /* genLeftShiftLiteral - left shifting by known count              */
8253 /*-----------------------------------------------------------------*/
8254 static bool
8255 genLeftShiftLiteral (operand * left,
8256                      operand * right,
8257                      operand * result,
8258                      iCode * ic)
8259 {
8260   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8261   int size;
8262
8263   size = getSize (operandType (result));
8264
8265   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8266
8267   /* We only handle certain easy cases so far. */
8268   if ((shCount != 0)
8269    && (shCount < (size * 8))
8270    && (size != 1)
8271    && (size != 2))
8272   {
8273       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8274       return FALSE;
8275   }
8276
8277   freeAsmop (right, NULL, ic, TRUE);
8278
8279   aopOp(left, ic, FALSE, FALSE);
8280   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8281
8282 #if 0 // debug spew
8283   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8284   {
8285         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8286         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8287         {
8288            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8289         }
8290   }
8291   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8292   {
8293         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8294         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8295         {
8296            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8297         }       
8298   }  
8299 #endif
8300   
8301 #if VIEW_SIZE
8302   emitcode ("; shift left ", "result %d, left %d", size,
8303             AOP_SIZE (left));
8304 #endif
8305
8306   /* I suppose that the left size >= result size */
8307   if (shCount == 0)
8308   {
8309         _startLazyDPSEvaluation();
8310         while (size--)
8311         {
8312           movLeft2Result (left, size, result, size, 0);
8313         }
8314         _endLazyDPSEvaluation();
8315   }
8316   else if (shCount >= (size * 8))
8317   {
8318     _startLazyDPSEvaluation();
8319     while (size--)
8320     {
8321       aopPut (AOP (result), zero, size);
8322     }
8323     _endLazyDPSEvaluation();
8324   }
8325   else
8326   {
8327       switch (size)
8328         {
8329         case 1:
8330           genlshOne (result, left, shCount);
8331           break;
8332
8333         case 2:
8334           genlshTwo (result, left, shCount);
8335           break;
8336 #if 0
8337         case 4:
8338           genlshFour (result, left, shCount);
8339           break;
8340 #endif
8341         default:
8342           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8343           break;
8344         }
8345     }
8346   freeAsmop (left, NULL, ic, TRUE);
8347   freeAsmop (result, NULL, ic, TRUE);
8348   return TRUE;
8349 }
8350 #endif
8351
8352 /*-----------------------------------------------------------------*/
8353 /* genLeftShift - generates code for left shifting                 */
8354 /*-----------------------------------------------------------------*/
8355 static void
8356 genLeftShift (iCode * ic)
8357 {
8358   operand *left, *right, *result;
8359   int size, offset;
8360   char *l;
8361   symbol *tlbl, *tlbl1;
8362
8363   D (emitcode (";", "genLeftShift "););
8364
8365   right = IC_RIGHT (ic);
8366   left = IC_LEFT (ic);
8367   result = IC_RESULT (ic);
8368
8369   aopOp (right, ic, FALSE, FALSE);
8370
8371
8372 #ifdef BETTER_LITERAL_SHIFT
8373   /* if the shift count is known then do it
8374      as efficiently as possible */
8375   if (AOP_TYPE (right) == AOP_LIT)
8376     {
8377       if (genLeftShiftLiteral (left, right, result, ic))
8378       {
8379         return;
8380       }
8381     }
8382 #endif
8383
8384   /* shift count is unknown then we have to form
8385      a loop get the loop count in B : Note: we take
8386      only the lower order byte since shifting
8387      more that 32 bits make no sense anyway, ( the
8388      largest size of an object can be only 32 bits ) */
8389
8390   if (AOP_TYPE (right) == AOP_LIT)
8391   {
8392       /* Really should be handled by genLeftShiftLiteral,
8393        * but since I'm too lazy to fix that today, at least we can make
8394        * some small improvement.
8395        */
8396        emitcode("mov", "b,#!constbyte",
8397                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8398   }
8399   else
8400   {
8401       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8402       emitcode ("inc", "b");
8403   }
8404   freeAsmop (right, NULL, ic, TRUE);
8405   aopOp (left, ic, FALSE, FALSE);
8406   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8407
8408   /* now move the left to the result if they are not the
8409      same */
8410   if (!sameRegs (AOP (left), AOP (result)) &&
8411       AOP_SIZE (result) > 1)
8412     {
8413
8414       size = AOP_SIZE (result);
8415       offset = 0;
8416       _startLazyDPSEvaluation ();
8417       while (size--)
8418         {
8419           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8420           if (*l == '@' && (IS_AOP_PREG (result)))
8421             {
8422
8423               emitcode ("mov", "a,%s", l);
8424               aopPut (AOP (result), "a", offset);
8425             }
8426           else
8427             aopPut (AOP (result), l, offset);
8428           offset++;
8429         }
8430       _endLazyDPSEvaluation ();
8431     }
8432
8433   tlbl = newiTempLabel (NULL);
8434   size = AOP_SIZE (result);
8435   offset = 0;
8436   tlbl1 = newiTempLabel (NULL);
8437
8438   /* if it is only one byte then */
8439   if (size == 1)
8440     {
8441       symbol *tlbl1 = newiTempLabel (NULL);
8442
8443       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8444       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8445       emitcode ("", "!tlabeldef", tlbl->key + 100);
8446       emitcode ("add", "a,acc");
8447       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8448       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8449       aopPut (AOP (result), "a", 0);
8450       goto release;
8451     }
8452
8453   reAdjustPreg (AOP (result));
8454
8455   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8456   emitcode ("", "!tlabeldef", tlbl->key + 100);
8457   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8458   emitcode ("add", "a,acc");
8459   aopPut (AOP (result), "a", offset++);
8460   _startLazyDPSEvaluation ();
8461   while (--size)
8462     {
8463       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8464       emitcode ("rlc", "a");
8465       aopPut (AOP (result), "a", offset++);
8466     }
8467   _endLazyDPSEvaluation ();
8468   reAdjustPreg (AOP (result));
8469
8470   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8471   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8472 release:
8473   freeAsmop (left, NULL, ic, TRUE);
8474   freeAsmop (result, NULL, ic, TRUE);
8475 }
8476
8477 #ifdef BETTER_LITERAL_SHIFT
8478 /*-----------------------------------------------------------------*/
8479 /* genrshOne - right shift a one byte quantity by known count      */
8480 /*-----------------------------------------------------------------*/
8481 static void
8482 genrshOne (operand * result, operand * left,
8483            int shCount, int sign)
8484 {
8485   D (emitcode (";", "genrshOne"););
8486   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8487 }
8488 #endif
8489
8490 #ifdef BETTER_LITERAL_SHIFT
8491 /*-----------------------------------------------------------------*/
8492 /* genrshTwo - right shift two bytes by known amount != 0          */
8493 /*-----------------------------------------------------------------*/
8494 static void
8495 genrshTwo (operand * result, operand * left,
8496            int shCount, int sign)
8497 {
8498   D (emitcode (";", "genrshTwo"););
8499
8500   /* if shCount >= 8 */
8501   if (shCount >= 8)
8502     {
8503       shCount -= 8;
8504       _startLazyDPSEvaluation();
8505       if (shCount)
8506       {
8507         shiftR1Left2Result (left, MSB16, result, LSB,
8508                             shCount, sign);
8509       }                     
8510       else
8511       {
8512         movLeft2Result (left, MSB16, result, LSB, sign);
8513       }
8514       addSign (result, MSB16, sign);
8515       _endLazyDPSEvaluation();
8516     }
8517
8518   /*  1 <= shCount <= 7 */
8519   else
8520   {
8521     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8522   }
8523 }
8524 #endif
8525
8526 /*-----------------------------------------------------------------*/
8527 /* shiftRLong - shift right one long from left to result           */
8528 /* offl = LSB or MSB16                                             */
8529 /*-----------------------------------------------------------------*/
8530 static void
8531 shiftRLong (operand * left, int offl,
8532             operand * result, int sign)
8533 {
8534   int isSameRegs=sameRegs(AOP(left),AOP(result));
8535
8536   if (isSameRegs && offl>1) {
8537     // we are in big trouble, but this shouldn't happen
8538     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8539   }
8540
8541   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8542   
8543   if (offl==MSB16) {
8544     // shift is > 8
8545     if (sign) {
8546       emitcode ("rlc", "a");
8547       emitcode ("subb", "a,acc");
8548       emitcode ("xch", "a,%s",
8549                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8550     } else {
8551       aopPut (AOP(result), zero, MSB32);
8552     }
8553   }
8554
8555   if (!sign) {
8556     emitcode ("clr", "c");
8557   } else {
8558     emitcode ("mov", "c,acc.7");
8559   }
8560
8561   emitcode ("rrc", "a");
8562
8563   if (isSameRegs && offl==MSB16) {
8564     emitcode ("xch",
8565               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8566   } else {
8567     aopPut (AOP (result), "a", MSB32);
8568     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8569   }
8570
8571   emitcode ("rrc", "a");
8572   if (isSameRegs && offl==1) {
8573     emitcode ("xch", "a,%s",
8574               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8575   } else {
8576     aopPut (AOP (result), "a", MSB24);
8577     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8578   }
8579   emitcode ("rrc", "a");
8580   aopPut (AOP (result), "a", MSB16 - offl);
8581
8582   if (offl == LSB)
8583     {
8584       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8585       emitcode ("rrc", "a");
8586       aopPut (AOP (result), "a", LSB);
8587     }
8588 }
8589
8590 /*-----------------------------------------------------------------*/
8591 /* genrshFour - shift four byte by a known amount != 0             */
8592 /*-----------------------------------------------------------------*/
8593 static void
8594 genrshFour (operand * result, operand * left,
8595             int shCount, int sign)
8596 {
8597   D (emitcode (";", "genrshFour"););
8598
8599   /* if shifting more that 3 bytes */
8600   if (shCount >= 24)
8601     {
8602       shCount -= 24;
8603       _startLazyDPSEvaluation();
8604       if (shCount)
8605         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8606       else
8607         movLeft2Result (left, MSB32, result, LSB, sign);
8608       addSign (result, MSB16, sign);
8609       _endLazyDPSEvaluation();
8610     }
8611   else if (shCount >= 16)
8612     {
8613       shCount -= 16;
8614       _startLazyDPSEvaluation();
8615       if (shCount)
8616         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8617       else
8618         {
8619           movLeft2Result (left, MSB24, result, LSB, 0);
8620           movLeft2Result (left, MSB32, result, MSB16, sign);
8621         }
8622       addSign (result, MSB24, sign);
8623       _endLazyDPSEvaluation();
8624     }
8625   else if (shCount >= 8)
8626     {
8627       shCount -= 8;
8628       _startLazyDPSEvaluation();
8629       if (shCount == 1)
8630         {
8631             shiftRLong (left, MSB16, result, sign);
8632         }
8633       else if (shCount == 0)
8634         {
8635           movLeft2Result (left, MSB16, result, LSB, 0);
8636           movLeft2Result (left, MSB24, result, MSB16, 0);
8637           movLeft2Result (left, MSB32, result, MSB24, sign);
8638           addSign (result, MSB32, sign);
8639         }
8640       else
8641         {
8642           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8643           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8644           /* the last shift is signed */
8645           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8646           addSign (result, MSB32, sign);
8647         }
8648         _endLazyDPSEvaluation();
8649     }
8650   else
8651     {   
8652         /* 1 <= shCount <= 7 */
8653       if (shCount <= 2)
8654         {
8655           shiftRLong (left, LSB, result, sign);
8656           if (shCount == 2)
8657             shiftRLong (result, LSB, result, sign);
8658         }
8659       else
8660         {
8661           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8662           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8663           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8664         }
8665     }
8666 }
8667
8668 #ifdef BETTER_LITERAL_SHIFT
8669 /*-----------------------------------------------------------------*/
8670 /* genRightShiftLiteral - right shifting by known count            */
8671 /*-----------------------------------------------------------------*/
8672 static bool
8673 genRightShiftLiteral (operand * left,
8674                       operand * right,
8675                       operand * result,
8676                       iCode * ic,
8677                       int sign)
8678 {
8679   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8680   int size;
8681
8682   size = getSize (operandType (result));
8683
8684   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8685
8686   /* We only handle certain easy cases so far. */
8687   if ((shCount != 0)
8688    && (shCount < (size * 8))
8689    && (size != 1)
8690    && (size != 2)
8691    && (size != 4))
8692   {
8693       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8694       return FALSE;
8695   }
8696
8697   freeAsmop (right, NULL, ic, TRUE);
8698
8699   aopOp (left, ic, FALSE, FALSE);
8700   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8701
8702 #if VIEW_SIZE
8703   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8704             AOP_SIZE (left));
8705 #endif
8706
8707   /* test the LEFT size !!! */
8708
8709   /* I suppose that the left size >= result size */
8710   if (shCount == 0)
8711   {
8712       size = getDataSize (result);
8713       _startLazyDPSEvaluation();
8714       while (size--)
8715       {
8716         movLeft2Result (left, size, result, size, 0);
8717       }
8718       _endLazyDPSEvaluation();
8719   }
8720   else if (shCount >= (size * 8))
8721     {
8722       if (sign)
8723       {
8724         /* get sign in acc.7 */
8725         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8726       }
8727       addSign (result, LSB, sign);
8728     }
8729   else
8730     {
8731       switch (size)
8732         {
8733         case 1:
8734           genrshOne (result, left, shCount, sign);
8735           break;
8736
8737         case 2:
8738           genrshTwo (result, left, shCount, sign);
8739           break;
8740 #if 1
8741         case 4:
8742           genrshFour (result, left, shCount, sign);
8743           break;
8744 #endif    
8745         default:
8746           break;
8747         }
8748     }
8749   freeAsmop (left, NULL, ic, TRUE);
8750   freeAsmop (result, NULL, ic, TRUE);
8751   
8752   return TRUE;
8753 }
8754 #endif
8755
8756 /*-----------------------------------------------------------------*/
8757 /* genSignedRightShift - right shift of signed number              */
8758 /*-----------------------------------------------------------------*/
8759 static void
8760 genSignedRightShift (iCode * ic)
8761 {
8762   operand *right, *left, *result;
8763   int size, offset;
8764   char *l;
8765   symbol *tlbl, *tlbl1;
8766
8767   D (emitcode (";", "genSignedRightShift "););
8768
8769   /* we do it the hard way put the shift count in b
8770      and loop thru preserving the sign */
8771
8772   right = IC_RIGHT (ic);
8773   left = IC_LEFT (ic);
8774   result = IC_RESULT (ic);
8775
8776   aopOp (right, ic, FALSE, FALSE);
8777
8778 #ifdef BETTER_LITERAL_SHIFT
8779   if (AOP_TYPE (right) == AOP_LIT)
8780     {
8781       if (genRightShiftLiteral (left, right, result, ic, 1))
8782       {
8783         return;
8784       }
8785     }
8786 #endif
8787   /* shift count is unknown then we have to form
8788      a loop get the loop count in B : Note: we take
8789      only the lower order byte since shifting
8790      more that 32 bits make no sense anyway, ( the
8791      largest size of an object can be only 32 bits ) */
8792
8793   if (AOP_TYPE (right) == AOP_LIT)
8794   {
8795       /* Really should be handled by genRightShiftLiteral,
8796        * but since I'm too lazy to fix that today, at least we can make
8797        * some small improvement.
8798        */
8799        emitcode("mov", "b,#!constbyte",
8800                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8801   }
8802   else
8803   {
8804         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8805         emitcode ("inc", "b");
8806   }
8807   freeAsmop (right, NULL, ic, TRUE);
8808   aopOp (left, ic, FALSE, FALSE);
8809   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8810
8811   /* now move the left to the result if they are not the
8812      same */
8813   if (!sameRegs (AOP (left), AOP (result)) &&
8814       AOP_SIZE (result) > 1)
8815     {
8816
8817       size = AOP_SIZE (result);
8818       offset = 0;
8819       _startLazyDPSEvaluation ();
8820       while (size--)
8821         {
8822           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8823           if (*l == '@' && IS_AOP_PREG (result))
8824             {
8825
8826               emitcode ("mov", "a,%s", l);
8827               aopPut (AOP (result), "a", offset);
8828             }
8829           else
8830             aopPut (AOP (result), l, offset);
8831           offset++;
8832         }
8833       _endLazyDPSEvaluation ();
8834     }
8835
8836   /* mov the highest order bit to OVR */
8837   tlbl = newiTempLabel (NULL);
8838   tlbl1 = newiTempLabel (NULL);
8839
8840   size = AOP_SIZE (result);
8841   offset = size - 1;
8842   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8843   emitcode ("rlc", "a");
8844   emitcode ("mov", "ov,c");
8845   /* if it is only one byte then */
8846   if (size == 1)
8847     {
8848       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8849       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8850       emitcode ("", "!tlabeldef", tlbl->key + 100);
8851       emitcode ("mov", "c,ov");
8852       emitcode ("rrc", "a");
8853       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8854       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8855       aopPut (AOP (result), "a", 0);
8856       goto release;
8857     }
8858
8859   reAdjustPreg (AOP (result));
8860   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8861   emitcode ("", "!tlabeldef", tlbl->key + 100);
8862   emitcode ("mov", "c,ov");
8863   _startLazyDPSEvaluation ();
8864   while (size--)
8865     {
8866       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8867       emitcode ("rrc", "a");
8868       aopPut (AOP (result), "a", offset--);
8869     }
8870   _endLazyDPSEvaluation ();
8871   reAdjustPreg (AOP (result));
8872   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8873   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8874
8875 release:
8876   freeAsmop (left, NULL, ic, TRUE);
8877   freeAsmop (result, NULL, ic, TRUE);
8878 }
8879
8880 /*-----------------------------------------------------------------*/
8881 /* genRightShift - generate code for right shifting                */
8882 /*-----------------------------------------------------------------*/
8883 static void
8884 genRightShift (iCode * ic)
8885 {
8886   operand *right, *left, *result;
8887   sym_link *retype;
8888   int size, offset;
8889   char *l;
8890   symbol *tlbl, *tlbl1;
8891
8892   D (emitcode (";", "genRightShift "););
8893
8894   /* if signed then we do it the hard way preserve the
8895      sign bit moving it inwards */
8896   retype = getSpec (operandType (IC_RESULT (ic)));
8897
8898   if (!SPEC_USIGN (retype))
8899     {
8900       genSignedRightShift (ic);
8901       return;
8902     }
8903
8904   /* signed & unsigned types are treated the same : i.e. the
8905      signed is NOT propagated inwards : quoting from the
8906      ANSI - standard : "for E1 >> E2, is equivalent to division
8907      by 2**E2 if unsigned or if it has a non-negative value,
8908      otherwise the result is implementation defined ", MY definition
8909      is that the sign does not get propagated */
8910
8911   right = IC_RIGHT (ic);
8912   left = IC_LEFT (ic);
8913   result = IC_RESULT (ic);
8914
8915   aopOp (right, ic, FALSE, FALSE);
8916
8917 #ifdef BETTER_LITERAL_SHIFT
8918   /* if the shift count is known then do it
8919      as efficiently as possible */
8920   if (AOP_TYPE (right) == AOP_LIT)
8921     {
8922       if (genRightShiftLiteral (left, right, result, ic, 0))
8923       {
8924         return;
8925       }
8926     }
8927 #endif
8928
8929   /* shift count is unknown then we have to form
8930      a loop get the loop count in B : Note: we take
8931      only the lower order byte since shifting
8932      more that 32 bits make no sense anyway, ( the
8933      largest size of an object can be only 32 bits ) */
8934   
8935   if (AOP_TYPE (right) == AOP_LIT)
8936   {
8937       /* Really should be handled by genRightShiftLiteral,
8938        * but since I'm too lazy to fix that today, at least we can make
8939        * some small improvement.
8940        */
8941        emitcode("mov", "b,#!constbyte",
8942                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8943   }
8944   else
8945   {
8946       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8947       emitcode ("inc", "b");
8948   }
8949   freeAsmop (right, NULL, ic, TRUE);
8950   aopOp (left, ic, FALSE, FALSE);
8951   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8952
8953   /* now move the left to the result if they are not the
8954      same */
8955   if (!sameRegs (AOP (left), AOP (result)) &&
8956       AOP_SIZE (result) > 1)
8957     {
8958
8959       size = AOP_SIZE (result);
8960       offset = 0;
8961       _startLazyDPSEvaluation ();
8962       while (size--)
8963         {
8964           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8965           if (*l == '@' && IS_AOP_PREG (result))
8966             {
8967
8968               emitcode ("mov", "a,%s", l);
8969               aopPut (AOP (result), "a", offset);
8970             }
8971           else
8972             aopPut (AOP (result), l, offset);
8973           offset++;
8974         }
8975       _endLazyDPSEvaluation ();
8976     }
8977
8978   tlbl = newiTempLabel (NULL);
8979   tlbl1 = newiTempLabel (NULL);
8980   size = AOP_SIZE (result);
8981   offset = size - 1;
8982
8983   /* if it is only one byte then */
8984   if (size == 1)
8985     {
8986       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8987       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8988       emitcode ("", "!tlabeldef", tlbl->key + 100);
8989       CLRC;
8990       emitcode ("rrc", "a");
8991       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8992       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8993       aopPut (AOP (result), "a", 0);
8994       goto release;
8995     }
8996
8997   reAdjustPreg (AOP (result));
8998   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8999   emitcode ("", "!tlabeldef", tlbl->key + 100);
9000   CLRC;
9001   _startLazyDPSEvaluation ();
9002   while (size--)
9003     {
9004       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9005       emitcode ("rrc", "a");
9006       aopPut (AOP (result), "a", offset--);
9007     }
9008   _endLazyDPSEvaluation ();
9009   reAdjustPreg (AOP (result));
9010
9011   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9012   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9013
9014 release:
9015   freeAsmop (left, NULL, ic, TRUE);
9016   freeAsmop (result, NULL, ic, TRUE);
9017 }
9018
9019
9020 /*-----------------------------------------------------------------*/
9021 /* emitPtrByteGet - emits code to get a byte into A through a      */
9022 /*                  pointer register (R0, R1, or DPTR). The        */
9023 /*                  original value of A can be preserved in B.     */
9024 /*-----------------------------------------------------------------*/
9025 static void
9026 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9027 {
9028   switch (p_type)
9029     {
9030     case IPOINTER:
9031     case POINTER:
9032       if (preserveAinB)
9033         emitcode ("mov", "b,a");
9034       emitcode ("mov", "a,@%s", rname);
9035       break;
9036
9037     case PPOINTER:
9038       if (preserveAinB)
9039         emitcode ("mov", "b,a");
9040       emitcode ("movx", "a,@%s", rname);
9041       break;
9042       
9043     case FPOINTER:
9044       if (preserveAinB)
9045         emitcode ("mov", "b,a");
9046       emitcode ("movx", "a,@dptr");
9047       break;
9048
9049     case CPOINTER:
9050       if (preserveAinB)
9051         emitcode ("mov", "b,a");
9052       emitcode ("clr", "a");
9053       emitcode ("movc", "a,@a+dptr");
9054       break;
9055
9056     case GPOINTER:
9057       if (preserveAinB)
9058         {
9059           emitcode ("push", "b");
9060           emitcode ("push", "acc");
9061         }
9062       emitcode ("lcall", "__gptrget");
9063       if (preserveAinB)
9064         emitcode ("pop", "b");
9065       break;
9066     }
9067 }
9068
9069 /*-----------------------------------------------------------------*/
9070 /* emitPtrByteSet - emits code to set a byte from src through a    */
9071 /*                  pointer register (R0, R1, or DPTR).            */
9072 /*-----------------------------------------------------------------*/
9073 static void
9074 emitPtrByteSet (char *rname, int p_type, char *src)
9075 {
9076   switch (p_type)
9077     {
9078     case IPOINTER:
9079     case POINTER:
9080       if (*src=='@')
9081         {
9082           MOVA (src);
9083           emitcode ("mov", "@%s,a", rname);
9084         }
9085       else
9086         emitcode ("mov", "@%s,%s", rname, src);
9087       break;
9088
9089     case PPOINTER:
9090       MOVA (src);
9091       emitcode ("movx", "@%s,a", rname);
9092       break;
9093       
9094     case FPOINTER:
9095       MOVA (src);
9096       emitcode ("movx", "@dptr,a");
9097       break;
9098
9099     case GPOINTER:
9100       MOVA (src);
9101       emitcode ("lcall", "__gptrput");
9102       break;
9103     }
9104 }
9105
9106 /*-----------------------------------------------------------------*/
9107 /* genUnpackBits - generates code for unpacking bits               */
9108 /*-----------------------------------------------------------------*/
9109 static void
9110 genUnpackBits (operand * result, char *rname, int ptype)
9111 {
9112   int offset = 0;       /* result byte offset */
9113   int rsize;            /* result size */
9114   int rlen = 0;         /* remaining bitfield length */
9115   sym_link *etype;      /* bitfield type information */
9116   int blen;             /* bitfield length */
9117   int bstr;             /* bitfield starting bit within byte */
9118
9119   D(emitcode (";     genUnpackBits",""));
9120
9121   etype = getSpec (operandType (result));
9122   rsize = getSize (operandType (result));
9123   blen = SPEC_BLEN (etype);
9124   bstr = SPEC_BSTR (etype);
9125
9126   /* If the bitfield length is less than a byte */
9127   if (blen < 8)
9128     {
9129       emitPtrByteGet (rname, ptype, FALSE);
9130       AccRsh (bstr);
9131       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9132       aopPut (AOP (result), "a", offset++);
9133       goto finish;
9134     }
9135
9136   /* Bit field did not fit in a byte. Copy all
9137      but the partial byte at the end.  */
9138   for (rlen=blen;rlen>=8;rlen-=8)
9139     {
9140       emitPtrByteGet (rname, ptype, FALSE);
9141       aopPut (AOP (result), "a", offset++);
9142       if (rlen>8)
9143         emitcode ("inc", "%s", rname);
9144     }
9145
9146   /* Handle the partial byte at the end */
9147   if (rlen)
9148     {
9149       emitPtrByteGet (rname, ptype, FALSE);
9150       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9151       aopPut (AOP (result), "a", offset++);
9152     }
9153
9154 finish:
9155   if (offset < rsize)
9156     {
9157       rsize -= offset;
9158       while (rsize--)
9159         aopPut (AOP (result), zero, offset++);
9160     }
9161 }
9162
9163
9164 /*-----------------------------------------------------------------*/
9165 /* genDataPointerGet - generates code when ptr offset is known     */
9166 /*-----------------------------------------------------------------*/
9167 static void
9168 genDataPointerGet (operand * left,
9169                    operand * result,
9170                    iCode * ic)
9171 {
9172   char *l;
9173   char buff[256];
9174   int size, offset = 0;
9175   aopOp (result, ic, TRUE, FALSE);
9176
9177   /* get the string representation of the name */
9178   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9179   size = AOP_SIZE (result);
9180   _startLazyDPSEvaluation ();
9181   while (size--)
9182     {
9183         if (offset)
9184         {
9185             SNPRINTF (buff, sizeof(buff), 
9186                       "(%s + %d)", l + 1, offset);
9187         }
9188         else
9189         {
9190             SNPRINTF (buff, sizeof(buff), 
9191                       "%s", l + 1);
9192         }
9193       aopPut (AOP (result), buff, offset++);
9194     }
9195   _endLazyDPSEvaluation ();
9196
9197   freeAsmop (left, NULL, ic, TRUE);
9198   freeAsmop (result, NULL, ic, TRUE);
9199 }
9200
9201 /*-----------------------------------------------------------------*/
9202 /* genNearPointerGet - emitcode for near pointer fetch             */
9203 /*-----------------------------------------------------------------*/
9204 static void
9205 genNearPointerGet (operand * left,
9206                    operand * result,
9207                    iCode * ic,
9208                    iCode *pi)
9209 {
9210   asmop *aop = NULL;
9211   regs *preg;
9212   char *rname;
9213   sym_link *rtype, *retype, *letype;
9214   sym_link *ltype = operandType (left);
9215   char buff[80];
9216
9217   rtype = operandType (result);
9218   retype = getSpec (rtype);
9219   letype = getSpec (ltype);
9220
9221   aopOp (left, ic, FALSE, FALSE);
9222
9223   /* if left is rematerialisable and
9224      result is not bit variable type and
9225      the left is pointer to data space i.e
9226      lower 128 bytes of space */
9227   if (AOP_TYPE (left) == AOP_IMMD &&
9228       !IS_BITVAR (retype) &&
9229       !IS_BITVAR (letype) &&
9230       DCL_TYPE (ltype) == POINTER)
9231     {
9232       genDataPointerGet (left, result, ic);
9233       return;
9234     }
9235
9236   /* if the value is already in a pointer register
9237      then don't need anything more */
9238   if (!AOP_INPREG (AOP (left)))
9239     {
9240       /* otherwise get a free pointer register */
9241       aop = newAsmop (0);
9242       preg = getFreePtr (ic, &aop, FALSE);
9243       emitcode ("mov", "%s,%s",
9244                 preg->name,
9245                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9246       rname = preg->name;
9247     }
9248   else
9249     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9250
9251   freeAsmop (left, NULL, ic, TRUE);
9252   aopOp (result, ic, FALSE, FALSE);
9253
9254   /* if bitfield then unpack the bits */
9255   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9256     genUnpackBits (result, rname, POINTER);
9257   else
9258     {
9259       /* we have can just get the values */
9260       int size = AOP_SIZE (result);
9261       int offset = 0;
9262
9263       while (size--)
9264         {
9265           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9266             {
9267
9268               emitcode ("mov", "a,@%s", rname);
9269               aopPut (AOP (result), "a", offset);
9270             }
9271           else
9272             {
9273               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9274               aopPut (AOP (result), buff, offset);
9275             }
9276           offset++;
9277           if (size || pi)
9278             {
9279                 emitcode ("inc", "%s", rname);
9280             }
9281         }
9282     }
9283
9284   /* now some housekeeping stuff */
9285   if (aop)
9286     {
9287       /* we had to allocate for this iCode */
9288       if (pi) { /* post increment present */
9289         aopPut(AOP ( left ),rname,0);
9290       }
9291       freeAsmop (NULL, aop, ic, TRUE);
9292     }
9293   else
9294     {
9295       /* we did not allocate which means left
9296          already in a pointer register, then
9297          if size > 0 && this could be used again
9298          we have to point it back to where it
9299          belongs */
9300       if (AOP_SIZE (result) > 1 &&
9301           !OP_SYMBOL (left)->remat &&
9302           (OP_SYMBOL (left)->liveTo > ic->seq ||
9303            ic->depth) &&
9304           !pi)
9305         {
9306           int size = AOP_SIZE (result) - 1;
9307           while (size--)
9308             emitcode ("dec", "%s", rname);
9309         }
9310     }
9311
9312   /* done */
9313   freeAsmop (result, NULL, ic, TRUE);
9314   if (pi) pi->generated = 1;
9315 }
9316
9317 /*-----------------------------------------------------------------*/
9318 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9319 /*-----------------------------------------------------------------*/
9320 static void
9321 genPagedPointerGet (operand * left,
9322                     operand * result,
9323                     iCode * ic,
9324                     iCode * pi)
9325 {
9326   asmop *aop = NULL;
9327   regs *preg;
9328   char *rname;
9329   sym_link *rtype, *retype, *letype;
9330
9331   rtype = operandType (result);
9332   retype = getSpec (rtype);
9333   letype = getSpec (operandType (left));
9334   aopOp (left, ic, FALSE, FALSE);
9335
9336   /* if the value is already in a pointer register
9337      then don't need anything more */
9338   if (!AOP_INPREG (AOP (left)))
9339     {
9340       /* otherwise get a free pointer register */
9341       aop = newAsmop (0);
9342       preg = getFreePtr (ic, &aop, FALSE);
9343       emitcode ("mov", "%s,%s",
9344                 preg->name,
9345                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9346       rname = preg->name;
9347     }
9348   else
9349     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9350
9351   freeAsmop (left, NULL, ic, TRUE);
9352   aopOp (result, ic, FALSE, FALSE);
9353
9354   /* if bitfield then unpack the bits */
9355   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9356     genUnpackBits (result, rname, PPOINTER);
9357   else
9358     {
9359       /* we have can just get the values */
9360       int size = AOP_SIZE (result);
9361       int offset = 0;
9362
9363       while (size--)
9364         {
9365
9366           emitcode ("movx", "a,@%s", rname);
9367           aopPut (AOP (result), "a", offset);
9368
9369           offset++;
9370
9371           if (size || pi)
9372             emitcode ("inc", "%s", rname);
9373         }
9374     }
9375
9376   /* now some housekeeping stuff */
9377   if (aop)
9378     {
9379       /* we had to allocate for this iCode */
9380       if (pi) aopPut ( AOP (left), rname, 0);
9381       freeAsmop (NULL, aop, ic, TRUE);
9382     }
9383   else
9384     {
9385       /* we did not allocate which means left
9386          already in a pointer register, then
9387          if size > 0 && this could be used again
9388          we have to point it back to where it
9389          belongs */
9390       if (AOP_SIZE (result) > 1 &&
9391           !OP_SYMBOL (left)->remat &&
9392           (OP_SYMBOL (left)->liveTo > ic->seq ||
9393            ic->depth) &&
9394           !pi)
9395         {
9396           int size = AOP_SIZE (result) - 1;
9397           while (size--)
9398             emitcode ("dec", "%s", rname);
9399         }
9400     }
9401
9402   /* done */
9403   freeAsmop (result, NULL, ic, TRUE);
9404   if (pi) pi->generated = 1;
9405 }
9406
9407 /*-----------------------------------------------------------------*/
9408 /* genFarPointerGet - gget value from far space                    */
9409 /*-----------------------------------------------------------------*/
9410 static void
9411 genFarPointerGet (operand * left,
9412                   operand * result, iCode * ic, iCode *pi)
9413 {
9414     int size, offset, dopi=1;
9415   sym_link *retype = getSpec (operandType (result));
9416   sym_link *letype = getSpec (operandType (left));
9417   D (emitcode (";", "genFarPointerGet"););
9418
9419   aopOp (left, ic, FALSE, FALSE);
9420
9421   /* if the operand is already in dptr
9422      then we do nothing else we move the value to dptr */
9423   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9424     {
9425       /* if this is remateriazable */
9426       if (AOP_TYPE (left) == AOP_IMMD)
9427         {
9428           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9429         }
9430       else
9431         {
9432           /* we need to get it byte by byte */
9433           _startLazyDPSEvaluation ();
9434           if (AOP_TYPE (left) != AOP_DPTR)
9435             {
9436               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9437               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9438               if (options.model == MODEL_FLAT24)
9439                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9440             }
9441           else
9442             {
9443               /* We need to generate a load to DPTR indirect through DPTR. */
9444               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9445               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9446               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9447               if (options.model == MODEL_FLAT24)
9448                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9449               emitcode ("pop", "dph");
9450               emitcode ("pop", "dpl");
9451               dopi =0;
9452             }
9453           _endLazyDPSEvaluation ();
9454         }
9455     }
9456   /* so dptr know contains the address */
9457   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9458
9459   /* if bit then unpack */
9460   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9461       if (AOP_INDPTRn(left)) {
9462           genSetDPTR(AOP(left)->aopu.dptr);
9463       }
9464       genUnpackBits (result, "dptr", FPOINTER);
9465       if (AOP_INDPTRn(left)) {
9466           genSetDPTR(0);
9467       }
9468   } else
9469     {
9470       size = AOP_SIZE (result);
9471       offset = 0;
9472
9473       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9474           while (size--) {
9475               genSetDPTR(AOP(left)->aopu.dptr);
9476               emitcode ("movx", "a,@dptr");
9477               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9478                   emitcode ("inc", "dptr");
9479               genSetDPTR (0);
9480               aopPut (AOP (result), "a", offset++);
9481           }
9482       } else {
9483           _startLazyDPSEvaluation ();
9484           while (size--) {
9485               if (AOP_INDPTRn(left)) {
9486                   genSetDPTR(AOP(left)->aopu.dptr);
9487               } else {
9488                   genSetDPTR (0);
9489               }
9490               _flushLazyDPS ();
9491               
9492               emitcode ("movx", "a,@dptr");
9493               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9494                   emitcode ("inc", "dptr");
9495               
9496               aopPut (AOP (result), "a", offset++);
9497           }
9498           _endLazyDPSEvaluation ();
9499       }
9500     }
9501   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9502       if (!AOP_INDPTRn(left)) {
9503           _startLazyDPSEvaluation ();
9504           aopPut ( AOP (left), "dpl", 0);
9505           aopPut ( AOP (left), "dph", 1);
9506           if (options.model == MODEL_FLAT24)
9507               aopPut ( AOP (left), "dpx", 2);
9508           _endLazyDPSEvaluation ();
9509       }
9510     pi->generated = 1;
9511   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9512              AOP_SIZE(result) > 1 &&
9513              IS_SYMOP(left) &&
9514              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9515       
9516       size = AOP_SIZE (result) - 1;
9517       if (AOP_INDPTRn(left)) {
9518           genSetDPTR(AOP(left)->aopu.dptr);
9519       }
9520       while (size--) emitcode ("lcall","__decdptr");
9521       if (AOP_INDPTRn(left)) {
9522           genSetDPTR(0);
9523       }
9524   }
9525
9526   freeAsmop (left, NULL, ic, TRUE);
9527   freeAsmop (result, NULL, ic, TRUE);
9528 }
9529
9530 /*-----------------------------------------------------------------*/
9531 /* genCodePointerGet - get value from code space                  */
9532 /*-----------------------------------------------------------------*/
9533 static void
9534 genCodePointerGet (operand * left,
9535                     operand * result, iCode * ic, iCode *pi)
9536 {
9537   int size, offset, dopi=1;
9538   sym_link *retype = getSpec (operandType (result));
9539
9540   aopOp (left, ic, FALSE, FALSE);
9541
9542   /* if the operand is already in dptr
9543      then we do nothing else we move the value to dptr */
9544   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9545     {
9546       /* if this is remateriazable */
9547       if (AOP_TYPE (left) == AOP_IMMD)
9548         {
9549           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9550         }
9551       else
9552         {                       /* we need to get it byte by byte */
9553           _startLazyDPSEvaluation ();
9554           if (AOP_TYPE (left) != AOP_DPTR)
9555             {
9556               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9557               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9558               if (options.model == MODEL_FLAT24)
9559                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9560             }
9561           else
9562             {
9563               /* We need to generate a load to DPTR indirect through DPTR. */
9564               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9565               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9566               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9567               if (options.model == MODEL_FLAT24)
9568                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9569               emitcode ("pop", "dph");
9570               emitcode ("pop", "dpl");
9571               dopi=0;
9572             }
9573           _endLazyDPSEvaluation ();
9574         }
9575     }
9576   /* so dptr know contains the address */
9577   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9578
9579   /* if bit then unpack */
9580   if (IS_BITVAR (retype)) {
9581       if (AOP_INDPTRn(left)) {
9582           genSetDPTR(AOP(left)->aopu.dptr);
9583       }
9584       genUnpackBits (result, "dptr", CPOINTER);
9585       if (AOP_INDPTRn(left)) {
9586           genSetDPTR(0);
9587       }
9588   } else
9589     {
9590       size = AOP_SIZE (result);
9591       offset = 0;
9592       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9593           while (size--) {
9594               genSetDPTR(AOP(left)->aopu.dptr);
9595               emitcode ("clr", "a");
9596               emitcode ("movc", "a,@a+dptr");
9597               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9598                   emitcode ("inc", "dptr");
9599               genSetDPTR (0);
9600               aopPut (AOP (result), "a", offset++);
9601           }
9602       } else {
9603           _startLazyDPSEvaluation ();
9604           while (size--)
9605               {
9606                   if (AOP_INDPTRn(left)) {
9607                       genSetDPTR(AOP(left)->aopu.dptr);
9608                   } else {
9609                       genSetDPTR (0);
9610                   }
9611                   _flushLazyDPS ();
9612                   
9613                   emitcode ("clr", "a");
9614                   emitcode ("movc", "a,@a+dptr");
9615                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9616                       emitcode ("inc", "dptr");
9617                   aopPut (AOP (result), "a", offset++);
9618               }
9619           _endLazyDPSEvaluation ();
9620       }
9621     }
9622   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9623       if (!AOP_INDPTRn(left)) {
9624           _startLazyDPSEvaluation ();
9625           
9626           aopPut ( AOP (left), "dpl", 0);
9627           aopPut ( AOP (left), "dph", 1);
9628           if (options.model == MODEL_FLAT24)
9629               aopPut ( AOP (left), "dpx", 2);
9630
9631           _endLazyDPSEvaluation ();
9632       }
9633       pi->generated = 1;
9634   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9635              AOP_SIZE(result) > 1 &&
9636              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9637       
9638       size = AOP_SIZE (result) - 1;
9639       if (AOP_INDPTRn(left)) {
9640           genSetDPTR(AOP(left)->aopu.dptr);
9641       }
9642       while (size--) emitcode ("lcall","__decdptr");
9643       if (AOP_INDPTRn(left)) {
9644           genSetDPTR(0);
9645       }
9646   }
9647   
9648   freeAsmop (left, NULL, ic, TRUE);
9649   freeAsmop (result, NULL, ic, TRUE);
9650 }
9651
9652 /*-----------------------------------------------------------------*/
9653 /* genGenPointerGet - gget value from generic pointer space        */
9654 /*-----------------------------------------------------------------*/
9655 static void
9656 genGenPointerGet (operand * left,
9657                   operand * result, iCode * ic, iCode * pi)
9658 {
9659   int size, offset;
9660   sym_link *retype = getSpec (operandType (result));
9661   sym_link *letype = getSpec (operandType (left));
9662
9663   D (emitcode (";", "genGenPointerGet "); );
9664
9665   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9666
9667   /* if the operand is already in dptr
9668      then we do nothing else we move the value to dptr */
9669   if (AOP_TYPE (left) != AOP_STR)
9670     {
9671       /* if this is remateriazable */
9672       if (AOP_TYPE (left) == AOP_IMMD)
9673         {
9674           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9675           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9676             {
9677                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9678             }
9679             else
9680             {
9681                 emitcode ("mov", "b,#%d", pointerCode (retype));
9682             }
9683         }
9684       else
9685         {                       /* we need to get it byte by byte */
9686             _startLazyDPSEvaluation ();
9687             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9688             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9689             if (options.model == MODEL_FLAT24) {
9690                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9691                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9692             } else {
9693                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9694             }
9695             _endLazyDPSEvaluation ();
9696         }
9697     }
9698
9699   /* so dptr-b now contains the address */
9700   _G.bInUse++;
9701   aopOp (result, ic, FALSE, TRUE);
9702   _G.bInUse--;
9703
9704   /* if bit then unpack */
9705   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9706   {
9707     genUnpackBits (result, "dptr", GPOINTER);
9708   }
9709   else
9710     {
9711         size = AOP_SIZE (result);
9712         offset = 0;
9713
9714         while (size--)
9715         {
9716             if (size)
9717             {
9718                 // Get two bytes at a time, results in _AP & A.
9719                 // dptr will be incremented ONCE by __gptrgetWord.
9720                 //
9721                 // Note: any change here must be coordinated
9722                 // with the implementation of __gptrgetWord
9723                 // in device/lib/_gptrget.c
9724                 emitcode ("lcall", "__gptrgetWord");
9725                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9726                 aopPut (AOP (result), "a", offset++);
9727                 size--;
9728             }
9729             else
9730             {
9731                 // Only one byte to get.
9732                 emitcode ("lcall", "__gptrget");
9733                 aopPut (AOP (result), "a", offset++);
9734             }
9735             
9736             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9737             {
9738                 emitcode ("inc", "dptr");
9739             }
9740         }
9741     }
9742
9743   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9744     _startLazyDPSEvaluation ();
9745       
9746     aopPut ( AOP (left), "dpl", 0);
9747     aopPut ( AOP (left), "dph", 1);
9748     if (options.model == MODEL_FLAT24) {
9749         aopPut ( AOP (left), "dpx", 2);
9750         aopPut ( AOP (left), "b", 3);   
9751     } else  aopPut ( AOP (left), "b", 2);       
9752     
9753     _endLazyDPSEvaluation ();
9754       
9755     pi->generated = 1;
9756   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9757              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9758       
9759       size = AOP_SIZE (result) - 1;
9760       while (size--) emitcode ("lcall","__decdptr");
9761   }
9762
9763   freeAsmop (left, NULL, ic, TRUE);
9764   freeAsmop (result, NULL, ic, TRUE);
9765 }
9766
9767 /*-----------------------------------------------------------------*/
9768 /* genPointerGet - generate code for pointer get                   */
9769 /*-----------------------------------------------------------------*/
9770 static void
9771 genPointerGet (iCode * ic, iCode *pi)
9772 {
9773   operand *left, *result;
9774   sym_link *type, *etype;
9775   int p_type;
9776
9777   D (emitcode (";", "genPointerGet ");
9778     );
9779
9780   left = IC_LEFT (ic);
9781   result = IC_RESULT (ic);
9782
9783   /* depending on the type of pointer we need to
9784      move it to the correct pointer register */
9785   type = operandType (left);
9786   etype = getSpec (type);
9787   /* if left is of type of pointer then it is simple */
9788   if (IS_PTR (type) && !IS_FUNC (type->next))
9789     p_type = DCL_TYPE (type);
9790   else
9791     {
9792       /* we have to go by the storage class */
9793       p_type = PTR_TYPE (SPEC_OCLS (etype));
9794     }
9795   /* special case when cast remat */
9796   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9797       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9798           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9799           type = operandType (left);
9800           p_type = DCL_TYPE (type);
9801   }
9802   /* now that we have the pointer type we assign
9803      the pointer values */
9804   switch (p_type)
9805     {
9806
9807     case POINTER:
9808     case IPOINTER:
9809       genNearPointerGet (left, result, ic, pi);
9810       break;
9811
9812     case PPOINTER:
9813       genPagedPointerGet (left, result, ic, pi);
9814       break;
9815
9816     case FPOINTER:
9817       genFarPointerGet (left, result, ic, pi);
9818       break;
9819
9820     case CPOINTER:
9821       genCodePointerGet (left, result, ic, pi);
9822       break;
9823
9824     case GPOINTER:
9825       genGenPointerGet (left, result, ic, pi);
9826       break;
9827     }
9828
9829 }
9830
9831 /*-----------------------------------------------------------------*/
9832 /* genPackBits - generates code for packed bit storage             */
9833 /*-----------------------------------------------------------------*/
9834 static void
9835 genPackBits (sym_link * etype,
9836              operand * right,
9837              char *rname, int p_type)
9838 {
9839   int offset = 0;       /* source byte offset */
9840   int rlen = 0;         /* remaining bitfield length */
9841   int blen;             /* bitfield length */
9842   int bstr;             /* bitfield starting bit within byte */
9843   int litval;           /* source literal value (if AOP_LIT) */
9844   unsigned char mask;   /* bitmask within current byte */
9845
9846   D(emitcode (";     genPackBits",""));
9847
9848   blen = SPEC_BLEN (etype);
9849   bstr = SPEC_BSTR (etype);
9850
9851   /* If the bitfield length is less than a byte */
9852   if (blen < 8)
9853     {
9854       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9855               (unsigned char) (0xFF >> (8 - bstr)));
9856
9857       if (AOP_TYPE (right) == AOP_LIT)
9858         {
9859           /* Case with a bitfield length <8 and literal source
9860           */
9861           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9862           litval <<= bstr;
9863           litval &= (~mask) & 0xff;
9864           emitPtrByteGet (rname, p_type, FALSE);
9865           if ((mask|litval)!=0xff)
9866             emitcode ("anl","a,#!constbyte", mask);
9867           if (litval)
9868             emitcode ("orl","a,#!constbyte", litval);
9869         }
9870       else
9871         {
9872           if ((blen==1) && (p_type!=GPOINTER))
9873             {
9874               /* Case with a bitfield length == 1 and no generic pointer
9875               */
9876               if (AOP_TYPE (right) == AOP_CRY)
9877                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9878               else
9879                 {
9880                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9881                   emitcode ("rrc","a");
9882                 }
9883               emitPtrByteGet (rname, p_type, FALSE);
9884               emitcode ("mov","acc.%d,c",bstr);
9885             }
9886           else
9887             {
9888               /* Case with a bitfield length < 8 and arbitrary source
9889               */
9890               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9891               /* shift and mask source value */
9892               AccLsh (bstr);
9893               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9894
9895               /* transfer A to B and get next byte */
9896               emitPtrByteGet (rname, p_type, TRUE);
9897
9898               emitcode ("anl", "a,#!constbyte", mask);
9899               emitcode ("orl", "a,b");
9900               if (p_type == GPOINTER)
9901                 emitcode ("pop", "b");
9902            }
9903         }
9904
9905       emitPtrByteSet (rname, p_type, "a");
9906       return;
9907     }
9908
9909   /* Bit length is greater than 7 bits. In this case, copy  */
9910   /* all except the partial byte at the end                 */
9911   for (rlen=blen;rlen>=8;rlen-=8)
9912     {
9913       emitPtrByteSet (rname, p_type, 
9914                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9915       if (rlen>8)
9916         emitcode ("inc", "%s", rname);
9917     }
9918
9919   /* If there was a partial byte at the end */
9920   if (rlen)
9921     {
9922       mask = (((unsigned char) -1 << rlen) & 0xff);
9923       
9924       if (AOP_TYPE (right) == AOP_LIT)
9925         {
9926           /* Case with partial byte and literal source
9927           */
9928           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9929           litval >>= (blen-rlen);
9930           litval &= (~mask) & 0xff;
9931           emitPtrByteGet (rname, p_type, FALSE);
9932           if ((mask|litval)!=0xff)
9933             emitcode ("anl","a,#!constbyte", mask);
9934           if (litval)
9935             emitcode ("orl","a,#!constbyte", litval);
9936         }
9937       else
9938         {
9939           /* Case with partial byte and arbitrary source
9940           */
9941           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9942           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9943
9944           /* transfer A to B and get next byte */
9945           emitPtrByteGet (rname, p_type, TRUE);
9946
9947           emitcode ("anl", "a,#!constbyte", mask);
9948           emitcode ("orl", "a,b");
9949           if (p_type == GPOINTER)
9950             emitcode ("pop", "b");
9951         }
9952       emitPtrByteSet (rname, p_type, "a");
9953     }
9954
9955 }
9956
9957
9958 /*-----------------------------------------------------------------*/
9959 /* genDataPointerSet - remat pointer to data space                 */
9960 /*-----------------------------------------------------------------*/
9961 static void
9962 genDataPointerSet (operand * right,
9963                    operand * result,
9964                    iCode * ic)
9965 {
9966   int size, offset = 0;
9967   char *l, buff[256];
9968
9969   aopOp (right, ic, FALSE, FALSE);
9970
9971   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9972   size = AOP_SIZE (right);
9973   while (size--)
9974     {
9975       if (offset)
9976         {
9977             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9978         }
9979       else
9980         {
9981             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9982         }
9983         
9984       emitcode ("mov", "%s,%s", buff,
9985                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9986     }
9987
9988   freeAsmop (right, NULL, ic, TRUE);
9989   freeAsmop (result, NULL, ic, TRUE);
9990 }
9991
9992 /*-----------------------------------------------------------------*/
9993 /* genNearPointerSet - emitcode for near pointer put                */
9994 /*-----------------------------------------------------------------*/
9995 static void
9996 genNearPointerSet (operand * right,
9997                    operand * result,
9998                    iCode * ic,
9999                    iCode * pi)
10000 {
10001   asmop *aop = NULL;
10002   char *rname, *l;
10003   sym_link *retype, *letype;
10004   sym_link *ptype = operandType (result);
10005
10006   retype = getSpec (operandType (right));
10007   letype = getSpec (ptype);
10008
10009   aopOp (result, ic, FALSE, FALSE);
10010
10011   /* if the result is rematerializable &
10012      in data space & not a bit variable */
10013   if (AOP_TYPE (result) == AOP_IMMD &&
10014       DCL_TYPE (ptype) == POINTER &&
10015       !IS_BITVAR (retype) &&
10016       !IS_BITVAR (letype))
10017     {
10018       genDataPointerSet (right, result, ic);
10019       return;
10020     }
10021
10022   /* if the value is already in a pointer register
10023      then don't need anything more */
10024   if (!AOP_INPREG (AOP (result)))
10025     {
10026       /* otherwise get a free pointer register */
10027       regs *preg;
10028         
10029       aop = newAsmop (0);
10030       preg = getFreePtr (ic, &aop, FALSE);
10031       emitcode ("mov", "%s,%s",
10032                 preg->name,
10033                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10034       rname = preg->name;
10035     }
10036   else
10037     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10038
10039   aopOp (right, ic, FALSE, FALSE);
10040
10041   /* if bitfield then unpack the bits */
10042   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10043     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10044   else
10045     {
10046       /* we have can just get the values */
10047       int size = AOP_SIZE (right);
10048       int offset = 0;
10049
10050       while (size--)
10051         {
10052           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10053           if (*l == '@')
10054             {
10055               MOVA (l);
10056               emitcode ("mov", "@%s,a", rname);
10057             }
10058           else
10059             emitcode ("mov", "@%s,%s", rname, l);
10060           if (size || pi)
10061             emitcode ("inc", "%s", rname);
10062           offset++;
10063         }
10064     }
10065
10066   /* now some housekeeping stuff */
10067   if (aop)
10068     {
10069       /* we had to allocate for this iCode */
10070       if (pi) aopPut (AOP (result),rname,0);
10071       freeAsmop (NULL, aop, ic, TRUE);
10072     }
10073   else
10074     {
10075       /* we did not allocate which means left
10076          already in a pointer register, then
10077          if size > 0 && this could be used again
10078          we have to point it back to where it
10079          belongs */
10080       if (AOP_SIZE (right) > 1 &&
10081           !OP_SYMBOL (result)->remat &&
10082           (OP_SYMBOL (result)->liveTo > ic->seq ||
10083            ic->depth) &&
10084           !pi)
10085         {
10086           int size = AOP_SIZE (right) - 1;
10087           while (size--)
10088             emitcode ("dec", "%s", rname);
10089         }
10090     }
10091
10092   /* done */
10093   if (pi) pi->generated = 1;
10094   freeAsmop (result, NULL, ic, TRUE);
10095   freeAsmop (right, NULL, ic, TRUE);
10096
10097
10098 }
10099
10100 /*-----------------------------------------------------------------*/
10101 /* genPagedPointerSet - emitcode for Paged pointer put             */
10102 /*-----------------------------------------------------------------*/
10103 static void
10104 genPagedPointerSet (operand * right,
10105                     operand * result,
10106                     iCode * ic,
10107                     iCode *pi)
10108 {
10109   asmop *aop = NULL;
10110   char *rname;
10111   sym_link *retype, *letype;
10112
10113   retype = getSpec (operandType (right));
10114   letype = getSpec (operandType (result));
10115
10116   aopOp (result, ic, FALSE, FALSE);
10117
10118   /* if the value is already in a pointer register
10119      then don't need anything more */
10120   if (!AOP_INPREG (AOP (result)))
10121     {
10122       /* otherwise get a free pointer register */
10123       regs *preg;
10124         
10125       aop = newAsmop (0);
10126       preg = getFreePtr (ic, &aop, FALSE);
10127       emitcode ("mov", "%s,%s",
10128                 preg->name,
10129                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10130       rname = preg->name;
10131     }
10132   else
10133     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10134
10135   aopOp (right, ic, FALSE, FALSE);
10136
10137   /* if bitfield then unpack the bits */
10138   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10139     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10140   else
10141     {
10142       /* we have can just get the values */
10143       int size = AOP_SIZE (right);
10144       int offset = 0;
10145
10146       while (size--)
10147         {
10148           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10149
10150           emitcode ("movx", "@%s,a", rname);
10151
10152           if (size || pi)
10153             emitcode ("inc", "%s", rname);
10154
10155           offset++;
10156         }
10157     }
10158
10159   /* now some housekeeping stuff */
10160   if (aop)
10161     {
10162       if (pi) aopPut (AOP (result),rname,0);
10163       /* we had to allocate for this iCode */
10164       freeAsmop (NULL, aop, ic, TRUE);
10165     }
10166   else
10167     {
10168       /* we did not allocate which means left
10169          already in a pointer register, then
10170          if size > 0 && this could be used again
10171          we have to point it back to where it
10172          belongs */
10173       if (AOP_SIZE (right) > 1 &&
10174           !OP_SYMBOL (result)->remat &&
10175           (OP_SYMBOL (result)->liveTo > ic->seq ||
10176            ic->depth) &&
10177           !pi)
10178         {
10179           int size = AOP_SIZE (right) - 1;
10180           while (size--)
10181             emitcode ("dec", "%s", rname);
10182         }
10183     }
10184
10185   /* done */
10186   if (pi) pi->generated = 1;
10187   freeAsmop (result, NULL, ic, TRUE);
10188   freeAsmop (right, NULL, ic, TRUE);
10189
10190
10191 }
10192
10193 /*-----------------------------------------------------------------*/
10194 /* genFarPointerSet - set value from far space                     */
10195 /*-----------------------------------------------------------------*/
10196 static void
10197 genFarPointerSet (operand * right,
10198                   operand * result, iCode * ic, iCode *pi)
10199 {
10200   int size, offset, dopi=1;
10201   sym_link *retype = getSpec (operandType (right));
10202   sym_link *letype = getSpec (operandType (result));
10203
10204   aopOp (result, ic, FALSE, FALSE);
10205
10206   /* if the operand is already in dptr
10207      then we do nothing else we move the value to dptr */
10208   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10209     {
10210       /* if this is remateriazable */
10211       if (AOP_TYPE (result) == AOP_IMMD)
10212         emitcode ("mov", "dptr,%s", 
10213                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10214       else
10215         {
10216           /* we need to get it byte by byte */
10217           _startLazyDPSEvaluation ();
10218           if (AOP_TYPE (result) != AOP_DPTR)
10219             {
10220               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10221               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10222               if (options.model == MODEL_FLAT24)
10223                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10224             }
10225           else
10226             {
10227               /* We need to generate a load to DPTR indirect through DPTR. */
10228               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10229                 
10230               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10231               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10232               if (options.model == MODEL_FLAT24)
10233                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10234               emitcode ("pop", "dph");
10235               emitcode ("pop", "dpl");
10236               dopi=0;
10237             }
10238           _endLazyDPSEvaluation ();
10239         }
10240     }
10241   /* so dptr know contains the address */
10242   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10243
10244   /* if bit then unpack */
10245   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10246       if (AOP_INDPTRn(result)) {
10247           genSetDPTR(AOP(result)->aopu.dptr);
10248       }
10249       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10250       if (AOP_INDPTRn(result)) {
10251           genSetDPTR(0);
10252       }
10253   } else {
10254       size = AOP_SIZE (right);
10255       offset = 0;
10256       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10257           while (size--) {
10258               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10259               
10260               genSetDPTR(AOP(result)->aopu.dptr);
10261               emitcode ("movx", "@dptr,a");
10262               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10263                   emitcode ("inc", "dptr");
10264               genSetDPTR (0);
10265           }
10266       } else {
10267           _startLazyDPSEvaluation ();
10268           while (size--) {
10269               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10270               
10271               if (AOP_INDPTRn(result)) {
10272                   genSetDPTR(AOP(result)->aopu.dptr);
10273               } else {
10274                   genSetDPTR (0);
10275               }
10276               _flushLazyDPS ();
10277               
10278               emitcode ("movx", "@dptr,a");
10279               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10280                   emitcode ("inc", "dptr");
10281           }
10282           _endLazyDPSEvaluation ();
10283       }
10284   }
10285   
10286   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10287       if (!AOP_INDPTRn(result)) {
10288           _startLazyDPSEvaluation ();
10289           
10290           aopPut (AOP(result),"dpl",0);
10291           aopPut (AOP(result),"dph",1);
10292           if (options.model == MODEL_FLAT24)
10293               aopPut (AOP(result),"dpx",2);
10294
10295           _endLazyDPSEvaluation ();
10296       }
10297       pi->generated=1;
10298   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10299              AOP_SIZE(right) > 1 &&
10300              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10301       
10302       size = AOP_SIZE (right) - 1;
10303       if (AOP_INDPTRn(result)) {
10304           genSetDPTR(AOP(result)->aopu.dptr);
10305       } 
10306       while (size--) emitcode ("lcall","__decdptr");
10307       if (AOP_INDPTRn(result)) {
10308           genSetDPTR(0);
10309       }
10310   }
10311   freeAsmop (result, NULL, ic, TRUE);
10312   freeAsmop (right, NULL, ic, TRUE);
10313 }
10314
10315 /*-----------------------------------------------------------------*/
10316 /* genGenPointerSet - set value from generic pointer space         */
10317 /*-----------------------------------------------------------------*/
10318 static void
10319 genGenPointerSet (operand * right,
10320                   operand * result, iCode * ic, iCode *pi)
10321 {
10322   int size, offset;
10323   sym_link *retype = getSpec (operandType (right));
10324   sym_link *letype = getSpec (operandType (result));
10325
10326   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10327
10328   /* if the operand is already in dptr
10329      then we do nothing else we move the value to dptr */
10330   if (AOP_TYPE (result) != AOP_STR)
10331     {
10332       _startLazyDPSEvaluation ();
10333       /* if this is remateriazable */
10334       if (AOP_TYPE (result) == AOP_IMMD)
10335         {
10336           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10337           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10338           {
10339               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10340           }
10341           else
10342           {
10343               emitcode ("mov", 
10344                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10345           }
10346         }
10347       else
10348         {                       /* we need to get it byte by byte */
10349           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10350           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10351           if (options.model == MODEL_FLAT24) {
10352             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10353             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10354           } else {
10355             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10356           }
10357         }
10358       _endLazyDPSEvaluation ();
10359     }
10360   /* so dptr + b now contains the address */
10361   _G.bInUse++;
10362   aopOp (right, ic, FALSE, TRUE);
10363   _G.bInUse--;
10364     
10365
10366   /* if bit then unpack */
10367   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10368     {
10369         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10370     }
10371   else
10372     {
10373         size = AOP_SIZE (right);
10374         offset = 0;
10375
10376         _startLazyDPSEvaluation ();
10377         while (size--)
10378         {
10379             if (size)
10380             {
10381                 // Set two bytes at a time, passed in _AP & A.
10382                 // dptr will be incremented ONCE by __gptrputWord.
10383                 //
10384                 // Note: any change here must be coordinated
10385                 // with the implementation of __gptrputWord
10386                 // in device/lib/_gptrput.c
10387                 emitcode("mov", "_ap, %s", 
10388                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10389                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10390                 
10391                 genSetDPTR (0);
10392                 _flushLazyDPS ();
10393                 emitcode ("lcall", "__gptrputWord");
10394                 size--;
10395             }
10396             else
10397             {
10398                 // Only one byte to put.
10399                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10400
10401                 genSetDPTR (0);
10402                 _flushLazyDPS ();               
10403                 emitcode ("lcall", "__gptrput");
10404             }
10405             
10406             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10407             {
10408                 emitcode ("inc", "dptr");
10409             }
10410         }
10411         _endLazyDPSEvaluation ();
10412     }
10413
10414   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10415       _startLazyDPSEvaluation ();
10416       
10417       aopPut (AOP(result),"dpl",0);
10418       aopPut (AOP(result),"dph",1);
10419       if (options.model == MODEL_FLAT24) {
10420           aopPut (AOP(result),"dpx",2);
10421           aopPut (AOP(result),"b",3);
10422       } else {
10423           aopPut (AOP(result),"b",2);
10424       }
10425       _endLazyDPSEvaluation ();
10426       
10427       pi->generated=1;
10428   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10429              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10430       
10431       size = AOP_SIZE (right) - 1;
10432       while (size--) emitcode ("lcall","__decdptr");
10433   }
10434   freeAsmop (result, NULL, ic, TRUE);
10435   freeAsmop (right, NULL, ic, TRUE);
10436 }
10437
10438 /*-----------------------------------------------------------------*/
10439 /* genPointerSet - stores the value into a pointer location        */
10440 /*-----------------------------------------------------------------*/
10441 static void
10442 genPointerSet (iCode * ic, iCode *pi)
10443 {
10444   operand *right, *result;
10445   sym_link *type, *etype;
10446   int p_type;
10447
10448   D (emitcode (";", "genPointerSet "););
10449
10450   right = IC_RIGHT (ic);
10451   result = IC_RESULT (ic);
10452
10453   /* depending on the type of pointer we need to
10454      move it to the correct pointer register */
10455   type = operandType (result);
10456   etype = getSpec (type);
10457   /* if left is of type of pointer then it is simple */
10458   if (IS_PTR (type) && !IS_FUNC (type->next))
10459     {
10460       p_type = DCL_TYPE (type);
10461     }
10462   else
10463     {
10464       /* we have to go by the storage class */
10465       p_type = PTR_TYPE (SPEC_OCLS (etype));
10466     }
10467   /* special case when cast remat */
10468   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10469       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10470           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10471           type = operandType (result);
10472           p_type = DCL_TYPE (type);
10473   }
10474
10475   /* now that we have the pointer type we assign
10476      the pointer values */
10477   switch (p_type)
10478     {
10479
10480     case POINTER:
10481     case IPOINTER:
10482       genNearPointerSet (right, result, ic, pi);
10483       break;
10484
10485     case PPOINTER:
10486       genPagedPointerSet (right, result, ic, pi);
10487       break;
10488
10489     case FPOINTER:
10490       genFarPointerSet (right, result, ic, pi);
10491       break;
10492
10493     case GPOINTER:
10494       genGenPointerSet (right, result, ic, pi);
10495       break;
10496
10497     default:
10498       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10499               "genPointerSet: illegal pointer type");
10500     }
10501
10502 }
10503
10504 /*-----------------------------------------------------------------*/
10505 /* genIfx - generate code for Ifx statement                        */
10506 /*-----------------------------------------------------------------*/
10507 static void
10508 genIfx (iCode * ic, iCode * popIc)
10509 {
10510   operand *cond = IC_COND (ic);
10511   int isbit = 0;
10512
10513   D (emitcode (";", "genIfx "););
10514
10515   aopOp (cond, ic, FALSE, FALSE);
10516
10517   /* get the value into acc */
10518   if (AOP_TYPE (cond) != AOP_CRY)
10519     {
10520         toBoolean (cond);
10521     }
10522   else
10523     {
10524         isbit = 1;
10525     }
10526     
10527   /* the result is now in the accumulator */
10528   freeAsmop (cond, NULL, ic, TRUE);
10529
10530   /* if there was something to be popped then do it */
10531   if (popIc)
10532     genIpop (popIc);
10533
10534   /* if the condition is  a bit variable */
10535   if (isbit && IS_ITEMP (cond) &&
10536       SPIL_LOC (cond))
10537     {
10538         genIfxJump (ic, SPIL_LOC (cond)->rname);
10539     }
10540   else if (isbit && !IS_ITEMP (cond))
10541     {
10542         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10543     }
10544   else
10545     {
10546         genIfxJump (ic, "a");
10547     }
10548
10549   ic->generated = 1;
10550 }
10551
10552 /*-----------------------------------------------------------------*/
10553 /* genAddrOf - generates code for address of                       */
10554 /*-----------------------------------------------------------------*/
10555 static void
10556 genAddrOf (iCode * ic)
10557 {
10558   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10559   int size, offset;
10560
10561   D (emitcode (";", "genAddrOf ");
10562     );
10563
10564   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10565
10566   /* if the operand is on the stack then we
10567      need to get the stack offset of this
10568      variable */
10569   if (sym->onStack) {
10570       
10571       /* if 10 bit stack */
10572       if (options.stack10bit) {
10573           char buff[10];
10574           int  offset;
10575           
10576           tsprintf(buff, sizeof(buff), 
10577                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10578           /* if it has an offset then we need to compute it */
10579 /*        emitcode ("subb", "a,#!constbyte", */
10580 /*                  -((sym->stack < 0) ? */
10581 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10582 /*                    ((short) sym->stack)) & 0xff); */
10583 /*        emitcode ("mov","b,a"); */
10584 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10585 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10586 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10587           if (sym->stack) {
10588               emitcode ("mov", "a,_bpx");
10589               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10590                                              ((char) (sym->stack - _G.nRegsSaved)) :
10591                                              ((char) sym->stack )) & 0xff);
10592               emitcode ("mov", "b,a");
10593               emitcode ("mov", "a,_bpx+1");
10594               
10595               offset = (((sym->stack < 0) ? 
10596                          ((short) (sym->stack - _G.nRegsSaved)) :
10597                          ((short) sym->stack )) >> 8) & 0xff;
10598           
10599               emitcode ("addc","a,#!constbyte", offset);
10600
10601               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10602               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10603               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10604           } else {
10605               /* we can just move _bp */
10606               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10607               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10608               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10609           }       
10610       } else {
10611           /* if it has an offset then we need to compute it */
10612           if (sym->stack) {
10613               emitcode ("mov", "a,_bp");
10614               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10615               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10616           } else {
10617               /* we can just move _bp */
10618               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10619           }
10620           /* fill the result with zero */
10621           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10622           
10623           
10624           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10625               fprintf (stderr,
10626                        "*** warning: pointer to stack var truncated.\n");
10627           }
10628
10629           offset = 1;
10630           while (size--) {
10631               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10632           }      
10633       }
10634       goto release;
10635   }
10636
10637   /* object not on stack then we need the name */
10638   size = AOP_SIZE (IC_RESULT (ic));
10639   offset = 0;
10640
10641   while (size--)
10642     {
10643       char s[SDCC_NAME_MAX];
10644       if (offset) {
10645           switch (offset) {
10646           case 1:
10647               tsprintf(s, sizeof(s), "#!his",sym->rname);
10648               break;
10649           case 2:
10650               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10651               break;
10652           case 3:
10653               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10654               break;
10655           default: /* should not need this (just in case) */
10656               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10657                        sym->rname,
10658                        offset * 8);
10659           }
10660       } 
10661       else
10662       {
10663           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10664       }
10665         
10666       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10667     }
10668
10669 release:
10670   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10671
10672 }
10673
10674 #if 0 // obsolete, and buggy for != xdata
10675 /*-----------------------------------------------------------------*/
10676 /* genArrayInit - generates code for address of                       */
10677 /*-----------------------------------------------------------------*/
10678 static void
10679 genArrayInit (iCode * ic)
10680 {
10681     literalList *iLoop;
10682     int         ix, count;
10683     int         elementSize = 0, eIndex;
10684     unsigned    val, lastVal;
10685     sym_link    *type;
10686     operand     *left=IC_LEFT(ic);
10687     
10688     D (emitcode (";", "genArrayInit "););
10689
10690     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10691     
10692     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10693     {
10694         // Load immediate value into DPTR.
10695         emitcode("mov", "dptr, %s",
10696              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10697     }
10698     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10699     {
10700 #if 0
10701       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10702               "Unexpected operand to genArrayInit.\n");
10703       exit(1);
10704 #else
10705       // a regression because of SDCCcse.c:1.52
10706       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10707       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10708       if (options.model == MODEL_FLAT24)
10709         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10710 #endif
10711     }
10712     
10713     type = operandType(IC_LEFT(ic));
10714     
10715     if (type && type->next)
10716     {
10717         elementSize = getSize(type->next);
10718     }
10719     else
10720     {
10721         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10722                                 "can't determine element size in genArrayInit.\n");
10723         exit(1);
10724     }
10725     
10726     iLoop = IC_ARRAYILIST(ic);
10727     lastVal = 0xffff;
10728     
10729     while (iLoop)
10730     {
10731         bool firstpass = TRUE;
10732         
10733         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10734                  iLoop->count, (int)iLoop->literalValue, elementSize);
10735         
10736         ix = iLoop->count;
10737         
10738         while (ix)
10739         {
10740             symbol *tlbl = NULL;
10741             
10742             count = ix > 256 ? 256 : ix;
10743             
10744             if (count > 1)
10745             {
10746                 tlbl = newiTempLabel (NULL);
10747                 if (firstpass || (count & 0xff))
10748                 {
10749                     emitcode("mov", "b, #!constbyte", count & 0xff);
10750                 }
10751                 
10752                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10753             }
10754             
10755             firstpass = FALSE;
10756                 
10757             for (eIndex = 0; eIndex < elementSize; eIndex++)
10758             {
10759                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10760                 if (val != lastVal)
10761                 {
10762                     emitcode("mov", "a, #!constbyte", val);
10763                     lastVal = val;
10764                 }
10765                 
10766                 emitcode("movx", "@dptr, a");
10767                 emitcode("inc", "dptr");
10768             }
10769             
10770             if (count > 1)
10771             {
10772                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10773             }
10774             
10775             ix -= count;
10776         }
10777         
10778         iLoop = iLoop->next;
10779     }
10780     
10781     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10782 }
10783 #endif
10784
10785 /*-----------------------------------------------------------------*/
10786 /* genFarFarAssign - assignment when both are in far space         */
10787 /*-----------------------------------------------------------------*/
10788 static void
10789 genFarFarAssign (operand * result, operand * right, iCode * ic)
10790 {
10791   int size = AOP_SIZE (right);
10792   int offset = 0;
10793   symbol *rSym = NULL;
10794
10795   if (size == 1)
10796   {
10797       /* quick & easy case. */
10798       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10799       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10800       freeAsmop (right, NULL, ic, FALSE);
10801       /* now assign DPTR to result */
10802       _G.accInUse++;
10803       aopOp(result, ic, FALSE, FALSE);
10804       _G.accInUse--;
10805       aopPut(AOP(result), "a", 0);
10806       freeAsmop(result, NULL, ic, FALSE);
10807       return;
10808   }
10809   
10810   /* See if we've got an underlying symbol to abuse. */
10811   if (IS_SYMOP(result) && OP_SYMBOL(result))
10812   {
10813       if (IS_TRUE_SYMOP(result))
10814       {
10815           rSym = OP_SYMBOL(result);
10816       }
10817       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10818       {
10819           rSym = OP_SYMBOL(result)->usl.spillLoc;
10820       }
10821   }
10822              
10823   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10824   {
10825       /* We can use the '390 auto-toggle feature to good effect here. */
10826       
10827       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10828       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10829       emitcode ("mov", "dptr,#%s", rSym->rname); 
10830       /* DP2 = result, DP1 = right, DP1 is current. */
10831       while (size)
10832       {
10833           emitcode("movx", "a,@dptr");
10834           emitcode("movx", "@dptr,a");
10835           if (--size)
10836           {
10837                emitcode("inc", "dptr");
10838                emitcode("inc", "dptr");
10839           }
10840       }
10841       emitcode("mov", "dps,#0");
10842       freeAsmop (right, NULL, ic, FALSE);
10843 #if 0
10844 some alternative code for processors without auto-toggle
10845 no time to test now, so later well put in...kpb
10846         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10847         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10848         emitcode ("mov", "dptr,#%s", rSym->rname); 
10849         /* DP2 = result, DP1 = right, DP1 is current. */
10850         while (size)
10851         {
10852           --size;
10853           emitcode("movx", "a,@dptr");
10854           if (size)
10855             emitcode("inc", "dptr");
10856           emitcode("inc", "dps");
10857           emitcode("movx", "@dptr,a");
10858           if (size)
10859             emitcode("inc", "dptr");
10860           emitcode("inc", "dps");
10861         }
10862         emitcode("mov", "dps,#0");
10863         freeAsmop (right, NULL, ic, FALSE);
10864 #endif
10865   }
10866   else
10867   {
10868       D (emitcode (";", "genFarFarAssign"););
10869       aopOp (result, ic, TRUE, TRUE);
10870
10871       _startLazyDPSEvaluation ();
10872       
10873       while (size--)
10874         {
10875           aopPut (AOP (result),
10876                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10877           offset++;
10878         }
10879       _endLazyDPSEvaluation ();
10880       freeAsmop (result, NULL, ic, FALSE);
10881       freeAsmop (right, NULL, ic, FALSE);
10882   }
10883 }
10884
10885 /*-----------------------------------------------------------------*/
10886 /* genAssign - generate code for assignment                        */
10887 /*-----------------------------------------------------------------*/
10888 static void
10889 genAssign (iCode * ic)
10890 {
10891   operand *result, *right;
10892   int size, offset;
10893   unsigned long lit = 0L;
10894
10895   D (emitcode (";", "genAssign ");
10896     );
10897
10898   result = IC_RESULT (ic);
10899   right = IC_RIGHT (ic);
10900
10901   /* if they are the same */
10902   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10903     return;
10904
10905   aopOp (right, ic, FALSE, FALSE);
10906
10907   emitcode (";", "genAssign: resultIsFar = %s",
10908             isOperandInFarSpace (result) ?
10909             "TRUE" : "FALSE");
10910
10911   /* special case both in far space */
10912   if ((AOP_TYPE (right) == AOP_DPTR ||
10913        AOP_TYPE (right) == AOP_DPTR2) &&
10914   /* IS_TRUE_SYMOP(result)       && */
10915       isOperandInFarSpace (result))
10916     {
10917       genFarFarAssign (result, right, ic);
10918       return;
10919     }
10920
10921   aopOp (result, ic, TRUE, FALSE);
10922
10923   /* if they are the same registers */
10924   if (sameRegs (AOP (right), AOP (result)))
10925     goto release;
10926
10927   /* if the result is a bit */
10928   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10929     {
10930       /* if the right size is a literal then
10931          we know what the value is */
10932       if (AOP_TYPE (right) == AOP_LIT)
10933         {
10934           if (((int) operandLitValue (right)))
10935             aopPut (AOP (result), one, 0);
10936           else
10937             aopPut (AOP (result), zero, 0);
10938           goto release;
10939         }
10940
10941       /* the right is also a bit variable */
10942       if (AOP_TYPE (right) == AOP_CRY)
10943         {
10944           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10945           aopPut (AOP (result), "c", 0);
10946           goto release;
10947         }
10948
10949       /* we need to or */
10950       toBoolean (right);
10951       aopPut (AOP (result), "a", 0);
10952       goto release;
10953     }
10954
10955   /* bit variables done */
10956   /* general case */
10957   size = AOP_SIZE (result);
10958   offset = 0;
10959   if (AOP_TYPE (right) == AOP_LIT)
10960     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10961
10962   if ((size > 1) &&
10963       (AOP_TYPE (result) != AOP_REG) &&
10964       (AOP_TYPE (right) == AOP_LIT) &&
10965       !IS_FLOAT (operandType (right)))
10966     {
10967       _startLazyDPSEvaluation ();
10968       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10969         {
10970           aopPut (AOP (result),
10971                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10972                   offset);
10973           offset++;
10974           size--;
10975         }
10976       /* And now fill the rest with zeros. */
10977       if (size)
10978         {
10979           emitcode ("clr", "a");
10980         }
10981       while (size--)
10982         {
10983           aopPut (AOP (result), "a", offset++);
10984         }
10985       _endLazyDPSEvaluation ();
10986     }
10987   else
10988     {
10989       _startLazyDPSEvaluation ();
10990       while (size--)
10991         {
10992           aopPut (AOP (result),
10993                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10994                   offset);
10995           offset++;
10996         }
10997       _endLazyDPSEvaluation ();
10998     }
10999
11000 release:
11001   freeAsmop (right, NULL, ic, FALSE);
11002   freeAsmop (result, NULL, ic, TRUE);
11003 }
11004
11005 /*-----------------------------------------------------------------*/
11006 /* genJumpTab - generates code for jump table                      */
11007 /*-----------------------------------------------------------------*/
11008 static void
11009 genJumpTab (iCode * ic)
11010 {
11011   symbol *jtab;
11012   char *l;
11013
11014   D (emitcode (";", "genJumpTab ");
11015     );
11016
11017   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11018   /* get the condition into accumulator */
11019   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11020   MOVA (l);
11021   /* multiply by four! */
11022   emitcode ("add", "a,acc");
11023   emitcode ("add", "a,acc");
11024   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11025
11026   jtab = newiTempLabel (NULL);
11027   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11028   emitcode ("jmp", "@a+dptr");
11029   emitcode ("", "!tlabeldef", jtab->key + 100);
11030   /* now generate the jump labels */
11031   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11032        jtab = setNextItem (IC_JTLABELS (ic)))
11033     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11034
11035 }
11036
11037 /*-----------------------------------------------------------------*/
11038 /* genCast - gen code for casting                                  */
11039 /*-----------------------------------------------------------------*/
11040 static void
11041 genCast (iCode * ic)
11042 {
11043   operand *result = IC_RESULT (ic);
11044   sym_link *ctype = operandType (IC_LEFT (ic));
11045   sym_link *rtype = operandType (IC_RIGHT (ic));
11046   operand *right = IC_RIGHT (ic);
11047   int size, offset;
11048
11049   D (emitcode (";", "genCast "););
11050
11051   /* if they are equivalent then do nothing */
11052   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11053     return;
11054
11055   aopOp (right, ic, FALSE, FALSE);
11056   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11057
11058   /* if the result is a bit */
11059   if (IS_BITVAR (OP_SYMBOL (result)->type)
11060       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11061     {
11062       /* if the right size is a literal then
11063          we know what the value is */
11064       if (AOP_TYPE (right) == AOP_LIT)
11065         {
11066           if (((int) operandLitValue (right)))
11067             aopPut (AOP (result), one, 0);
11068           else
11069             aopPut (AOP (result), zero, 0);
11070
11071           goto release;
11072         }
11073
11074       /* the right is also a bit variable */
11075       if (AOP_TYPE (right) == AOP_CRY)
11076         {
11077           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11078           aopPut (AOP (result), "c", 0);
11079           goto release;
11080         }
11081
11082       /* we need to or */
11083       toBoolean (right);
11084       aopPut (AOP (result), "a", 0);
11085       goto release;
11086     }
11087
11088   /* if they are the same size : or less */
11089   if (AOP_SIZE (result) <= AOP_SIZE (right))
11090     {
11091
11092       /* if they are in the same place */
11093       if (sameRegs (AOP (right), AOP (result)))
11094         goto release;
11095
11096       /* if they in different places then copy */
11097       size = AOP_SIZE (result);
11098       offset = 0;
11099       _startLazyDPSEvaluation ();
11100       while (size--)
11101         {
11102           aopPut (AOP (result),
11103                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11104                   offset);
11105           offset++;
11106         }
11107       _endLazyDPSEvaluation ();
11108       goto release;
11109     }
11110
11111
11112   /* if the result is of type pointer */
11113   if (IS_PTR (ctype))
11114     {
11115
11116       int p_type;
11117       sym_link *type = operandType (right);
11118
11119       /* pointer to generic pointer */
11120       if (IS_GENPTR (ctype))
11121         {
11122           if (IS_PTR (type))
11123             {
11124               p_type = DCL_TYPE (type);
11125             }
11126           else
11127             {
11128 #if OLD_CAST_BEHAVIOR
11129               /* KV: we are converting a non-pointer type to
11130                * a generic pointer. This (ifdef'd out) code
11131                * says that the resulting generic pointer
11132                * should have the same class as the storage
11133                * location of the non-pointer variable.
11134                *
11135                * For example, converting an int (which happens
11136                * to be stored in DATA space) to a pointer results
11137                * in a DATA generic pointer; if the original int
11138                * in XDATA space, so will be the resulting pointer.
11139                *
11140                * I don't like that behavior, and thus this change:
11141                * all such conversions will be forced to XDATA and
11142                * throw a warning. If you want some non-XDATA
11143                * type, or you want to suppress the warning, you
11144                * must go through an intermediate cast, like so:
11145                *
11146                * char _generic *gp = (char _xdata *)(intVar);
11147                */
11148               sym_link *etype = getSpec (type);
11149
11150               /* we have to go by the storage class */
11151               if (SPEC_OCLS (etype) != generic)
11152                 {
11153                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11154                 }
11155               else
11156 #endif
11157                 {
11158                   /* Converting unknown class (i.e. register variable)
11159                    * to generic pointer. This is not good, but
11160                    * we'll make a guess (and throw a warning).
11161                    */
11162                   p_type = FPOINTER;
11163                   werror (W_INT_TO_GEN_PTR_CAST);
11164                 }
11165             }
11166
11167           /* the first two bytes are known */
11168           size = GPTRSIZE - 1;
11169           offset = 0;
11170           _startLazyDPSEvaluation ();
11171           while (size--)
11172             {
11173               aopPut (AOP (result),
11174                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11175                       offset);
11176               offset++;
11177             }
11178           _endLazyDPSEvaluation ();
11179
11180           /* the last byte depending on type */
11181             {
11182                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11183                 char gpValStr[10];
11184             
11185                 if (gpVal == -1)
11186                 {
11187                     // pointerTypeToGPByte will have bitched.
11188                     exit(1);
11189                 }
11190             
11191                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11192                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11193             }
11194           goto release;
11195         }
11196
11197       /* just copy the pointers */
11198       size = AOP_SIZE (result);
11199       offset = 0;
11200       _startLazyDPSEvaluation ();
11201       while (size--)
11202         {
11203           aopPut (AOP (result),
11204                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11205                   offset);
11206           offset++;
11207         }
11208       _endLazyDPSEvaluation ();
11209       goto release;
11210     }
11211
11212   /* so we now know that the size of destination is greater
11213      than the size of the source */
11214   /* we move to result for the size of source */
11215   size = AOP_SIZE (right);
11216   offset = 0;
11217   _startLazyDPSEvaluation ();
11218   while (size--)
11219     {
11220       aopPut (AOP (result),
11221               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11222               offset);
11223       offset++;
11224     }
11225   _endLazyDPSEvaluation ();
11226
11227   /* now depending on the sign of the source && destination */
11228   size = AOP_SIZE (result) - AOP_SIZE (right);
11229   /* if unsigned or not an integral type */
11230   /* also, if the source is a bit, we don't need to sign extend, because
11231    * it can't possibly have set the sign bit.
11232    */
11233   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11234     {
11235       while (size--)
11236         {
11237           aopPut (AOP (result), zero, offset++);
11238         }
11239     }
11240   else
11241     {
11242       /* we need to extend the sign :{ */
11243       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11244                         FALSE, FALSE, NULL));
11245       emitcode ("rlc", "a");
11246       emitcode ("subb", "a,acc");
11247       while (size--)
11248         aopPut (AOP (result), "a", offset++);
11249     }
11250
11251   /* we are done hurray !!!! */
11252
11253 release:
11254   freeAsmop (right, NULL, ic, TRUE);
11255   freeAsmop (result, NULL, ic, TRUE);
11256
11257 }
11258
11259 /*-----------------------------------------------------------------*/
11260 /* genDjnz - generate decrement & jump if not zero instrucion      */
11261 /*-----------------------------------------------------------------*/
11262 static int
11263 genDjnz (iCode * ic, iCode * ifx)
11264 {
11265   symbol *lbl, *lbl1;
11266   if (!ifx)
11267     return 0;
11268
11269   /* if the if condition has a false label
11270      then we cannot save */
11271   if (IC_FALSE (ifx))
11272     return 0;
11273
11274   /* if the minus is not of the form
11275      a = a - 1 */
11276   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11277       !IS_OP_LITERAL (IC_RIGHT (ic)))
11278     return 0;
11279
11280   if (operandLitValue (IC_RIGHT (ic)) != 1)
11281     return 0;
11282
11283   /* if the size of this greater than one then no
11284      saving */
11285   if (getSize (operandType (IC_RESULT (ic))) > 1)
11286     return 0;
11287
11288   /* otherwise we can save BIG */
11289   D(emitcode(";", "genDjnz"););
11290
11291   lbl = newiTempLabel (NULL);
11292   lbl1 = newiTempLabel (NULL);
11293
11294   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11295
11296   if (AOP_NEEDSACC(IC_RESULT(ic)))
11297   {
11298       /* If the result is accessed indirectly via
11299        * the accumulator, we must explicitly write
11300        * it back after the decrement.
11301        */
11302       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11303       
11304       if (strcmp(rByte, "a"))
11305       {
11306            /* Something is hopelessly wrong */
11307            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11308                    __FILE__, __LINE__);
11309            /* We can just give up; the generated code will be inefficient,
11310             * but what the hey.
11311             */
11312            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11313            return 0;
11314       }
11315       emitcode ("dec", "%s", rByte);
11316       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11317       emitcode ("jnz", "!tlabel", lbl->key + 100);
11318   }
11319   else if (IS_AOP_PREG (IC_RESULT (ic)))
11320     {
11321       emitcode ("dec", "%s",
11322                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11323       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11324       emitcode ("jnz", "!tlabel", lbl->key + 100);
11325     }
11326   else
11327     {
11328       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11329                 lbl->key + 100);
11330     }
11331   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11332   emitcode ("", "!tlabeldef", lbl->key + 100);
11333   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11334   emitcode ("", "!tlabeldef", lbl1->key + 100);
11335
11336   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11337   ifx->generated = 1;
11338   return 1;
11339 }
11340
11341 /*-----------------------------------------------------------------*/
11342 /* genReceive - generate code for a receive iCode                  */
11343 /*-----------------------------------------------------------------*/
11344 static void
11345 genReceive (iCode * ic)
11346 {
11347     int size = getSize (operandType (IC_RESULT (ic)));
11348     int offset = 0;
11349     int rb1off ;
11350     
11351     D (emitcode (";", "genReceive "););
11352
11353     if (ic->argreg == 1) 
11354     {
11355         /* first parameter */
11356         if (AOP_IS_STR(IC_RESULT(ic)))
11357         {
11358             /* Nothing to do: it's already in the proper place. */
11359             return;
11360         }
11361         else
11362         {
11363             bool useDp2;
11364             
11365             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11366                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11367                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11368             
11369             _G.accInUse++;
11370             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11371             _G.accInUse--; 
11372             
11373             /* Sanity checking... */
11374             if (AOP_USESDPTR(IC_RESULT(ic)))
11375             {
11376                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11377                         "genReceive got unexpected DPTR.");
11378             }
11379             assignResultValue (IC_RESULT (ic));
11380         }
11381     } 
11382     else 
11383     { 
11384         /* second receive onwards */
11385         /* this gets a little tricky since unused recevies will be
11386          eliminated, we have saved the reg in the type field . and
11387          we use that to figure out which register to use */
11388         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11389         rb1off = ic->argreg;
11390         while (size--) 
11391         {
11392             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11393         }
11394     }
11395     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11396 }
11397
11398 /*-----------------------------------------------------------------*/
11399 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11400 /*-----------------------------------------------------------------*/
11401 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11402 {
11403     operand *from , *to , *count;
11404     symbol *lbl;
11405     bitVect *rsave;
11406     int i;
11407
11408     /* we know it has to be 3 parameters */
11409     assert (nparms == 3);
11410     
11411     rsave = newBitVect(16);
11412     /* save DPTR if it needs to be saved */
11413     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11414             if (bitVectBitValue(ic->rMask,i))
11415                     rsave = bitVectSetBit(rsave,i);
11416     }
11417     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11418                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11419     savermask(rsave);
11420     
11421     to = parms[0];
11422     from = parms[1];
11423     count = parms[2];
11424
11425     aopOp (from, ic->next, FALSE, FALSE);
11426
11427     /* get from into DPTR1 */
11428     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11429     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11430     if (options.model == MODEL_FLAT24) {
11431         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11432     }
11433
11434     freeAsmop (from, NULL, ic, FALSE);
11435     aopOp (to, ic, FALSE, FALSE);
11436     /* get "to" into DPTR */
11437     /* if the operand is already in dptr
11438        then we do nothing else we move the value to dptr */
11439     if (AOP_TYPE (to) != AOP_STR) {
11440         /* if already in DPTR then we need to push */
11441         if (AOP_TYPE(to) == AOP_DPTR) {
11442             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11443             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11444             if (options.model == MODEL_FLAT24)
11445                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11446             emitcode ("pop", "dph");
11447             emitcode ("pop", "dpl");        
11448         } else {
11449             _startLazyDPSEvaluation ();
11450             /* if this is remateriazable */
11451             if (AOP_TYPE (to) == AOP_IMMD) {
11452                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11453             } else {                    /* we need to get it byte by byte */
11454                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11455                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11456                 if (options.model == MODEL_FLAT24) {
11457                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11458                 }
11459             }
11460             _endLazyDPSEvaluation ();
11461         }
11462     }
11463     freeAsmop (to, NULL, ic, FALSE);
11464     _G.dptrInUse = _G.dptr1InUse = 1;
11465     aopOp (count, ic->next->next, FALSE,FALSE);
11466     lbl =newiTempLabel(NULL);
11467
11468     /* now for the actual copy */
11469     if (AOP_TYPE(count) == AOP_LIT && 
11470         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11471         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11472         if (fromc) {
11473             emitcode ("lcall","__bi_memcpyc2x_s");
11474         } else {
11475             emitcode ("lcall","__bi_memcpyx2x_s");
11476         }
11477         freeAsmop (count, NULL, ic, FALSE);
11478     } else {
11479         symbol *lbl1 = newiTempLabel(NULL);
11480         
11481         emitcode (";"," Auto increment but no djnz");
11482         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11483         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11484         freeAsmop (count, NULL, ic, FALSE);
11485         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11486         emitcode ("","!tlabeldef",lbl->key+100);
11487         if (fromc) {
11488             emitcode ("clr","a");
11489             emitcode ("movc", "a,@a+dptr");
11490         } else 
11491             emitcode ("movx", "a,@dptr");
11492         emitcode ("movx", "@dptr,a");
11493         emitcode ("inc", "dptr");
11494         emitcode ("inc", "dptr");
11495         emitcode ("mov","a,b");
11496         emitcode ("orl","a,_ap");
11497         emitcode ("jz","!tlabel",lbl1->key+100);
11498         emitcode ("mov","a,_ap");
11499         emitcode ("add","a,#!constbyte",0xFF);
11500         emitcode ("mov","_ap,a");
11501         emitcode ("mov","a,b");
11502         emitcode ("addc","a,#!constbyte",0xFF);
11503         emitcode ("mov","b,a");
11504         emitcode ("sjmp","!tlabel",lbl->key+100);
11505         emitcode ("","!tlabeldef",lbl1->key+100);
11506     }
11507     emitcode ("mov", "dps,#0"); 
11508     _G.dptrInUse = _G.dptr1InUse = 0;
11509     unsavermask(rsave);
11510
11511 }
11512
11513 /*-----------------------------------------------------------------*/
11514 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11515 /*-----------------------------------------------------------------*/
11516 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11517 {
11518     operand *from , *to , *count;
11519     symbol *lbl,*lbl2;
11520     bitVect *rsave;
11521     int i;
11522
11523     /* we know it has to be 3 parameters */
11524     assert (nparms == 3);
11525     
11526     rsave = newBitVect(16);
11527     /* save DPTR if it needs to be saved */
11528     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11529             if (bitVectBitValue(ic->rMask,i))
11530                     rsave = bitVectSetBit(rsave,i);
11531     }
11532     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11533                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11534     savermask(rsave);
11535     
11536     to = parms[0];
11537     from = parms[1];
11538     count = parms[2];
11539
11540     aopOp (from, ic->next, FALSE, FALSE);
11541
11542     /* get from into DPTR1 */
11543     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11544     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11545     if (options.model == MODEL_FLAT24) {
11546         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11547     }
11548
11549     freeAsmop (from, NULL, ic, FALSE);
11550     aopOp (to, ic, FALSE, FALSE);
11551     /* get "to" into DPTR */
11552     /* if the operand is already in dptr
11553        then we do nothing else we move the value to dptr */
11554     if (AOP_TYPE (to) != AOP_STR) {
11555         /* if already in DPTR then we need to push */
11556         if (AOP_TYPE(to) == AOP_DPTR) {
11557             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11558             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11559             if (options.model == MODEL_FLAT24)
11560                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11561             emitcode ("pop", "dph");
11562             emitcode ("pop", "dpl");        
11563         } else {
11564             _startLazyDPSEvaluation ();
11565             /* if this is remateriazable */
11566             if (AOP_TYPE (to) == AOP_IMMD) {
11567                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11568             } else {                    /* we need to get it byte by byte */
11569                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11570                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11571                 if (options.model == MODEL_FLAT24) {
11572                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11573                 }
11574             }
11575             _endLazyDPSEvaluation ();
11576         }
11577     }
11578     freeAsmop (to, NULL, ic, FALSE);
11579     _G.dptrInUse = _G.dptr1InUse = 1;
11580     aopOp (count, ic->next->next, FALSE,FALSE);
11581     lbl =newiTempLabel(NULL);
11582     lbl2 =newiTempLabel(NULL);
11583
11584     /* now for the actual compare */
11585     if (AOP_TYPE(count) == AOP_LIT && 
11586         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11587         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11588         if (fromc)
11589             emitcode("lcall","__bi_memcmpc2x_s");
11590         else
11591             emitcode("lcall","__bi_memcmpx2x_s");
11592         freeAsmop (count, NULL, ic, FALSE);
11593         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11594         aopPut(AOP(IC_RESULT(ic)),"a",0);
11595         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11596     } else {
11597         symbol *lbl1 = newiTempLabel(NULL);
11598
11599         emitcode("push","ar0");         
11600         emitcode (";"," Auto increment but no djnz");
11601         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11602         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11603         freeAsmop (count, NULL, ic, FALSE);
11604         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11605         emitcode ("","!tlabeldef",lbl->key+100);
11606         if (fromc) {
11607             emitcode ("clr","a");
11608             emitcode ("movc", "a,@a+dptr");
11609         } else 
11610             emitcode ("movx", "a,@dptr");
11611         emitcode ("mov","r0,a");
11612         emitcode ("movx", "a,@dptr");
11613         emitcode ("clr","c");
11614         emitcode ("subb","a,r0");
11615         emitcode ("jnz","!tlabel",lbl2->key+100);
11616         emitcode ("inc", "dptr");
11617         emitcode ("inc", "dptr");
11618         emitcode ("mov","a,b");
11619         emitcode ("orl","a,_ap");
11620         emitcode ("jz","!tlabel",lbl1->key+100);
11621         emitcode ("mov","a,_ap");
11622         emitcode ("add","a,#!constbyte",0xFF);
11623         emitcode ("mov","_ap,a");
11624         emitcode ("mov","a,b");
11625         emitcode ("addc","a,#!constbyte",0xFF);
11626         emitcode ("mov","b,a");
11627         emitcode ("sjmp","!tlabel",lbl->key+100);
11628         emitcode ("","!tlabeldef",lbl1->key+100);
11629         emitcode ("clr","a");
11630         emitcode ("","!tlabeldef",lbl2->key+100);
11631         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11632         aopPut(AOP(IC_RESULT(ic)),"a",0);
11633         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11634         emitcode("pop","ar0");
11635         emitcode ("mov", "dps,#0");      
11636     }
11637     _G.dptrInUse = _G.dptr1InUse = 0;
11638     unsavermask(rsave);
11639
11640 }
11641
11642 /*-----------------------------------------------------------------*/
11643 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11644 /* port, first parameter output area second parameter pointer to   */
11645 /* port third parameter count                                      */
11646 /*-----------------------------------------------------------------*/
11647 static void genInp( iCode *ic, int nparms, operand **parms)
11648 {
11649     operand *from , *to , *count;
11650     symbol *lbl;
11651     bitVect *rsave;
11652     int i;
11653
11654     /* we know it has to be 3 parameters */
11655     assert (nparms == 3);
11656     
11657     rsave = newBitVect(16);
11658     /* save DPTR if it needs to be saved */
11659     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11660             if (bitVectBitValue(ic->rMask,i))
11661                     rsave = bitVectSetBit(rsave,i);
11662     }
11663     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11664                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11665     savermask(rsave);
11666     
11667     to = parms[0];
11668     from = parms[1];
11669     count = parms[2];
11670
11671     aopOp (from, ic->next, FALSE, FALSE);
11672
11673     /* get from into DPTR1 */
11674     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11675     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11676     if (options.model == MODEL_FLAT24) {
11677         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11678     }
11679
11680     freeAsmop (from, NULL, ic, FALSE);
11681     aopOp (to, ic, FALSE, FALSE);
11682     /* get "to" into DPTR */
11683     /* if the operand is already in dptr
11684        then we do nothing else we move the value to dptr */
11685     if (AOP_TYPE (to) != AOP_STR) {
11686         /* if already in DPTR then we need to push */
11687         if (AOP_TYPE(to) == AOP_DPTR) {
11688             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11689             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11690             if (options.model == MODEL_FLAT24)
11691                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11692             emitcode ("pop", "dph");
11693             emitcode ("pop", "dpl");        
11694         } else {
11695             _startLazyDPSEvaluation ();
11696             /* if this is remateriazable */
11697             if (AOP_TYPE (to) == AOP_IMMD) {
11698                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11699             } else {                    /* we need to get it byte by byte */
11700                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11701                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11702                 if (options.model == MODEL_FLAT24) {
11703                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11704                 }
11705             }
11706             _endLazyDPSEvaluation ();
11707         }
11708     }
11709     freeAsmop (to, NULL, ic, FALSE);
11710
11711     _G.dptrInUse = _G.dptr1InUse = 1;
11712     aopOp (count, ic->next->next, FALSE,FALSE);
11713     lbl =newiTempLabel(NULL);
11714
11715     /* now for the actual copy */
11716     if (AOP_TYPE(count) == AOP_LIT && 
11717         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11718         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11719         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11720         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11721         freeAsmop (count, NULL, ic, FALSE);
11722         emitcode ("","!tlabeldef",lbl->key+100);
11723         emitcode ("movx", "a,@dptr");   /* read data from port */
11724         emitcode ("dec","dps");         /* switch to DPTR */
11725         emitcode ("movx", "@dptr,a");   /* save into location */
11726         emitcode ("inc", "dptr");       /* point to next area */
11727         emitcode ("inc","dps");         /* switch to DPTR2 */
11728         emitcode ("djnz","b,!tlabel",lbl->key+100);
11729     } else {
11730         symbol *lbl1 = newiTempLabel(NULL);
11731         
11732         emitcode (";"," Auto increment but no djnz");
11733         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11734         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11735         freeAsmop (count, NULL, ic, FALSE);
11736         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11737         emitcode ("","!tlabeldef",lbl->key+100);
11738         emitcode ("movx", "a,@dptr");
11739         emitcode ("dec","dps");         /* switch to DPTR */
11740         emitcode ("movx", "@dptr,a");
11741         emitcode ("inc", "dptr");
11742         emitcode ("inc","dps");         /* switch to DPTR2 */
11743 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11744 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11745         emitcode ("mov","a,b");
11746         emitcode ("orl","a,_ap");
11747         emitcode ("jz","!tlabel",lbl1->key+100);
11748         emitcode ("mov","a,_ap");
11749         emitcode ("add","a,#!constbyte",0xFF);
11750         emitcode ("mov","_ap,a");
11751         emitcode ("mov","a,b");
11752         emitcode ("addc","a,#!constbyte",0xFF);
11753         emitcode ("mov","b,a");
11754         emitcode ("sjmp","!tlabel",lbl->key+100);
11755         emitcode ("","!tlabeldef",lbl1->key+100);
11756     }
11757     emitcode ("mov", "dps,#0"); 
11758     _G.dptrInUse = _G.dptr1InUse = 0;
11759     unsavermask(rsave);
11760
11761 }
11762
11763 /*-----------------------------------------------------------------*/
11764 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11765 /* port, first parameter output area second parameter pointer to   */
11766 /* port third parameter count                                      */
11767 /*-----------------------------------------------------------------*/
11768 static void genOutp( iCode *ic, int nparms, operand **parms)
11769 {
11770     operand *from , *to , *count;
11771     symbol *lbl;
11772     bitVect *rsave;
11773     int i;
11774
11775     /* we know it has to be 3 parameters */
11776     assert (nparms == 3);
11777     
11778     rsave = newBitVect(16);
11779     /* save DPTR if it needs to be saved */
11780     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11781             if (bitVectBitValue(ic->rMask,i))
11782                     rsave = bitVectSetBit(rsave,i);
11783     }
11784     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11785                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11786     savermask(rsave);
11787     
11788     to = parms[0];
11789     from = parms[1];
11790     count = parms[2];
11791
11792     aopOp (from, ic->next, FALSE, FALSE);
11793
11794     /* get from into DPTR1 */
11795     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11796     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11797     if (options.model == MODEL_FLAT24) {
11798         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11799     }
11800
11801     freeAsmop (from, NULL, ic, FALSE);
11802     aopOp (to, ic, FALSE, FALSE);
11803     /* get "to" into DPTR */
11804     /* if the operand is already in dptr
11805        then we do nothing else we move the value to dptr */
11806     if (AOP_TYPE (to) != AOP_STR) {
11807         /* if already in DPTR then we need to push */
11808         if (AOP_TYPE(to) == AOP_DPTR) {
11809             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11810             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11811             if (options.model == MODEL_FLAT24)
11812                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11813             emitcode ("pop", "dph");
11814             emitcode ("pop", "dpl");        
11815         } else {
11816             _startLazyDPSEvaluation ();
11817             /* if this is remateriazable */
11818             if (AOP_TYPE (to) == AOP_IMMD) {
11819                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11820             } else {                    /* we need to get it byte by byte */
11821                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11822                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11823                 if (options.model == MODEL_FLAT24) {
11824                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11825                 }
11826             }
11827             _endLazyDPSEvaluation ();
11828         }
11829     }
11830     freeAsmop (to, NULL, ic, FALSE);
11831
11832     _G.dptrInUse = _G.dptr1InUse = 1;
11833     aopOp (count, ic->next->next, FALSE,FALSE);
11834     lbl =newiTempLabel(NULL);
11835
11836     /* now for the actual copy */
11837     if (AOP_TYPE(count) == AOP_LIT && 
11838         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11839         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11840         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11841         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11842         emitcode ("","!tlabeldef",lbl->key+100);
11843         emitcode ("movx", "a,@dptr");   /* read data from port */
11844         emitcode ("inc","dps");         /* switch to DPTR2 */
11845         emitcode ("movx", "@dptr,a");   /* save into location */
11846         emitcode ("inc", "dptr");       /* point to next area */
11847         emitcode ("dec","dps");         /* switch to DPTR */
11848         emitcode ("djnz","b,!tlabel",lbl->key+100);
11849         freeAsmop (count, NULL, ic, FALSE);
11850     } else {
11851         symbol *lbl1 = newiTempLabel(NULL);
11852         
11853         emitcode (";"," Auto increment but no djnz");
11854         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11855         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11856         freeAsmop (count, NULL, ic, FALSE);
11857         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11858         emitcode ("","!tlabeldef",lbl->key+100);
11859         emitcode ("movx", "a,@dptr");
11860         emitcode ("inc", "dptr");
11861         emitcode ("inc","dps");         /* switch to DPTR2 */
11862         emitcode ("movx", "@dptr,a");
11863         emitcode ("dec","dps");         /* switch to DPTR */
11864         emitcode ("mov","a,b");
11865         emitcode ("orl","a,_ap");
11866         emitcode ("jz","!tlabel",lbl1->key+100);
11867         emitcode ("mov","a,_ap");
11868         emitcode ("add","a,#!constbyte",0xFF);
11869         emitcode ("mov","_ap,a");
11870         emitcode ("mov","a,b");
11871         emitcode ("addc","a,#!constbyte",0xFF);
11872         emitcode ("mov","b,a");
11873         emitcode ("sjmp","!tlabel",lbl->key+100);
11874         emitcode ("","!tlabeldef",lbl1->key+100);
11875     }
11876     emitcode ("mov", "dps,#0"); 
11877     _G.dptrInUse = _G.dptr1InUse = 0;
11878     unsavermask(rsave);
11879
11880 }
11881
11882 /*-----------------------------------------------------------------*/
11883 /* genSwapW - swap lower & high order bytes                        */
11884 /*-----------------------------------------------------------------*/
11885 static void genSwapW(iCode *ic, int nparms, operand **parms)
11886 {
11887     operand *dest;
11888     operand *src;
11889     assert (nparms==1);
11890
11891     src = parms[0];
11892     dest=IC_RESULT(ic);
11893
11894     assert(getSize(operandType(src))==2);
11895
11896     aopOp (src, ic, FALSE, FALSE);
11897     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11898     _G.accInUse++;
11899     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11900     _G.accInUse--;
11901     freeAsmop (src, NULL, ic, FALSE);
11902     
11903     aopOp (dest,ic, FALSE, FALSE);
11904     aopPut(AOP(dest),"b",0);
11905     aopPut(AOP(dest),"a",1);
11906     freeAsmop (dest, NULL, ic, FALSE);    
11907 }
11908
11909 /*-----------------------------------------------------------------*/
11910 /* genMemsetX - gencode for memSetX data                           */
11911 /*-----------------------------------------------------------------*/
11912 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11913 {
11914     operand *to , *val , *count;
11915     symbol *lbl;
11916     char *l;
11917     int i;
11918     bitVect *rsave;
11919
11920     /* we know it has to be 3 parameters */
11921     assert (nparms == 3);
11922     
11923     to = parms[0];
11924     val = parms[1];
11925     count = parms[2];
11926         
11927     /* save DPTR if it needs to be saved */
11928     rsave = newBitVect(16);
11929     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11930             if (bitVectBitValue(ic->rMask,i))
11931                     rsave = bitVectSetBit(rsave,i);
11932     }
11933     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11934                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11935     savermask(rsave);
11936
11937     aopOp (to, ic, FALSE, FALSE);
11938     /* get "to" into DPTR */
11939     /* if the operand is already in dptr
11940        then we do nothing else we move the value to dptr */
11941     if (AOP_TYPE (to) != AOP_STR) {
11942         /* if already in DPTR then we need to push */
11943         if (AOP_TYPE(to) == AOP_DPTR) {
11944             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11945             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11946             if (options.model == MODEL_FLAT24)
11947                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11948             emitcode ("pop", "dph");
11949             emitcode ("pop", "dpl");        
11950         } else {
11951             _startLazyDPSEvaluation ();
11952             /* if this is remateriazable */
11953             if (AOP_TYPE (to) == AOP_IMMD) {
11954                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11955             } else {                    /* we need to get it byte by byte */
11956                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11957                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11958                 if (options.model == MODEL_FLAT24) {
11959                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11960                 }
11961             }
11962             _endLazyDPSEvaluation ();
11963         }
11964     }
11965     freeAsmop (to, NULL, ic, FALSE);
11966
11967     aopOp (val, ic->next->next, FALSE,FALSE);
11968     aopOp (count, ic->next->next, FALSE,FALSE);    
11969     lbl =newiTempLabel(NULL);
11970     /* now for the actual copy */
11971     if (AOP_TYPE(count) == AOP_LIT && 
11972         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11973         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11974         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11975         MOVA(l);
11976         emitcode ("","!tlabeldef",lbl->key+100);
11977         emitcode ("movx", "@dptr,a");
11978         emitcode ("inc", "dptr");
11979         emitcode ("djnz","b,!tlabel",lbl->key+100);
11980     } else {
11981         symbol *lbl1 = newiTempLabel(NULL);
11982         
11983         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11984         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11985         emitcode ("","!tlabeldef",lbl->key+100);
11986         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11987         emitcode ("movx", "@dptr,a");
11988         emitcode ("inc", "dptr");
11989         emitcode ("mov","a,b");
11990         emitcode ("orl","a,_ap");
11991         emitcode ("jz","!tlabel",lbl1->key+100);
11992         emitcode ("mov","a,_ap");
11993         emitcode ("add","a,#!constbyte",0xFF);
11994         emitcode ("mov","_ap,a");
11995         emitcode ("mov","a,b");
11996         emitcode ("addc","a,#!constbyte",0xFF);
11997         emitcode ("mov","b,a");
11998         emitcode ("sjmp","!tlabel",lbl->key+100);
11999         emitcode ("","!tlabeldef",lbl1->key+100);
12000     }
12001     freeAsmop (count, NULL, ic, FALSE);
12002     unsavermask(rsave);
12003 }
12004
12005 /*-----------------------------------------------------------------*/
12006 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12007 /*-----------------------------------------------------------------*/
12008 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12009 {
12010         bitVect *rsave ;
12011         operand *pnum, *result;
12012         int i;
12013     
12014         assert (nparms==1);
12015         /* save registers that need to be saved */
12016         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12017                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12018     
12019         pnum = parms[0]; 
12020         aopOp (pnum, ic, FALSE, FALSE);
12021         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12022         freeAsmop (pnum, NULL, ic, FALSE);
12023         emitcode ("lcall","NatLib_LoadPrimitive");
12024         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12025         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
12026             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12027                 for (i = (size-1) ; i >= 0 ; i-- ) {
12028                         emitcode ("push","a%s",javaRet[i]);
12029                 }
12030                 for (i=0; i < size ; i++ ) {
12031                         emitcode ("pop","a%s",
12032                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12033                 }
12034         } else {
12035                 for (i = 0 ; i < size ; i++ ) {
12036                         aopPut(AOP(result),javaRet[i],i);
12037                 }
12038         }    
12039         freeAsmop (result, NULL, ic, FALSE);
12040         unsavermask(rsave);
12041 }
12042
12043 /*-----------------------------------------------------------------*/
12044 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12045 /*-----------------------------------------------------------------*/
12046 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12047 {
12048         bitVect *rsave ;
12049         operand *pnum, *result;
12050         int size = 3;
12051         int i;
12052     
12053         assert (nparms==1);
12054         /* save registers that need to be saved */
12055         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12056                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12057     
12058         pnum = parms[0]; 
12059         aopOp (pnum, ic, FALSE, FALSE);
12060         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12061         freeAsmop (pnum, NULL, ic, FALSE);
12062         emitcode ("lcall","NatLib_LoadPointer");
12063         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12064         if (AOP_TYPE(result)!=AOP_STR) {
12065                 for (i = 0 ; i < size ; i++ ) {
12066                         aopPut(AOP(result),fReturn[i],i);
12067                 }
12068         }    
12069         freeAsmop (result, NULL, ic, FALSE);
12070         unsavermask(rsave);
12071 }
12072
12073 /*-----------------------------------------------------------------*/
12074 /* genNatLibInstallStateBlock -                                    */
12075 /*-----------------------------------------------------------------*/
12076 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12077                                        operand **parms, const char *name)
12078 {
12079         bitVect *rsave ;
12080         operand *psb, *handle;
12081         assert (nparms==2);
12082
12083         /* save registers that need to be saved */
12084         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12085                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12086         psb = parms[0];
12087         handle = parms[1];
12088
12089         /* put pointer to state block into DPTR1 */
12090         aopOp (psb, ic, FALSE, FALSE);
12091         if (AOP_TYPE (psb) == AOP_IMMD) {
12092                 emitcode ("mov","dps,#1");
12093                 emitcode ("mov", "dptr,%s",
12094                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12095                 emitcode ("mov","dps,#0");
12096         } else {
12097                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12098                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12099                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12100         }
12101         freeAsmop (psb, NULL, ic, FALSE);
12102
12103         /* put libraryID into DPTR */
12104         emitcode ("mov","dptr,#LibraryID");
12105
12106         /* put handle into r3:r2 */
12107         aopOp (handle, ic, FALSE, FALSE);
12108         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12109                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12110                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12111                 emitcode ("pop","ar3");
12112                 emitcode ("pop","ar2");
12113         } else {        
12114                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12115                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12116         }
12117         freeAsmop (psb, NULL, ic, FALSE);
12118
12119         /* make the call */
12120         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12121
12122         /* put return value into place*/
12123         _G.accInUse++;
12124         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12125         _G.accInUse--;
12126         aopPut(AOP(IC_RESULT(ic)),"a",0);
12127         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12128         unsavermask(rsave);
12129 }
12130
12131 /*-----------------------------------------------------------------*/
12132 /* genNatLibRemoveStateBlock -                                     */
12133 /*-----------------------------------------------------------------*/
12134 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12135 {
12136         bitVect *rsave ;
12137
12138         assert(nparms==0);
12139
12140         /* save registers that need to be saved */
12141         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12142                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12143
12144         /* put libraryID into DPTR */
12145         emitcode ("mov","dptr,#LibraryID");
12146         /* make the call */
12147         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12148         unsavermask(rsave);
12149 }
12150
12151 /*-----------------------------------------------------------------*/
12152 /* genNatLibGetStateBlock -                                        */
12153 /*-----------------------------------------------------------------*/
12154 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12155                                    operand **parms,const char *name)
12156 {
12157         bitVect *rsave ;
12158         symbol *lbl = newiTempLabel(NULL);
12159         
12160         assert(nparms==0);
12161         /* save registers that need to be saved */
12162         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12163                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12164
12165         /* put libraryID into DPTR */
12166         emitcode ("mov","dptr,#LibraryID");
12167         /* make the call */
12168         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12169         emitcode ("jnz","!tlabel",lbl->key+100);
12170
12171         /* put return value into place */
12172         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12173         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12174                 emitcode ("push","ar3");
12175                 emitcode ("push","ar2");
12176                 emitcode ("pop","%s",
12177                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12178                 emitcode ("pop","%s",
12179                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12180         } else {
12181                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12182                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12183         }
12184         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12185         emitcode ("","!tlabeldef",lbl->key+100);
12186         unsavermask(rsave);
12187 }
12188
12189 /*-----------------------------------------------------------------*/
12190 /* genMMMalloc -                                                   */
12191 /*-----------------------------------------------------------------*/
12192 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12193                          int size, const char *name)
12194 {
12195         bitVect *rsave ;
12196         operand *bsize;
12197         symbol *rsym;
12198         symbol *lbl = newiTempLabel(NULL);
12199
12200         assert (nparms == 1);
12201         /* save registers that need to be saved */
12202         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12203                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12204         
12205         bsize=parms[0];
12206         aopOp (bsize,ic,FALSE,FALSE);
12207
12208         /* put the size in R4-R2 */
12209         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12210                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12211                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12212                 if (size==3) {
12213                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12214                         emitcode("pop","ar4");
12215                 }
12216                 emitcode("pop","ar3");
12217                 emitcode("pop","ar2");          
12218         } else {
12219                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12220                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12221                 if (size==3) {
12222                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12223                 }
12224         }
12225         freeAsmop (bsize, NULL, ic, FALSE);
12226
12227         /* make the call */
12228         emitcode ("lcall","MM_%s",name);
12229         emitcode ("jz","!tlabel",lbl->key+100);
12230         emitcode ("mov","r2,#!constbyte",0xff);
12231         emitcode ("mov","r3,#!constbyte",0xff);
12232         emitcode ("","!tlabeldef",lbl->key+100);
12233         /* we don't care about the pointer : we just save the handle */
12234         rsym = OP_SYMBOL(IC_RESULT(ic));
12235         if (rsym->liveFrom != rsym->liveTo) {
12236                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12237                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12238                         emitcode ("push","ar3");
12239                         emitcode ("push","ar2");
12240                         emitcode ("pop","%s",
12241                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12242                         emitcode ("pop","%s",
12243                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12244                 } else {
12245                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12246                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12247                 }
12248                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12249         }
12250         unsavermask(rsave);
12251 }
12252
12253 /*-----------------------------------------------------------------*/
12254 /* genMMDeref -                                                    */
12255 /*-----------------------------------------------------------------*/
12256 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12257 {
12258         bitVect *rsave ;
12259         operand *handle;
12260
12261         assert (nparms == 1);
12262         /* save registers that need to be saved */
12263         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12264                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12265         
12266         handle=parms[0];
12267         aopOp (handle,ic,FALSE,FALSE);
12268
12269         /* put the size in R4-R2 */
12270         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12271                 emitcode("push","%s",
12272                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12273                 emitcode("push","%s",
12274                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12275                 emitcode("pop","ar3");
12276                 emitcode("pop","ar2");          
12277         } else {
12278                 emitcode ("mov","r2,%s",
12279                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12280                 emitcode ("mov","r3,%s",
12281                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12282         }
12283         freeAsmop (handle, NULL, ic, FALSE);
12284
12285         /* make the call */
12286         emitcode ("lcall","MM_Deref");
12287         
12288         {
12289                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12290                 if (rsym->liveFrom != rsym->liveTo) {                   
12291                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12292                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12293                             _startLazyDPSEvaluation ();
12294                             
12295                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12296                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12297                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12298
12299                             _endLazyDPSEvaluation ();
12300                             
12301                         }
12302                 }
12303         }
12304         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12305         unsavermask(rsave);
12306 }
12307
12308 /*-----------------------------------------------------------------*/
12309 /* genMMUnrestrictedPersist -                                      */
12310 /*-----------------------------------------------------------------*/
12311 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12312 {
12313         bitVect *rsave ;
12314         operand *handle;
12315
12316         assert (nparms == 1);
12317         /* save registers that need to be saved */
12318         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12319                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12320         
12321         handle=parms[0];
12322         aopOp (handle,ic,FALSE,FALSE);
12323
12324         /* put the size in R3-R2 */
12325         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12326                 emitcode("push","%s",
12327                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12328                 emitcode("push","%s",
12329                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12330                 emitcode("pop","ar3");
12331                 emitcode("pop","ar2");          
12332         } else {
12333                 emitcode ("mov","r2,%s",
12334                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12335                 emitcode ("mov","r3,%s",
12336                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12337         }
12338         freeAsmop (handle, NULL, ic, FALSE);
12339
12340         /* make the call */
12341         emitcode ("lcall","MM_UnrestrictedPersist");
12342
12343         {
12344                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12345                 if (rsym->liveFrom != rsym->liveTo) {   
12346                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12347                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12348                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12349                 }
12350         }
12351         unsavermask(rsave);
12352 }
12353
12354 /*-----------------------------------------------------------------*/
12355 /* genSystemExecJavaProcess -                                      */
12356 /*-----------------------------------------------------------------*/
12357 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12358 {
12359         bitVect *rsave ;
12360         operand *handle, *pp;
12361
12362         assert (nparms==2);
12363         /* save registers that need to be saved */
12364         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12365                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12366         
12367         pp = parms[0];
12368         handle = parms[1];
12369         
12370         /* put the handle in R3-R2 */
12371         aopOp (handle,ic,FALSE,FALSE);
12372         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12373                 emitcode("push","%s",
12374                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12375                 emitcode("push","%s",
12376                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12377                 emitcode("pop","ar3");
12378                 emitcode("pop","ar2");          
12379         } else {
12380                 emitcode ("mov","r2,%s",
12381                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12382                 emitcode ("mov","r3,%s",
12383                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12384         }
12385         freeAsmop (handle, NULL, ic, FALSE);
12386         
12387         /* put pointer in DPTR */
12388         aopOp (pp,ic,FALSE,FALSE);
12389         if (AOP_TYPE(pp) == AOP_IMMD) {
12390                 emitcode ("mov", "dptr,%s",
12391                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12392         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12393                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12394                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12395                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12396         }
12397         freeAsmop (handle, NULL, ic, FALSE);
12398
12399         /* make the call */
12400         emitcode ("lcall","System_ExecJavaProcess");
12401         
12402         /* put result in place */
12403         {
12404                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12405                 if (rsym->liveFrom != rsym->liveTo) {   
12406                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12407                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12408                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12409                 }
12410         }
12411         
12412         unsavermask(rsave);
12413 }
12414
12415 /*-----------------------------------------------------------------*/
12416 /* genSystemRTCRegisters -                                         */
12417 /*-----------------------------------------------------------------*/
12418 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12419                                   char *name)
12420 {
12421         bitVect *rsave ;
12422         operand *pp;
12423
12424         assert (nparms==1);
12425         /* save registers that need to be saved */
12426         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12427                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12428         
12429         pp=parms[0];
12430         /* put pointer in DPTR */
12431         aopOp (pp,ic,FALSE,FALSE);
12432         if (AOP_TYPE (pp) == AOP_IMMD) {
12433                 emitcode ("mov","dps,#1");
12434                 emitcode ("mov", "dptr,%s", 
12435                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12436                 emitcode ("mov","dps,#0");
12437         } else {
12438                 emitcode ("mov","dpl1,%s",
12439                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12440                 emitcode ("mov","dph1,%s",
12441                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12442                 emitcode ("mov","dpx1,%s",
12443                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12444         }
12445         freeAsmop (pp, NULL, ic, FALSE);
12446
12447         /* make the call */
12448         emitcode ("lcall","System_%sRTCRegisters",name);
12449
12450         unsavermask(rsave);
12451 }
12452
12453 /*-----------------------------------------------------------------*/
12454 /* genSystemThreadSleep -                                          */
12455 /*-----------------------------------------------------------------*/
12456 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12457 {
12458         bitVect *rsave ;
12459         operand *to, *s;
12460
12461         assert (nparms==1);
12462         /* save registers that need to be saved */
12463         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12464                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12465
12466         to = parms[0];
12467         aopOp(to,ic,FALSE,FALSE);
12468         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12469             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12470                 emitcode ("push","%s",
12471                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12472                 emitcode ("push","%s",
12473                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12474                 emitcode ("push","%s",
12475                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12476                 emitcode ("push","%s",
12477                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12478                 emitcode ("pop","ar3");
12479                 emitcode ("pop","ar2");
12480                 emitcode ("pop","ar1");
12481                 emitcode ("pop","ar0");
12482         } else {
12483                 emitcode ("mov","r0,%s",
12484                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12485                 emitcode ("mov","r1,%s",
12486                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12487                 emitcode ("mov","r2,%s",
12488                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12489                 emitcode ("mov","r3,%s",
12490                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12491         }
12492         freeAsmop (to, NULL, ic, FALSE);
12493
12494         /* suspend in acc */
12495         s = parms[1];
12496         aopOp(s,ic,FALSE,FALSE);
12497         emitcode ("mov","a,%s",
12498                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12499         freeAsmop (s, NULL, ic, FALSE);
12500
12501         /* make the call */
12502         emitcode ("lcall","System_%s",name);
12503
12504         unsavermask(rsave);
12505 }
12506
12507 /*-----------------------------------------------------------------*/
12508 /* genSystemThreadResume -                                         */
12509 /*-----------------------------------------------------------------*/
12510 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12511 {
12512         bitVect *rsave ;
12513         operand *tid,*pid;
12514
12515         assert (nparms==2);
12516         /* save registers that need to be saved */
12517         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12518                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12519         
12520         tid = parms[0];
12521         pid = parms[1];
12522         
12523         /* PID in R0 */
12524         aopOp(pid,ic,FALSE,FALSE);
12525         emitcode ("mov","r0,%s",
12526                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12527         freeAsmop (pid, NULL, ic, FALSE);
12528         
12529         /* tid into ACC */
12530         aopOp(tid,ic,FALSE,FALSE);
12531         emitcode ("mov","a,%s",
12532                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12533         freeAsmop (tid, NULL, ic, FALSE);
12534         
12535         emitcode ("lcall","System_ThreadResume");
12536
12537         /* put result into place */
12538         {
12539                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12540                 if (rsym->liveFrom != rsym->liveTo) {   
12541                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12542                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12543                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12544                 }
12545         }
12546         unsavermask(rsave);
12547 }
12548
12549 /*-----------------------------------------------------------------*/
12550 /* genSystemProcessResume -                                        */
12551 /*-----------------------------------------------------------------*/
12552 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12553 {
12554         bitVect *rsave ;
12555         operand *pid;
12556
12557         assert (nparms==1);
12558         /* save registers that need to be saved */
12559         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12560                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12561         
12562         pid = parms[0];
12563         
12564         /* pid into ACC */
12565         aopOp(pid,ic,FALSE,FALSE);
12566         emitcode ("mov","a,%s",
12567                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12568         freeAsmop (pid, NULL, ic, FALSE);
12569         
12570         emitcode ("lcall","System_ProcessResume");
12571
12572         unsavermask(rsave);
12573 }
12574
12575 /*-----------------------------------------------------------------*/
12576 /* genSystem -                                                     */
12577 /*-----------------------------------------------------------------*/
12578 static void genSystem (iCode *ic,int nparms,char *name)
12579 {
12580         assert(nparms == 0);
12581
12582         emitcode ("lcall","System_%s",name);
12583 }
12584
12585 /*-----------------------------------------------------------------*/
12586 /* genSystemPoll -                                                  */
12587 /*-----------------------------------------------------------------*/
12588 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12589 {
12590         bitVect *rsave ;
12591         operand *fp;
12592
12593         assert (nparms==1);
12594         /* save registers that need to be saved */
12595         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12596                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12597
12598         fp = parms[0];
12599         aopOp (fp,ic,FALSE,FALSE);
12600         if (AOP_TYPE (fp) == AOP_IMMD) {
12601                 emitcode ("mov", "dptr,%s", 
12602                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12603         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12604                 emitcode ("mov","dpl,%s",
12605                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12606                 emitcode ("mov","dph,%s",
12607                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12608                 emitcode ("mov","dpx,%s",
12609                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12610         }
12611         freeAsmop (fp, NULL, ic, FALSE);
12612
12613         emitcode ("lcall","System_%sPoll",name);
12614
12615         /* put result into place */
12616         {
12617                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12618                 if (rsym->liveFrom != rsym->liveTo) {   
12619                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12620                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12621                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12622                 }
12623         }
12624         unsavermask(rsave);
12625 }
12626
12627 /*-----------------------------------------------------------------*/
12628 /* genSystemGetCurrentID -                                         */
12629 /*-----------------------------------------------------------------*/
12630 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12631 {
12632         assert (nparms==0);
12633
12634         emitcode ("lcall","System_GetCurrent%sId",name);
12635         /* put result into place */
12636         {
12637                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12638                 if (rsym->liveFrom != rsym->liveTo) {   
12639                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12640                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12641                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12642                 }
12643         }
12644 }
12645
12646 /*-----------------------------------------------------------------*/
12647 /* genDummyRead - generate code for dummy read of volatiles        */
12648 /*-----------------------------------------------------------------*/
12649 static void
12650 genDummyRead (iCode * ic)
12651 {
12652   operand *right;
12653   int size, offset;
12654
12655   D(emitcode(";     genDummyRead",""));
12656
12657   right = IC_RIGHT (ic);
12658
12659   aopOp (right, ic, FALSE, FALSE);
12660
12661   /* if the result is a bit */
12662   if (AOP_TYPE (right) == AOP_CRY)
12663     {
12664       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12665       goto release;
12666     }
12667
12668   /* bit variables done */
12669   /* general case */
12670   size = AOP_SIZE (right);
12671   offset = 0;
12672   while (size--)
12673     {
12674       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12675       offset++;
12676     }
12677
12678 release:
12679   freeAsmop (right, NULL, ic, TRUE);
12680 }
12681
12682 /*-----------------------------------------------------------------*/
12683 /* genCritical - generate code for start of a critical sequence    */
12684 /*-----------------------------------------------------------------*/
12685 static void
12686 genCritical (iCode *ic)
12687 {
12688   symbol *tlbl = newiTempLabel (NULL);
12689
12690   D(emitcode(";     genCritical",""));
12691   
12692   if (IC_RESULT (ic))
12693     aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
12694
12695   emitcode ("setb", "c");
12696   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
12697   emitcode ("clr", "c");
12698   emitcode ("", "%05d$:", (tlbl->key + 100));
12699
12700   if (IC_RESULT (ic))
12701     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
12702   else
12703     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
12704
12705   if (IC_RESULT (ic))
12706     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12707 }
12708
12709 /*-----------------------------------------------------------------*/
12710 /* genEndCritical - generate code for end of a critical sequence   */
12711 /*-----------------------------------------------------------------*/
12712 static void
12713 genEndCritical (iCode *ic)
12714 {
12715   D(emitcode(";     genEndCritical",""));
12716   
12717   if (IC_RIGHT (ic))
12718     {
12719       aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
12720       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
12721         {
12722           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
12723           emitcode ("mov", "ea,c");
12724         }
12725       else
12726         {
12727           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
12728           emitcode ("rrc", "a");
12729           emitcode ("mov", "ea,c");
12730         }
12731       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
12732     }
12733   else
12734     {
12735       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
12736       emitcode ("mov", "ea,c");
12737     }
12738 }
12739
12740
12741
12742 /*-----------------------------------------------------------------*/
12743 /* genBuiltIn - calls the appropriate function to  generating code */
12744 /* for a built in function                                         */
12745 /*-----------------------------------------------------------------*/
12746 static void genBuiltIn (iCode *ic)
12747 {
12748         operand *bi_parms[MAX_BUILTIN_ARGS];
12749         int nbi_parms;
12750         iCode *bi_iCode;
12751         symbol *bif;
12752
12753         /* get all the arguments for a built in function */
12754         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12755
12756         /* which function is it */
12757         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12758         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12759                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12760         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12761                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12762         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12763                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12764         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12765                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12766         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12767                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12768         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12769                 genInp(bi_iCode,nbi_parms,bi_parms);
12770         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12771                 genOutp(bi_iCode,nbi_parms,bi_parms);
12772         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12773                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12774                 /* JavaNative builtIns */               
12775         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12776                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12777         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12778                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12779         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12780                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12781         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12782                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12783         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12784                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12785         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12786                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12787         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12788                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12789         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12790                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12791         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12792                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12793         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12794                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12795         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12796                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12797         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12798                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12799         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12800                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12801         } else if (strcmp(bif->name,"MM_Free")==0) {
12802                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12803         } else if (strcmp(bif->name,"MM_Deref")==0) {
12804                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12805         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12806                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12807         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12808                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12809         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12810                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12811         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12812                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12813         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12814                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12815         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12816                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12817         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12818                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12819         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12820                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12821         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12822                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12823         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12824                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12825         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12826                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12827         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12828                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12829         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12830                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12831         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12832                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12833         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12834                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12835         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12836                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12837         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12838                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12839         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12840                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12841         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12842                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12843         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12844                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12845         } else {
12846                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12847                 return ;
12848         }
12849         return ;    
12850 }
12851
12852 /*-----------------------------------------------------------------*/
12853 /* gen390Code - generate code for Dallas 390 based controllers     */
12854 /*-----------------------------------------------------------------*/
12855 void
12856 gen390Code (iCode * lic)
12857 {
12858   iCode *ic;
12859   int cln = 0;
12860
12861   lineHead = lineCurr = NULL;
12862   dptrn[1][0] = "dpl1";
12863   dptrn[1][1] = "dph1";
12864   dptrn[1][2] = "dpx1";
12865   
12866   if (options.model == MODEL_FLAT24) {
12867     fReturnSizeDS390 = 5;
12868     fReturn = fReturn24;
12869   } else {
12870     fReturnSizeDS390 = 4;
12871     fReturn = fReturn16;
12872     options.stack10bit=0;
12873   }
12874 #if 1
12875   /* print the allocation information */
12876   if (allocInfo && currFunc)
12877     printAllocInfo (currFunc, codeOutFile);
12878 #endif
12879   /* if debug information required */
12880   if (options.debug && currFunc)
12881     {
12882       debugFile->writeFunction(currFunc);
12883       _G.debugLine = 1;
12884       if (IS_STATIC (currFunc->etype))
12885         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12886       else
12887         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12888       _G.debugLine = 0;
12889     }
12890   /* stack pointer name */
12891   if (options.useXstack)
12892     spname = "_spx";
12893   else
12894     spname = "sp";
12895
12896
12897   for (ic = lic; ic; ic = ic->next)
12898     {
12899
12900       if (ic->lineno && cln != ic->lineno)
12901         {
12902           if (options.debug)
12903             {
12904               _G.debugLine = 1;
12905               emitcode ("", "C$%s$%d$%d$%d ==.",
12906                         FileBaseName (ic->filename), ic->lineno,
12907                         ic->level, ic->block);
12908               _G.debugLine = 0;
12909             }
12910           if (!options.noCcodeInAsm) {
12911             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12912                       printCLine(ic->filename, ic->lineno));
12913           }
12914           cln = ic->lineno;
12915         }
12916       if (options.iCodeInAsm) {
12917         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12918       }
12919       /* if the result is marked as
12920          spilt and rematerializable or code for
12921          this has already been generated then
12922          do nothing */
12923       if (resultRemat (ic) || ic->generated)
12924         continue;
12925
12926       /* depending on the operation */
12927       switch (ic->op)
12928         {
12929         case '!':
12930           genNot (ic);
12931           break;
12932
12933         case '~':
12934           genCpl (ic);
12935           break;
12936
12937         case UNARYMINUS:
12938           genUminus (ic);
12939           break;
12940
12941         case IPUSH:
12942           genIpush (ic);
12943           break;
12944
12945         case IPOP:
12946           /* IPOP happens only when trying to restore a
12947              spilt live range, if there is an ifx statement
12948              following this pop then the if statement might
12949              be using some of the registers being popped which
12950              would destory the contents of the register so
12951              we need to check for this condition and handle it */
12952           if (ic->next &&
12953               ic->next->op == IFX &&
12954               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12955             genIfx (ic->next, ic);
12956           else
12957             genIpop (ic);
12958           break;
12959
12960         case CALL:
12961           genCall (ic);
12962           break;
12963
12964         case PCALL:
12965           genPcall (ic);
12966           break;
12967
12968         case FUNCTION:
12969           genFunction (ic);
12970           break;
12971
12972         case ENDFUNCTION:
12973           genEndFunction (ic);
12974           break;
12975
12976         case RETURN:
12977           genRet (ic);
12978           break;
12979
12980         case LABEL:
12981           genLabel (ic);
12982           break;
12983
12984         case GOTO:
12985           genGoto (ic);
12986           break;
12987
12988         case '+':
12989           genPlus (ic);
12990           break;
12991
12992         case '-':
12993           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12994             genMinus (ic);
12995           break;
12996
12997         case '*':
12998           genMult (ic);
12999           break;
13000
13001         case '/':
13002           genDiv (ic);
13003           break;
13004
13005         case '%':
13006           genMod (ic);
13007           break;
13008
13009         case '>':
13010           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13011           break;
13012
13013         case '<':
13014           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13015           break;
13016
13017         case LE_OP:
13018         case GE_OP:
13019         case NE_OP:
13020
13021           /* note these two are xlated by algebraic equivalence
13022              during parsing SDCC.y */
13023           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13024                   "got '>=' or '<=' shouldn't have come here");
13025           break;
13026
13027         case EQ_OP:
13028           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13029           break;
13030
13031         case AND_OP:
13032           genAndOp (ic);
13033           break;
13034
13035         case OR_OP:
13036           genOrOp (ic);
13037           break;
13038
13039         case '^':
13040           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13041           break;
13042
13043         case '|':
13044           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13045           break;
13046
13047         case BITWISEAND:
13048           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13049           break;
13050
13051         case INLINEASM:
13052           genInline (ic);
13053           break;
13054
13055         case RRC:
13056           genRRC (ic);
13057           break;
13058
13059         case RLC:
13060           genRLC (ic);
13061           break;
13062
13063         case GETHBIT:
13064           genGetHbit (ic);
13065           break;
13066
13067         case LEFT_OP:
13068           genLeftShift (ic);
13069           break;
13070
13071         case RIGHT_OP:
13072           genRightShift (ic);
13073           break;
13074
13075         case GET_VALUE_AT_ADDRESS:
13076           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13077           break;
13078
13079         case '=':
13080           if (POINTER_SET (ic))
13081             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13082           else
13083             genAssign (ic);
13084           break;
13085
13086         case IFX:
13087           genIfx (ic, NULL);
13088           break;
13089
13090         case ADDRESS_OF:
13091           genAddrOf (ic);
13092           break;
13093
13094         case JUMPTABLE:
13095           genJumpTab (ic);
13096           break;
13097
13098         case CAST:
13099           genCast (ic);
13100           break;
13101
13102         case RECEIVE:
13103           genReceive (ic);
13104           break;
13105
13106         case SEND:
13107           if (ic->builtinSEND) genBuiltIn(ic);
13108           else addSet (&_G.sendSet, ic);
13109           break;
13110
13111         case DUMMY_READ_VOLATILE:
13112           genDummyRead (ic);
13113           break;
13114
13115         case CRITICAL:
13116           genCritical (ic);
13117           break;
13118
13119         case ENDCRITICAL:
13120           genEndCritical (ic);
13121           break;
13122           
13123 #if 0 // obsolete, and buggy for != xdata
13124         case ARRAYINIT:
13125             genArrayInit(ic);
13126             break;
13127 #endif
13128             
13129         default:
13130           ic = ic;
13131         }
13132     }
13133
13134
13135   /* now we are ready to call the
13136      peep hole optimizer */
13137   if (!options.nopeep)
13138     peepHole (&lineHead);
13139
13140   /* now do the actual printing */
13141   printLine (lineHead, codeOutFile);
13142   return;
13143 }