* src/ds390/gen.c (genCpl): fixed bit=~(char/bit) bugs, added warning
[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 "main.h"
35 #include "ralloc.h"
36 #include "gen.h"
37 #include "SDCCglobl.h"
38 #include "newalloc.h"
39
40 #define BETTER_LITERAL_SHIFT
41
42 char *aopLiteral (value * val, int offset);
43 extern int allocInfo;
44
45 /* this is the down and dirty file with all kinds of
46    kludgy & hacky stuff. This is what it is all about
47    CODE GENERATION for a specific MCU . some of the
48    routines may be reusable, will have to see */
49
50 static char *zero = "#0";
51 static char *one = "#1";
52 static char *spname;
53
54 #define D(x) x
55
56 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
57 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
58
59 short fReturnSizeDS390 = 5;
60 static char *fReturn24[] =
61 {"dpl", "dph", "dpx", "b", "a"};
62 static char *fReturn16[] =
63 {"dpl", "dph", "b", "a"};
64 static char **fReturn = fReturn24;
65 static char *accUse[] =
66 {"a", "b"};
67 static char *dptrn[2][3];
68 static char *javaRet[] = { "r0","r1","r2","r3"};
69 static short rbank = -1;
70
71 static struct
72   {
73     short r0Pushed;
74     short r1Pushed;
75     short accInUse;
76     short bInUse;
77     short inLine;
78     short debugLine;
79     short nRegsSaved;
80     short dptrInUse;
81     short dptr1InUse;
82     set *sendSet;
83     iCode *current_iCode;
84   }
85 _G;
86
87 static char *rb1regs[] = {
88     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
89 };
90
91 static void saveRBank (int, iCode *, bool);
92
93 #define RESULTONSTACK(x) \
94                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
95                          IC_RESULT(x)->aop->type == AOP_STK )
96
97 #define MOVA(x) _movA(x)
98 #define MOVB(x) _movB(x)
99
100 #define CLRC    emitcode("clr","c")
101 #define SETC    emitcode("setb","c")
102
103 // A scratch register which will be used to hold
104 // result bytes from operands in far space via DPTR2.
105 #define DP2_RESULT_REG  "_ap"
106
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
109
110 static unsigned char SLMask[] =
111 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
112  0xE0, 0xC0, 0x80, 0x00};
113 static unsigned char SRMask[] =
114 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115  0x07, 0x03, 0x01, 0x00};
116
117 #define LSB     0
118 #define MSB16   1
119 #define MSB24   2
120 #define MSB32   3
121 #define PROTECT_SP      {if (options.protect_sp_update) {                       \
122                                 symbol *lbl = newiTempLabel(NULL);              \
123                                 emitcode ("setb","F1");                         \
124                                 emitcode ("jbc","EA,!tlabel",lbl->key+100);     \
125                                 emitcode ("clr","F1");                          \
126                                 emitcode ("","!tlabeldef",lbl->key+100);        \
127                         }}
128 #define UNPROTECT_SP    { if (options.protect_sp_update) {                      \
129                                 symbol *lbl = newiTempLabel(NULL);              \
130                                 emitcode ("jnb","F1,!tlabel",lbl->key+100);     \
131                                 emitcode ("setb","EA");                         \
132                                 emitcode ("","!tlabeldef",lbl->key+100);        \
133                         }}
134
135 static int _currentDPS;         /* Current processor DPS. */
136 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
137 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
138
139 /*-----------------------------------------------------------------*/
140 /* emitcode - writes the code into a file : for now it is simple    */
141 /*-----------------------------------------------------------------*/
142 static void
143 emitcode (char *inst, const char *fmt,...)
144 {
145   va_list ap;
146   char lb[INITIAL_INLINEASM];
147   char *lbp = lb;
148
149   va_start (ap, fmt);
150
151   if (inst && *inst)
152     {
153       if (fmt && *fmt)
154         {
155           SNPRINTF (lb, sizeof(lb), "%s\t", inst);
156         }
157       else
158         {
159           SNPRINTF (lb, sizeof(lb), "%s", inst);
160         }
161
162       tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
163     }
164   else
165     {
166       tvsprintf (lb, sizeof(lb), fmt, ap);
167     }
168
169   while (isspace (*lbp))
170     {
171       lbp++;
172     }
173
174   if (lbp && *lbp)
175     {
176       lineCurr = (lineCurr ?
177                   connectLine (lineCurr, newLineNode (lb)) :
178                   (lineHead = newLineNode (lb)));
179     }
180
181   lineCurr->isInline = _G.inLine;
182   lineCurr->isDebug = _G.debugLine;
183   lineCurr->ic = _G.current_iCode;
184   lineCurr->aln = ds390newAsmLineNode(_currentDPS);
185   va_end (ap);
186 }
187
188 /*-----------------------------------------------------------------*/
189 /* ds390_emitDebuggerSymbol - associate the current code location  */
190 /*   with a debugger symbol                                        */
191 /*-----------------------------------------------------------------*/
192 void
193 ds390_emitDebuggerSymbol (char * debugSym)
194 {
195   _G.debugLine = 1;
196   emitcode ("", "%s ==.", debugSym);
197   _G.debugLine = 0;
198 }
199
200 //
201 // Move the passed value into A unless it is already there.
202 //
203 static void
204 _movA(const char *s)
205 {
206     if (strcmp(s,"a") && strcmp(s,"acc"))
207     {
208         emitcode("mov","a,%s",s);
209     }
210 }
211
212 //
213 // Move the passed value into B unless it is already there.
214 //
215 static void
216 _movB(const char *s)
217 {
218     if (strcmp(s,"b"))
219     {
220         emitcode("mov","b,%s",s);
221     }
222 }
223
224 /*-----------------------------------------------------------------*/
225 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
226 /*-----------------------------------------------------------------*/
227 static regs *
228 getFreePtr (iCode * ic, asmop ** aopp, bool result)
229 {
230   bool r0iu, r1iu;
231   bool r0ou, r1ou;
232
233   /* the logic: if r0 & r1 used in the instruction
234      then we are in trouble otherwise */
235
236   /* first check if r0 & r1 are used by this
237      instruction, in which case we are in trouble */
238   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
239   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
240   if (r0iu && r1iu) {
241       goto endOfWorld;
242     }
243
244   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
245   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
246
247   /* if no usage of r0 then return it */
248   if (!r0iu && !r0ou)
249     {
250       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
251       (*aopp)->type = AOP_R0;
252
253       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
254     }
255
256   /* if no usage of r1 then return it */
257   if (!r1iu && !r1ou)
258     {
259       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
260       (*aopp)->type = AOP_R1;
261
262       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
263     }
264
265   /* now we know they both have usage */
266   /* if r0 not used in this instruction */
267   if (!r0iu)
268     {
269       /* push it if not already pushed */
270       if (!_G.r0Pushed)
271         {
272           emitcode ("push", "%s",
273                     ds390_regWithIdx (R0_IDX)->dname);
274           _G.r0Pushed++;
275         }
276
277       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
278       (*aopp)->type = AOP_R0;
279
280       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
281     }
282
283   /* if r1 not used then */
284
285   if (!r1iu)
286     {
287       /* push it if not already pushed */
288       if (!_G.r1Pushed)
289         {
290           emitcode ("push", "%s",
291                     ds390_regWithIdx (R1_IDX)->dname);
292           _G.r1Pushed++;
293         }
294
295       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
296       (*aopp)->type = AOP_R1;
297       return ds390_regWithIdx (R1_IDX);
298     }
299
300 endOfWorld:
301   /* I said end of world but not quite end of world yet */
302   /* if this is a result then we can push it on the stack */
303   if (result)
304     {
305       (*aopp)->type = AOP_STK;
306       return NULL;
307     }
308
309   /* other wise this is true end of the world */
310   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
311           "getFreePtr should never reach here");
312   exit (1);
313
314   return NULL; // notreached, but makes compiler happy.
315 }
316
317 /*-----------------------------------------------------------------*/
318 /* newAsmop - creates a new asmOp                                  */
319 /*-----------------------------------------------------------------*/
320 static asmop *
321 newAsmop (short type)
322 {
323   asmop *aop;
324
325   aop = Safe_calloc (1, sizeof (asmop));
326   aop->type = type;
327   return aop;
328 }
329
330
331 /*-----------------------------------------------------------------*/
332 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
333 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
334 /* alternate DPTR (DPL1/DPH1/DPX1).          */
335 /*-----------------------------------------------------------------*/
336 static void
337 genSetDPTR (int n)
338 {
339
340   /* If we are doing lazy evaluation, simply note the desired
341    * change, but don't emit any code yet.
342    */
343   if (_lazyDPS)
344     {
345       _desiredDPS = n;
346       return;
347     }
348
349   if (!n)
350     {
351       emitcode ("mov", "dps,#0");
352     }
353   else
354     {
355       TR_DPTR("#1");
356       emitcode ("mov", "dps,#1");
357     }
358 }
359
360 /*-----------------------------------------------------------------*/
361 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
362 /*                   */
363 /* Any code that operates on DPTR (NB: not on the individual     */
364 /* components, like DPH) *must* call _flushLazyDPS() before using  */
365 /* DPTR within a lazy DPS evaluation block.        */
366 /*                   */
367 /* Note that aopPut and aopGet already contain the proper calls to */
368 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
369 /* DPS evaluation block.             */
370 /*                   */
371 /* Also, _flushLazyDPS must be called before any flow control      */
372 /* operations that could potentially branch out of the block.    */
373 /*                         */
374 /* Lazy DPS evaluation is simply an optimization (though an      */
375 /* important one), so if in doubt, leave it out.       */
376 /*-----------------------------------------------------------------*/
377 static void
378 _startLazyDPSEvaluation (void)
379 {
380   _currentDPS = 0;
381   _desiredDPS = 0;
382 #ifdef BETTER_LITERAL_SHIFT
383   _lazyDPS++;
384 #else
385   _lazyDPS = 1;
386 #endif
387 }
388
389 /*-----------------------------------------------------------------*/
390 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
391 /* desired one. Call before using DPTR within a lazy DPS evaluation */
392 /* block.                */
393 /*-----------------------------------------------------------------*/
394 static void
395 _flushLazyDPS (void)
396 {
397   if (!_lazyDPS)
398     {
399       /* nothing to do. */
400       return;
401     }
402
403   if (_desiredDPS != _currentDPS)
404     {
405       if (_desiredDPS)
406         {
407           emitcode ("inc", "dps");
408         }
409       else
410         {
411           emitcode ("dec", "dps");
412         }
413       _currentDPS = _desiredDPS;
414     }
415 }
416
417 /*-----------------------------------------------------------------*/
418 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
419 /*                   */
420 /* Forces us back to the safe state (standard DPTR selected).    */
421 /*-----------------------------------------------------------------*/
422 static void
423 _endLazyDPSEvaluation (void)
424 {
425 #ifdef BETTER_LITERAL_SHIFT
426   _lazyDPS--;
427 #else
428   _lazyDPS = 0;
429 #endif
430   if (!_lazyDPS)
431   {
432     if (_currentDPS)
433     {
434       genSetDPTR (0);
435       _flushLazyDPS ();
436     }
437     _currentDPS = 0;
438     _desiredDPS = 0;
439   }
440 }
441
442
443
444 /*-----------------------------------------------------------------*/
445 /* pointerCode - returns the code for a pointer type               */
446 /*-----------------------------------------------------------------*/
447 static int
448 pointerCode (sym_link * etype)
449 {
450
451   return PTR_TYPE (SPEC_OCLS (etype));
452
453 }
454
455 /*-----------------------------------------------------------------*/
456 /* leftRightUseAcc - returns size of accumulator use by operands   */
457 /*-----------------------------------------------------------------*/
458 static int
459 leftRightUseAcc(iCode *ic)
460 {
461   operand *op;
462   int size;
463   int accuseSize = 0;
464   int accuse = 0;
465
466   if (!ic)
467     {
468       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
469               "null iCode pointer");
470       return 0;
471     }
472
473   if (ic->op == IFX)
474     {
475       op = IC_COND (ic);
476       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
477         {
478           accuse = 1;
479           size = getSize (OP_SYMBOL (op)->type);
480           if (size>accuseSize)
481             accuseSize = size;
482         }
483     }
484   else if (ic->op == JUMPTABLE)
485     {
486       op = IC_JTCOND (ic);
487       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
488         {
489           accuse = 1;
490           size = getSize (OP_SYMBOL (op)->type);
491           if (size>accuseSize)
492             accuseSize = size;
493         }
494     }
495   else
496     {
497       op = IC_LEFT (ic);
498       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
499         {
500           accuse = 1;
501           size = getSize (OP_SYMBOL (op)->type);
502           if (size>accuseSize)
503             accuseSize = size;
504         }
505       op = IC_RIGHT (ic);
506       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
507         {
508           accuse = 1;
509           size = getSize (OP_SYMBOL (op)->type);
510           if (size>accuseSize)
511             accuseSize = size;
512         }
513     }
514
515   if (accuseSize)
516     return accuseSize;
517   else
518     return accuse;
519 }
520
521 /*-----------------------------------------------------------------*/
522 /* aopForSym - for a true symbol                                   */
523 /*-----------------------------------------------------------------*/
524 static asmop *
525 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
526 {
527   asmop *aop;
528   memmap *space = SPEC_OCLS (sym->etype);
529   int accuse = leftRightUseAcc (ic);
530
531   /* if already has one */
532   if (sym->aop)
533     {
534       if ((sym->aop->type == AOP_DPTR && useDP2)
535           || (sym->aop->type == AOP_DPTR2 && !useDP2))
536         sym->aop = NULL;
537       else
538         return sym->aop;
539     }
540
541   /* assign depending on the storage class */
542   /* if it is on the stack or indirectly addressable */
543   /* space we need to assign either r0 or r1 to it   */
544   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
545     {
546       sym->aop = aop = newAsmop (0);
547       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
548       aop->size = getSize (sym->type);
549
550       /* now assign the address of the variable to
551          the pointer register */
552       if (aop->type != AOP_STK)
553         {
554
555           if (sym->onStack)
556             {
557               if (_G.accInUse || accuse)
558                 emitcode ("push", "acc");
559
560               if (_G.bInUse || (accuse>1))
561                 emitcode ("push", "b");
562
563               emitcode ("mov", "a,_bp");
564               emitcode ("add", "a,#!constbyte",
565                         ((sym->stack < 0) ?
566                          ((char) (sym->stack - _G.nRegsSaved)) :
567                          ((char) sym->stack)) & 0xff);
568               emitcode ("mov", "%s,a",
569                         aop->aopu.aop_ptr->name);
570
571               if (_G.bInUse || (accuse>1))
572                 emitcode ("pop", "b");
573
574               if (_G.accInUse || accuse)
575                 emitcode ("pop", "acc");
576             }
577           else
578             emitcode ("mov", "%s,#%s",
579                       aop->aopu.aop_ptr->name,
580                       sym->rname);
581           aop->paged = space->paged;
582         }
583       else
584         aop->aopu.aop_stk = sym->stack;
585       return aop;
586     }
587
588   if (sym->onStack && options.stack10bit)
589     {
590         short stack_val = -((sym->stack < 0) ?
591                             ((short) (sym->stack - _G.nRegsSaved)) :
592                             ((short) sym->stack)) ;
593         if (useDP2 && _G.dptr1InUse) {
594             emitcode ("push","dpl1");
595             emitcode ("push","dph1");
596             emitcode ("push","dpx1");
597         } else if (_G.dptrInUse ) {
598             emitcode ("push","dpl");
599             emitcode ("push","dph");
600             emitcode ("push","dpx");
601         }
602       /* It's on the 10 bit stack, which is located in
603        * far data space.
604        */
605         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
606             if (useDP2) {
607                 if (options.model == MODEL_FLAT24)
608                 {
609                     emitcode ("mov", "dpx1,#!constbyte",
610                               (options.stack_loc >> 16) & 0xff);
611                 }
612                 emitcode ("mov", "dph1,_bpx+1");
613
614                 emitcode ("mov", "dpl1,_bpx");
615                 emitcode ("mov","dps,#1");
616             } else {
617                 if (options.model == MODEL_FLAT24)
618                 {
619                     emitcode ("mov", "dpx,#!constbyte",
620                               (options.stack_loc >> 16) & 0xff);
621                 }
622                 emitcode ("mov", "dph,_bpx+1");
623                 emitcode ("mov", "dpl,_bpx");
624             }
625             stack_val = -stack_val;
626             while (stack_val--) {
627                 emitcode ("inc","dptr");
628             }
629             if (useDP2) {
630                 emitcode("mov","dps,#0");
631             }
632         }  else {
633             if (_G.accInUse || accuse)
634                 emitcode ("push", "acc");
635
636             if (_G.bInUse || (accuse>1))
637                 emitcode ("push", "b");
638
639             emitcode ("mov", "a,_bpx");
640             emitcode ("clr","c");
641             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
642             emitcode ("mov","b,a");
643             emitcode ("mov","a,_bpx+1");
644             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
645             if (useDP2) {
646                 if (options.model == MODEL_FLAT24)
647                 {
648                     emitcode ("mov", "dpx1,#!constbyte",
649                               (options.stack_loc >> 16) & 0xff);
650                 }
651                 emitcode ("mov", "dph1,a");
652                 emitcode ("mov", "dpl1,b");
653             } else {
654                 if (options.model == MODEL_FLAT24)
655                 {
656                     emitcode ("mov", "dpx,#!constbyte",
657                               (options.stack_loc >> 16) & 0xff);
658                 }
659                 emitcode ("mov", "dph,a");
660                 emitcode ("mov", "dpl,b");
661             }
662
663             if (_G.bInUse || (accuse>1))
664                 emitcode ("pop", "b");
665
666             if (_G.accInUse || accuse)
667                 emitcode ("pop", "acc");
668         }
669         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
670         aop->size = getSize (sym->type);
671         return aop;
672     }
673
674   /* if in bit space */
675   if (IN_BITSPACE (space))
676     {
677       sym->aop = aop = newAsmop (AOP_CRY);
678       aop->aopu.aop_dir = sym->rname;
679       aop->size = getSize (sym->type);
680       return aop;
681     }
682   /* if it is in direct space */
683   if (IN_DIRSPACE (space))
684     {
685       sym->aop = aop = newAsmop (AOP_DIR);
686       aop->aopu.aop_dir = sym->rname;
687       aop->size = getSize (sym->type);
688       return aop;
689     }
690
691   /* special case for a function */
692   if (IS_FUNC (sym->type) && !(sym->isitmp))
693     {
694       sym->aop = aop = newAsmop (AOP_IMMD);
695       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
696       aop->size = FPTRSIZE;
697       return aop;
698     }
699
700   /* only remaining is far space */
701   /* in which case DPTR gets the address */
702   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
703   if (useDP2)
704     {
705       genSetDPTR (1);
706       _flushLazyDPS ();
707       emitcode ("mov", "dptr,#%s", sym->rname);
708       genSetDPTR (0);
709     }
710   else
711     {
712       emitcode ("mov", "dptr,#%s", sym->rname);
713     }
714   aop->size = getSize (sym->type);
715
716   /* if it is in code space */
717   if (IN_CODESPACE (space))
718     aop->code = 1;
719
720   return aop;
721 }
722
723 /*-----------------------------------------------------------------*/
724 /* aopForRemat - rematerialzes an object                           */
725 /*-----------------------------------------------------------------*/
726 static asmop *
727 aopForRemat (symbol * sym)
728 {
729   iCode *ic = sym->rematiCode;
730   asmop *aop = newAsmop (AOP_IMMD);
731   int ptr_type = 0;
732   int val = 0;
733
734   for (;;)
735     {
736       if (ic->op == '+')
737         val += (int) operandLitValue (IC_RIGHT (ic));
738       else if (ic->op == '-')
739         val -= (int) operandLitValue (IC_RIGHT (ic));
740       else if (IS_CAST_ICODE(ic)) {
741               sym_link *from_type = operandType(IC_RIGHT(ic));
742               aop->aopu.aop_immd.from_cast_remat = 1;
743               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
744               ptr_type = DCL_TYPE(from_type);
745               if (ptr_type == IPOINTER) {
746                 // bug #481053
747                 ptr_type = POINTER;
748               }
749               continue ;
750       } else break;
751
752       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
753     }
754
755   if (val)
756   {
757       SNPRINTF (buffer, sizeof(buffer),
758                 "(%s %c 0x%04x)",
759                 OP_SYMBOL (IC_LEFT (ic))->rname,
760                 val >= 0 ? '+' : '-',
761                 abs (val) & 0xffffff);
762   }
763   else
764   {
765       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
766       {
767           SNPRINTF(buffer, sizeof(buffer),
768                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
769       }
770       else
771       {
772           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
773       }
774   }
775
776   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
777   /* set immd2 field if required */
778   if (aop->aopu.aop_immd.from_cast_remat)
779   {
780       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
781       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
782   }
783
784   return aop;
785 }
786
787 /*-----------------------------------------------------------------*/
788 /* aopHasRegs - returns true if aop has regs between from-to       */
789 /*-----------------------------------------------------------------*/
790 static int aopHasRegs(asmop *aop, int from, int to)
791 {
792     int size =0;
793
794     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
795
796     for (; size < aop->size ; size++) {
797         int reg;
798         for (reg = from ; reg <= to ; reg++)
799             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
800     }
801     return 0;
802 }
803
804 /*-----------------------------------------------------------------*/
805 /* regsInCommon - two operands have some registers in common       */
806 /*-----------------------------------------------------------------*/
807 static bool
808 regsInCommon (operand * op1, operand * op2)
809 {
810   symbol *sym1, *sym2;
811   int i;
812
813   /* if they have registers in common */
814   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
815     return FALSE;
816
817   sym1 = OP_SYMBOL (op1);
818   sym2 = OP_SYMBOL (op2);
819
820   if (sym1->nRegs == 0 || sym2->nRegs == 0)
821     return FALSE;
822
823   for (i = 0; i < sym1->nRegs; i++)
824     {
825       int j;
826       if (!sym1->regs[i])
827         continue;
828
829       for (j = 0; j < sym2->nRegs; j++)
830         {
831           if (!sym2->regs[j])
832             continue;
833
834           if (sym2->regs[j] == sym1->regs[i])
835             return TRUE;
836         }
837     }
838
839   return FALSE;
840 }
841
842 /*-----------------------------------------------------------------*/
843 /* operandsEqu - equivalent                                        */
844 /*-----------------------------------------------------------------*/
845 static bool
846 operandsEqu (operand * op1, operand * op2)
847 {
848   symbol *sym1, *sym2;
849
850   /* if they not symbols */
851   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
852     return FALSE;
853
854   sym1 = OP_SYMBOL (op1);
855   sym2 = OP_SYMBOL (op2);
856
857   /* if both are itemps & one is spilt
858      and the other is not then false */
859   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
860       sym1->isspilt != sym2->isspilt)
861     return FALSE;
862
863   /* if they are the same */
864   if (sym1 == sym2)
865     return TRUE;
866
867   if (sym1->rname[0] && sym2->rname[0]
868       && strcmp (sym1->rname, sym2->rname) == 0)
869     return TRUE;
870
871   /* if left is a tmp & right is not */
872   if (IS_ITEMP (op1) &&
873       !IS_ITEMP (op2) &&
874       sym1->isspilt &&
875       (sym1->usl.spillLoc == sym2))
876     return TRUE;
877
878   if (IS_ITEMP (op2) &&
879       !IS_ITEMP (op1) &&
880       sym2->isspilt &&
881       sym1->level > 0 &&
882       (sym2->usl.spillLoc == sym1))
883     return TRUE;
884
885   /* are they spilt to the same location */
886   if (IS_ITEMP (op2) &&
887       IS_ITEMP (op1) &&
888       sym2->isspilt &&
889       sym1->isspilt &&
890       (sym1->usl.spillLoc == sym2->usl.spillLoc))
891     return TRUE;
892
893   return FALSE;
894 }
895
896 /*-----------------------------------------------------------------*/
897 /* sameRegs - two asmops have the same registers                   */
898 /*-----------------------------------------------------------------*/
899 static bool
900 sameRegs (asmop * aop1, asmop * aop2)
901 {
902   int i;
903
904   if (aop1 == aop2)
905     {
906       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
907         {
908           return FALSE;
909         }
910       return TRUE;
911     }
912
913   if (aop1->type != AOP_REG ||
914       aop2->type != AOP_REG)
915     return FALSE;
916
917   if (aop1->size != aop2->size)
918     return FALSE;
919
920   for (i = 0; i < aop1->size; i++)
921     if (aop1->aopu.aop_reg[i] !=
922         aop2->aopu.aop_reg[i])
923       return FALSE;
924
925   return TRUE;
926 }
927
928 /*-----------------------------------------------------------------*/
929 /* aopOp - allocates an asmop for an operand  :                    */
930 /*-----------------------------------------------------------------*/
931 static void
932 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
933 {
934   asmop *aop;
935   symbol *sym;
936   int i;
937
938   if (!op)
939     return;
940
941   /* if this a literal */
942   if (IS_OP_LITERAL (op))
943     {
944       op->aop = aop = newAsmop (AOP_LIT);
945       aop->aopu.aop_lit = op->operand.valOperand;
946       aop->size = getSize (operandType (op));
947       return;
948     }
949
950   /* if already has a asmop then continue */
951   if (op->aop)
952     {
953       if ((op->aop->type == AOP_DPTR && useDP2)
954           || (op->aop->type == AOP_DPTR2 && !useDP2))
955         op->aop = NULL;
956       else
957         return;
958     }
959
960   /* if the underlying symbol has a aop */
961   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
962     {
963       op->aop = OP_SYMBOL (op)->aop;
964       if ((op->aop->type == AOP_DPTR && useDP2)
965           || (op->aop->type == AOP_DPTR2 && !useDP2))
966         op->aop = NULL;
967       else
968         return;
969     }
970
971   /* if this is a true symbol */
972   if (IS_TRUE_SYMOP (op))
973     {
974       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
975       return;
976     }
977
978   /* this is a temporary : this has
979      only four choices :
980      a) register
981      b) spillocation
982      c) rematerialize
983      d) conditional
984      e) can be a return use only */
985
986   sym = OP_SYMBOL (op);
987
988   /* if the type is a conditional */
989   if (sym->regType == REG_CND)
990     {
991       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
992       aop->size = 0;
993       return;
994     }
995
996   /* if it is spilt then two situations
997      a) is rematerialize
998      b) has a spill location */
999   if (sym->isspilt || sym->nRegs == 0)
1000     {
1001
1002       /* rematerialize it NOW */
1003       if (sym->remat)
1004         {
1005           sym->aop = op->aop = aop =
1006             aopForRemat (sym);
1007           aop->size = getSize (sym->type);
1008           return;
1009         }
1010
1011       if (sym->accuse)
1012         {
1013           int i;
1014           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1015           aop->size = getSize (sym->type);
1016           for (i = 0; i < 2; i++)
1017             aop->aopu.aop_str[i] = accUse[i];
1018           return;
1019         }
1020
1021       if (sym->ruonly)
1022         {
1023           int i;
1024
1025           if (useDP2)
1026             {
1027               /* a AOP_STR uses DPTR, but DPTR is already in use;
1028                * we're just hosed.
1029                */
1030                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1031             }
1032
1033           aop = op->aop = sym->aop = newAsmop (AOP_STR);
1034           aop->size = getSize (sym->type);
1035           for (i = 0; i < fReturnSizeDS390; i++)
1036             aop->aopu.aop_str[i] = fReturn[i];
1037           return;
1038         }
1039
1040       if (sym->dptr) { /* has been allocated to a DPTRn */
1041           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1042           aop->size = getSize (sym->type);
1043           aop->aopu.dptr = sym->dptr;
1044           return ;
1045       }
1046
1047       if (sym->usl.spillLoc)
1048         {
1049           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1050             {
1051               /* force a new aop if sizes differ */
1052               sym->usl.spillLoc->aop = NULL;
1053             }
1054           sym->aop = op->aop = aop =
1055                      aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1056           aop->size = getSize (sym->type);
1057           return;
1058         }
1059
1060       /* else must be a dummy iTemp */
1061       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1062       aop->size = getSize (sym->type);
1063       return;
1064     }
1065
1066   /* must be in a register */
1067   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1068   aop->size = sym->nRegs;
1069   for (i = 0; i < sym->nRegs; i++)
1070     aop->aopu.aop_reg[i] = sym->regs[i];
1071 }
1072
1073 /*-----------------------------------------------------------------*/
1074 /* freeAsmop - free up the asmop given to an operand               */
1075 /*----------------------------------------------------------------*/
1076 static void
1077 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1078 {
1079   asmop *aop;
1080
1081   if (!op)
1082     aop = aaop;
1083   else
1084     aop = op->aop;
1085
1086   if (!aop)
1087     return;
1088
1089   if (aop->freed)
1090     goto dealloc;
1091
1092   aop->freed = 1;
1093
1094   /* depending on the asmop type only three cases need work AOP_RO
1095      , AOP_R1 && AOP_STK */
1096   switch (aop->type)
1097     {
1098     case AOP_R0:
1099       if (_G.r0Pushed)
1100         {
1101           if (pop)
1102             {
1103               emitcode ("pop", "ar0");
1104               _G.r0Pushed--;
1105             }
1106         }
1107       bitVectUnSetBit (ic->rUsed, R0_IDX);
1108       break;
1109
1110     case AOP_R1:
1111       if (_G.r1Pushed)
1112         {
1113           if (pop)
1114             {
1115               emitcode ("pop", "ar1");
1116               _G.r1Pushed--;
1117             }
1118         }
1119       bitVectUnSetBit (ic->rUsed, R1_IDX);
1120       break;
1121
1122     case AOP_STK:
1123       {
1124         int sz = aop->size;
1125         int stk = aop->aopu.aop_stk + aop->size;
1126         bitVectUnSetBit (ic->rUsed, R0_IDX);
1127         bitVectUnSetBit (ic->rUsed, R1_IDX);
1128
1129         getFreePtr (ic, &aop, FALSE);
1130
1131         if (options.stack10bit)
1132           {
1133             /* I'm not sure what to do here yet... */
1134             /* #STUB */
1135             fprintf (stderr,
1136                      "*** Warning: probably generating bad code for "
1137                      "10 bit stack mode.\n");
1138           }
1139
1140         if (stk)
1141           {
1142             emitcode ("mov", "a,_bp");
1143             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1144             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1145           }
1146         else
1147           {
1148             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1149           }
1150
1151         while (sz--)
1152           {
1153             emitcode ("pop", "acc");
1154             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1155             if (!sz)
1156               break;
1157             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1158           }
1159         op->aop = aop;
1160         freeAsmop (op, NULL, ic, TRUE);
1161         if (_G.r0Pushed)
1162           {
1163             emitcode ("pop", "ar0");
1164             _G.r0Pushed--;
1165           }
1166
1167         if (_G.r1Pushed)
1168           {
1169             emitcode ("pop", "ar1");
1170             _G.r1Pushed--;
1171           }
1172       }
1173     case AOP_DPTR2:
1174         if (_G.dptr1InUse) {
1175             emitcode ("pop","dpx1");
1176             emitcode ("pop","dph1");
1177             emitcode ("pop","dpl1");
1178         }
1179         break;
1180     case AOP_DPTR:
1181         if (_G.dptrInUse) {
1182             emitcode ("pop","dpx");
1183             emitcode ("pop","dph");
1184             emitcode ("pop","dpl");
1185         }
1186         break;
1187     }
1188 dealloc:
1189   /* all other cases just dealloc */
1190   if (op)
1191     {
1192       op->aop = NULL;
1193       if (IS_SYMOP (op))
1194         {
1195           OP_SYMBOL (op)->aop = NULL;
1196           /* if the symbol has a spill */
1197           if (SPIL_LOC (op))
1198             SPIL_LOC (op)->aop = NULL;
1199         }
1200     }
1201 }
1202
1203 #define DEFAULT_ACC_WARNING 0
1204 static int saveAccWarn = DEFAULT_ACC_WARNING;
1205
1206 /*-------------------------------------------------------------------*/
1207 /* aopGet - for fetching value of the aop                            */
1208 /*                                                                   */
1209 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1210 /* in the accumulator. Set it to the name of a free register         */
1211 /* if acc must be preserved; the register will be used to preserve   */
1212 /* acc temporarily and to return the result byte.                    */
1213 /*-------------------------------------------------------------------*/
1214
1215 static char *
1216 aopGet (asmop *aop,
1217         int   offset,
1218         bool  bit16,
1219         bool  dname,
1220         char  *saveAcc)
1221 {
1222   /* offset is greater than
1223      size then zero */
1224   if (offset > (aop->size - 1) &&
1225       aop->type != AOP_LIT)
1226     return zero;
1227
1228   /* depending on type */
1229   switch (aop->type)
1230     {
1231     case AOP_DUMMY:
1232       return zero;
1233
1234     case AOP_R0:
1235     case AOP_R1:
1236       /* if we need to increment it */
1237       while (offset > aop->coff)
1238         {
1239           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1240           aop->coff++;
1241         }
1242
1243       while (offset < aop->coff)
1244         {
1245           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1246           aop->coff--;
1247         }
1248
1249       aop->coff = offset;
1250       if (aop->paged)
1251         {
1252           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1253           return (dname ? "acc" : "a");
1254         }
1255       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1256       return Safe_strdup(buffer);
1257
1258     case AOP_DPTRn:
1259         assert(offset <= 3);
1260         return dptrn[aop->aopu.dptr][offset];
1261
1262     case AOP_DPTR:
1263     case AOP_DPTR2:
1264
1265       if (aop->type == AOP_DPTR2)
1266         {
1267           genSetDPTR (1);
1268         }
1269
1270       if (saveAcc)
1271         {
1272             TR_AP("#1");
1273 //          if (aop->type != AOP_DPTR2)
1274 //          {
1275 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1276 //              emitcode(";", "spanky: saveAcc for DPTR");
1277 //          }
1278
1279             emitcode ("xch", "a, %s", saveAcc);
1280         }
1281
1282       _flushLazyDPS ();
1283
1284       while (offset > aop->coff)
1285         {
1286           emitcode ("inc", "dptr");
1287           aop->coff++;
1288         }
1289
1290       while (offset < aop->coff)
1291         {
1292           emitcode ("lcall", "__decdptr");
1293           aop->coff--;
1294         }
1295
1296       aop->coff = offset;
1297       if (aop->code)
1298         {
1299           emitcode ("clr", "a");
1300           emitcode ("movc", "a,@a+dptr");
1301         }
1302       else
1303         {
1304           emitcode ("movx", "a,@dptr");
1305         }
1306
1307       if (aop->type == AOP_DPTR2)
1308         {
1309           genSetDPTR (0);
1310         }
1311
1312         if (saveAcc)
1313         {
1314        TR_AP("#2");
1315               emitcode ("xch", "a, %s", saveAcc);
1316 //            if (strcmp(saveAcc, "_ap"))
1317 //            {
1318 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1319 //            }
1320
1321               return saveAcc;
1322         }
1323       return (dname ? "acc" : "a");
1324
1325     case AOP_IMMD:
1326       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1327       {
1328           SNPRINTF(buffer, sizeof(buffer),
1329                    "%s",aop->aopu.aop_immd.aop_immd2);
1330       }
1331       else if (bit16)
1332       {
1333          SNPRINTF(buffer, sizeof(buffer),
1334                   "#%s", aop->aopu.aop_immd.aop_immd1);
1335       }
1336       else if (offset)
1337       {
1338           switch (offset) {
1339           case 1:
1340               tsprintf(buffer, sizeof(buffer),
1341                        "#!his",aop->aopu.aop_immd.aop_immd1);
1342               break;
1343           case 2:
1344               tsprintf(buffer, sizeof(buffer),
1345                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1346               break;
1347           case 3:
1348               tsprintf(buffer, sizeof(buffer),
1349                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1350               break;
1351           default: /* should not need this (just in case) */
1352               SNPRINTF (buffer, sizeof(buffer),
1353                         "#(%s >> %d)",
1354                        aop->aopu.aop_immd.aop_immd1,
1355                        offset * 8);
1356           }
1357       }
1358       else
1359       {
1360         SNPRINTF (buffer, sizeof(buffer),
1361                   "#%s", aop->aopu.aop_immd.aop_immd1);
1362       }
1363       return Safe_strdup(buffer);
1364
1365     case AOP_DIR:
1366       if (offset)
1367       {
1368         SNPRINTF (buffer, sizeof(buffer),
1369                   "(%s + %d)",
1370                  aop->aopu.aop_dir,
1371                  offset);
1372       }
1373       else
1374       {
1375         SNPRINTF(buffer, sizeof(buffer),
1376                  "%s", aop->aopu.aop_dir);
1377       }
1378
1379       return Safe_strdup(buffer);
1380
1381     case AOP_REG:
1382       if (dname)
1383         return aop->aopu.aop_reg[offset]->dname;
1384       else
1385         return aop->aopu.aop_reg[offset]->name;
1386
1387     case AOP_CRY:
1388       emitcode ("clr", "a");
1389       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1390       emitcode ("rlc", "a");
1391       return (dname ? "acc" : "a");
1392
1393     case AOP_ACC:
1394       if (!offset && dname)
1395         return "acc";
1396       return aop->aopu.aop_str[offset];
1397
1398     case AOP_LIT:
1399       return aopLiteral (aop->aopu.aop_lit, offset);
1400
1401     case AOP_STR:
1402       aop->coff = offset;
1403       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1404           dname)
1405         return "acc";
1406
1407       return aop->aopu.aop_str[offset];
1408
1409     }
1410
1411   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1412           "aopget got unsupported aop->type");
1413   exit (1);
1414
1415   return NULL;  // not reached, but makes compiler happy.
1416 }
1417 /*-----------------------------------------------------------------*/
1418 /* aopPut - puts a string for a aop                                */
1419 /*-----------------------------------------------------------------*/
1420 static void
1421 aopPut (asmop * aop, char *s, int offset)
1422 {
1423   if (aop->size && offset > (aop->size - 1))
1424     {
1425       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1426               "aopPut got offset > aop->size");
1427       exit (1);
1428     }
1429
1430   /* will assign value to value */
1431   /* depending on where it is ofcourse */
1432   switch (aop->type)
1433     {
1434     case AOP_DUMMY:
1435       MOVA (s);         /* read s in case it was volatile */
1436       break;
1437
1438     case AOP_DIR:
1439         if (offset)
1440         {
1441             SNPRINTF (buffer, sizeof(buffer),
1442                       "(%s + %d)",
1443                       aop->aopu.aop_dir, offset);
1444         }
1445         else
1446         {
1447             SNPRINTF (buffer, sizeof(buffer),
1448                      "%s", aop->aopu.aop_dir);
1449         }
1450
1451
1452         if (strcmp (buffer, s))
1453         {
1454             emitcode ("mov", "%s,%s", buffer, s);
1455         }
1456       break;
1457
1458     case AOP_REG:
1459       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1460           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1461         {
1462           if (*s == '@' ||
1463               strcmp (s, "r0") == 0 ||
1464               strcmp (s, "r1") == 0 ||
1465               strcmp (s, "r2") == 0 ||
1466               strcmp (s, "r3") == 0 ||
1467               strcmp (s, "r4") == 0 ||
1468               strcmp (s, "r5") == 0 ||
1469               strcmp (s, "r6") == 0 ||
1470               strcmp (s, "r7") == 0)
1471             {
1472                 emitcode ("mov", "%s,%s",
1473                           aop->aopu.aop_reg[offset]->dname, s);
1474             }
1475             else
1476             {
1477                 emitcode ("mov", "%s,%s",
1478                           aop->aopu.aop_reg[offset]->name, s);
1479             }
1480         }
1481       break;
1482
1483     case AOP_DPTRn:
1484         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1485         break;
1486
1487     case AOP_DPTR:
1488     case AOP_DPTR2:
1489
1490       if (aop->type == AOP_DPTR2)
1491         {
1492           genSetDPTR (1);
1493         }
1494       _flushLazyDPS ();
1495
1496       if (aop->code)
1497         {
1498           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1499                   "aopPut writting to code space");
1500           exit (1);
1501         }
1502
1503       while (offset > aop->coff)
1504         {
1505           aop->coff++;
1506           emitcode ("inc", "dptr");
1507         }
1508
1509       while (offset < aop->coff)
1510         {
1511           aop->coff--;
1512           emitcode ("lcall", "__decdptr");
1513         }
1514
1515       aop->coff = offset;
1516
1517       /* if not in accumulater */
1518       MOVA (s);
1519
1520       emitcode ("movx", "@dptr,a");
1521
1522       if (aop->type == AOP_DPTR2)
1523         {
1524           genSetDPTR (0);
1525         }
1526       break;
1527
1528     case AOP_R0:
1529     case AOP_R1:
1530       while (offset > aop->coff)
1531         {
1532           aop->coff++;
1533           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1534         }
1535       while (offset < aop->coff)
1536         {
1537           aop->coff--;
1538           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1539         }
1540       aop->coff = offset;
1541
1542       if (aop->paged)
1543         {
1544           MOVA (s);
1545           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1546
1547         }
1548       else if (*s == '@')
1549         {
1550           MOVA (s);
1551           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1552         }
1553       else if (strcmp (s, "r0") == 0 ||
1554                strcmp (s, "r1") == 0 ||
1555                strcmp (s, "r2") == 0 ||
1556                strcmp (s, "r3") == 0 ||
1557                strcmp (s, "r4") == 0 ||
1558                strcmp (s, "r5") == 0 ||
1559                strcmp (s, "r6") == 0 ||
1560                strcmp (s, "r7") == 0)
1561         {
1562           char buff[10];
1563           SNPRINTF(buff, sizeof(buff),
1564                    "a%s", s);
1565           emitcode ("mov", "@%s,%s",
1566                     aop->aopu.aop_ptr->name, buff);
1567         }
1568         else
1569         {
1570             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1571         }
1572       break;
1573
1574     case AOP_STK:
1575       if (strcmp (s, "a") == 0)
1576         emitcode ("push", "acc");
1577       else
1578         if (*s=='@') {
1579           MOVA(s);
1580           emitcode ("push", "acc");
1581         } else {
1582           emitcode ("push", s);
1583         }
1584
1585       break;
1586
1587     case AOP_CRY:
1588       /* if bit variable */
1589       if (!aop->aopu.aop_dir)
1590         {
1591           emitcode ("clr", "a");
1592           emitcode ("rlc", "a");
1593         }
1594       else
1595         {
1596           if (s == zero)
1597             emitcode ("clr", "%s", aop->aopu.aop_dir);
1598           else if (s == one)
1599             emitcode ("setb", "%s", aop->aopu.aop_dir);
1600           else if (!strcmp (s, "c"))
1601             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1602           else
1603             {
1604               if (strcmp (s, "a"))
1605                 {
1606                   MOVA (s);
1607                 }
1608               {
1609                 /* set C, if a >= 1 */
1610                 emitcode ("add", "a,#!constbyte",0xff);
1611                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1612               }
1613             }
1614         }
1615       break;
1616
1617     case AOP_STR:
1618       aop->coff = offset;
1619       if (strcmp (aop->aopu.aop_str[offset], s))
1620         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1621       break;
1622
1623     case AOP_ACC:
1624       aop->coff = offset;
1625       if (!offset && (strcmp (s, "acc") == 0))
1626         break;
1627
1628       if (strcmp (aop->aopu.aop_str[offset], s))
1629         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1630       break;
1631
1632     default:
1633       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1634               "aopPut got unsupported aop->type");
1635       exit (1);
1636     }
1637
1638 }
1639
1640
1641 /*--------------------------------------------------------------------*/
1642 /* reAdjustPreg - points a register back to where it should (coff==0) */
1643 /*--------------------------------------------------------------------*/
1644 static void
1645 reAdjustPreg (asmop * aop)
1646 {
1647   if ((aop->coff==0) || (aop->size <= 1)) {
1648     return;
1649   }
1650
1651   switch (aop->type)
1652     {
1653     case AOP_R0:
1654     case AOP_R1:
1655       while (aop->coff--)
1656         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1657       break;
1658     case AOP_DPTR:
1659     case AOP_DPTR2:
1660       if (aop->type == AOP_DPTR2)
1661         {
1662           genSetDPTR (1);
1663           _flushLazyDPS ();
1664         }
1665       while (aop->coff--)
1666         {
1667           emitcode ("lcall", "__decdptr");
1668         }
1669
1670       if (aop->type == AOP_DPTR2)
1671         {
1672           genSetDPTR (0);
1673         }
1674       break;
1675
1676     }
1677   aop->coff=0;
1678 }
1679
1680 #define AOP(op) op->aop
1681 #define AOP_TYPE(op) AOP(op)->type
1682 #define AOP_SIZE(op) AOP(op)->size
1683 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1684                        AOP_TYPE(x) == AOP_R0))
1685
1686 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1687                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1688                          AOP(x)->paged))
1689
1690 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1691                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1692                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1693 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1694 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1695 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1696
1697 // The following two macros can be used even if the aop has not yet been aopOp'd.
1698 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1699 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1700
1701 /* Workaround for DS80C390 bug: div ab may return bogus results
1702  * if A is accessed in instruction immediately before the div.
1703  *
1704  * Will be fixed in B4 rev of processor, Dallas claims.
1705  */
1706
1707 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1708     if (!AOP_NEEDSACC(RIGHT))         \
1709     {               \
1710       /* We can load A first, then B, since     \
1711        * B (the RIGHT operand) won't clobber A,   \
1712        * thus avoiding touching A right before the div. \
1713        */             \
1714       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1715       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1716       MOVA(L);            \
1717       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1718       MOVB(L); \
1719     }               \
1720     else              \
1721     {               \
1722       /* Just stuff in a nop after loading A. */    \
1723       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1724       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1725       MOVA(L);            \
1726       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1727     }
1728
1729
1730 /*-----------------------------------------------------------------*/
1731 /* opIsGptr: returns non-zero if the passed operand is       */
1732 /* a generic pointer type.             */
1733 /*-----------------------------------------------------------------*/
1734 static int
1735 opIsGptr (operand * op)
1736 {
1737   sym_link *type = operandType (op);
1738
1739   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1740     {
1741       return 1;
1742     }
1743   return 0;
1744 }
1745
1746 /*-----------------------------------------------------------------*/
1747 /* getDataSize - get the operand data size                         */
1748 /*-----------------------------------------------------------------*/
1749 static int
1750 getDataSize (operand * op)
1751 {
1752   int size;
1753   size = AOP_SIZE (op);
1754   if (size == GPTRSIZE)
1755     {
1756       sym_link *type = operandType (op);
1757       if (IS_GENPTR (type))
1758         {
1759           /* generic pointer; arithmetic operations
1760            * should ignore the high byte (pointer type).
1761            */
1762           size--;
1763         }
1764     }
1765   return size;
1766 }
1767
1768 /*-----------------------------------------------------------------*/
1769 /* outAcc - output Acc                                             */
1770 /*-----------------------------------------------------------------*/
1771 static void
1772 outAcc (operand * result)
1773 {
1774   int size, offset;
1775   size = getDataSize (result);
1776   if (size)
1777     {
1778       aopPut (AOP (result), "a", 0);
1779       size--;
1780       offset = 1;
1781       /* unsigned or positive */
1782       while (size--)
1783         {
1784           aopPut (AOP (result), zero, offset++);
1785         }
1786     }
1787 }
1788
1789 /*-----------------------------------------------------------------*/
1790 /* outBitC - output a bit C                                        */
1791 /*-----------------------------------------------------------------*/
1792 static void
1793 outBitC (operand * result)
1794 {
1795   /* if the result is bit */
1796   if (AOP_TYPE (result) == AOP_CRY)
1797     {
1798       aopPut (AOP (result), "c", 0);
1799     }
1800   else
1801     {
1802       emitcode ("clr", "a");
1803       emitcode ("rlc", "a");
1804       outAcc (result);
1805     }
1806 }
1807
1808 /*-----------------------------------------------------------------*/
1809 /* toBoolean - emit code for orl a,operator(sizeop)                */
1810 /*-----------------------------------------------------------------*/
1811 static void
1812 toBoolean (operand * oper)
1813 {
1814   int   size = AOP_SIZE (oper) - 1;
1815   int   offset = 1;
1816   bool usedB = FALSE;
1817
1818   /* The generic part of a generic pointer should
1819    * not participate in it's truth value.
1820    *
1821    * i.e. 0x10000000 is zero.
1822    */
1823   if (opIsGptr (oper))
1824     {
1825       D (emitcode (";", "toBoolean: generic ptr special case."););
1826       size--;
1827     }
1828
1829   _startLazyDPSEvaluation ();
1830   if (AOP_NEEDSACC (oper) && size)
1831     {
1832       usedB = TRUE;
1833       if (_G.bInUse)
1834       {
1835           emitcode ("push", "b");
1836       }
1837       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1838     }
1839   else
1840     {
1841       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1842     }
1843
1844   while (size--)
1845     {
1846       if (usedB)
1847         {
1848           emitcode ("orl", "b,%s",
1849                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1850         }
1851       else
1852         {
1853           emitcode ("orl", "a,%s",
1854                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1855         }
1856     }
1857   _endLazyDPSEvaluation ();
1858
1859   if (usedB)
1860     {
1861       emitcode ("mov", "a,b");
1862       if (_G.bInUse)
1863       {
1864           emitcode ("pop", "b");
1865       }
1866
1867     }
1868 }
1869
1870
1871 /*-----------------------------------------------------------------*/
1872 /* genNot - generate code for ! operation                          */
1873 /*-----------------------------------------------------------------*/
1874 static void
1875 genNot (iCode * ic)
1876 {
1877   symbol *tlbl;
1878
1879   D (emitcode (";", "genNot "););
1880
1881   /* assign asmOps to operand & result */
1882   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1883   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1884
1885   /* if in bit space then a special case */
1886   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1887     {
1888       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1889       emitcode ("cpl", "c");
1890       outBitC (IC_RESULT (ic));
1891       goto release;
1892     }
1893
1894   toBoolean (IC_LEFT (ic));
1895
1896   tlbl = newiTempLabel (NULL);
1897   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1898   emitcode ("", "!tlabeldef", tlbl->key + 100);
1899   outBitC (IC_RESULT (ic));
1900
1901 release:
1902   /* release the aops */
1903   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1904   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1905 }
1906
1907
1908 /*-----------------------------------------------------------------*/
1909 /* genCpl - generate code for complement                           */
1910 /*-----------------------------------------------------------------*/
1911 static void
1912 genCpl (iCode * ic)
1913 {
1914   int offset = 0;
1915   int size;
1916   symbol *tlbl;
1917   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1918
1919   D(emitcode (";", "genCpl"));
1920
1921   /* assign asmOps to operand & result */
1922   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1923   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1924
1925   /* special case if in bit space */
1926   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1927     {
1928       char *l;
1929
1930       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1931           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1932         {
1933           /* promotion rules are responsible for this strange result:
1934              bit -> int -> ~int -> bit
1935              uchar -> int -> ~int -> bit
1936           */
1937           werror(W_COMPLEMENT);
1938           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1939       goto release;
1940     }
1941     tlbl=newiTempLabel(NULL);
1942       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE,NULL);
1943       if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1944           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1945           IS_AOP_PREG (IC_LEFT (ic)))
1946         {
1947           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1948         }
1949       else
1950         {
1951           MOVA (l);
1952           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1953         }
1954     emitcode ("", "%05d$:", tlbl->key+100);
1955     outBitC (IC_RESULT(ic));
1956     goto release;
1957   }
1958
1959   size = AOP_SIZE (IC_RESULT (ic));
1960   _startLazyDPSEvaluation ();
1961   while (size--)
1962     {
1963       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1964       emitcode ("cpl", "a");
1965       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1966     }
1967   _endLazyDPSEvaluation ();
1968
1969
1970 release:
1971   /* release the aops */
1972   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1973   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1974 }
1975
1976 /*-----------------------------------------------------------------*/
1977 /* genUminusFloat - unary minus for floating points                */
1978 /*-----------------------------------------------------------------*/
1979 static void
1980 genUminusFloat (operand * op, operand * result)
1981 {
1982   int size, offset = 0;
1983
1984   D(emitcode (";", "genUminusFloat"););
1985
1986   /* for this we just copy and then flip the bit */
1987
1988   _startLazyDPSEvaluation ();
1989   size = AOP_SIZE (op) - 1;
1990
1991   while (size--)
1992   {
1993       aopPut (AOP (result),
1994               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1995               offset);
1996       offset++;
1997     }
1998
1999   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
2000
2001   emitcode ("cpl", "acc.7");
2002   aopPut (AOP (result), "a", offset);
2003   _endLazyDPSEvaluation ();
2004 }
2005
2006 /*-----------------------------------------------------------------*/
2007 /* genUminus - unary minus code generation                         */
2008 /*-----------------------------------------------------------------*/
2009 static void
2010 genUminus (iCode * ic)
2011 {
2012   int offset, size;
2013   sym_link *optype;
2014
2015   D (emitcode (";", "genUminus "););
2016
2017   /* assign asmops */
2018   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2019   aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2020
2021   /* if both in bit space then special
2022      case */
2023   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2024       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2025     {
2026
2027       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2028       emitcode ("cpl", "c");
2029       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2030       goto release;
2031     }
2032
2033   optype = operandType (IC_LEFT (ic));
2034
2035   /* if float then do float stuff */
2036   if (IS_FLOAT (optype))
2037     {
2038       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2039       goto release;
2040     }
2041
2042   /* otherwise subtract from zero */
2043   size = AOP_SIZE (IC_LEFT (ic));
2044   offset = 0;
2045   _startLazyDPSEvaluation ();
2046   while (size--)
2047     {
2048       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
2049       if (!strcmp (l, "a"))
2050         {
2051           if (offset == 0)
2052             SETC;
2053           emitcode ("cpl", "a");
2054           emitcode ("addc", "a,#0");
2055         }
2056       else
2057         {
2058           if (offset == 0)
2059             CLRC;
2060           emitcode ("clr", "a");
2061           emitcode ("subb", "a,%s", l);
2062         }
2063       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2064     }
2065   _endLazyDPSEvaluation ();
2066
2067   /* if any remaining bytes in the result */
2068   /* we just need to propagate the sign   */
2069   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2070     {
2071       emitcode ("rlc", "a");
2072       emitcode ("subb", "a,acc");
2073       while (size--)
2074         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2075     }
2076
2077 release:
2078   /* release the aops */
2079   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2080   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2081 }
2082
2083 /*-----------------------------------------------------------------*/
2084 /* savermask - saves registers in the mask                         */
2085 /*-----------------------------------------------------------------*/
2086 static void savermask(bitVect *rs_mask)
2087 {
2088     int i;
2089     if (options.useXstack) {
2090         if (bitVectBitValue (rs_mask, R0_IDX))
2091             emitcode ("mov", "b,r0");
2092         emitcode ("mov", "r0,%s", spname);
2093         for (i = 0; i < ds390_nRegs; i++) {
2094             if (bitVectBitValue (rs_mask, i)) {
2095                 if (i == R0_IDX)
2096                     emitcode ("mov", "a,b");
2097                 else
2098                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2099                 emitcode ("movx", "@r0,a");
2100                 emitcode ("inc", "r0");
2101             }
2102         }
2103         emitcode ("mov", "%s,r0", spname);
2104         if (bitVectBitValue (rs_mask, R0_IDX))
2105             emitcode ("mov", "r0,b");
2106     } else {
2107         for (i = 0; i < ds390_nRegs; i++) {
2108             if (bitVectBitValue (rs_mask, i))
2109                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2110         }
2111     }
2112 }
2113
2114 /*-----------------------------------------------------------------*/
2115 /* saveRegisters - will look for a call and save the registers     */
2116 /*-----------------------------------------------------------------*/
2117 static void
2118 saveRegisters (iCode * lic)
2119 {
2120   iCode *ic;
2121   bitVect *rsave;
2122
2123   /* look for call */
2124   for (ic = lic; ic; ic = ic->next)
2125     if (ic->op == CALL || ic->op == PCALL)
2126       break;
2127
2128   if (!ic)
2129     {
2130       fprintf (stderr, "found parameter push with no function call\n");
2131       return;
2132     }
2133
2134   /* if the registers have been saved already then
2135      do nothing */
2136   if (ic->regsSaved
2137       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2138     return ;
2139
2140   /* special case if DPTR alive across a function call then must save it
2141      even though callee saves */
2142   if (IS_SYMOP(IC_LEFT(ic)) &&
2143       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     /* safe 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   ic->regsSaved = 1;
2158   savermask(rsave);
2159 }
2160
2161 /*-----------------------------------------------------------------*/
2162 /* usavermask - restore registers with mask                        */
2163 /*-----------------------------------------------------------------*/
2164 static void unsavermask(bitVect *rs_mask)
2165 {
2166     int i;
2167     if (options.useXstack) {
2168         emitcode ("mov", "r0,%s", spname);
2169         for (i = ds390_nRegs; i >= 0; i--) {
2170             if (bitVectBitValue (rs_mask, i)) {
2171                 emitcode ("dec", "r0");
2172                 emitcode ("movx", "a,@r0");
2173                 if (i == R0_IDX)
2174                     emitcode ("mov", "b,a");
2175                 else
2176                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2177             }
2178         }
2179         emitcode ("mov", "%s,r0", spname);
2180         if (bitVectBitValue (rs_mask, R0_IDX))
2181             emitcode ("mov", "r0,b");
2182     } else {
2183         for (i = ds390_nRegs; i >= 0; i--) {
2184             if (bitVectBitValue (rs_mask, i))
2185                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2186         }
2187     }
2188 }
2189
2190 /*-----------------------------------------------------------------*/
2191 /* unsaveRegisters - pop the pushed registers                      */
2192 /*-----------------------------------------------------------------*/
2193 static void
2194 unsaveRegisters (iCode * ic)
2195 {
2196   bitVect *rsave;
2197
2198   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2199       int i;
2200       rsave = newBitVect(ic->rMask->size);
2201       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2202           if (bitVectBitValue(ic->rMask,i))
2203               rsave = bitVectSetBit(rsave,i);
2204       }
2205       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2206   } else {
2207     /* restore the registers in use at this time but skip the
2208        ones for the result */
2209     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2210                            ds390_rUmaskForOp (IC_RESULT(ic)));
2211   }
2212   unsavermask(rsave);
2213 }
2214
2215
2216 /*-----------------------------------------------------------------*/
2217 /* pushSide -                */
2218 /*-----------------------------------------------------------------*/
2219 static void
2220 pushSide (operand * oper, int size)
2221 {
2222   int offset = 0;
2223   _startLazyDPSEvaluation ();
2224   while (size--)
2225     {
2226       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2227       if (AOP_TYPE (oper) != AOP_REG &&
2228           AOP_TYPE (oper) != AOP_DIR &&
2229           strcmp (l, "a"))
2230         {
2231           emitcode ("mov", "a,%s", l);
2232           emitcode ("push", "acc");
2233         }
2234       else
2235         emitcode ("push", "%s", l);
2236     }
2237   _endLazyDPSEvaluation ();
2238 }
2239
2240 /*-----------------------------------------------------------------*/
2241 /* assignResultValue -               */
2242 /*-----------------------------------------------------------------*/
2243 static void
2244 assignResultValue (operand * oper)
2245 {
2246   int offset = 0;
2247   int size = AOP_SIZE (oper);
2248   bool pushedAcc = FALSE;
2249
2250   if (size == fReturnSizeDS390)
2251   {
2252       /* I don't think this case can ever happen... */
2253       /* ACC is the last part of this. If writing the result
2254        * uses AC, we must preserve it.
2255        */
2256       if (AOP_NEEDSACC(oper))
2257       {
2258           emitcode(";", "assignResultValue special case for ACC.");
2259           emitcode("push", "acc");
2260           pushedAcc = TRUE;
2261           size--;
2262       }
2263   }
2264
2265
2266   _startLazyDPSEvaluation ();
2267   while (size--)
2268     {
2269       aopPut (AOP (oper), fReturn[offset], offset);
2270       offset++;
2271     }
2272   _endLazyDPSEvaluation ();
2273
2274   if (pushedAcc)
2275     {
2276         emitcode("pop", "acc");
2277         aopPut(AOP(oper), "a", offset);
2278     }
2279 }
2280
2281
2282 /*-----------------------------------------------------------------*/
2283 /* genXpush - pushes onto the external stack                       */
2284 /*-----------------------------------------------------------------*/
2285 static void
2286 genXpush (iCode * ic)
2287 {
2288   asmop *aop = newAsmop (0);
2289   regs *r;
2290   int size, offset = 0;
2291
2292   D (emitcode (";", "genXpush ");
2293     );
2294
2295   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2296   r = getFreePtr (ic, &aop, FALSE);
2297
2298
2299   emitcode ("mov", "%s,_spx", r->name);
2300
2301   size = AOP_SIZE (IC_LEFT (ic));
2302   _startLazyDPSEvaluation ();
2303   while (size--)
2304     {
2305
2306       MOVA (aopGet (AOP (IC_LEFT (ic)),
2307                         offset++, FALSE, FALSE, NULL));
2308       emitcode ("movx", "@%s,a", r->name);
2309       emitcode ("inc", "%s", r->name);
2310
2311     }
2312   _endLazyDPSEvaluation ();
2313
2314
2315   emitcode ("mov", "_spx,%s", r->name);
2316
2317   freeAsmop (NULL, aop, ic, TRUE);
2318   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2319 }
2320
2321 /*-----------------------------------------------------------------*/
2322 /* genIpush - generate code for pushing this gets a little complex  */
2323 /*-----------------------------------------------------------------*/
2324 static void
2325 genIpush (iCode * ic)
2326 {
2327   int size, offset = 0;
2328   char *l;
2329
2330   D (emitcode (";", "genIpush ");
2331     );
2332
2333   /* if this is not a parm push : ie. it is spill push
2334      and spill push is always done on the local stack */
2335   if (!ic->parmPush)
2336     {
2337
2338       /* and the item is spilt then do nothing */
2339       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2340         return;
2341
2342       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2343       size = AOP_SIZE (IC_LEFT (ic));
2344       /* push it on the stack */
2345       _startLazyDPSEvaluation ();
2346       while (size--)
2347         {
2348           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2349           if (*l == '#')
2350             {
2351               MOVA (l);
2352               l = "acc";
2353             }
2354           emitcode ("push", "%s", l);
2355         }
2356       _endLazyDPSEvaluation ();
2357       return;
2358     }
2359
2360   /* this is a paramter push: in this case we call
2361      the routine to find the call and save those
2362      registers that need to be saved */
2363   saveRegisters (ic);
2364
2365   /* if use external stack then call the external
2366      stack pushing routine */
2367   if (options.useXstack)
2368     {
2369       genXpush (ic);
2370       return;
2371     }
2372
2373   /* then do the push */
2374   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2375
2376   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2377   size = AOP_SIZE (IC_LEFT (ic));
2378
2379   _startLazyDPSEvaluation ();
2380   while (size--)
2381     {
2382       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2383       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2384           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2385           strcmp (l, "acc"))
2386         {
2387           emitcode ("mov", "a,%s", l);
2388           emitcode ("push", "acc");
2389         }
2390       else
2391         {
2392             emitcode ("push", "%s", l);
2393         }
2394     }
2395   _endLazyDPSEvaluation ();
2396
2397   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2398 }
2399
2400 /*-----------------------------------------------------------------*/
2401 /* genIpop - recover the registers: can happen only for spilling   */
2402 /*-----------------------------------------------------------------*/
2403 static void
2404 genIpop (iCode * ic)
2405 {
2406   int size, offset;
2407
2408   D (emitcode (";", "genIpop ");
2409     );
2410
2411
2412   /* if the temp was not pushed then */
2413   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2414     return;
2415
2416   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2417   size = AOP_SIZE (IC_LEFT (ic));
2418   offset = (size - 1);
2419   _startLazyDPSEvaluation ();
2420   while (size--)
2421     {
2422       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2423                                      FALSE, TRUE, NULL));
2424     }
2425   _endLazyDPSEvaluation ();
2426
2427   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2428 }
2429
2430 /*-----------------------------------------------------------------*/
2431 /* unsaveRBank - restores the resgister bank from stack            */
2432 /*-----------------------------------------------------------------*/
2433 static void
2434 unsaveRBank (int bank, iCode * ic, bool popPsw)
2435 {
2436   int i;
2437   asmop *aop = NULL;
2438   regs *r = NULL;
2439
2440   if (options.useXstack)
2441   {
2442       if (!ic)
2443       {
2444           /* Assume r0 is available for use. */
2445           r = ds390_regWithIdx (R0_IDX);;
2446       }
2447       else
2448       {
2449           aop = newAsmop (0);
2450           r = getFreePtr (ic, &aop, FALSE);
2451       }
2452       emitcode ("mov", "%s,_spx", r->name);
2453   }
2454
2455   if (popPsw)
2456     {
2457       if (options.useXstack)
2458       {
2459           emitcode ("movx", "a,@%s", r->name);
2460           emitcode ("mov", "psw,a");
2461           emitcode ("dec", "%s", r->name);
2462         }
2463       else
2464       {
2465         emitcode ("pop", "psw");
2466       }
2467     }
2468
2469   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2470     {
2471       if (options.useXstack)
2472         {
2473           emitcode ("movx", "a,@%s", r->name);
2474           emitcode ("mov", "(%s+%d),a",
2475                     regs390[i].base, 8 * bank + regs390[i].offset);
2476           emitcode ("dec", "%s", r->name);
2477
2478         }
2479       else
2480         emitcode ("pop", "(%s+%d)",
2481                   regs390[i].base, 8 * bank + regs390[i].offset);
2482     }
2483
2484   if (options.useXstack)
2485     {
2486       emitcode ("mov", "_spx,%s", r->name);
2487     }
2488
2489   if (aop)
2490   {
2491       freeAsmop (NULL, aop, ic, TRUE);
2492   }
2493 }
2494
2495 /*-----------------------------------------------------------------*/
2496 /* saveRBank - saves an entire register bank on the stack          */
2497 /*-----------------------------------------------------------------*/
2498 static void
2499 saveRBank (int bank, iCode * ic, bool pushPsw)
2500 {
2501   int i;
2502   asmop *aop = NULL;
2503   regs *r = NULL;
2504
2505   if (options.useXstack)
2506     {
2507         if (!ic)
2508         {
2509           /* Assume r0 is available for use. */
2510                   r = ds390_regWithIdx (R0_IDX);;
2511         }
2512         else
2513         {
2514           aop = newAsmop (0);
2515           r = getFreePtr (ic, &aop, FALSE);
2516         }
2517         emitcode ("mov", "%s,_spx", r->name);
2518     }
2519
2520   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2521     {
2522       if (options.useXstack)
2523         {
2524           emitcode ("inc", "%s", r->name);
2525           emitcode ("mov", "a,(%s+%d)",
2526                     regs390[i].base, 8 * bank + regs390[i].offset);
2527           emitcode ("movx", "@%s,a", r->name);
2528         }
2529       else
2530         emitcode ("push", "(%s+%d)",
2531                   regs390[i].base, 8 * bank + regs390[i].offset);
2532     }
2533
2534   if (pushPsw)
2535     {
2536       if (options.useXstack)
2537         {
2538           emitcode ("mov", "a,psw");
2539           emitcode ("movx", "@%s,a", r->name);
2540           emitcode ("inc", "%s", r->name);
2541           emitcode ("mov", "_spx,%s", r->name);
2542         }
2543       else
2544       {
2545         emitcode ("push", "psw");
2546       }
2547
2548       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2549     }
2550
2551   if (aop)
2552   {
2553     freeAsmop (NULL, aop, ic, TRUE);
2554   }
2555
2556   if (ic)
2557   {
2558     ic->bankSaved = 1;
2559   }
2560 }
2561
2562 /*-----------------------------------------------------------------*/
2563 /* genSend - gen code for SEND                                     */
2564 /*-----------------------------------------------------------------*/
2565 static void genSend(set *sendSet)
2566 {
2567     iCode *sic;
2568     int sendCount = 0 ;
2569     static int rb1_count = 0;
2570
2571     for (sic = setFirstItem (sendSet); sic;
2572          sic = setNextItem (sendSet)) {
2573         int size, offset = 0;
2574
2575         size=getSize(operandType(IC_LEFT(sic)));
2576         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2577         if (sendCount == 0) { /* first parameter */
2578             // we know that dpl(hxb) is the result, so
2579             rb1_count = 0 ;
2580             _startLazyDPSEvaluation ();
2581             if (size>1) {
2582                 aopOp (IC_LEFT (sic), sic, FALSE,
2583                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2584             } else {
2585                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2586             }
2587             while (size--) {
2588                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2589                                   FALSE, FALSE, NULL);
2590                 if (strcmp (l, fReturn[offset])) {
2591                     emitcode ("mov", "%s,%s",
2592                               fReturn[offset],
2593                               l);
2594                 }
2595                 offset++;
2596             }
2597             _endLazyDPSEvaluation ();
2598             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2599             rb1_count =0;
2600         } else { /* if more parameter in registers */
2601             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2602             while (size--) {
2603                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2604                                                                 FALSE, FALSE, NULL));
2605             }
2606             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2607         }
2608         sendCount++;
2609     }
2610 }
2611
2612 static void
2613 adjustEsp(const char *reg)
2614 {
2615     emitcode ("anl","%s,#3", reg);
2616     if (TARGET_IS_DS400)
2617     {
2618         emitcode ("orl","%s,#!constbyte",
2619                   reg,
2620                   (options.stack_loc >> 8) & 0xff);
2621     }
2622 }
2623
2624 /*-----------------------------------------------------------------*/
2625 /* genCall - generates a call statement                            */
2626 /*-----------------------------------------------------------------*/
2627 static void
2628 genCall (iCode * ic)
2629 {
2630   sym_link *dtype;
2631   bool restoreBank = FALSE;
2632   bool swapBanks = FALSE;
2633
2634   D (emitcode (";", "genCall "););
2635
2636   /* if we are calling a not _naked function that is not using
2637      the same register bank then we need to save the
2638      destination registers on the stack */
2639   dtype = operandType (IC_LEFT (ic));
2640   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2641       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2642       IFFUNC_ISISR (currFunc->type))
2643   {
2644       if (!ic->bankSaved)
2645       {
2646            /* This is unexpected; the bank should have been saved in
2647             * genFunction.
2648             */
2649            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2650            restoreBank = TRUE;
2651       }
2652       swapBanks = TRUE;
2653   }
2654
2655     /* if caller saves & we have not saved then */
2656     if (!ic->regsSaved)
2657       saveRegisters (ic);
2658
2659   /* if send set is not empty then assign */
2660   /* We've saved all the registers we care about;
2661   * therefore, we may clobber any register not used
2662   * in the calling convention (i.e. anything not in
2663   * fReturn.
2664   */
2665   if (_G.sendSet)
2666     {
2667         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2668             genSend(reverseSet(_G.sendSet));
2669         } else {
2670             genSend(_G.sendSet);
2671         }
2672       _G.sendSet = NULL;
2673     }
2674
2675   if (swapBanks)
2676   {
2677         emitcode ("mov", "psw,#!constbyte",
2678            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2679   }
2680
2681   /* make the call */
2682   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2683                             OP_SYMBOL (IC_LEFT (ic))->rname :
2684                             OP_SYMBOL (IC_LEFT (ic))->name));
2685
2686   if (swapBanks)
2687   {
2688        emitcode ("mov", "psw,#!constbyte",
2689           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2690   }
2691
2692   /* if we need assign a result value */
2693   if ((IS_ITEMP (IC_RESULT (ic)) &&
2694        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2695         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2696         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2697       IS_TRUE_SYMOP (IC_RESULT (ic)))
2698     {
2699       if (isOperandInFarSpace (IC_RESULT (ic))
2700           && getSize (operandType (IC_RESULT (ic))) <= 2)
2701         {
2702           int size = getSize (operandType (IC_RESULT (ic)));
2703
2704           /* Special case for 1 or 2 byte return in far space. */
2705           MOVA (fReturn[0]);
2706           if (size > 1)
2707             {
2708               emitcode ("mov", "b,%s", fReturn[1]);
2709               _G.bInUse++;
2710             }
2711
2712           _G.accInUse++;
2713           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2714           _G.accInUse--;
2715
2716           if (size > 1)
2717             _G.bInUse--;
2718
2719           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2720
2721           if (size > 1)
2722             {
2723               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2724             }
2725           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2726         }
2727       else
2728         {
2729           _G.bInUse++;
2730           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2731           _G.bInUse--;
2732
2733           assignResultValue (IC_RESULT (ic));
2734
2735           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2736         }
2737     }
2738
2739   /* adjust the stack for parameters if
2740      required */
2741   if (ic->parmBytes) {
2742       int i;
2743       if (options.stack10bit) {
2744           if (ic->parmBytes <= 10) {
2745               emitcode(";","stack adjustment for parms");
2746               for (i=0; i < ic->parmBytes ; i++) {
2747                   emitcode("pop","acc");
2748               }
2749           } else {
2750               PROTECT_SP;
2751               emitcode ("clr","c");
2752               emitcode ("mov","a,sp");
2753               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2754               emitcode ("mov","sp,a");
2755               emitcode ("mov","a,esp");
2756               adjustEsp("a");
2757               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2758               emitcode ("mov","esp,a");
2759               UNPROTECT_SP;
2760           }
2761       } else {
2762           if (ic->parmBytes > 3) {
2763               emitcode ("mov", "a,%s", spname);
2764               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2765               emitcode ("mov", "%s,a", spname);
2766           } else
2767               for (i = 0; i < ic->parmBytes; i++)
2768                   emitcode ("dec", "%s", spname);
2769       }
2770   }
2771
2772   /* if we hade saved some registers then unsave them */
2773   if (ic->regsSaved)
2774     unsaveRegisters (ic);
2775
2776   /* if register bank was saved then pop them */
2777   if (restoreBank)
2778     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2779 }
2780
2781 /*-----------------------------------------------------------------*/
2782 /* genPcall - generates a call by pointer statement                */
2783 /*-----------------------------------------------------------------*/
2784 static void
2785 genPcall (iCode * ic)
2786 {
2787   sym_link *dtype;
2788   symbol *rlbl = newiTempLabel (NULL);
2789   bool restoreBank=FALSE;
2790
2791   D (emitcode (";", "genPcall ");
2792     );
2793
2794
2795   /* if caller saves & we have not saved then */
2796   if (!ic->regsSaved)
2797     saveRegisters (ic);
2798
2799   /* if we are calling a function that is not using
2800      the same register bank then we need to save the
2801      destination registers on the stack */
2802   dtype = operandType (IC_LEFT (ic));
2803   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2804       IFFUNC_ISISR (currFunc->type) &&
2805       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2806     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2807     restoreBank=TRUE;
2808   }
2809
2810   /* push the return address on to the stack */
2811   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2812   emitcode ("push", "acc");
2813   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2814   emitcode ("push", "acc");
2815
2816   if (options.model == MODEL_FLAT24)
2817     {
2818       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2819       emitcode ("push", "acc");
2820     }
2821
2822   /* now push the calling address */
2823   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2824
2825   pushSide (IC_LEFT (ic), FPTRSIZE);
2826
2827   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2828
2829   /* if send set is not empty the assign */
2830   if (_G.sendSet)
2831     {
2832         genSend(reverseSet(_G.sendSet));
2833         _G.sendSet = NULL;
2834     }
2835
2836   emitcode ("ret", "");
2837   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2838
2839
2840   /* if we need assign a result value */
2841   if ((IS_ITEMP (IC_RESULT (ic)) &&
2842        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2843         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2844       IS_TRUE_SYMOP (IC_RESULT (ic)))
2845     {
2846
2847       _G.accInUse++;
2848       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2849       _G.accInUse--;
2850
2851       assignResultValue (IC_RESULT (ic));
2852
2853       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2854     }
2855
2856   /* adjust the stack for parameters if
2857      required */
2858   if (ic->parmBytes)
2859     {
2860       int i;
2861       if (options.stack10bit) {
2862           if (ic->parmBytes <= 10) {
2863               emitcode(";","stack adjustment for parms");
2864               for (i=0; i < ic->parmBytes ; i++) {
2865                   emitcode("pop","acc");
2866               }
2867           } else {
2868               PROTECT_SP;
2869               emitcode ("clr","c");
2870               emitcode ("mov","a,sp");
2871               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2872               emitcode ("mov","sp,a");
2873               emitcode ("mov","a,esp");
2874               adjustEsp("a");
2875               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2876               emitcode ("mov","esp,a");
2877               UNPROTECT_SP;
2878           }
2879       } else {
2880           if (ic->parmBytes > 3) {
2881               emitcode ("mov", "a,%s", spname);
2882               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2883               emitcode ("mov", "%s,a", spname);
2884           }
2885           else
2886               for (i = 0; i < ic->parmBytes; i++)
2887                   emitcode ("dec", "%s", spname);
2888
2889       }
2890     }
2891   /* if register bank was saved then unsave them */
2892   if (restoreBank)
2893     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2894
2895   /* if we hade saved some registers then
2896      unsave them */
2897   if (ic->regsSaved)
2898     unsaveRegisters (ic);
2899
2900 }
2901
2902 /*-----------------------------------------------------------------*/
2903 /* resultRemat - result  is rematerializable                       */
2904 /*-----------------------------------------------------------------*/
2905 static int
2906 resultRemat (iCode * ic)
2907 {
2908   if (SKIP_IC (ic) || ic->op == IFX)
2909     return 0;
2910
2911   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2912     {
2913       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2914       if (sym->remat && !POINTER_SET (ic))
2915         return 1;
2916     }
2917
2918   return 0;
2919 }
2920
2921 #if defined(__BORLANDC__) || defined(_MSC_VER)
2922 #define STRCASECMP stricmp
2923 #else
2924 #define STRCASECMP strcasecmp
2925 #endif
2926
2927 /*-----------------------------------------------------------------*/
2928 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2929 /*-----------------------------------------------------------------*/
2930 static int
2931 regsCmp(void *p1, void *p2)
2932 {
2933   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2934 }
2935
2936 static bool
2937 inExcludeList (char *s)
2938 {
2939   const char *p = setFirstItem(options.excludeRegsSet);
2940
2941   if (p == NULL || STRCASECMP(p, "none") == 0)
2942     return FALSE;
2943
2944
2945   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2946 }
2947
2948 /*-----------------------------------------------------------------*/
2949 /* genFunction - generated code for function entry                 */
2950 /*-----------------------------------------------------------------*/
2951 static void
2952 genFunction (iCode * ic)
2953 {
2954   symbol *sym;
2955   sym_link *ftype;
2956   bool   switchedPSW = FALSE;
2957
2958   D (emitcode (";", "genFunction "););
2959
2960   _G.nRegsSaved = 0;
2961   /* create the function header */
2962   emitcode (";", "-----------------------------------------");
2963   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2964   emitcode (";", "-----------------------------------------");
2965
2966   emitcode ("", "%s:", sym->rname);
2967   ftype = operandType (IC_LEFT (ic));
2968
2969   if (IFFUNC_ISNAKED(ftype))
2970   {
2971       emitcode(";", "naked function: no prologue.");
2972       return;
2973   }
2974
2975   if (options.stack_probe)
2976       emitcode ("lcall","__stack_probe");
2977
2978   /* here we need to generate the equates for the
2979      register bank if required */
2980   if (FUNC_REGBANK (ftype) != rbank)
2981     {
2982       int i;
2983
2984       rbank = FUNC_REGBANK (ftype);
2985       for (i = 0; i < ds390_nRegs; i++)
2986         {
2987           if (regs390[i].print) {
2988               if (strcmp (regs390[i].base, "0") == 0)
2989                   emitcode ("", "%s !equ !constbyte",
2990                             regs390[i].dname,
2991                             8 * rbank + regs390[i].offset);
2992               else
2993                   emitcode ("", "%s !equ %s + !constbyte",
2994                             regs390[i].dname,
2995                             regs390[i].base,
2996                             8 * rbank + regs390[i].offset);
2997           }
2998         }
2999     }
3000
3001   /* if this is an interrupt service routine then
3002      save acc, b, dpl, dph  */
3003   if (IFFUNC_ISISR (sym->type))
3004       { /* is ISR */
3005       if (!inExcludeList ("acc"))
3006         emitcode ("push", "acc");
3007       if (!inExcludeList ("b"))
3008         emitcode ("push", "b");
3009       if (!inExcludeList ("dpl"))
3010         emitcode ("push", "dpl");
3011       if (!inExcludeList ("dph"))
3012         emitcode ("push", "dph");
3013       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3014         {
3015           emitcode ("push", "dpx");
3016           /* Make sure we're using standard DPTR */
3017           emitcode ("push", "dps");
3018           emitcode ("mov", "dps,#0");
3019           if (options.stack10bit)
3020             {
3021               /* This ISR could conceivably use DPTR2. Better save it. */
3022               emitcode ("push", "dpl1");
3023               emitcode ("push", "dph1");
3024               emitcode ("push", "dpx1");
3025               emitcode ("push",  DP2_RESULT_REG);
3026             }
3027         }
3028       /* if this isr has no bank i.e. is going to
3029          run with bank 0 , then we need to save more
3030          registers :-) */
3031       if (!FUNC_REGBANK (sym->type))
3032         {
3033             int i;
3034
3035           /* if this function does not call any other
3036              function then we can be economical and
3037              save only those registers that are used */
3038           if (!IFFUNC_HASFCALL(sym->type))
3039             {
3040
3041               /* if any registers used */
3042               if (sym->regsUsed)
3043                 {
3044                   /* save the registers used */
3045                   for (i = 0; i < sym->regsUsed->size; i++)
3046                     {
3047                       if (bitVectBitValue (sym->regsUsed, i))
3048                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3049                     }
3050                 }
3051             }
3052           else
3053             {
3054               /* this function has  a function call cannot
3055                  determines register usage so we will have to push the
3056                  entire bank */
3057               saveRBank (0, ic, FALSE);
3058               if (options.parms_in_bank1) {
3059                   for (i=0; i < 8 ; i++ ) {
3060                       emitcode ("push","%s",rb1regs[i]);
3061                   }
3062               }
3063             }
3064         }
3065         else
3066         {
3067             /* This ISR uses a non-zero bank.
3068              *
3069              * We assume that the bank is available for our
3070              * exclusive use.
3071              *
3072              * However, if this ISR calls a function which uses some
3073              * other bank, we must save that bank entirely.
3074              */
3075             unsigned long banksToSave = 0;
3076
3077             if (IFFUNC_HASFCALL(sym->type))
3078             {
3079
3080 #define MAX_REGISTER_BANKS 4
3081
3082                 iCode *i;
3083                 int ix;
3084
3085                 for (i = ic; i; i = i->next)
3086                 {
3087                     if (i->op == ENDFUNCTION)
3088                     {
3089                         /* we got to the end OK. */
3090                         break;
3091                     }
3092
3093                     if (i->op == CALL)
3094                     {
3095                         sym_link *dtype;
3096
3097                         dtype = operandType (IC_LEFT(i));
3098                         if (dtype
3099                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3100                         {
3101                              /* Mark this bank for saving. */
3102                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3103                              {
3104                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3105                              }
3106                              else
3107                              {
3108                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3109                              }
3110
3111                              /* And note that we don't need to do it in
3112                               * genCall.
3113                               */
3114                              i->bankSaved = 1;
3115                         }
3116                     }
3117                     if (i->op == PCALL)
3118                     {
3119                         /* This is a mess; we have no idea what
3120                          * register bank the called function might
3121                          * use.
3122                          *
3123                          * The only thing I can think of to do is
3124                          * throw a warning and hope.
3125                          */
3126                         werror(W_FUNCPTR_IN_USING_ISR);
3127                     }
3128                 }
3129
3130                 if (banksToSave && options.useXstack)
3131                 {
3132                     /* Since we aren't passing it an ic,
3133                      * saveRBank will assume r0 is available to abuse.
3134                      *
3135                      * So switch to our (trashable) bank now, so
3136                      * the caller's R0 isn't trashed.
3137                      */
3138                     emitcode ("push", "psw");
3139                     emitcode ("mov", "psw,#!constbyte",
3140                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3141                     switchedPSW = TRUE;
3142                 }
3143
3144                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3145                 {
3146                      if (banksToSave & (1 << ix))
3147                      {
3148                          saveRBank(ix, NULL, FALSE);
3149                      }
3150                 }
3151             }
3152             // TODO: this needs a closer look
3153             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3154         }
3155     }
3156   else
3157     {
3158       /* if callee-save to be used for this function
3159          then save the registers being used in this function */
3160       if (IFFUNC_CALLEESAVES(sym->type))
3161         {
3162           int i;
3163
3164           /* if any registers used */
3165           if (sym->regsUsed)
3166             {
3167               /* save the registers used */
3168               for (i = 0; i < sym->regsUsed->size; i++)
3169                 {
3170                   if (bitVectBitValue (sym->regsUsed, i))
3171                     {
3172                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3173                       _G.nRegsSaved++;
3174                     }
3175                 }
3176             }
3177         }
3178     }
3179
3180   /* set the register bank to the desired value */
3181   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3182    && !switchedPSW)
3183     {
3184       emitcode ("push", "psw");
3185       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3186     }
3187
3188   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3189        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3190       if (options.stack10bit) {
3191           emitcode ("push","_bpx");
3192           emitcode ("push","_bpx+1");
3193           emitcode ("mov","_bpx,%s",spname);
3194           emitcode ("mov","_bpx+1,esp");
3195           adjustEsp("_bpx+1");
3196       } else {
3197           if (options.useXstack) {
3198               emitcode ("mov", "r0,%s", spname);
3199               emitcode ("mov", "a,_bp");
3200               emitcode ("movx", "@r0,a");
3201               emitcode ("inc", "%s", spname);
3202           } else {
3203               /* set up the stack */
3204               emitcode ("push", "_bp"); /* save the callers stack  */
3205           }
3206           emitcode ("mov", "_bp,%s", spname);
3207       }
3208   }
3209
3210   /* adjust the stack for the function */
3211   if (sym->stack) {
3212       int i = sym->stack;
3213       if (options.stack10bit) {
3214           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3215           assert (sym->recvSize <= 4);
3216           if (sym->stack <= 8) {
3217               while (i--) emitcode ("push","acc");
3218           } else {
3219               PROTECT_SP;
3220               emitcode ("mov","a,sp");
3221               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3222               emitcode ("mov","sp,a");
3223               emitcode ("mov","a,esp");
3224               adjustEsp("a");
3225               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3226               emitcode ("mov","esp,a");
3227               UNPROTECT_SP;
3228           }
3229       } else {
3230           if (i > 256)
3231               werror (W_STACK_OVERFLOW, sym->name);
3232
3233           if (i > 3 && sym->recvSize < 4) {
3234
3235               emitcode ("mov", "a,sp");
3236               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3237               emitcode ("mov", "sp,a");
3238
3239           } else
3240               while (i--)
3241                   emitcode ("inc", "sp");
3242       }
3243   }
3244
3245   if (sym->xstack)
3246     {
3247
3248       emitcode ("mov", "a,_spx");
3249       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3250       emitcode ("mov", "_spx,a");
3251     }
3252
3253   /* if critical function then turn interrupts off */
3254   if (IFFUNC_ISCRITICAL (ftype))
3255     {
3256       symbol *tlbl = newiTempLabel (NULL);
3257       emitcode ("setb", "c");
3258       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3259       emitcode ("clr", "c");
3260       emitcode ("", "%05d$:", (tlbl->key + 100));
3261       emitcode ("push", "psw"); /* save old ea via c in psw */
3262     }
3263
3264 }
3265
3266 /*-----------------------------------------------------------------*/
3267 /* genEndFunction - generates epilogue for functions               */
3268 /*-----------------------------------------------------------------*/
3269 static void
3270 genEndFunction (iCode * ic)
3271 {
3272   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3273   lineNode *lnp = lineCurr;
3274   bitVect *regsUsed;
3275   bitVect *regsUsedPrologue;
3276   bitVect *regsUnneeded;
3277   int idx;
3278
3279   D (emitcode (";", "genEndFunction "););
3280
3281   if (IFFUNC_ISNAKED(sym->type))
3282   {
3283       emitcode(";", "naked function: no epilogue.");
3284       if (options.debug && currFunc)
3285         debugFile->writeEndFunction (currFunc, ic, 0);
3286       return;
3287   }
3288
3289   if (IFFUNC_ISCRITICAL (sym->type))
3290     {
3291       emitcode ("pop", "psw"); /* restore ea via c in psw */
3292       emitcode ("mov", "ea,c");
3293     }
3294
3295   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3296        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3297
3298       if (options.stack10bit) {
3299           PROTECT_SP;
3300           emitcode ("mov", "sp,_bpx", spname);
3301           emitcode ("mov", "esp,_bpx+1", spname);
3302           UNPROTECT_SP;
3303       } else {
3304           emitcode ("mov", "%s,_bp", spname);
3305       }
3306   }
3307
3308   /* if use external stack but some variables were
3309      added to the local stack then decrement the
3310      local stack */
3311   if (options.useXstack && sym->stack) {
3312       emitcode ("mov", "a,sp");
3313       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3314       emitcode ("mov", "sp,a");
3315   }
3316
3317
3318   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3319        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3320
3321       if (options.useXstack) {
3322           emitcode ("mov", "r0,%s", spname);
3323           emitcode ("movx", "a,@r0");
3324           emitcode ("mov", "_bp,a");
3325           emitcode ("dec", "%s", spname);
3326       } else {
3327           if (options.stack10bit) {
3328               emitcode ("pop", "_bpx+1");
3329               emitcode ("pop", "_bpx");
3330           } else {
3331               emitcode ("pop", "_bp");
3332           }
3333       }
3334   }
3335
3336   /* restore the register bank  */
3337   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3338   {
3339     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3340      || !options.useXstack)
3341     {
3342         /* Special case of ISR using non-zero bank with useXstack
3343          * is handled below.
3344          */
3345         emitcode ("pop", "psw");
3346     }
3347   }
3348
3349   if (IFFUNC_ISISR (sym->type))
3350       { /* is ISR */
3351
3352       /* now we need to restore the registers */
3353       /* if this isr has no bank i.e. is going to
3354          run with bank 0 , then we need to save more
3355          registers :-) */
3356       if (!FUNC_REGBANK (sym->type))
3357         {
3358             int i;
3359           /* if this function does not call any other
3360              function then we can be economical and
3361              save only those registers that are used */
3362           if (!IFFUNC_HASFCALL(sym->type))
3363             {
3364
3365               /* if any registers used */
3366               if (sym->regsUsed)
3367                 {
3368                   /* save the registers used */
3369                   for (i = sym->regsUsed->size; i >= 0; i--)
3370                     {
3371                       if (bitVectBitValue (sym->regsUsed, i))
3372                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3373                     }
3374                 }
3375             }
3376           else
3377             {
3378               /* this function has  a function call cannot
3379                  determines register usage so we will have to pop the
3380                  entire bank */
3381               if (options.parms_in_bank1) {
3382                   for (i = 7 ; i >= 0 ; i-- ) {
3383                       emitcode ("pop","%s",rb1regs[i]);
3384                   }
3385               }
3386               unsaveRBank (0, ic, FALSE);
3387             }
3388         }
3389         else
3390         {
3391             /* This ISR uses a non-zero bank.
3392              *
3393              * Restore any register banks saved by genFunction
3394              * in reverse order.
3395              */
3396             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3397             int ix;
3398
3399             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3400             {
3401                 if (savedBanks & (1 << ix))
3402                 {
3403                     unsaveRBank(ix, NULL, FALSE);
3404                 }
3405             }
3406
3407             if (options.useXstack)
3408             {
3409                 /* Restore bank AFTER calling unsaveRBank,
3410                  * since it can trash r0.
3411                  */
3412                 emitcode ("pop", "psw");
3413             }
3414         }
3415
3416       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3417         {
3418           if (options.stack10bit)
3419             {
3420               emitcode ("pop", DP2_RESULT_REG);
3421               emitcode ("pop", "dpx1");
3422               emitcode ("pop", "dph1");
3423               emitcode ("pop", "dpl1");
3424             }
3425           emitcode ("pop", "dps");
3426           emitcode ("pop", "dpx");
3427         }
3428       if (!inExcludeList ("dph"))
3429         emitcode ("pop", "dph");
3430       if (!inExcludeList ("dpl"))
3431         emitcode ("pop", "dpl");
3432       if (!inExcludeList ("b"))
3433         emitcode ("pop", "b");
3434       if (!inExcludeList ("acc"))
3435         emitcode ("pop", "acc");
3436
3437       /* if debug then send end of function */
3438       if (options.debug && currFunc) {
3439           debugFile->writeEndFunction (currFunc, ic, 1);
3440         }
3441
3442       emitcode ("reti", "");
3443     }
3444   else
3445     {
3446       if (IFFUNC_CALLEESAVES(sym->type))
3447         {
3448           int i;
3449
3450           /* if any registers used */
3451           if (sym->regsUsed)
3452             {
3453               /* save the registers used */
3454               for (i = sym->regsUsed->size; i >= 0; i--)
3455                 {
3456                   if (bitVectBitValue (sym->regsUsed, i))
3457                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3458                 }
3459             }
3460         }
3461
3462       /* if debug then send end of function */
3463       if (options.debug && currFunc)
3464         {
3465           debugFile->writeEndFunction (currFunc, ic, 1);
3466         }
3467
3468       emitcode ("ret", "");
3469     }
3470
3471   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3472     return;
3473
3474   /* If this was an interrupt handler using bank 0 that called another */
3475   /* function, then all registers must be saved; nothing to optimized. */
3476   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3477       && !FUNC_REGBANK(sym->type))
3478     return;
3479
3480   /* There are no push/pops to optimize if not callee-saves or ISR */
3481   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3482     return;
3483
3484   /* If there were stack parameters, we cannot optimize without also    */
3485   /* fixing all of the stack offsets; this is too dificult to consider. */
3486   if (FUNC_HASSTACKPARM(sym->type))
3487     return;
3488
3489   /* Compute the registers actually used */
3490   regsUsed = newBitVect (ds390_nRegs);
3491   regsUsedPrologue = newBitVect (ds390_nRegs);
3492   while (lnp)
3493     {
3494       if (lnp->ic && lnp->ic->op == FUNCTION)
3495         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3496       else
3497         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3498
3499       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3500           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3501         break;
3502       if (!lnp->prev)
3503         break;
3504       lnp = lnp->prev;
3505     }
3506
3507   if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3508       && !bitVectBitValue (regsUsed, DPS_IDX))
3509     {
3510       bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3511     }
3512
3513   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3514       && !bitVectBitValue (regsUsed, CND_IDX))
3515     {
3516       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3517       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3518           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3519         bitVectUnSetBit (regsUsed, CND_IDX);
3520     }
3521   else
3522     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3523
3524   /* If this was an interrupt handler that called another function */
3525   /* function, then assume working registers may be modified by it. */
3526   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3527     {
3528       regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3529       regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3530       regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3531       regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3532       regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3533       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3534       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3535       regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3536       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3537       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3538       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3539     }
3540
3541   /* Remove the unneeded push/pops */
3542   regsUnneeded = newBitVect (ds390_nRegs);
3543   while (lnp)
3544     {
3545       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3546         {
3547           if (!strncmp(lnp->line, "push", 4))
3548             {
3549               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3550               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3551                 {
3552                   connectLine (lnp->prev, lnp->next);
3553                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3554                 }
3555             }
3556           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3557             {
3558               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3559               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3560                 {
3561                   connectLine (lnp->prev, lnp->next);
3562                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3563                 }
3564             }
3565         }
3566       lnp = lnp->next;
3567     }
3568
3569   for (idx = 0; idx < regsUnneeded->size; idx++)
3570     if (bitVectBitValue (regsUnneeded, idx))
3571       emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname);
3572
3573   freeBitVect (regsUnneeded);
3574   freeBitVect (regsUsed);
3575   freeBitVect (regsUsedPrologue);
3576 }
3577
3578 /*-----------------------------------------------------------------*/
3579 /* genJavaNativeRet - generate code for return JavaNative          */
3580 /*-----------------------------------------------------------------*/
3581 static void genJavaNativeRet(iCode *ic)
3582 {
3583     int i, size;
3584
3585     aopOp (IC_LEFT (ic), ic, FALSE,
3586            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3587     size = AOP_SIZE (IC_LEFT (ic));
3588
3589     assert (size <= 4);
3590
3591     /* it is assigned to GPR0-R3 then push them */
3592     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3593         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3594         for (i = 0 ; i < size ; i++ ) {
3595             emitcode ("push","%s",
3596                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3597         }
3598         for (i = (size-1) ; i >= 0 ; i--) {
3599             emitcode ("pop","a%s",javaRet[i]);
3600         }
3601     } else {
3602         for (i = 0 ; i < size ; i++)
3603             emitcode ("mov","%s,%s",javaRet[i],
3604                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3605     }
3606     for (i = size ; i < 4 ; i++ )
3607             emitcode ("mov","%s,#0",javaRet[i]);
3608     return;
3609 }
3610
3611 /*-----------------------------------------------------------------*/
3612 /* genRet - generate code for return statement                     */
3613 /*-----------------------------------------------------------------*/
3614 static void
3615 genRet (iCode * ic)
3616 {
3617   int size, offset = 0, pushed = 0;
3618
3619   D (emitcode (";", "genRet "););
3620
3621   /* if we have no return value then
3622      just generate the "ret" */
3623   if (!IC_LEFT (ic))
3624     goto jumpret;
3625
3626   /* if this is a JavaNative function then return
3627      value in different register */
3628   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3629       genJavaNativeRet(ic);
3630       goto jumpret;
3631   }
3632   /* we have something to return then
3633      move the return value into place */
3634   aopOp (IC_LEFT (ic), ic, FALSE,
3635          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3636   size = AOP_SIZE (IC_LEFT (ic));
3637
3638   _startLazyDPSEvaluation ();
3639   while (size--)
3640     {
3641       char *l;
3642       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3643         {
3644           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3645                       FALSE, TRUE, NULL);
3646           emitcode ("push", "%s", l);
3647           pushed++;
3648         }
3649       else
3650         {
3651           /* Since A is the last element of fReturn,
3652            * is is OK to clobber it in the aopGet.
3653            */
3654           l = aopGet (AOP (IC_LEFT (ic)), offset,
3655                       FALSE, FALSE, NULL);
3656           if (strcmp (fReturn[offset], l))
3657             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3658         }
3659     }
3660   _endLazyDPSEvaluation ();
3661
3662   if (pushed)
3663     {
3664       while (pushed)
3665         {
3666           pushed--;
3667           if (strcmp (fReturn[pushed], "a"))
3668             emitcode ("pop", fReturn[pushed]);
3669           else
3670             emitcode ("pop", "acc");
3671         }
3672     }
3673   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3674
3675 jumpret:
3676   /* generate a jump to the return label
3677      if the next is not the return statement */
3678   if (!(ic->next && ic->next->op == LABEL &&
3679         IC_LABEL (ic->next) == returnLabel))
3680
3681     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3682
3683 }
3684
3685 /*-----------------------------------------------------------------*/
3686 /* genLabel - generates a label                                    */
3687 /*-----------------------------------------------------------------*/
3688 static void
3689 genLabel (iCode * ic)
3690 {
3691   /* special case never generate */
3692   if (IC_LABEL (ic) == entryLabel)
3693     return;
3694
3695   D (emitcode (";", "genLabel ");
3696     );
3697
3698   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3699 }
3700
3701 /*-----------------------------------------------------------------*/
3702 /* genGoto - generates a ljmp                                      */
3703 /*-----------------------------------------------------------------*/
3704 static void
3705 genGoto (iCode * ic)
3706 {
3707   D (emitcode (";", "genGoto ");
3708     );
3709   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3710 }
3711
3712 /*-----------------------------------------------------------------*/
3713 /* findLabelBackwards: walks back through the iCode chain looking  */
3714 /* for the given label. Returns number of iCode instructions     */
3715 /* between that label and given ic.          */
3716 /* Returns zero if label not found.          */
3717 /*-----------------------------------------------------------------*/
3718 static int
3719 findLabelBackwards (iCode * ic, int key)
3720 {
3721   int count = 0;
3722
3723   while (ic->prev)
3724     {
3725       ic = ic->prev;
3726       count++;
3727
3728       /* If we have any pushes or pops, we cannot predict the distance.
3729          I don't like this at all, this should be dealt with in the
3730          back-end */
3731       if (ic->op == IPUSH || ic->op == IPOP) {
3732         return 0;
3733       }
3734
3735       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3736         {
3737           /* printf("findLabelBackwards = %d\n", count); */
3738           return count;
3739         }
3740     }
3741
3742   return 0;
3743 }
3744
3745 /*-----------------------------------------------------------------*/
3746 /* genPlusIncr :- does addition with increment if possible         */
3747 /*-----------------------------------------------------------------*/
3748 static bool
3749 genPlusIncr (iCode * ic)
3750 {
3751   unsigned int icount;
3752   unsigned int size = getDataSize (IC_RESULT (ic));
3753
3754   /* will try to generate an increment */
3755   /* if the right side is not a literal
3756      we cannot */
3757   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3758     return FALSE;
3759
3760   /* if the literal value of the right hand side
3761      is greater than 4 then it is not worth it */
3762   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3763     return FALSE;
3764
3765   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3766       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3767       while (icount--) {
3768           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3769       }
3770       return TRUE;
3771   }
3772   /* if increment 16 bits in register */
3773   if (
3774        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3775        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3776        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3777        (size > 1) &&
3778        (icount == 1))
3779     {
3780       symbol  *tlbl;
3781       int     emitTlbl;
3782       int     labelRange;
3783       char    *l;
3784
3785       /* If the next instruction is a goto and the goto target
3786        * is <= 5 instructions previous to this, we can generate
3787        * jumps straight to that target.
3788        */
3789       if (ic->next && ic->next->op == GOTO
3790           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3791           && labelRange <= 5)
3792         {
3793           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3794           tlbl = IC_LABEL (ic->next);
3795           emitTlbl = 0;
3796         }
3797       else
3798         {
3799           tlbl = newiTempLabel (NULL);
3800           emitTlbl = 1;
3801         }
3802
3803       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3804       emitcode ("inc", "%s", l);
3805
3806       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3807           IS_AOP_PREG (IC_RESULT (ic)))
3808         {
3809           emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3810         }
3811       else
3812         {
3813           emitcode ("clr", "a");
3814           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3815         }
3816
3817       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3818       emitcode ("inc", "%s", l);
3819       if (size > 2)
3820         {
3821           if (!strcmp(l, "acc"))
3822             {
3823                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3824             }
3825           else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3826                    IS_AOP_PREG (IC_RESULT (ic)))
3827             {
3828                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3829             }
3830           else
3831             {
3832                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3833             }
3834
3835           l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3836           emitcode ("inc", "%s", l);
3837         }
3838       if (size > 3)
3839         {
3840           if (!strcmp(l, "acc"))
3841             {
3842                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3843             }
3844           else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3845                    IS_AOP_PREG (IC_RESULT (ic)))
3846             {
3847                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3848             }
3849           else
3850             {
3851                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3852             }
3853
3854           l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3855           emitcode ("inc", "%s", l);
3856         }
3857
3858       if (emitTlbl)
3859         {
3860           emitcode ("", "!tlabeldef", tlbl->key + 100);
3861         }
3862       return TRUE;
3863     }
3864
3865   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3866       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3867       options.model == MODEL_FLAT24 )
3868     {
3869       if (IC_RESULT(ic)->isGptr)
3870         {
3871           emitcode ("mov","b,%s",aopGet(AOP (IC_LEFT (ic)), 3, FALSE, FALSE, NULL));
3872         }
3873       switch (size) {
3874       case 3:
3875           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3876       case 2:
3877           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3878       case 1:
3879           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3880           break;
3881       }
3882       while (icount--) emitcode ("inc","dptr");
3883       return TRUE;
3884   }
3885
3886   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3887       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3888       icount <= 5 ) {
3889       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3890       while (icount--) emitcode ("inc","dptr");
3891       emitcode ("mov","dps,#0");
3892       return TRUE;
3893   }
3894
3895   /* if the sizes are greater than 1 then we cannot */
3896   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3897       AOP_SIZE (IC_LEFT (ic)) > 1)
3898     return FALSE;
3899
3900   /* we can if the aops of the left & result match or
3901      if they are in registers and the registers are the
3902      same */
3903   if (
3904        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3905        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3906        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3907     {
3908
3909       if (icount > 3)
3910         {
3911           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3912           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3913           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3914         }
3915       else
3916         {
3917
3918           _startLazyDPSEvaluation ();
3919           while (icount--)
3920             {
3921               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3922             }
3923           _endLazyDPSEvaluation ();
3924         }
3925
3926       return TRUE;
3927     }
3928
3929   return FALSE;
3930 }
3931
3932 /*-----------------------------------------------------------------*/
3933 /* outBitAcc - output a bit in acc                                 */
3934 /*-----------------------------------------------------------------*/
3935 static void
3936 outBitAcc (operand * result)
3937 {
3938   symbol *tlbl = newiTempLabel (NULL);
3939   /* if the result is a bit */
3940   if (AOP_TYPE (result) == AOP_CRY)
3941     {
3942       aopPut (AOP (result), "a", 0);
3943     }
3944   else
3945     {
3946       emitcode ("jz", "!tlabel", tlbl->key + 100);
3947       emitcode ("mov", "a,%s", one);
3948       emitcode ("", "!tlabeldef", tlbl->key + 100);
3949       outAcc (result);
3950     }
3951 }
3952
3953 /*-----------------------------------------------------------------*/
3954 /* genPlusBits - generates code for addition of two bits           */
3955 /*-----------------------------------------------------------------*/
3956 static void
3957 genPlusBits (iCode * ic)
3958 {
3959   D (emitcode (";", "genPlusBits "););
3960
3961   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3962     {
3963       symbol *lbl = newiTempLabel (NULL);
3964       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3965       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3966       emitcode ("cpl", "c");
3967       emitcode ("", "!tlabeldef", (lbl->key + 100));
3968       outBitC (IC_RESULT (ic));
3969     }
3970   else
3971     {
3972       emitcode ("clr", "a");
3973       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3974       emitcode ("rlc", "a");
3975       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3976       emitcode ("addc", "a,#0");
3977       outAcc (IC_RESULT (ic));
3978     }
3979 }
3980
3981 static void
3982 adjustArithmeticResult (iCode * ic)
3983 {
3984   if (opIsGptr (IC_RESULT (ic)) &&
3985       opIsGptr (IC_LEFT (ic)) &&
3986       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3987     {
3988       aopPut (AOP (IC_RESULT (ic)),
3989               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3990               GPTRSIZE - 1);
3991     }
3992
3993   if (opIsGptr (IC_RESULT (ic)) &&
3994       opIsGptr (IC_RIGHT (ic)) &&
3995       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3996     {
3997       aopPut (AOP (IC_RESULT (ic)),
3998             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3999               GPTRSIZE - 1);
4000     }
4001
4002   if (opIsGptr (IC_RESULT (ic)) &&
4003       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4004       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4005       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4006       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4007     {
4008       char buff[5];
4009       SNPRINTF (buff, sizeof(buff),
4010                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
4011       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
4012     }
4013 }
4014
4015 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4016 // generates the result if possible. If result is generated, returns TRUE; otherwise
4017 // returns false and caller must deal with fact that result isn't aopOp'd.
4018 bool aopOp3(iCode * ic)
4019 {
4020     bool dp1InUse, dp2InUse;
4021     bool useDp2;
4022
4023     // First, generate the right opcode. DPTR may be used if neither left nor result are
4024     // of type AOP_STR.
4025
4026 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4027 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4028 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4029 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4030 //      );
4031 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4032 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4033 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4034 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4035 //      );
4036
4037     // Right uses DPTR unless left or result is an AOP_STR; however,
4038     // if right is an AOP_STR, it must use DPTR regardless.
4039     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4040      && !AOP_IS_STR(IC_RIGHT(ic)))
4041     {
4042         useDp2 = TRUE;
4043     }
4044     else
4045     {
4046         useDp2 = FALSE;
4047     }
4048
4049     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4050
4051     // if the right used DPTR, left MUST use DPTR2.
4052     // if the right used DPTR2, left MUST use DPTR.
4053     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4054     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4055     // enabling us to assign DPTR to result.
4056
4057     if (AOP_USESDPTR(IC_RIGHT(ic)))
4058     {
4059         useDp2 = TRUE;
4060     }
4061     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4062     {
4063         useDp2 = FALSE;
4064     }
4065     else
4066     {
4067         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4068         {
4069             useDp2 = TRUE;
4070         }
4071         else
4072         {
4073             useDp2 = FALSE;
4074         }
4075     }
4076
4077     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4078
4079
4080     // We've op'd the left & right. So, if left or right are the same operand as result,
4081     // we know aopOp will succeed, and we can just do it & bail.
4082     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4083       {
4084         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4085         return TRUE;
4086       }
4087     if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4088       {
4089 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
4090         aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4091         return TRUE;
4092       }
4093
4094     // Operands may be equivalent (but not equal) if they share a spill location. If
4095     // so, use the same DPTR or DPTR2.
4096     if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4097       {
4098         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4099         return TRUE;
4100       }
4101     if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4102       {
4103         aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4104         return TRUE;
4105       }
4106
4107     // Note which dptrs are currently in use.
4108     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4109     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4110
4111     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4112     // generate it.
4113     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4114     {
4115         return FALSE;
4116     }
4117
4118     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4119     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4120     {
4121         return FALSE;
4122     }
4123
4124     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4125     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4126     {
4127         return FALSE;
4128     }
4129
4130     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4131
4132     // Some sanity checking...
4133     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4134     {
4135         fprintf(stderr,
4136                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4137                 __FILE__, __LINE__, ic->filename, ic->lineno);
4138         emitcode(";", ">>> unexpected DPTR here.");
4139     }
4140
4141     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4142     {
4143         fprintf(stderr,
4144                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4145                 __FILE__, __LINE__, ic->filename, ic->lineno);
4146         emitcode(";", ">>> unexpected DPTR2 here.");
4147     }
4148
4149     return TRUE;
4150 }
4151
4152 // Macro to aopOp all three operands of an ic. If this cannot be done,
4153 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4154 // will be set TRUE. The caller must then handle the case specially, noting
4155 // that the IC_RESULT operand is not aopOp'd.
4156 //
4157 #define AOP_OP_3_NOFATAL(ic, rc) \
4158             do { rc = !aopOp3(ic); } while (0)
4159
4160 // aopOp the left & right operands of an ic.
4161 #define AOP_OP_2(ic) \
4162     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4163     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4164
4165 // convienience macro.
4166 #define AOP_SET_LOCALS(ic) \
4167     left = IC_LEFT(ic); \
4168     right = IC_RIGHT(ic); \
4169     result = IC_RESULT(ic);
4170
4171
4172 // Given an integer value of pushedSize bytes on the stack,
4173 // adjust it to be resultSize bytes, either by discarding
4174 // the most significant bytes or by zero-padding.
4175 //
4176 // On exit from this macro, pushedSize will have been adjusted to
4177 // equal resultSize, and ACC may be trashed.
4178 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
4179       /* If the pushed data is bigger than the result,          \
4180        * simply discard unused bytes. Icky, but works.          \
4181        */                                                       \
4182       while (pushedSize > resultSize)                           \
4183       {                                                         \
4184           D (emitcode (";", "discarding unused result byte."););\
4185           emitcode ("pop", "acc");                              \
4186           pushedSize--;                                         \
4187       }                                                         \
4188       if (pushedSize < resultSize)                              \
4189       {                                                         \
4190           emitcode ("clr", "a");                                \
4191           /* Conversly, we haven't pushed enough here.          \
4192            * just zero-pad, and all is well.                    \
4193            */                                                   \
4194           while (pushedSize < resultSize)                       \
4195           {                                                     \
4196               emitcode("push", "acc");                          \
4197               pushedSize++;                                     \
4198           }                                                     \
4199       }                                                         \
4200       assert(pushedSize == resultSize);
4201
4202 /*-----------------------------------------------------------------*/
4203 /* genPlus - generates code for addition                           */
4204 /*-----------------------------------------------------------------*/
4205 static void
4206 genPlus (iCode * ic)
4207 {
4208   int size, offset = 0;
4209   bool pushResult;
4210   int rSize;
4211
4212   D (emitcode (";", "genPlus "););
4213
4214   /* special cases :- */
4215   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4216       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4217       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4218       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4219       if (size <= 9) {
4220           while (size--) emitcode ("inc","dptr");
4221       } else {
4222           emitcode ("mov","a,dpl");
4223           emitcode ("add","a,#!constbyte",size & 0xff);
4224           emitcode ("mov","dpl,a");
4225           emitcode ("mov","a,dph");
4226           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4227           emitcode ("mov","dph,a");
4228           emitcode ("mov","a,dpx");
4229           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4230           emitcode ("mov","dpx,a");
4231       }
4232       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4233       return ;
4234   }
4235   if ( IS_SYMOP(IC_LEFT(ic)) &&
4236        OP_SYMBOL(IC_LEFT(ic))->remat &&
4237        isOperandInFarSpace(IC_RIGHT(ic))) {
4238       operand *op = IC_RIGHT(ic);
4239       IC_RIGHT(ic) = IC_LEFT(ic);
4240       IC_LEFT(ic) = op;
4241   }
4242
4243   AOP_OP_3_NOFATAL (ic, pushResult);
4244
4245   if (pushResult)
4246     {
4247       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4248     }
4249
4250   if (!pushResult)
4251     {
4252       /* if literal, literal on the right or
4253          if left requires ACC or right is already
4254          in ACC */
4255       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4256        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4257           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4258         {
4259           operand *t = IC_RIGHT (ic);
4260           IC_RIGHT (ic) = IC_LEFT (ic);
4261           IC_LEFT (ic) = t;
4262           emitcode (";", "Swapped plus args.");
4263         }
4264
4265       /* if both left & right are in bit
4266          space */
4267       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4268           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4269         {
4270           genPlusBits (ic);
4271           goto release;
4272         }
4273
4274       /* if left in bit space & right literal */
4275       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4276           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4277         {
4278           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4279           /* if result in bit space */
4280           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4281             {
4282               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4283                 emitcode ("cpl", "c");
4284               outBitC (IC_RESULT (ic));
4285             }
4286           else
4287             {
4288               size = getDataSize (IC_RESULT (ic));
4289               _startLazyDPSEvaluation ();
4290               while (size--)
4291                 {
4292                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4293                   emitcode ("addc", "a,#0");
4294                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4295                 }
4296               _endLazyDPSEvaluation ();
4297             }
4298           goto release;
4299         }
4300
4301       /* if I can do an increment instead
4302          of add then GOOD for ME */
4303       if (genPlusIncr (ic) == TRUE)
4304         {
4305           emitcode (";", "did genPlusIncr");
4306           goto release;
4307         }
4308
4309     }
4310   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4311
4312   _startLazyDPSEvaluation ();
4313   while (size--)
4314     {
4315       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4316         {
4317           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4318           if (offset == 0)
4319             emitcode ("add", "a,%s",
4320                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4321           else
4322             emitcode ("addc", "a,%s",
4323                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4324         }
4325       else
4326         {
4327           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4328           {
4329               /* right is going to use ACC or we would have taken the
4330                * above branch.
4331                */
4332               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4333        TR_AP("#3");
4334               D(emitcode(";", "+ AOP_ACC special case."););
4335               emitcode("xch", "a, %s", DP2_RESULT_REG);
4336           }
4337           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4338           if (offset == 0)
4339           {
4340             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4341             {
4342          TR_AP("#4");
4343                 emitcode("add", "a, %s", DP2_RESULT_REG);
4344             }
4345             else
4346             {
4347                 emitcode ("add", "a,%s",
4348                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4349                                   DP2_RESULT_REG));
4350             }
4351           }
4352           else
4353           {
4354             emitcode ("addc", "a,%s",
4355                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4356                           DP2_RESULT_REG));
4357           }
4358         }
4359       if (!pushResult)
4360         {
4361           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4362         }
4363       else
4364         {
4365           emitcode ("push", "acc");
4366         }
4367       offset++;
4368     }
4369   _endLazyDPSEvaluation ();
4370
4371   if (pushResult)
4372     {
4373       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4374
4375       size = getDataSize (IC_LEFT (ic));
4376       rSize = getDataSize (IC_RESULT (ic));
4377
4378       ADJUST_PUSHED_RESULT(size, rSize);
4379
4380       _startLazyDPSEvaluation ();
4381       while (size--)
4382         {
4383           emitcode ("pop", "acc");
4384           aopPut (AOP (IC_RESULT (ic)), "a", size);
4385         }
4386       _endLazyDPSEvaluation ();
4387     }
4388
4389   adjustArithmeticResult (ic);
4390
4391 release:
4392   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4393   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4394   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4395 }
4396
4397 /*-----------------------------------------------------------------*/
4398 /* genMinusDec :- does subtraction with deccrement if possible     */
4399 /*-----------------------------------------------------------------*/
4400 static bool
4401 genMinusDec (iCode * ic)
4402 {
4403   unsigned int icount;
4404   unsigned int size = getDataSize (IC_RESULT (ic));
4405
4406   /* will try to generate an increment */
4407   /* if the right side is not a literal
4408      we cannot */
4409   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4410     return FALSE;
4411
4412   /* if the literal value of the right hand side
4413      is greater than 4 then it is not worth it */
4414   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4415     return FALSE;
4416
4417   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4418       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4419       while (icount--) {
4420           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4421       }
4422       return TRUE;
4423   }
4424   /* if decrement 16 bits in register */
4425   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4426       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4427       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4428       (size > 1) &&
4429       (icount == 1))
4430     {
4431       symbol *tlbl;
4432       int    emitTlbl;
4433       int    labelRange;
4434       char   *l;
4435
4436       /* If the next instruction is a goto and the goto target
4437          * is <= 5 instructions previous to this, we can generate
4438          * jumps straight to that target.
4439        */
4440       if (ic->next && ic->next->op == GOTO
4441           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4442           && labelRange <= 5)
4443         {
4444           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4445           tlbl = IC_LABEL (ic->next);
4446           emitTlbl = 0;
4447         }
4448       else
4449         {
4450           tlbl = newiTempLabel (NULL);
4451           emitTlbl = 1;
4452         }
4453
4454       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4455       emitcode ("dec", "%s", l);
4456
4457       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4458           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4459           IS_AOP_PREG (IC_RESULT (ic)))
4460       {
4461           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4462       }
4463       else
4464       {
4465           emitcode ("mov", "a,#!constbyte",0xff);
4466           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4467       }
4468       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4469       emitcode ("dec", "%s", l);
4470       if (size > 2)
4471         {
4472             if (!strcmp(l, "acc"))
4473             {
4474                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4475             }
4476             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4477                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4478                      IS_AOP_PREG (IC_RESULT (ic)))
4479             {
4480                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4481             }
4482             else
4483             {
4484                 emitcode ("mov", "a,#!constbyte",0xff);
4485                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4486             }
4487             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4488             emitcode ("dec", "%s", l);
4489         }
4490       if (size > 3)
4491         {
4492             if (!strcmp(l, "acc"))
4493             {
4494                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4495             }
4496             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4497                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4498                      IS_AOP_PREG (IC_RESULT (ic)))
4499             {
4500                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4501             }
4502             else
4503             {
4504                 emitcode ("mov", "a,#!constbyte",0xff);
4505                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4506             }
4507             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4508             emitcode ("dec", "%s", l);
4509         }
4510       if (emitTlbl)
4511         {
4512           emitcode ("", "!tlabeldef", tlbl->key + 100);
4513         }
4514       return TRUE;
4515     }
4516
4517   /* if the sizes are greater than 1 then we cannot */
4518   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4519       AOP_SIZE (IC_LEFT (ic)) > 1)
4520     return FALSE;
4521
4522   /* we can if the aops of the left & result match or
4523      if they are in registers and the registers are the
4524      same */
4525   if (
4526        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4527        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4528        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4529     {
4530
4531       _startLazyDPSEvaluation ();
4532       while (icount--)
4533         {
4534           emitcode ("dec", "%s",
4535                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4536         }
4537       _endLazyDPSEvaluation ();
4538
4539       return TRUE;
4540     }
4541
4542   return FALSE;
4543 }
4544
4545 /*-----------------------------------------------------------------*/
4546 /* addSign - complete with sign                                    */
4547 /*-----------------------------------------------------------------*/
4548 static void
4549 addSign (operand * result, int offset, int sign)
4550 {
4551   int size = (getDataSize (result) - offset);
4552   if (size > 0)
4553     {
4554       _startLazyDPSEvaluation();
4555       if (sign)
4556         {
4557           emitcode ("rlc", "a");
4558           emitcode ("subb", "a,acc");
4559           while (size--)
4560           {
4561             aopPut (AOP (result), "a", offset++);
4562           }
4563         }
4564       else
4565       {
4566         while (size--)
4567         {
4568           aopPut (AOP (result), zero, offset++);
4569         }
4570       }
4571       _endLazyDPSEvaluation();
4572     }
4573 }
4574
4575 /*-----------------------------------------------------------------*/
4576 /* genMinusBits - generates code for subtraction  of two bits      */
4577 /*-----------------------------------------------------------------*/
4578 static void
4579 genMinusBits (iCode * ic)
4580 {
4581   symbol *lbl = newiTempLabel (NULL);
4582
4583   D (emitcode (";", "genMinusBits "););
4584
4585   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4586     {
4587       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4588       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4589       emitcode ("cpl", "c");
4590       emitcode ("", "!tlabeldef", (lbl->key + 100));
4591       outBitC (IC_RESULT (ic));
4592     }
4593   else
4594     {
4595       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4596       emitcode ("subb", "a,acc");
4597       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4598       emitcode ("inc", "a");
4599       emitcode ("", "!tlabeldef", (lbl->key + 100));
4600       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4601       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4602     }
4603 }
4604
4605 /*-----------------------------------------------------------------*/
4606 /* genMinus - generates code for subtraction                       */
4607 /*-----------------------------------------------------------------*/
4608 static void
4609 genMinus (iCode * ic)
4610 {
4611     int size, offset = 0;
4612     int rSize;
4613     long lit = 0L;
4614     bool pushResult;
4615
4616     D (emitcode (";", "genMinus "););
4617
4618     AOP_OP_3_NOFATAL(ic, pushResult);
4619
4620     if (!pushResult)
4621     {
4622       /* special cases :- */
4623       /* if both left & right are in bit space */
4624       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4625           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4626         {
4627           genMinusBits (ic);
4628           goto release;
4629         }
4630
4631       /* if I can do an decrement instead
4632          of subtract then GOOD for ME */
4633       if (genMinusDec (ic) == TRUE)
4634         goto release;
4635
4636     }
4637
4638   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4639
4640   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4641     {
4642       CLRC;
4643     }
4644   else
4645     {
4646       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4647       lit = -lit;
4648     }
4649
4650
4651   /* if literal, add a,#-lit, else normal subb */
4652   _startLazyDPSEvaluation ();
4653   while (size--) {
4654       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4655           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4656               emitcode ("mov","b,%s",
4657                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4658               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4659               emitcode ("subb","a,b");
4660           } else {
4661               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4662               emitcode ("subb", "a,%s",
4663                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4664                                 DP2_RESULT_REG));
4665           }
4666       } else {
4667           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4668           /* first add without previous c */
4669           if (!offset) {
4670               if (!size && lit==-1) {
4671                   emitcode ("dec", "a");
4672               } else {
4673                   emitcode ("add", "a,#!constbyte",
4674                             (unsigned int) (lit & 0x0FFL));
4675               }
4676           } else {
4677               emitcode ("addc", "a,#!constbyte",
4678                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4679           }
4680       }
4681
4682       if (pushResult) {
4683           emitcode ("push", "acc");
4684       } else {
4685           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4686       }
4687       offset++;
4688   }
4689   _endLazyDPSEvaluation ();
4690
4691   if (pushResult)
4692     {
4693       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4694
4695       size = getDataSize (IC_LEFT (ic));
4696       rSize = getDataSize (IC_RESULT (ic));
4697
4698       ADJUST_PUSHED_RESULT(size, rSize);
4699
4700       _startLazyDPSEvaluation ();
4701       while (size--)
4702         {
4703           emitcode ("pop", "acc");
4704           aopPut (AOP (IC_RESULT (ic)), "a", size);
4705         }
4706       _endLazyDPSEvaluation ();
4707     }
4708
4709   adjustArithmeticResult (ic);
4710
4711 release:
4712   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4713   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4714   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4715 }
4716
4717
4718 /*-----------------------------------------------------------------*/
4719 /* genMultbits :- multiplication of bits                           */
4720 /*-----------------------------------------------------------------*/
4721 static void
4722 genMultbits (operand * left,
4723              operand * right,
4724              operand * result,
4725              iCode   * ic)
4726 {
4727   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4728   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4729   aopOp(result, ic, TRUE, FALSE);
4730   outBitC (result);
4731 }
4732
4733
4734 /*-----------------------------------------------------------------*/
4735 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4736 /*-----------------------------------------------------------------*/
4737 static void
4738 genMultOneByte (operand * left,
4739                 operand * right,
4740                 operand * result,
4741                 iCode   * ic)
4742 {
4743   int size;
4744   symbol *lbl;
4745   bool runtimeSign, compiletimeSign;
4746   bool lUnsigned, rUnsigned;
4747
4748
4749   /* (if two literals: the value is computed before) */
4750   /* if one literal, literal on the right */
4751   if (AOP_TYPE (left) == AOP_LIT)
4752     {
4753       operand *t = right;
4754       right = left;
4755       left = t;
4756       emitcode (";", "swapped left and right");
4757     }
4758
4759   /* (if two literals: the value is computed before) */
4760   /* if one literal, literal on the right */
4761   if (AOP_TYPE (left) == AOP_LIT)
4762     {
4763       operand *t = right;
4764       right = left;
4765       left = t;
4766       /* emitcode (";", "swapped left and right"); */
4767     }
4768   /* if no literal, unsigned on the right: shorter code */
4769   if (   AOP_TYPE (right) != AOP_LIT
4770       && SPEC_USIGN (getSpec (operandType (left))))
4771     {
4772       operand *t = right;
4773       right = left;
4774       left = t;
4775     }
4776
4777   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4778   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4779
4780   if ((lUnsigned && rUnsigned)
4781 /* sorry, I don't know how to get size
4782    without calling aopOp (result,...);
4783    see Feature Request  */
4784       /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
4785                    no need to take care about the signedness! */
4786     {
4787       /* just an unsigned 8 * 8 = 8 multiply
4788          or 8u * 8u = 16u */
4789       /* emitcode (";","unsigned"); */
4790       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4791       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4792       emitcode ("mul", "ab");
4793
4794       _G.accInUse++; _G.bInUse++;
4795       aopOp (result, ic, TRUE, FALSE);
4796       size = AOP_SIZE (result);
4797
4798       if (size < 1 || size > 2)
4799         {
4800           /* this should never happen */
4801           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4802                    size, __FILE__, lineno);
4803           exit (1);
4804         }
4805
4806       aopPut (AOP (result), "a", 0);
4807       _G.accInUse--; _G.bInUse--;
4808       if (size == 2)
4809         aopPut (AOP (result), "b", 1);
4810       return;
4811     }
4812
4813   /* we have to do a signed multiply */
4814   /* emitcode (";", "signed"); */
4815
4816   /* now sign adjust for both left & right */
4817
4818   /* let's see what's needed: */
4819   /* apply negative sign during runtime */
4820   runtimeSign = FALSE;
4821   /* negative sign from literals */
4822   compiletimeSign = FALSE;
4823
4824   if (!lUnsigned)
4825     {
4826       if (AOP_TYPE(left) == AOP_LIT)
4827         {
4828           /* signed literal */
4829           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4830           if (val < 0)
4831             compiletimeSign = TRUE;
4832         }
4833       else
4834         /* signed but not literal */
4835         runtimeSign = TRUE;
4836     }
4837
4838   if (!rUnsigned)
4839     {
4840       if (AOP_TYPE(right) == AOP_LIT)
4841         {
4842           /* signed literal */
4843           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4844           if (val < 0)
4845             compiletimeSign ^= TRUE;
4846         }
4847       else
4848         /* signed but not literal */
4849         runtimeSign = TRUE;
4850     }
4851
4852   /* initialize F0, which stores the runtime sign */
4853   if (runtimeSign)
4854     {
4855       if (compiletimeSign)
4856         emitcode ("setb", "F0"); /* set sign flag */
4857       else
4858         emitcode ("clr", "F0"); /* reset sign flag */
4859     }
4860
4861   /* save the signs of the operands */
4862   if (AOP_TYPE(right) == AOP_LIT)
4863     {
4864       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4865
4866       if (!rUnsigned && val < 0)
4867         emitcode ("mov", "b,#!constbyte", -val);
4868       else
4869         emitcode ("mov", "b,#!constbyte", (unsigned char) val);
4870     }
4871   else /* ! literal */
4872     {
4873       if (rUnsigned)  /* emitcode (";", "signed"); */
4874         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4875       else
4876         {
4877           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4878           lbl = newiTempLabel (NULL);
4879           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4880           emitcode ("cpl", "F0"); /* complement sign flag */
4881           emitcode ("cpl", "a");  /* 2's complement */
4882           emitcode ("inc", "a");
4883           emitcode ("", "!tlabeldef", lbl->key + 100);
4884           emitcode ("mov", "b,a");
4885         }
4886     }
4887
4888   if (AOP_TYPE(left) == AOP_LIT)
4889     {
4890       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4891
4892       if (!lUnsigned && val < 0)
4893         emitcode ("mov", "a,#!constbyte", -val);
4894       else
4895         emitcode ("mov", "a,#!constbyte", (unsigned char) val);
4896     }
4897   else /* ! literal */
4898     {
4899       if (lUnsigned)  /* emitcode (";", "signed"); */
4900
4901         emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4902       else
4903         {
4904           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4905           lbl = newiTempLabel (NULL);
4906           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
4907           emitcode ("cpl", "F0"); /* complement sign flag */
4908           emitcode ("cpl", "a");  /* 2's complement */
4909           emitcode ("inc", "a");
4910           emitcode ("", "!tlabeldef", lbl->key + 100);
4911         }
4912     }
4913
4914   /* now the multiplication */
4915   emitcode ("mul", "ab");
4916   _G.accInUse++;_G.bInUse++;
4917   aopOp(result, ic, TRUE, FALSE);
4918   size = AOP_SIZE (result);
4919
4920   if (size < 1 || size > 2)
4921     {
4922       /* this should never happen */
4923       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4924                size, __FILE__, lineno);
4925       exit (1);
4926     }
4927
4928   if (runtimeSign || compiletimeSign)
4929     {
4930       lbl = newiTempLabel (NULL);
4931       if (runtimeSign)
4932         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
4933       emitcode ("cpl", "a"); /* lsb 2's complement */
4934       if (size != 2)
4935         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4936       else
4937         {
4938           emitcode ("add", "a,#1"); /* this sets carry flag */
4939           emitcode ("xch", "a,b");
4940           emitcode ("cpl", "a"); /* msb 2's complement */
4941           emitcode ("addc", "a,#0");
4942           emitcode ("xch", "a,b");
4943         }
4944       emitcode ("", "!tlabeldef", lbl->key + 100);
4945     }
4946   aopPut (AOP (result), "a", 0);
4947   _G.accInUse--;_G.bInUse--;
4948   if (size == 2)
4949     aopPut (AOP (result), "b", 1);
4950 }
4951
4952 /*-----------------------------------------------------------------*/
4953 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4954 /*-----------------------------------------------------------------*/
4955 static void genMultTwoByte (operand *left, operand *right,
4956                             operand *result, iCode *ic)
4957 {
4958         sym_link *retype = getSpec(operandType(right));
4959         sym_link *letype = getSpec(operandType(left));
4960         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4961         symbol *lbl;
4962
4963         if (AOP_TYPE (left) == AOP_LIT) {
4964                 operand *t = right;
4965                 right = left;
4966                 left = t;
4967         }
4968         /* save EA bit in F1 */
4969         lbl = newiTempLabel(NULL);
4970         emitcode ("setb","F1");
4971         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4972         emitcode ("clr","F1");
4973         emitcode("","!tlabeldef",lbl->key+100);
4974
4975         /* load up MB with right */
4976         if (!umult) {
4977                 emitcode("clr","F0");
4978                 if (AOP_TYPE(right) == AOP_LIT) {
4979                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4980                         if (val < 0) {
4981                                 emitcode("setb","F0");
4982                                 val = -val;
4983                         }
4984                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4985                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4986                 } else {
4987                         lbl = newiTempLabel(NULL);
4988                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4989                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4990                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4991                         emitcode ("xch", "a,b");
4992                         emitcode ("cpl","a");
4993                         emitcode ("add", "a,#1");
4994                         emitcode ("xch", "a,b");
4995                         emitcode ("cpl", "a"); // msb
4996                         emitcode ("addc", "a,#0");
4997                         emitcode ("setb","F0");
4998                         emitcode ("","!tlabeldef",lbl->key+100);
4999                         emitcode ("mov","mb,b");
5000                         emitcode ("mov","mb,a");
5001                 }
5002         } else {
5003                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5004                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5005         }
5006         /* load up MA with left */
5007         if (!umult) {
5008                 lbl = newiTempLabel(NULL);
5009                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5010                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5011                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5012                 emitcode ("xch", "a,b");
5013                 emitcode ("cpl","a");
5014                 emitcode ("add", "a,#1");
5015                 emitcode ("xch", "a,b");
5016                 emitcode ("cpl", "a"); // msb
5017                 emitcode ("addc","a,#0");
5018                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5019                 emitcode ("setb","F0");
5020                 emitcode ("","!tlabeldef",lbl->key+100);
5021                 emitcode ("mov","ma,b");
5022                 emitcode ("mov","ma,a");
5023         } else {
5024                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5025                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5026         }
5027         /* wait for multiplication to finish */
5028         lbl = newiTempLabel(NULL);
5029         emitcode("","!tlabeldef", lbl->key+100);
5030         emitcode("mov","a,mcnt1");
5031         emitcode("anl","a,#!constbyte",0x80);
5032         emitcode("jnz","!tlabel",lbl->key+100);
5033
5034         freeAsmop (left, NULL, ic, TRUE);
5035         freeAsmop (right, NULL, ic,TRUE);
5036         aopOp(result, ic, TRUE, FALSE);
5037
5038         /* if unsigned then simple */
5039         if (umult) {
5040                 emitcode ("mov","a,ma");
5041                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
5042                 emitcode ("mov","a,ma");
5043                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
5044                 aopPut(AOP(result),"ma",1);
5045                 aopPut(AOP(result),"ma",0);
5046         } else {
5047                 emitcode("push","ma");
5048                 emitcode("push","ma");
5049                 emitcode("push","ma");
5050                 MOVA("ma");
5051                 /* negate result if needed */
5052                 lbl = newiTempLabel(NULL);
5053                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5054                 emitcode("cpl","a");
5055                 emitcode("add","a,#1");
5056                 emitcode("","!tlabeldef", lbl->key+100);
5057                 if (AOP_TYPE(result) == AOP_ACC)
5058                 {
5059                     D(emitcode(";", "ACC special case."););
5060                     /* We know result is the only live aop, and
5061                      * it's obviously not a DPTR2, so AP is available.
5062                      */
5063                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
5064                 }
5065                 else
5066                 {
5067                     aopPut(AOP(result),"a",0);
5068                 }
5069
5070                 emitcode("pop","acc");
5071                 lbl = newiTempLabel(NULL);
5072                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5073                 emitcode("cpl","a");
5074                 emitcode("addc","a,#0");
5075                 emitcode("","!tlabeldef", lbl->key+100);
5076                 aopPut(AOP(result),"a",1);
5077                 emitcode("pop","acc");
5078                 if (AOP_SIZE(result) >= 3) {
5079                         lbl = newiTempLabel(NULL);
5080                         emitcode("jnb","F0,!tlabel",lbl->key+100);
5081                         emitcode("cpl","a");
5082                         emitcode("addc","a,#0");
5083                         emitcode("","!tlabeldef", lbl->key+100);
5084                         aopPut(AOP(result),"a",2);
5085                 }
5086                 emitcode("pop","acc");
5087                 if (AOP_SIZE(result) >= 4) {
5088                         lbl = newiTempLabel(NULL);
5089                         emitcode("jnb","F0,!tlabel",lbl->key+100);
5090                         emitcode("cpl","a");
5091                         emitcode("addc","a,#0");
5092                         emitcode("","!tlabeldef", lbl->key+100);
5093                         aopPut(AOP(result),"a",3);
5094                 }
5095                 if (AOP_TYPE(result) == AOP_ACC)
5096                 {
5097                     /* We stashed the result away above. */
5098                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
5099                 }
5100
5101         }
5102         freeAsmop (result, NULL, ic, TRUE);
5103
5104         /* restore EA bit in F1 */
5105         lbl = newiTempLabel(NULL);
5106         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5107         emitcode ("setb","EA");
5108         emitcode("","!tlabeldef",lbl->key+100);
5109         return ;
5110 }
5111
5112 /*-----------------------------------------------------------------*/
5113 /* genMult - generates code for multiplication                     */
5114 /*-----------------------------------------------------------------*/
5115 static void
5116 genMult (iCode * ic)
5117 {
5118   operand *left = IC_LEFT (ic);
5119   operand *right = IC_RIGHT (ic);
5120   operand *result = IC_RESULT (ic);
5121
5122   D (emitcode (";", "genMult "););
5123
5124   /* assign the amsops */
5125   AOP_OP_2 (ic);
5126
5127   /* special cases first */
5128   /* both are bits */
5129   if (AOP_TYPE (left) == AOP_CRY &&
5130       AOP_TYPE (right) == AOP_CRY)
5131     {
5132       genMultbits (left, right, result, ic);
5133       goto release;
5134     }
5135
5136   /* if both are of size == 1 */
5137   if (AOP_SIZE (left) == 1 &&
5138       AOP_SIZE (right) == 1)
5139     {
5140       genMultOneByte (left, right, result, ic);
5141       goto release;
5142     }
5143
5144   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5145           /* use the ds390 ARITHMETIC accel UNIT */
5146           genMultTwoByte (left, right, result, ic);
5147           return ;
5148   }
5149   /* should have been converted to function call */
5150   assert (0);
5151
5152 release:
5153   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5154   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5155   freeAsmop (result, NULL, ic, TRUE);
5156 }
5157
5158 /*-----------------------------------------------------------------*/
5159 /* genDivbits :- division of bits                                  */
5160 /*-----------------------------------------------------------------*/
5161 static void
5162 genDivbits (operand * left,
5163             operand * right,
5164             operand * result,
5165             iCode   * ic)
5166 {
5167
5168   char *l;
5169
5170   /* the result must be bit */
5171   LOAD_AB_FOR_DIV (left, right, l);
5172   emitcode ("div", "ab");
5173   emitcode ("rrc", "a");
5174   aopOp(result, ic, TRUE, FALSE);
5175
5176   aopPut (AOP (result), "c", 0);
5177 }
5178
5179 /*-----------------------------------------------------------------*/
5180 /* genDivOneByte : 8 bit division                                  */
5181 /*-----------------------------------------------------------------*/
5182 static void
5183 genDivOneByte (operand * left,
5184                operand * right,
5185                operand * result,
5186                iCode   * ic)
5187 {
5188   bool lUnsigned, rUnsigned;
5189   bool runtimeSign, compiletimeSign;
5190   char *l;
5191   symbol *lbl;
5192   int size, offset;
5193
5194   offset = 1;
5195   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5196   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5197
5198   /* signed or unsigned */
5199   if (lUnsigned && rUnsigned)
5200     {
5201       /* unsigned is easy */
5202       LOAD_AB_FOR_DIV (left, right, l);
5203       emitcode ("div", "ab");
5204
5205       _G.accInUse++;
5206       aopOp (result, ic, TRUE, FALSE);
5207       aopPut (AOP (result), "a", 0);
5208       _G.accInUse--;
5209
5210       size = AOP_SIZE (result) - 1;
5211
5212       while (size--)
5213         aopPut (AOP (result), zero, offset++);
5214       return;
5215     }
5216
5217   /* signed is a little bit more difficult */
5218
5219   /* now sign adjust for both left & right */
5220
5221   /* let's see what's needed: */
5222   /* apply negative sign during runtime */
5223   runtimeSign = FALSE;
5224   /* negative sign from literals */
5225   compiletimeSign = FALSE;
5226
5227   if (!lUnsigned)
5228     {
5229       if (AOP_TYPE(left) == AOP_LIT)
5230         {
5231           /* signed literal */
5232           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5233           if (val < 0)
5234             compiletimeSign = TRUE;
5235         }
5236       else
5237         /* signed but not literal */
5238         runtimeSign = TRUE;
5239     }
5240
5241   if (!rUnsigned)
5242     {
5243       if (AOP_TYPE(right) == AOP_LIT)
5244         {
5245           /* signed literal */
5246           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5247           if (val < 0)
5248             compiletimeSign ^= TRUE;
5249         }
5250       else
5251         /* signed but not literal */
5252         runtimeSign = TRUE;
5253     }
5254
5255   /* initialize F0, which stores the runtime sign */
5256   if (runtimeSign)
5257     {
5258       if (compiletimeSign)
5259         emitcode ("setb", "F0"); /* set sign flag */
5260       else
5261         emitcode ("clr", "F0"); /* reset sign flag */
5262     }
5263
5264   /* save the signs of the operands */
5265   if (AOP_TYPE(right) == AOP_LIT)
5266     {
5267       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5268
5269       if (!rUnsigned && val < 0)
5270         emitcode ("mov", "b,#0x%02x", -val);
5271       else
5272         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5273     }
5274   else /* ! literal */
5275     {
5276       if (rUnsigned)
5277         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5278       else
5279         {
5280           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5281           lbl = newiTempLabel (NULL);
5282           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5283           emitcode ("cpl", "F0"); /* complement sign flag */
5284           emitcode ("cpl", "a");  /* 2's complement */
5285           emitcode ("inc", "a");
5286           emitcode ("", "!tlabeldef", lbl->key + 100);
5287           emitcode ("mov", "b,a");
5288         }
5289     }
5290
5291   if (AOP_TYPE(left) == AOP_LIT)
5292     {
5293       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5294
5295       if (!lUnsigned && val < 0)
5296         emitcode ("mov", "a,#0x%02x", -val);
5297       else
5298         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5299     }
5300   else /* ! literal */
5301     {
5302       if (lUnsigned)
5303         emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5304       else
5305         {
5306           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5307           lbl = newiTempLabel (NULL);
5308           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5309           emitcode ("cpl", "F0"); /* complement sign flag */
5310           emitcode ("cpl", "a");  /* 2's complement */
5311           emitcode ("inc", "a");
5312           emitcode ("", "!tlabeldef", lbl->key + 100);
5313         }
5314     }
5315
5316   /* now the division */
5317   emitcode ("nop", "; workaround for DS80C390 div bug.");
5318   emitcode ("div", "ab");
5319
5320   if (runtimeSign || compiletimeSign)
5321     {
5322       lbl = newiTempLabel (NULL);
5323       if (runtimeSign)
5324         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5325       emitcode ("cpl", "a"); /* lsb 2's complement */
5326       emitcode ("inc", "a");
5327       emitcode ("", "!tlabeldef", lbl->key + 100);
5328
5329       _G.accInUse++;     _G.bInUse++;
5330       aopOp (result, ic, TRUE, FALSE);
5331       size = AOP_SIZE (result) - 1;
5332
5333       if (size > 0)
5334         {
5335           /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5336              then the result will be in b, a */
5337           emitcode ("mov", "b,a"); /* 1 */
5338           /* msb is 0x00 or 0xff depending on the sign */
5339           if (runtimeSign)
5340             {
5341               emitcode ("mov",  "c,F0");
5342               emitcode ("subb", "a,acc");
5343               emitcode ("xch",  "a,b"); /* 2 */
5344               while (size--)
5345                 aopPut (AOP (result), "b", offset++); /* write msb's */
5346             }
5347           else /* compiletimeSign */
5348             while (size--)
5349               aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5350         }
5351       aopPut (AOP (result), "a", 0); /* 3: write lsb */
5352     }
5353   else
5354     {
5355       _G.accInUse++;     _G.bInUse++;
5356       aopOp(result, ic, TRUE, FALSE);
5357       size = AOP_SIZE (result) - 1;
5358
5359       aopPut (AOP (result), "a", 0);
5360       while (size--)
5361         aopPut (AOP (result), zero, offset++);
5362     }
5363   _G.accInUse--;     _G.bInUse--;
5364
5365 }
5366
5367 /*-----------------------------------------------------------------*/
5368 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
5369 /*-----------------------------------------------------------------*/
5370 static void genDivTwoByte (operand *left, operand *right,
5371                             operand *result, iCode *ic)
5372 {
5373         sym_link *retype = getSpec(operandType(right));
5374         sym_link *letype = getSpec(operandType(left));
5375         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5376         symbol *lbl;
5377
5378         /* save EA bit in F1 */
5379         lbl = newiTempLabel(NULL);
5380         emitcode ("setb","F1");
5381         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5382         emitcode ("clr","F1");
5383         emitcode("","!tlabeldef",lbl->key+100);
5384
5385         /* load up MA with left */
5386         if (!umult) {
5387                 emitcode("clr","F0");
5388                 lbl = newiTempLabel(NULL);
5389                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5390                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5391                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5392                 emitcode ("xch", "a,b");
5393                 emitcode ("cpl","a");
5394                 emitcode ("add", "a,#1");
5395                 emitcode ("xch", "a,b");
5396                 emitcode ("cpl", "a"); // msb
5397                 emitcode ("addc","a,#0");
5398                 emitcode ("setb","F0");
5399                 emitcode ("","!tlabeldef",lbl->key+100);
5400                 emitcode ("mov","ma,b");
5401                 emitcode ("mov","ma,a");
5402         } else {
5403                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5404                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5405         }
5406
5407         /* load up MB with right */
5408         if (!umult) {
5409                 if (AOP_TYPE(right) == AOP_LIT) {
5410                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5411                         if (val < 0) {
5412                                 lbl = newiTempLabel(NULL);
5413                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5414                                 emitcode("setb","F0");
5415                                 emitcode ("","!tlabeldef",lbl->key+100);
5416                                 val = -val;
5417                         }
5418                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5419                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5420                 } else {
5421                         lbl = newiTempLabel(NULL);
5422                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5423                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5424                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5425                         emitcode ("xch", "a,b");
5426                         emitcode ("cpl","a");
5427                         emitcode ("add", "a,#1");
5428                         emitcode ("xch", "a,b");
5429                         emitcode ("cpl", "a"); // msb
5430                         emitcode ("addc", "a,#0");
5431                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5432                         emitcode ("setb","F0");
5433                         emitcode ("","!tlabeldef",lbl->key+100);
5434                         emitcode ("mov","mb,b");
5435                         emitcode ("mov","mb,a");
5436                 }
5437         } else {
5438                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5439                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5440         }
5441
5442         /* wait for multiplication to finish */
5443         lbl = newiTempLabel(NULL);
5444         emitcode("","!tlabeldef", lbl->key+100);
5445         emitcode("mov","a,mcnt1");
5446         emitcode("anl","a,#!constbyte",0x80);
5447         emitcode("jnz","!tlabel",lbl->key+100);
5448
5449         freeAsmop (left, NULL, ic, TRUE);
5450         freeAsmop (right, NULL, ic,TRUE);
5451         aopOp(result, ic, TRUE, FALSE);
5452
5453         /* if unsigned then simple */
5454         if (umult) {
5455                 aopPut(AOP(result),"ma",1);
5456                 aopPut(AOP(result),"ma",0);
5457         } else {
5458                 emitcode("push","ma");
5459                 MOVA("ma");
5460                 /* negate result if needed */
5461                 lbl = newiTempLabel(NULL);
5462                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5463                 emitcode("cpl","a");
5464                 emitcode("add","a,#1");
5465                 emitcode("","!tlabeldef", lbl->key+100);
5466                 aopPut(AOP(result),"a",0);
5467                 emitcode("pop","acc");
5468                 lbl = newiTempLabel(NULL);
5469                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5470                 emitcode("cpl","a");
5471                 emitcode("addc","a,#0");
5472                 emitcode("","!tlabeldef", lbl->key+100);
5473                 aopPut(AOP(result),"a",1);
5474         }
5475         freeAsmop (result, NULL, ic, TRUE);
5476         /* restore EA bit in F1 */
5477         lbl = newiTempLabel(NULL);
5478         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5479         emitcode ("setb","EA");
5480         emitcode("","!tlabeldef",lbl->key+100);
5481         return ;
5482 }
5483
5484 /*-----------------------------------------------------------------*/
5485 /* genDiv - generates code for division                            */
5486 /*-----------------------------------------------------------------*/
5487 static void
5488 genDiv (iCode * ic)
5489 {
5490   operand *left = IC_LEFT (ic);
5491   operand *right = IC_RIGHT (ic);
5492   operand *result = IC_RESULT (ic);
5493
5494   D (emitcode (";", "genDiv "););
5495
5496   /* assign the amsops */
5497   AOP_OP_2 (ic);
5498
5499   /* special cases first */
5500   /* both are bits */
5501   if (AOP_TYPE (left) == AOP_CRY &&
5502       AOP_TYPE (right) == AOP_CRY)
5503     {
5504       genDivbits (left, right, result, ic);
5505       goto release;
5506     }
5507
5508   /* if both are of size == 1 */
5509   if (AOP_SIZE (left) == 1 &&
5510       AOP_SIZE (right) == 1)
5511     {
5512       genDivOneByte (left, right, result, ic);
5513       goto release;
5514     }
5515
5516   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5517           /* use the ds390 ARITHMETIC accel UNIT */
5518           genDivTwoByte (left, right, result, ic);
5519           return ;
5520   }
5521   /* should have been converted to function call */
5522   assert (0);
5523 release:
5524   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5525   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5526   freeAsmop (result, NULL, ic, TRUE);
5527 }
5528
5529 /*-----------------------------------------------------------------*/
5530 /* genModbits :- modulus of bits                                   */
5531 /*-----------------------------------------------------------------*/
5532 static void
5533 genModbits (operand * left,
5534             operand * right,
5535             operand * result,
5536             iCode   * ic)
5537 {
5538
5539   char *l;
5540
5541   /* the result must be bit */
5542   LOAD_AB_FOR_DIV (left, right, l);
5543   emitcode ("div", "ab");
5544   emitcode ("mov", "a,b");
5545   emitcode ("rrc", "a");
5546   aopOp(result, ic, TRUE, FALSE);
5547   aopPut (AOP (result), "c", 0);
5548 }
5549
5550 /*-----------------------------------------------------------------*/
5551 /* genModOneByte : 8 bit modulus                                   */
5552 /*-----------------------------------------------------------------*/
5553 static void
5554 genModOneByte (operand * left,
5555                operand * right,
5556                operand * result,
5557                iCode   * ic)
5558 {
5559   bool lUnsigned, rUnsigned;
5560   bool runtimeSign, compiletimeSign;
5561   char *l;
5562   symbol *lbl;
5563   int size, offset;
5564
5565   offset = 1;
5566   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5567   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5568
5569   /* signed or unsigned */
5570   if (lUnsigned && rUnsigned)
5571     {
5572       /* unsigned is easy */
5573       LOAD_AB_FOR_DIV (left, right, l);
5574       emitcode ("div", "ab");
5575       aopOp (result, ic, TRUE, FALSE);
5576       aopPut (AOP (result), "b", 0);
5577
5578       for (size = AOP_SIZE (result) - 1; size--;)
5579         aopPut (AOP (result), zero, offset++);
5580       return;
5581     }
5582
5583   /* signed is a little bit more difficult */
5584
5585   /* now sign adjust for both left & right */
5586
5587   /* modulus: sign of the right operand has no influence on the result! */
5588   if (AOP_TYPE(right) == AOP_LIT)
5589     {
5590       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5591
5592       if (!rUnsigned && val < 0)
5593         emitcode ("mov", "b,#0x%02x", -val);
5594       else
5595         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5596     }
5597   else /* ! literal */
5598     {
5599       if (rUnsigned)
5600         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5601       else
5602         {
5603           MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5604           lbl = newiTempLabel (NULL);
5605           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5606           emitcode ("cpl", "a");  /* 2's complement */
5607           emitcode ("inc", "a");
5608           emitcode ("", "!tlabeldef", lbl->key + 100);
5609           emitcode ("mov", "b,a");
5610         }
5611     }
5612
5613   /* let's see what's needed: */
5614   /* apply negative sign during runtime */
5615   runtimeSign = FALSE;
5616   /* negative sign from literals */
5617   compiletimeSign = FALSE;
5618
5619   /* sign adjust left side */
5620   if (AOP_TYPE(left) == AOP_LIT)
5621     {
5622       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5623
5624       if (!lUnsigned && val < 0)
5625         {
5626           compiletimeSign = TRUE; /* set sign flag */
5627           emitcode ("mov", "a,#0x%02x", -val);
5628         }
5629       else
5630         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5631     }
5632   else /* ! literal */
5633     {
5634       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5635
5636       if (!lUnsigned)
5637         {
5638           runtimeSign = TRUE;
5639           emitcode ("clr", "F0"); /* clear sign flag */
5640
5641           lbl = newiTempLabel (NULL);
5642           emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5643           emitcode ("setb", "F0"); /* set sign flag */
5644           emitcode ("cpl", "a");   /* 2's complement */
5645           emitcode ("inc", "a");
5646           emitcode ("", "!tlabeldef", lbl->key + 100);
5647         }
5648     }
5649
5650   /* now the modulus */
5651   emitcode ("nop", "; workaround for DS80C390 div bug.");
5652   emitcode ("div", "ab");
5653
5654   if (runtimeSign || compiletimeSign)
5655     {
5656       emitcode ("mov", "a,b");
5657       lbl = newiTempLabel (NULL);
5658       if (runtimeSign)
5659         emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5660       emitcode ("cpl", "a"); /* lsb 2's complement */
5661       emitcode ("inc", "a");
5662       emitcode ("", "!tlabeldef", lbl->key + 100);
5663
5664       _G.accInUse++;     _G.bInUse++;
5665       aopOp (result, ic, TRUE, FALSE);
5666       size = AOP_SIZE (result) - 1;
5667
5668       if (size > 0)
5669         {
5670           /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5671              then the result will be in b, a */
5672           emitcode ("mov", "b,a"); /* 1 */
5673           /* msb is 0x00 or 0xff depending on the sign */
5674           if (runtimeSign)
5675             {
5676               emitcode ("mov",  "c,F0");
5677               emitcode ("subb", "a,acc");
5678               emitcode ("xch",  "a,b"); /* 2 */
5679               while (size--)
5680                 aopPut (AOP (result), "b", offset++); /* write msb's */
5681             }
5682           else /* compiletimeSign */
5683             while (size--)
5684               aopPut (AOP (result), "#0xff", offset++); /* write msb's */
5685         }
5686       aopPut (AOP (result), "a", 0); /* 3: write lsb */
5687     }
5688   else
5689     {
5690       _G.accInUse++;     _G.bInUse++;
5691       aopOp(result, ic, TRUE, FALSE);
5692       size = AOP_SIZE (result) - 1;
5693
5694       aopPut (AOP (result), "b", 0);
5695       while (size--)
5696         aopPut (AOP (result), zero, offset++);
5697     }
5698   _G.accInUse--;     _G.bInUse--;
5699
5700 }
5701
5702 /*-----------------------------------------------------------------*/
5703 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5704 /*-----------------------------------------------------------------*/
5705 static void genModTwoByte (operand *left, operand *right,
5706                             operand *result, iCode *ic)
5707 {
5708         sym_link *retype = getSpec(operandType(right));
5709         sym_link *letype = getSpec(operandType(left));
5710         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5711         symbol *lbl;
5712
5713         /* load up MA with left */
5714         /* save EA bit in F1 */
5715         lbl = newiTempLabel(NULL);
5716         emitcode ("setb","F1");
5717         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5718         emitcode ("clr","F1");
5719         emitcode("","!tlabeldef",lbl->key+100);
5720
5721         if (!umult) {
5722                 lbl = newiTempLabel(NULL);
5723                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5724                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5725                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5726                 emitcode ("xch", "a,b");
5727                 emitcode ("cpl","a");
5728                 emitcode ("add", "a,#1");
5729                 emitcode ("xch", "a,b");
5730                 emitcode ("cpl", "a"); // msb
5731                 emitcode ("addc","a,#0");
5732                 emitcode ("","!tlabeldef",lbl->key+100);
5733                 emitcode ("mov","ma,b");
5734                 emitcode ("mov","ma,a");
5735         } else {
5736                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5737                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5738         }
5739
5740         /* load up MB with right */
5741         if (!umult) {
5742                 if (AOP_TYPE(right) == AOP_LIT) {
5743                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5744                         if (val < 0) {
5745                                 val = -val;
5746                         }
5747                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5748                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5749                 } else {
5750                         lbl = newiTempLabel(NULL);
5751                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5752                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5753                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5754                         emitcode ("xch", "a,b");
5755                         emitcode ("cpl","a");
5756                         emitcode ("add", "a,#1");
5757                         emitcode ("xch", "a,b");
5758                         emitcode ("cpl", "a"); // msb
5759                         emitcode ("addc", "a,#0");
5760                         emitcode ("","!tlabeldef",lbl->key+100);
5761                         emitcode ("mov","mb,b");
5762                         emitcode ("mov","mb,a");
5763                 }
5764         } else {
5765                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5766                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5767         }
5768
5769         /* wait for multiplication to finish */
5770         lbl = newiTempLabel(NULL);
5771         emitcode("","!tlabeldef", lbl->key+100);
5772         emitcode("mov","a,mcnt1");
5773         emitcode("anl","a,#!constbyte",0x80);
5774         emitcode("jnz","!tlabel",lbl->key+100);
5775
5776         freeAsmop (left, NULL, ic, TRUE);
5777         freeAsmop (right, NULL, ic,TRUE);
5778         aopOp(result, ic, TRUE, FALSE);
5779
5780         aopPut(AOP(result),"mb",1);
5781         aopPut(AOP(result),"mb",0);
5782         freeAsmop (result, NULL, ic, TRUE);
5783
5784         /* restore EA bit in F1 */
5785         lbl = newiTempLabel(NULL);
5786         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5787         emitcode ("setb","EA");
5788         emitcode("","!tlabeldef",lbl->key+100);
5789         return ;
5790 }
5791
5792 /*-----------------------------------------------------------------*/
5793 /* genMod - generates code for division                            */
5794 /*-----------------------------------------------------------------*/
5795 static void
5796 genMod (iCode * ic)
5797 {
5798   operand *left = IC_LEFT (ic);
5799   operand *right = IC_RIGHT (ic);
5800   operand *result = IC_RESULT (ic);
5801
5802   D (emitcode (";", "genMod "); );
5803
5804   /* assign the amsops */
5805   AOP_OP_2 (ic);
5806
5807   /* special cases first */
5808   /* both are bits */
5809   if (AOP_TYPE (left) == AOP_CRY &&
5810       AOP_TYPE (right) == AOP_CRY)
5811     {
5812       genModbits (left, right, result, ic);
5813       goto release;
5814     }
5815
5816   /* if both are of size == 1 */
5817   if (AOP_SIZE (left) == 1 &&
5818       AOP_SIZE (right) == 1)
5819     {
5820       genModOneByte (left, right, result, ic);
5821       goto release;
5822     }
5823
5824   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5825           /* use the ds390 ARITHMETIC accel UNIT */
5826           genModTwoByte (left, right, result, ic);
5827           return ;
5828   }
5829
5830   /* should have been converted to function call */
5831   assert (0);
5832
5833 release:
5834   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5835   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5836   freeAsmop (result, NULL, ic, TRUE);
5837 }
5838
5839 /*-----------------------------------------------------------------*/
5840 /* genIfxJump :- will create a jump depending on the ifx           */
5841 /*-----------------------------------------------------------------*/
5842 static void
5843 genIfxJump (iCode * ic, char *jval)
5844 {
5845   symbol *jlbl;
5846   symbol *tlbl = newiTempLabel (NULL);
5847   char *inst;
5848
5849   D (emitcode (";", "genIfxJump"););
5850
5851   /* if true label then we jump if condition
5852      supplied is true */
5853   if (IC_TRUE (ic))
5854     {
5855       jlbl = IC_TRUE (ic);
5856       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5857                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5858     }
5859   else
5860     {
5861       /* false label is present */
5862       jlbl = IC_FALSE (ic);
5863       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5864                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5865     }
5866   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5867     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5868   else
5869     emitcode (inst, "!tlabel", tlbl->key + 100);
5870   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5871   emitcode ("", "!tlabeldef", tlbl->key + 100);
5872
5873   /* mark the icode as generated */
5874   ic->generated = 1;
5875 }
5876
5877 /*-----------------------------------------------------------------*/
5878 /* genCmp :- greater or less than comparison                       */
5879 /*-----------------------------------------------------------------*/
5880 static void
5881 genCmp (operand * left, operand * right,
5882         iCode * ic, iCode * ifx, int sign)
5883 {
5884   int size, offset = 0;
5885   unsigned long lit = 0L;
5886   operand *result;
5887
5888   D (emitcode (";", "genCmp"););
5889
5890   result = IC_RESULT (ic);
5891
5892   /* if left & right are bit variables */
5893   if (AOP_TYPE (left) == AOP_CRY &&
5894       AOP_TYPE (right) == AOP_CRY)
5895     {
5896       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5897       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5898     }
5899   else
5900     {
5901       /* subtract right from left if at the
5902          end the carry flag is set then we know that
5903          left is greater than right */
5904       size = max (AOP_SIZE (left), AOP_SIZE (right));
5905
5906       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5907       if ((size == 1) && !sign
5908           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5909         {
5910           symbol *lbl = newiTempLabel (NULL);
5911           emitcode ("cjne", "%s,%s,!tlabel",
5912                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5913                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5914                     lbl->key + 100);
5915           emitcode ("", "!tlabeldef", lbl->key + 100);
5916         }
5917       else
5918         {
5919           if (AOP_TYPE (right) == AOP_LIT)
5920             {
5921               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5922               /* optimize if(x < 0) or if(x >= 0) */
5923               if (lit == 0L)
5924                 {
5925                   if (!sign)
5926                     {
5927                       CLRC;
5928                     }
5929                   else
5930                     {
5931                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5932
5933                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5934                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5935
5936                       aopOp (result, ic, FALSE, FALSE);
5937
5938                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5939                         {
5940                           freeAsmop (result, NULL, ic, TRUE);
5941                           genIfxJump (ifx, "acc.7");
5942                           return;
5943                         }
5944                       else
5945                         {
5946                           emitcode ("rlc", "a");
5947                         }
5948                       goto release_freedLR;
5949                     }
5950                   goto release;
5951                 }
5952             }
5953           CLRC;
5954           while (size--)
5955             {
5956               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5957               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5958               // emitcode (";", "genCmp #2");
5959               if (sign && (size == 0))
5960                 {
5961                   // emitcode (";", "genCmp #3");
5962                   emitcode ("xrl", "a,#!constbyte",0x80);
5963                   if (AOP_TYPE (right) == AOP_LIT)
5964                     {
5965                       unsigned long lit = (unsigned long)
5966                       floatFromVal (AOP (right)->aopu.aop_lit);
5967                       // emitcode (";", "genCmp #3.1");
5968                       emitcode ("subb", "a,#!constbyte",
5969                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5970                     }
5971                   else
5972                     {
5973                       // emitcode (";", "genCmp #3.2");
5974                       saveAccWarn = 0;
5975                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5976                       saveAccWarn = DEFAULT_ACC_WARNING;
5977                       emitcode ("xrl", "b,#!constbyte",0x80);
5978                       emitcode ("subb", "a,b");
5979                     }
5980                 }
5981               else
5982                 {
5983                   const char *s;
5984
5985                   // emitcode (";", "genCmp #4");
5986                   saveAccWarn = 0;
5987                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5988                   saveAccWarn = DEFAULT_ACC_WARNING;
5989
5990                   emitcode ("subb", "a,%s", s);
5991                 }
5992             }
5993         }
5994     }
5995
5996 release:
5997 /* Don't need the left & right operands any more; do need the result. */
5998   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5999   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6000
6001   aopOp (result, ic, FALSE, FALSE);
6002
6003 release_freedLR:
6004
6005   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6006     {
6007       outBitC (result);
6008     }
6009   else
6010     {
6011       /* if the result is used in the next
6012          ifx conditional branch then generate
6013          code a little differently */
6014       if (ifx)
6015         {
6016           genIfxJump (ifx, "c");
6017         }
6018       else
6019         {
6020           outBitC (result);
6021         }
6022       /* leave the result in acc */
6023     }
6024   freeAsmop (result, NULL, ic, TRUE);
6025 }
6026
6027 /*-----------------------------------------------------------------*/
6028 /* genCmpGt :- greater than comparison                             */
6029 /*-----------------------------------------------------------------*/
6030 static void
6031 genCmpGt (iCode * ic, iCode * ifx)
6032 {
6033   operand *left, *right;
6034   sym_link *letype, *retype;
6035   int sign;
6036
6037   D (emitcode (";", "genCmpGt ");
6038     );
6039
6040   left = IC_LEFT (ic);
6041   right = IC_RIGHT (ic);
6042
6043   letype = getSpec (operandType (left));
6044   retype = getSpec (operandType (right));
6045   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6046
6047   /* assign the left & right amsops */
6048   AOP_OP_2 (ic);
6049
6050   genCmp (right, left, ic, ifx, sign);
6051 }
6052
6053 /*-----------------------------------------------------------------*/
6054 /* genCmpLt - less than comparisons                                */
6055 /*-----------------------------------------------------------------*/
6056 static void
6057 genCmpLt (iCode * ic, iCode * ifx)
6058 {
6059   operand *left, *right;
6060   sym_link *letype, *retype;
6061   int sign;
6062
6063   D (emitcode (";", "genCmpLt "););
6064
6065   left = IC_LEFT (ic);
6066   right = IC_RIGHT (ic);
6067
6068   letype = getSpec (operandType (left));
6069   retype = getSpec (operandType (right));
6070   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6071
6072   /* assign the left & right amsops */
6073   AOP_OP_2 (ic);
6074
6075   genCmp (left, right, ic, ifx, sign);
6076 }
6077
6078 /*-----------------------------------------------------------------*/
6079 /* gencjneshort - compare and jump if not equal                    */
6080 /*-----------------------------------------------------------------*/
6081 static void
6082 gencjneshort (operand * left, operand * right, symbol * lbl)
6083 {
6084   int size = max (AOP_SIZE (left), AOP_SIZE (right));
6085   int offset = 0;
6086   unsigned long lit = 0L;
6087
6088   D (emitcode (";", "gencjneshort");
6089     );
6090
6091   /* if the left side is a literal or
6092      if the right is in a pointer register and left
6093      is not */
6094   if ((AOP_TYPE (left) == AOP_LIT) ||
6095       (AOP_TYPE (left) == AOP_IMMD) ||
6096       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6097     {
6098       operand *t = right;
6099       right = left;
6100       left = t;
6101     }
6102
6103   if (AOP_TYPE (right) == AOP_LIT)
6104     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6105
6106   if (opIsGptr (left) || opIsGptr (right))
6107     {
6108       /* We are comparing a generic pointer to something.
6109        * Exclude the generic type byte from the comparison.
6110        */
6111       size--;
6112       D (emitcode (";", "cjneshort: generic ptr special case."););
6113     }
6114
6115
6116   /* if the right side is a literal then anything goes */
6117   if (AOP_TYPE (right) == AOP_LIT &&
6118       AOP_TYPE (left) != AOP_DIR)
6119     {
6120       while (size--)
6121         {
6122           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6123           emitcode ("cjne", "a,%s,!tlabel",
6124                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
6125                     lbl->key + 100);
6126           offset++;
6127         }
6128     }
6129
6130   /* if the right side is in a register or in direct space or
6131      if the left is a pointer register & right is not */
6132   else if (AOP_TYPE (right) == AOP_REG ||
6133            AOP_TYPE (right) == AOP_DIR ||
6134            AOP_TYPE (right) == AOP_LIT ||
6135            AOP_TYPE (right) == AOP_IMMD ||
6136            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6137            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6138     {
6139       while (size--)
6140         {
6141           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6142           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6143               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6144             emitcode ("jnz", "!tlabel", lbl->key + 100);
6145           else
6146             emitcode ("cjne", "a,%s,!tlabel",
6147                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
6148                       lbl->key + 100);
6149           offset++;
6150         }
6151     }
6152   else
6153     {
6154       /* right is a pointer reg need both a & b */
6155       while (size--)
6156         {
6157           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6158           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6159           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6160           offset++;
6161         }
6162     }
6163 }
6164
6165 /*-----------------------------------------------------------------*/
6166 /* gencjne - compare and jump if not equal                         */
6167 /*-----------------------------------------------------------------*/
6168 static void
6169 gencjne (operand * left, operand * right, symbol * lbl)
6170 {
6171   symbol *tlbl = newiTempLabel (NULL);
6172
6173   D (emitcode (";", "gencjne");
6174     );
6175
6176   gencjneshort (left, right, lbl);
6177
6178   emitcode ("mov", "a,%s", one);
6179   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6180   emitcode ("", "!tlabeldef", lbl->key + 100);
6181   emitcode ("clr", "a");
6182   emitcode ("", "!tlabeldef", tlbl->key + 100);
6183 }
6184
6185 /*-----------------------------------------------------------------*/
6186 /* genCmpEq - generates code for equal to                          */
6187 /*-----------------------------------------------------------------*/
6188 static void
6189 genCmpEq (iCode * ic, iCode * ifx)
6190 {
6191   operand *left, *right, *result;
6192
6193   D (emitcode (";", "genCmpEq ");
6194     );
6195
6196   AOP_OP_2 (ic);
6197   AOP_SET_LOCALS (ic);
6198
6199   /* if literal, literal on the right or
6200      if the right is in a pointer register and left
6201      is not */
6202   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6203       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6204     {
6205       operand *t = IC_RIGHT (ic);
6206       IC_RIGHT (ic) = IC_LEFT (ic);
6207       IC_LEFT (ic) = t;
6208     }
6209
6210   if (ifx &&                    /* !AOP_SIZE(result) */
6211       OP_SYMBOL (result) &&
6212       OP_SYMBOL (result)->regType == REG_CND)
6213     {
6214       symbol *tlbl;
6215       /* if they are both bit variables */
6216       if (AOP_TYPE (left) == AOP_CRY &&
6217           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6218         {
6219           if (AOP_TYPE (right) == AOP_LIT)
6220             {
6221               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6222               if (lit == 0L)
6223                 {
6224                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6225                   emitcode ("cpl", "c");
6226                 }
6227               else if (lit == 1L)
6228                 {
6229                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6230                 }
6231               else
6232                 {
6233                   emitcode ("clr", "c");
6234                 }
6235               /* AOP_TYPE(right) == AOP_CRY */
6236             }
6237           else
6238             {
6239               symbol *lbl = newiTempLabel (NULL);
6240               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6241               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6242               emitcode ("cpl", "c");
6243               emitcode ("", "!tlabeldef", (lbl->key + 100));
6244             }
6245           /* if true label then we jump if condition
6246              supplied is true */
6247           tlbl = newiTempLabel (NULL);
6248           if (IC_TRUE (ifx))
6249             {
6250               emitcode ("jnc", "!tlabel", tlbl->key + 100);
6251               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6252             }
6253           else
6254             {
6255               emitcode ("jc", "!tlabel", tlbl->key + 100);
6256               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6257             }
6258           emitcode ("", "!tlabeldef", tlbl->key + 100);
6259         }
6260       else
6261         {
6262           tlbl = newiTempLabel (NULL);
6263           gencjneshort (left, right, tlbl);
6264           if (IC_TRUE (ifx))
6265             {
6266               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6267               emitcode ("", "!tlabeldef", tlbl->key + 100);
6268             }
6269           else
6270             {
6271               symbol *lbl = newiTempLabel (NULL);
6272               emitcode ("sjmp", "!tlabel", lbl->key + 100);
6273               emitcode ("", "!tlabeldef", tlbl->key + 100);
6274               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6275               emitcode ("", "!tlabeldef", lbl->key + 100);
6276             }
6277         }
6278       /* mark the icode as generated */
6279       ifx->generated = 1;
6280
6281       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6282       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6283       return;
6284     }
6285
6286   /* if they are both bit variables */
6287   if (AOP_TYPE (left) == AOP_CRY &&
6288       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6289     {
6290       if (AOP_TYPE (right) == AOP_LIT)
6291         {
6292           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6293           if (lit == 0L)
6294             {
6295               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6296               emitcode ("cpl", "c");
6297             }
6298           else if (lit == 1L)
6299             {
6300               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6301             }
6302           else
6303             {
6304               emitcode ("clr", "c");
6305             }
6306           /* AOP_TYPE(right) == AOP_CRY */
6307         }
6308       else
6309         {
6310           symbol *lbl = newiTempLabel (NULL);
6311           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6312           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6313           emitcode ("cpl", "c");
6314           emitcode ("", "!tlabeldef", (lbl->key + 100));
6315         }
6316
6317       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6318       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6319
6320       aopOp (result, ic, TRUE, FALSE);
6321
6322       /* c = 1 if egal */
6323       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6324         {
6325           outBitC (result);
6326           goto release;
6327         }
6328       if (ifx)
6329         {
6330           genIfxJump (ifx, "c");
6331           goto release;
6332         }
6333       /* if the result is used in an arithmetic operation
6334          then put the result in place */
6335       outBitC (result);
6336     }
6337   else
6338     {
6339       gencjne (left, right, newiTempLabel (NULL));
6340
6341       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6342       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6343
6344       aopOp (result, ic, TRUE, FALSE);
6345
6346       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6347         {
6348           aopPut (AOP (result), "a", 0);
6349           goto release;
6350         }
6351       if (ifx)
6352         {
6353           genIfxJump (ifx, "a");
6354           goto release;
6355         }
6356       /* if the result is used in an arithmetic operation
6357          then put the result in place */
6358       if (AOP_TYPE (result) != AOP_CRY)
6359         outAcc (result);
6360       /* leave the result in acc */
6361     }
6362
6363 release:
6364   freeAsmop (result, NULL, ic, TRUE);
6365 }
6366
6367 /*-----------------------------------------------------------------*/
6368 /* ifxForOp - returns the icode containing the ifx for operand     */
6369 /*-----------------------------------------------------------------*/
6370 static iCode *
6371 ifxForOp (operand * op, iCode * ic)
6372 {
6373   /* if true symbol then needs to be assigned */
6374   if (IS_TRUE_SYMOP (op))
6375     return NULL;
6376
6377   /* if this has register type condition and
6378      the next instruction is ifx with the same operand
6379      and live to of the operand is upto the ifx only then */
6380   if (ic->next &&
6381       ic->next->op == IFX &&
6382       IC_COND (ic->next)->key == op->key &&
6383       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6384     return ic->next;
6385
6386   return NULL;
6387 }
6388 /*-----------------------------------------------------------------*/
6389 /* hasInc - operand is incremented before any other use            */
6390 /*-----------------------------------------------------------------*/
6391 static iCode *
6392 hasInc (operand *op, iCode *ic, int osize)
6393 {
6394   sym_link *type = operandType(op);
6395   sym_link *retype = getSpec (type);
6396   iCode *lic = ic->next;
6397   int isize ;
6398
6399   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6400   if (!IS_SYMOP(op)) return NULL;
6401
6402   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6403   if (IS_AGGREGATE(type->next)) return NULL;
6404   if (osize != (isize = getSize(type->next))) return NULL;
6405
6406   while (lic) {
6407       /* if operand of the form op = op + <sizeof *op> */
6408       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6409           isOperandEqual(IC_RESULT(lic),op) &&
6410           isOperandLiteral(IC_RIGHT(lic)) &&
6411           operandLitValue(IC_RIGHT(lic)) == isize) {
6412           return lic;
6413       }
6414       /* if the operand used or deffed */
6415       if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6416           return NULL;
6417       }
6418       /* if GOTO or IFX */
6419       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6420       lic = lic->next;
6421   }
6422   return NULL;
6423 }
6424
6425 /*-----------------------------------------------------------------*/
6426 /* genAndOp - for && operation                                     */
6427 /*-----------------------------------------------------------------*/
6428 static void
6429 genAndOp (iCode * ic)
6430 {
6431   operand *left, *right, *result;
6432   symbol *tlbl;
6433
6434   D (emitcode (";", "genAndOp "););
6435
6436   /* note here that && operations that are in an
6437      if statement are taken away by backPatchLabels
6438      only those used in arthmetic operations remain */
6439   AOP_OP_2 (ic);
6440   AOP_SET_LOCALS (ic);
6441
6442   /* if both are bit variables */
6443   if (AOP_TYPE (left) == AOP_CRY &&
6444       AOP_TYPE (right) == AOP_CRY)
6445     {
6446       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6447       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6448       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6449       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6450
6451       aopOp (result,ic,FALSE, FALSE);
6452       outBitC (result);
6453     }
6454   else
6455     {
6456       tlbl = newiTempLabel (NULL);
6457       toBoolean (left);
6458       emitcode ("jz", "!tlabel", tlbl->key + 100);
6459       toBoolean (right);
6460       emitcode ("", "!tlabeldef", tlbl->key + 100);
6461       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6462       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6463
6464       aopOp (result,ic,FALSE, FALSE);
6465       outBitAcc (result);
6466     }
6467     freeAsmop (result, NULL, ic, TRUE);
6468 }
6469
6470
6471 /*-----------------------------------------------------------------*/
6472 /* genOrOp - for || operation                                      */
6473 /*-----------------------------------------------------------------*/
6474 static void
6475 genOrOp (iCode * ic)
6476 {
6477   operand *left, *right, *result;
6478   symbol *tlbl;
6479
6480   D (emitcode (";", "genOrOp "););
6481
6482   /* note here that || operations that are in an
6483      if statement are taken away by backPatchLabels
6484      only those used in arthmetic operations remain */
6485   AOP_OP_2 (ic);
6486   AOP_SET_LOCALS (ic);
6487
6488   /* if both are bit variables */
6489   if (AOP_TYPE (left) == AOP_CRY &&
6490       AOP_TYPE (right) == AOP_CRY)
6491     {
6492       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6493       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6494       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6495       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6496
6497       aopOp (result,ic,FALSE, FALSE);
6498
6499       outBitC (result);
6500     }
6501   else
6502     {
6503       tlbl = newiTempLabel (NULL);
6504       toBoolean (left);
6505       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6506       toBoolean (right);
6507       emitcode ("", "!tlabeldef", tlbl->key + 100);
6508       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6509       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6510
6511       aopOp (result,ic,FALSE, FALSE);
6512
6513       outBitAcc (result);
6514     }
6515
6516   freeAsmop (result, NULL, ic, TRUE);
6517 }
6518
6519 /*-----------------------------------------------------------------*/
6520 /* isLiteralBit - test if lit == 2^n                               */
6521 /*-----------------------------------------------------------------*/
6522 static int
6523 isLiteralBit (unsigned long lit)
6524 {
6525   unsigned long pw[32] =
6526   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6527    0x100L, 0x200L, 0x400L, 0x800L,
6528    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6529    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6530    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6531    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6532    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6533   int idx;
6534
6535   for (idx = 0; idx < 32; idx++)
6536     if (lit == pw[idx])
6537       return idx + 1;
6538   return 0;
6539 }
6540
6541 /*-----------------------------------------------------------------*/
6542 /* continueIfTrue -                                                */
6543 /*-----------------------------------------------------------------*/
6544 static void
6545 continueIfTrue (iCode * ic)
6546 {
6547   if (IC_TRUE (ic))
6548     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6549   ic->generated = 1;
6550 }
6551
6552 /*-----------------------------------------------------------------*/
6553 /* jmpIfTrue -                                                     */
6554 /*-----------------------------------------------------------------*/
6555 static void
6556 jumpIfTrue (iCode * ic)
6557 {
6558   if (!IC_TRUE (ic))
6559     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6560   ic->generated = 1;
6561 }
6562
6563 /*-----------------------------------------------------------------*/
6564 /* jmpTrueOrFalse -                                                */
6565 /*-----------------------------------------------------------------*/
6566 static void
6567 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6568 {
6569   // ugly but optimized by peephole
6570   if (IC_TRUE (ic))
6571     {
6572       symbol *nlbl = newiTempLabel (NULL);
6573       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6574       emitcode ("", "!tlabeldef", tlbl->key + 100);
6575       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6576       emitcode ("", "!tlabeldef", nlbl->key + 100);
6577     }
6578   else
6579     {
6580       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6581       emitcode ("", "!tlabeldef", tlbl->key + 100);
6582     }
6583   ic->generated = 1;
6584 }
6585
6586 // Generate code to perform a bit-wise logic operation
6587 // on two operands in far space (assumed to already have been
6588 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6589 // in far space. This requires pushing the result on the stack
6590 // then popping it into the result.
6591 static void
6592 genFarFarLogicOp(iCode *ic, char *logicOp)
6593 {
6594       int size, resultSize, compSize;
6595       int offset = 0;
6596
6597       TR_AP("#5");
6598       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6599       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6600                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6601
6602       _startLazyDPSEvaluation();
6603       for (size = compSize; (size--); offset++)
6604       {
6605           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6606           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6607           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6608
6609           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6610           emitcode ("push", "acc");
6611       }
6612       _endLazyDPSEvaluation();
6613
6614       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6615       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6616       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6617
6618       resultSize = AOP_SIZE(IC_RESULT(ic));
6619
6620       ADJUST_PUSHED_RESULT(compSize, resultSize);
6621
6622       _startLazyDPSEvaluation();
6623       while (compSize--)
6624       {
6625           emitcode ("pop", "acc");
6626           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6627       }
6628       _endLazyDPSEvaluation();
6629       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6630 }
6631
6632
6633 /*-----------------------------------------------------------------*/
6634 /* genAnd  - code for and                                          */
6635 /*-----------------------------------------------------------------*/
6636 static void
6637 genAnd (iCode * ic, iCode * ifx)
6638 {
6639   operand *left, *right, *result;
6640   int size, offset = 0;
6641   unsigned long lit = 0L;
6642   int bytelit;
6643   char buff[10];
6644   bool pushResult;
6645
6646   D (emitcode (";", "genAnd "););
6647
6648   AOP_OP_3_NOFATAL (ic, pushResult);
6649   AOP_SET_LOCALS (ic);
6650
6651   if (pushResult)
6652   {
6653       genFarFarLogicOp(ic, "anl");
6654       return;
6655   }
6656
6657 #ifdef DEBUG_TYPE
6658   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6659             AOP_TYPE (result),
6660             AOP_TYPE (left), AOP_TYPE (right));
6661   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6662             AOP_SIZE (result),
6663             AOP_SIZE (left), AOP_SIZE (right));
6664 #endif
6665
6666   /* if left is a literal & right is not then exchange them */
6667   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6668 #ifdef LOGIC_OPS_BROKEN
6669     ||  AOP_NEEDSACC (left)
6670 #endif
6671     )
6672     {
6673       operand *tmp = right;
6674       right = left;
6675       left = tmp;
6676     }
6677
6678   /* if result = right then exchange left and right */
6679   if (sameRegs (AOP (result), AOP (right)))
6680     {
6681       operand *tmp = right;
6682       right = left;
6683       left = tmp;
6684     }
6685
6686   /* if right is bit then exchange them */
6687   if (AOP_TYPE (right) == AOP_CRY &&
6688       AOP_TYPE (left) != AOP_CRY)
6689     {
6690       operand *tmp = right;
6691       right = left;
6692       left = tmp;
6693     }
6694   if (AOP_TYPE (right) == AOP_LIT)
6695     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6696
6697   size = AOP_SIZE (result);
6698
6699   // if(bit & yy)
6700   // result = bit & yy;
6701   if (AOP_TYPE (left) == AOP_CRY)
6702     {
6703       // c = bit & literal;
6704       if (AOP_TYPE (right) == AOP_LIT)
6705         {
6706           if (lit & 1)
6707             {
6708               if (size && sameRegs (AOP (result), AOP (left)))
6709                 // no change
6710                 goto release;
6711               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6712             }
6713           else
6714             {
6715               // bit(result) = 0;
6716               if (size && (AOP_TYPE (result) == AOP_CRY))
6717                 {
6718                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6719                   goto release;
6720                 }
6721               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6722                 {
6723                   jumpIfTrue (ifx);
6724                   goto release;
6725                 }
6726               emitcode ("clr", "c");
6727             }
6728         }
6729       else
6730         {
6731           if (AOP_TYPE (right) == AOP_CRY)
6732             {
6733               // c = bit & bit;
6734               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6735               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6736             }
6737           else
6738             {
6739               // c = bit & val;
6740               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6741               // c = lsb
6742               emitcode ("rrc", "a");
6743               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6744             }
6745         }
6746       // bit = c
6747       // val = c
6748       if (size)
6749         outBitC (result);
6750       // if(bit & ...)
6751       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6752         genIfxJump (ifx, "c");
6753       goto release;
6754     }
6755
6756   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6757   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6758   if ((AOP_TYPE (right) == AOP_LIT) &&
6759       (AOP_TYPE (result) == AOP_CRY) &&
6760       (AOP_TYPE (left) != AOP_CRY))
6761     {
6762       int posbit = isLiteralBit (lit);
6763       /* left &  2^n */
6764       if (posbit)
6765         {
6766           posbit--;
6767           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6768           // bit = left & 2^n
6769           if (size)
6770             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6771           // if(left &  2^n)
6772           else
6773             {
6774               if (ifx)
6775                 {
6776                   SNPRINTF (buff, sizeof(buff),
6777                             "acc.%d", posbit & 0x07);
6778                   genIfxJump (ifx, buff);
6779                 }
6780               else
6781                   {
6782                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6783                   }
6784               goto release;
6785             }
6786         }
6787       else
6788         {
6789           symbol *tlbl = newiTempLabel (NULL);
6790           int sizel = AOP_SIZE (left);
6791           if (size)
6792             emitcode ("setb", "c");
6793           while (sizel--)
6794             {
6795               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6796                 {
6797                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6798                   // byte ==  2^n ?
6799                   if ((posbit = isLiteralBit (bytelit)) != 0)
6800                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6801                   else
6802                     {
6803                       if (bytelit != 0x0FFL)
6804                         emitcode ("anl", "a,%s",
6805                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6806                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6807                     }
6808                 }
6809               offset++;
6810             }
6811           // bit = left & literal
6812           if (size)
6813             {
6814               emitcode ("clr", "c");
6815               emitcode ("", "!tlabeldef", tlbl->key + 100);
6816             }
6817           // if(left & literal)
6818           else
6819             {
6820               if (ifx)
6821                 jmpTrueOrFalse (ifx, tlbl);
6822               else
6823                 emitcode ("", "!tlabeldef", tlbl->key + 100);
6824               goto release;
6825             }
6826         }
6827       outBitC (result);
6828       goto release;
6829     }
6830
6831   /* if left is same as result */
6832   if (sameRegs (AOP (result), AOP (left)))
6833     {
6834       for (; size--; offset++)
6835         {
6836           if (AOP_TYPE (right) == AOP_LIT)
6837             {
6838               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6839               if (bytelit == 0x0FF)
6840                 {
6841                   /* dummy read of volatile operand */
6842                   if (isOperandVolatile (left, FALSE))
6843                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6844                   else
6845                     continue;
6846                 }
6847               else if (bytelit == 0)
6848                 {
6849                   aopPut (AOP (result), zero, offset);
6850                 }
6851               else if (IS_AOP_PREG (result))
6852                 {
6853                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6854                   emitcode ("anl", "a,%s",
6855                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6856                   aopPut (AOP (result), "a", offset);
6857                 }
6858               else
6859                 emitcode ("anl", "%s,%s",
6860                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6861                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6862             }
6863           else
6864             {
6865               if (AOP_TYPE (left) == AOP_ACC)
6866                 emitcode ("anl", "a,%s",
6867                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6868               else
6869                 {
6870                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6871                   if (IS_AOP_PREG (result))
6872                     {
6873                       emitcode ("anl", "a,%s",
6874                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6875                       aopPut (AOP (result), "a", offset);
6876                     }
6877                   else
6878                     emitcode ("anl", "%s,a",
6879                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6880                 }
6881             }
6882         }
6883     }
6884   else
6885     {
6886       // left & result in different registers
6887       if (AOP_TYPE (result) == AOP_CRY)
6888         {
6889           // result = bit
6890           // if(size), result in bit
6891           // if(!size && ifx), conditional oper: if(left & right)
6892           symbol *tlbl = newiTempLabel (NULL);
6893           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6894           if (size)
6895             emitcode ("setb", "c");
6896           while (sizer--)
6897             {
6898               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6899                 emitcode ("anl", "a,%s",
6900                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6901               } else {
6902                 if (AOP_TYPE(left)==AOP_ACC) {
6903                   emitcode("mov", "b,a");
6904                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6905                   emitcode("anl", "a,b");
6906                 }else {
6907                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6908                   emitcode ("anl", "a,%s",
6909                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6910                 }
6911               }
6912               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6913               offset++;
6914             }
6915           if (size)
6916             {
6917               CLRC;
6918               emitcode ("", "!tlabeldef", tlbl->key + 100);
6919               outBitC (result);
6920             }
6921           else if (ifx)
6922             jmpTrueOrFalse (ifx, tlbl);
6923           else
6924             emitcode ("", "!tlabeldef", tlbl->key + 100);
6925         }
6926       else
6927         {
6928           for (; (size--); offset++)
6929             {
6930               // normal case
6931               // result = left & right
6932               if (AOP_TYPE (right) == AOP_LIT)
6933                 {
6934                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6935                   if (bytelit == 0x0FF)
6936                     {
6937                       aopPut (AOP (result),
6938                               aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6939                               offset);
6940                       continue;
6941                     }
6942                   else if (bytelit == 0)
6943                     {
6944                       /* dummy read of volatile operand */
6945                       if (isOperandVolatile (left, FALSE))
6946                         MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6947                       aopPut (AOP (result), zero, offset);
6948                       continue;
6949                     }
6950                   D (emitcode (";", "better literal AND."););
6951                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6952                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6953                                                     FALSE, FALSE, DP2_RESULT_REG));
6954
6955                 }
6956               else
6957                 {
6958                   // faster than result <- left, anl result,right
6959                   // and better if result is SFR
6960                   if (AOP_TYPE (left) == AOP_ACC)
6961                     {
6962                       emitcode ("anl", "a,%s",
6963                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6964                     }
6965                   else
6966                     {
6967                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6968                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6969                       {
6970                           emitcode("mov", "b,a");
6971                           rOp = "b";
6972                       }
6973
6974                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6975                       emitcode ("anl", "a,%s", rOp);
6976                     }
6977                 }
6978               aopPut (AOP (result), "a", offset);
6979             }
6980         }
6981     }
6982
6983 release:
6984   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6985   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6986   freeAsmop (result, NULL, ic, TRUE);
6987 }
6988
6989
6990 /*-----------------------------------------------------------------*/
6991 /* genOr  - code for or                                            */
6992 /*-----------------------------------------------------------------*/
6993 static void
6994 genOr (iCode * ic, iCode * ifx)
6995 {
6996   operand *left, *right, *result;
6997   int size, offset = 0;
6998   unsigned long lit = 0L;
6999   int bytelit = 0;
7000   bool     pushResult;
7001
7002   D (emitcode (";", "genOr "););
7003
7004   AOP_OP_3_NOFATAL (ic, pushResult);
7005   AOP_SET_LOCALS (ic);
7006
7007   if (pushResult)
7008   {
7009       genFarFarLogicOp(ic, "orl");
7010       return;
7011   }
7012
7013
7014 #ifdef DEBUG_TYPE
7015   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7016             AOP_TYPE (result),
7017             AOP_TYPE (left), AOP_TYPE (right));
7018   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7019             AOP_SIZE (result),
7020             AOP_SIZE (left), AOP_SIZE (right));
7021 #endif
7022
7023   /* if left is a literal & right is not then exchange them */
7024   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7025 #ifdef LOGIC_OPS_BROKEN
7026    || AOP_NEEDSACC (left) // I think this is a net loss now.
7027 #endif
7028       )
7029     {
7030       operand *tmp = right;
7031       right = left;
7032       left = tmp;
7033     }
7034
7035   /* if result = right then exchange them */
7036   if (sameRegs (AOP (result), AOP (right)))
7037     {
7038       operand *tmp = right;
7039       right = left;
7040       left = tmp;
7041     }
7042
7043   /* if right is bit then exchange them */
7044   if (AOP_TYPE (right) == AOP_CRY &&
7045       AOP_TYPE (left) != AOP_CRY)
7046     {
7047       operand *tmp = right;
7048       right = left;
7049       left = tmp;
7050     }
7051   if (AOP_TYPE (right) == AOP_LIT)
7052     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7053
7054   size = AOP_SIZE (result);
7055
7056   // if(bit | yy)
7057   // xx = bit | yy;
7058   if (AOP_TYPE (left) == AOP_CRY)
7059     {
7060       if (AOP_TYPE (right) == AOP_LIT)
7061         {
7062           // c = bit & literal;
7063           if (lit)
7064             {
7065               // lit != 0 => result = 1
7066               if (AOP_TYPE (result) == AOP_CRY)
7067                 {
7068                   if (size)
7069                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7070                   else if (ifx)
7071                     continueIfTrue (ifx);
7072                   goto release;
7073                 }
7074               emitcode ("setb", "c");
7075             }
7076           else
7077             {
7078               // lit == 0 => result = left
7079               if (size && sameRegs (AOP (result), AOP (left)))
7080                 goto release;
7081               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7082             }
7083         }
7084       else
7085         {
7086           if (AOP_TYPE (right) == AOP_CRY)
7087             {
7088               // c = bit | bit;
7089               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7090               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7091             }
7092           else
7093             {
7094               // c = bit | val;
7095               symbol *tlbl = newiTempLabel (NULL);
7096               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7097                 emitcode ("setb", "c");
7098               emitcode ("jb", "%s,!tlabel",
7099                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
7100               toBoolean (right);
7101               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7102               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7103                 {
7104                   jmpTrueOrFalse (ifx, tlbl);
7105                   goto release;
7106                 }
7107               else
7108                 {
7109                   CLRC;
7110                   emitcode ("", "!tlabeldef", tlbl->key + 100);
7111                 }
7112             }
7113         }
7114       // bit = c
7115       // val = c
7116       if (size)
7117         outBitC (result);
7118       // if(bit | ...)
7119       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7120            genIfxJump (ifx, "c");
7121       goto release;
7122     }
7123
7124   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7125   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7126   if ((AOP_TYPE (right) == AOP_LIT) &&
7127       (AOP_TYPE (result) == AOP_CRY) &&
7128       (AOP_TYPE (left) != AOP_CRY))
7129     {
7130       if (lit)
7131         {
7132           // result = 1
7133           if (size)
7134             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7135           else
7136             continueIfTrue (ifx);
7137           goto release;
7138         }
7139       else
7140         {
7141           // lit = 0, result = boolean(left)
7142           if (size)
7143             emitcode ("setb", "c");
7144           toBoolean (right);
7145           if (size)
7146             {
7147               symbol *tlbl = newiTempLabel (NULL);
7148               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7149               CLRC;
7150               emitcode ("", "!tlabeldef", tlbl->key + 100);
7151             }
7152           else
7153             {
7154               genIfxJump (ifx, "a");
7155               goto release;
7156             }
7157         }
7158       outBitC (result);
7159       goto release;
7160     }
7161
7162   /* if left is same as result */
7163   if (sameRegs (AOP (result), AOP (left)))
7164     {
7165       for (; size--; offset++)
7166         {
7167           if (AOP_TYPE (right) == AOP_LIT)
7168             {
7169               bytelit = (int)((lit >> (offset * 8)) & 0x0FFL);
7170               if (bytelit == 0x00L)
7171                 {
7172                   /* dummy read of volatile operand */
7173                   if (isOperandVolatile (left, FALSE))
7174                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7175                   else
7176                     continue;
7177                 }
7178               else if (bytelit == 0x0FF)
7179                 {
7180                   aopPut (AOP (result), "#0xFF", offset);
7181                 }
7182               else if (IS_AOP_PREG (left))
7183                 {
7184                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7185                   emitcode ("orl", "a,%s",
7186                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7187                   aopPut (AOP (result), "a", offset);
7188                 }
7189               else
7190                 {
7191                   emitcode ("orl", "%s,%s",
7192                             aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7193                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7194                 }
7195             }
7196           else
7197             {
7198               if (AOP_TYPE (left) == AOP_ACC)
7199                 {
7200                   emitcode ("orl", "a,%s",
7201                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7202                 }
7203               else
7204                 {
7205                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7206                   if (IS_AOP_PREG (left))
7207                     {
7208                       emitcode ("orl", "a,%s",
7209                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7210                       aopPut (AOP (result), "a", offset);
7211                     }
7212                   else
7213                     {
7214                       emitcode ("orl", "%s,a",
7215                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7216                     }
7217                 }
7218             }
7219         }
7220     }
7221   else
7222     {
7223       // left & result in different registers
7224       if (AOP_TYPE (result) == AOP_CRY)
7225         {
7226           // result = bit
7227           // if(size), result in bit
7228           // if(!size && ifx), conditional oper: if(left | right)
7229           symbol *tlbl = newiTempLabel (NULL);
7230           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7231           if (size)
7232             emitcode ("setb", "c");
7233           while (sizer--)
7234             {
7235               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7236                 emitcode ("orl", "a,%s",
7237                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7238               } else {
7239                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7240                 emitcode ("orl", "a,%s",
7241                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
7242               }
7243               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7244               offset++;
7245             }
7246           if (size)
7247             {
7248               CLRC;
7249               emitcode ("", "!tlabeldef", tlbl->key + 100);
7250               outBitC (result);
7251             }
7252           else if (ifx)
7253             jmpTrueOrFalse (ifx, tlbl);
7254           else
7255             emitcode ("", "!tlabeldef", tlbl->key + 100);
7256         }
7257       else
7258         {
7259             _startLazyDPSEvaluation();
7260           for (; (size--); offset++)
7261             {
7262               // normal case
7263               // result = left & right
7264               if (AOP_TYPE (right) == AOP_LIT)
7265                 {
7266                   bytelit = (int)((lit >> (offset * 8)) & 0x0FFL);
7267                   if (bytelit == 0x00L)
7268                     {
7269                       aopPut (AOP (result),
7270                               aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7271                               offset);
7272                       continue;
7273                     }
7274                   else if (bytelit == 0x0FF)
7275                     {
7276                       /* dummy read of volatile operand */
7277                       if (isOperandVolatile (left, FALSE))
7278                         MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7279                       aopPut (AOP (result), "#0xFF", offset);
7280                       continue;
7281                     }
7282                   D (emitcode (";", "better literal OR."););
7283                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7284                   emitcode ("orl", "a, %s",
7285                             aopGet (AOP (right), offset,
7286                                     FALSE, FALSE, DP2_RESULT_REG));
7287
7288                 }
7289               else
7290                 {
7291                   // faster than result <- left, anl result,right
7292                   // and better if result is SFR
7293                   if (AOP_TYPE (left) == AOP_ACC)
7294                     {
7295                       emitcode ("orl", "a,%s",
7296                                 aopGet (AOP (right), offset,
7297                                         FALSE, FALSE, DP2_RESULT_REG));
7298                     }
7299                   else
7300                     {
7301                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7302
7303                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7304                       {
7305                           emitcode("mov", "b,a");
7306                           rOp = "b";
7307                       }
7308
7309                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7310                       emitcode ("orl", "a,%s", rOp);
7311                     }
7312                 }
7313               aopPut (AOP (result), "a", offset);
7314             }
7315             _endLazyDPSEvaluation();
7316         }
7317     }
7318
7319 release:
7320   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7321   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7322   freeAsmop (result, NULL, ic, TRUE);
7323 }
7324
7325 /*-----------------------------------------------------------------*/
7326 /* genXor - code for xclusive or                                   */
7327 /*-----------------------------------------------------------------*/
7328 static void
7329 genXor (iCode * ic, iCode * ifx)
7330 {
7331   operand *left, *right, *result;
7332   int size, offset = 0;
7333   unsigned long lit = 0L;
7334   int bytelit = 0;
7335   bool pushResult;
7336
7337   D (emitcode (";", "genXor "););
7338
7339   AOP_OP_3_NOFATAL (ic, pushResult);
7340   AOP_SET_LOCALS (ic);
7341
7342   if (pushResult)
7343   {
7344       genFarFarLogicOp(ic, "xrl");
7345       return;
7346   }
7347
7348 #ifdef DEBUG_TYPE
7349   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7350             AOP_TYPE (result),
7351             AOP_TYPE (left), AOP_TYPE (right));
7352   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7353             AOP_SIZE (result),
7354             AOP_SIZE (left), AOP_SIZE (right));
7355 #endif
7356
7357   /* if left is a literal & right is not ||
7358      if left needs acc & right does not */
7359   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7360 #ifdef LOGIC_OPS_BROKEN
7361       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7362 #endif
7363      )
7364     {
7365       operand *tmp = right;
7366       right = left;
7367       left = tmp;
7368     }
7369
7370   /* if result = right then exchange them */
7371   if (sameRegs (AOP (result), AOP (right)))
7372     {
7373       operand *tmp = right;
7374       right = left;
7375       left = tmp;
7376     }
7377
7378   /* if right is bit then exchange them */
7379   if (AOP_TYPE (right) == AOP_CRY &&
7380       AOP_TYPE (left) != AOP_CRY)
7381     {
7382       operand *tmp = right;
7383       right = left;
7384       left = tmp;
7385     }
7386   if (AOP_TYPE (right) == AOP_LIT)
7387     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7388
7389   size = AOP_SIZE (result);
7390
7391   // if(bit ^ yy)
7392   // xx = bit ^ yy;
7393   if (AOP_TYPE (left) == AOP_CRY)
7394     {
7395       if (AOP_TYPE (right) == AOP_LIT)
7396         {
7397           // c = bit & literal;
7398           if (lit >> 1)
7399             {
7400               // lit>>1  != 0 => result = 1
7401               if (AOP_TYPE (result) == AOP_CRY)
7402                 {
7403                   if (size)
7404                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7405                   else if (ifx)
7406                     continueIfTrue (ifx);
7407                   goto release;
7408                 }
7409               emitcode ("setb", "c");
7410             }
7411           else
7412             {
7413               // lit == (0 or 1)
7414               if (lit == 0)
7415                 {
7416                   // lit == 0, result = left
7417                   if (size && sameRegs (AOP (result), AOP (left)))
7418                     goto release;
7419                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7420                 }
7421               else
7422                 {
7423                   // lit == 1, result = not(left)
7424                   if (size && sameRegs (AOP (result), AOP (left)))
7425                     {
7426                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7427                       goto release;
7428                     }
7429                   else
7430                     {
7431                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7432                       emitcode ("cpl", "c");
7433                     }
7434                 }
7435             }
7436
7437         }
7438       else
7439         {
7440           // right != literal
7441           symbol *tlbl = newiTempLabel (NULL);
7442           if (AOP_TYPE (right) == AOP_CRY)
7443             {
7444               // c = bit ^ bit;
7445               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7446             }
7447           else
7448             {
7449               int sizer = AOP_SIZE (right);
7450               // c = bit ^ val
7451               // if val>>1 != 0, result = 1
7452               emitcode ("setb", "c");
7453               while (sizer)
7454                 {
7455                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
7456                   if (sizer == 1)
7457                     // test the msb of the lsb
7458                     emitcode ("anl", "a,#!constbyte",0xfe);
7459                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
7460                   sizer--;
7461                 }
7462               // val = (0,1)
7463               emitcode ("rrc", "a");
7464             }
7465           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7466           emitcode ("cpl", "c");
7467           emitcode ("", "!tlabeldef", (tlbl->key + 100));
7468         }
7469       // bit = c
7470       // val = c
7471       if (size)
7472         outBitC (result);
7473       // if(bit | ...)
7474       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7475         genIfxJump (ifx, "c");
7476       goto release;
7477     }
7478
7479   /* if left is same as result */
7480   if (sameRegs (AOP (result), AOP (left)))
7481     {
7482       for (; size--; offset++)
7483         {
7484           if (AOP_TYPE (right) == AOP_LIT)
7485             {
7486               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7487               if (bytelit == 0x00L)
7488                 {
7489                   /* dummy read of volatile operand */
7490                   if (isOperandVolatile (left, FALSE))
7491                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7492                   else
7493                     continue;
7494                 }
7495               else if (IS_AOP_PREG (left))
7496                 {
7497                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7498                   emitcode ("xrl", "a,%s",
7499                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7500                   aopPut (AOP (result), "a", offset);
7501                 }
7502               else
7503                 {
7504                   emitcode ("xrl", "%s,%s",
7505                             aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7506                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7507                 }
7508             }
7509           else
7510             {
7511               if (AOP_TYPE (left) == AOP_ACC)
7512                 emitcode ("xrl", "a,%s",
7513                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7514               else
7515                 {
7516                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7517                   if (IS_AOP_PREG (left))
7518                     {
7519                       emitcode ("xrl", "a,%s",
7520                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7521                       aopPut (AOP (result), "a", offset);
7522                     }
7523                   else
7524                     emitcode ("xrl", "%s,a",
7525                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7526                 }
7527             }
7528         }
7529     }
7530   else
7531     {
7532       // left & result in different registers
7533       if (AOP_TYPE (result) == AOP_CRY)
7534         {
7535           // result = bit
7536           // if(size), result in bit
7537           // if(!size && ifx), conditional oper: if(left ^ right)
7538           symbol *tlbl = newiTempLabel (NULL);
7539           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7540
7541           if (size)
7542             emitcode ("setb", "c");
7543           while (sizer--)
7544             {
7545               if ((AOP_TYPE (right) == AOP_LIT) &&
7546                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7547                 {
7548                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7549                 }
7550               else
7551                 {
7552                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7553                     emitcode ("xrl", "a,%s",
7554                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7555                   } else {
7556                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7557                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7558                       {
7559                           emitcode("mov", "b,a");
7560                           rOp = "b";
7561                       }
7562
7563                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7564                       emitcode ("xrl", "a,%s", rOp);
7565                   }
7566                 }
7567               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7568               offset++;
7569             }
7570           if (size)
7571             {
7572               CLRC;
7573               emitcode ("", "!tlabeldef", tlbl->key + 100);
7574               outBitC (result);
7575             }
7576           else if (ifx)
7577             jmpTrueOrFalse (ifx, tlbl);
7578         }
7579       else
7580         {
7581         for (; (size--); offset++)
7582           {
7583             // normal case
7584             // result = left & right
7585             if (AOP_TYPE (right) == AOP_LIT)
7586               {
7587                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7588                   {
7589                     aopPut (AOP (result),
7590                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7591                             offset);
7592                     continue;
7593                   }
7594                 D (emitcode (";", "better literal XOR."););
7595                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7596                 emitcode ("xrl", "a, %s",
7597                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7598               }
7599             else
7600               {
7601                 // faster than result <- left, anl result,right
7602                 // and better if result is SFR
7603                 if (AOP_TYPE (left) == AOP_ACC)
7604                   {
7605                     emitcode ("xrl", "a,%s",
7606                               aopGet (AOP (right), offset,
7607                                       FALSE, FALSE, DP2_RESULT_REG));
7608                   }
7609                 else
7610                   {
7611                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7612                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7613                       {
7614                           emitcode("mov", "b,a");
7615                           rOp = "b";
7616                       }
7617
7618                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7619                       emitcode ("xrl", "a,%s", rOp);
7620                   }
7621               }
7622             aopPut (AOP (result), "a", offset);
7623           }
7624         }
7625
7626     }
7627
7628 release:
7629   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7630   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7631   freeAsmop (result, NULL, ic, TRUE);
7632 }
7633
7634 /*-----------------------------------------------------------------*/
7635 /* genInline - write the inline code out                           */
7636 /*-----------------------------------------------------------------*/
7637 static void
7638 genInline (iCode * ic)
7639 {
7640   char *buffer, *bp, *bp1;
7641
7642   D (emitcode (";", "genInline "); );
7643
7644   _G.inLine += (!options.asmpeep);
7645
7646   buffer = Safe_strdup(IC_INLINE(ic));
7647   bp = buffer;
7648   bp1 = buffer;
7649
7650   /* emit each line as a code */
7651   while (*bp)
7652     {
7653       if (*bp == '\n')
7654         {
7655           *bp++ = '\0';
7656           emitcode (bp1, "");
7657           bp1 = bp;
7658         }
7659       else
7660         {
7661           if (*bp == ':')
7662             {
7663               bp++;
7664               *bp = '\0';
7665               bp++;
7666               emitcode (bp1, "");
7667               bp1 = bp;
7668             }
7669           else
7670             bp++;
7671         }
7672     }
7673   if (bp1 != bp)
7674     emitcode (bp1, "");
7675   /*     emitcode("",buffer); */
7676   _G.inLine -= (!options.asmpeep);
7677 }
7678
7679 /*-----------------------------------------------------------------*/
7680 /* genRRC - rotate right with carry                                */
7681 /*-----------------------------------------------------------------*/
7682 static void
7683 genRRC (iCode * ic)
7684 {
7685   operand *left, *result;
7686   int     size, offset;
7687
7688   D (emitcode (";", "genRRC "););
7689
7690   /* rotate right with carry */
7691   left = IC_LEFT (ic);
7692   result = IC_RESULT (ic);
7693   aopOp (left, ic, FALSE, FALSE);
7694   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7695
7696   /* move it to the result */
7697   size = AOP_SIZE (result);
7698   offset = size - 1;
7699   CLRC;
7700
7701   _startLazyDPSEvaluation ();
7702   while (size--)
7703     {
7704       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7705       emitcode ("rrc", "a");
7706       if (AOP_SIZE (result) > 1)
7707         aopPut (AOP (result), "a", offset--);
7708     }
7709   _endLazyDPSEvaluation ();
7710
7711   /* now we need to put the carry into the
7712      highest order byte of the result */
7713   if (AOP_SIZE (result) > 1)
7714     {
7715       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7716     }
7717   emitcode ("mov", "acc.7,c");
7718   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7719   freeAsmop (left, NULL, ic, TRUE);
7720   freeAsmop (result, NULL, ic, TRUE);
7721 }
7722
7723 /*-----------------------------------------------------------------*/
7724 /* genRLC - generate code for rotate left with carry               */
7725 /*-----------------------------------------------------------------*/
7726 static void
7727 genRLC (iCode * ic)
7728 {
7729   operand *left, *result;
7730   int size, offset;
7731   char *l;
7732
7733   D (emitcode (";", "genRLC "););
7734
7735   /* rotate right with carry */
7736   left = IC_LEFT (ic);
7737   result = IC_RESULT (ic);
7738   aopOp (left, ic, FALSE, FALSE);
7739   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7740
7741   /* move it to the result */
7742   size = AOP_SIZE (result);
7743   offset = 0;
7744   if (size--)
7745     {
7746       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7747       MOVA (l);
7748       emitcode ("add", "a,acc");
7749       if (AOP_SIZE (result) > 1)
7750         {
7751           aopPut (AOP (result), "a", offset++);
7752         }
7753
7754       _startLazyDPSEvaluation ();
7755       while (size--)
7756         {
7757           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7758           MOVA (l);
7759           emitcode ("rlc", "a");
7760           if (AOP_SIZE (result) > 1)
7761             aopPut (AOP (result), "a", offset++);
7762         }
7763       _endLazyDPSEvaluation ();
7764     }
7765   /* now we need to put the carry into the
7766      highest order byte of the result */
7767   if (AOP_SIZE (result) > 1)
7768     {
7769       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7770       MOVA (l);
7771     }
7772   emitcode ("mov", "acc.0,c");
7773   aopPut (AOP (result), "a", 0);
7774   freeAsmop (left, NULL, ic, TRUE);
7775   freeAsmop (result, NULL, ic, TRUE);
7776 }
7777
7778 /*-----------------------------------------------------------------*/
7779 /* genGetHbit - generates code get highest order bit               */
7780 /*-----------------------------------------------------------------*/
7781 static void
7782 genGetHbit (iCode * ic)
7783 {
7784   operand *left, *result;
7785   left = IC_LEFT (ic);
7786   result = IC_RESULT (ic);
7787   aopOp (left, ic, FALSE, FALSE);
7788   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7789
7790   D (emitcode (";", "genGetHbit "););
7791
7792   /* get the highest order byte into a */
7793   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7794   if (AOP_TYPE (result) == AOP_CRY)
7795     {
7796       emitcode ("rlc", "a");
7797       outBitC (result);
7798     }
7799   else
7800     {
7801       emitcode ("rl", "a");
7802       emitcode ("anl", "a,#1");
7803       outAcc (result);
7804     }
7805
7806
7807   freeAsmop (left, NULL, ic, TRUE);
7808   freeAsmop (result, NULL, ic, TRUE);
7809 }
7810
7811 /*-----------------------------------------------------------------*/
7812 /* genSwap - generates code to swap nibbles or bytes               */
7813 /*-----------------------------------------------------------------*/
7814 static void
7815 genSwap (iCode * ic)
7816 {
7817   operand *left, *result;
7818
7819   D(emitcode (";     genSwap",""));
7820
7821   left = IC_LEFT (ic);
7822   result = IC_RESULT (ic);
7823   aopOp (left, ic, FALSE, FALSE);
7824   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7825
7826   _startLazyDPSEvaluation ();
7827   switch (AOP_SIZE (left))
7828     {
7829     case 1: /* swap nibbles in byte */
7830       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7831       emitcode ("swap", "a");
7832       aopPut (AOP (result), "a", 0);
7833       break;
7834     case 2: /* swap bytes in word */
7835       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7836         {
7837           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7838           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7839           aopPut (AOP (result), "a", 1);
7840         }
7841       else if (operandsEqu (left, result))
7842         {
7843           char * reg = "a";
7844           MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
7845           if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
7846             {
7847               emitcode ("mov", "b,a");
7848               reg = "b";
7849               _G.bInUse=1;
7850             }
7851           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7852           aopPut (AOP (result), reg, 1);
7853           _G.bInUse=0;
7854         }
7855       else
7856         {
7857           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0);
7858           aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1);
7859         }
7860       break;
7861     default:
7862       wassertl(FALSE, "unsupported SWAP operand size");
7863     }
7864   _endLazyDPSEvaluation ();
7865
7866   freeAsmop (left, NULL, ic, TRUE);
7867   freeAsmop (result, NULL, ic, TRUE);
7868 }
7869
7870 /*-----------------------------------------------------------------*/
7871 /* AccRol - rotate left accumulator by known count                 */
7872 /*-----------------------------------------------------------------*/
7873 static void
7874 AccRol (int shCount)
7875 {
7876   shCount &= 0x0007;            // shCount : 0..7
7877
7878   switch (shCount)
7879     {
7880     case 0:
7881       break;
7882     case 1:
7883       emitcode ("rl", "a");
7884       break;
7885     case 2:
7886       emitcode ("rl", "a");
7887       emitcode ("rl", "a");
7888       break;
7889     case 3:
7890       emitcode ("swap", "a");
7891       emitcode ("rr", "a");
7892       break;
7893     case 4:
7894       emitcode ("swap", "a");
7895       break;
7896     case 5:
7897       emitcode ("swap", "a");
7898       emitcode ("rl", "a");
7899       break;
7900     case 6:
7901       emitcode ("rr", "a");
7902       emitcode ("rr", "a");
7903       break;
7904     case 7:
7905       emitcode ("rr", "a");
7906       break;
7907     }
7908 }
7909
7910 /*-----------------------------------------------------------------*/
7911 /* AccLsh - left shift accumulator by known count                  */
7912 /*-----------------------------------------------------------------*/
7913 static void
7914 AccLsh (int shCount)
7915 {
7916   if (shCount != 0)
7917     {
7918       if (shCount == 1)
7919         emitcode ("add", "a,acc");
7920       else if (shCount == 2)
7921         {
7922           emitcode ("add", "a,acc");
7923           emitcode ("add", "a,acc");
7924         }
7925       else
7926         {
7927           /* rotate left accumulator */
7928           AccRol (shCount);
7929           /* and kill the lower order bits */
7930           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7931         }
7932     }
7933 }
7934
7935 /*-----------------------------------------------------------------*/
7936 /* AccRsh - right shift accumulator by known count                 */
7937 /*-----------------------------------------------------------------*/
7938 static void
7939 AccRsh (int shCount)
7940 {
7941   if (shCount != 0)
7942     {
7943       if (shCount == 1)
7944         {
7945           CLRC;
7946           emitcode ("rrc", "a");
7947         }
7948       else
7949         {
7950           /* rotate right accumulator */
7951           AccRol (8 - shCount);
7952           /* and kill the higher order bits */
7953           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7954         }
7955     }
7956 }
7957
7958 #ifdef BETTER_LITERAL_SHIFT
7959 /*-----------------------------------------------------------------*/
7960 /* AccSRsh - signed right shift accumulator by known count                 */
7961 /*-----------------------------------------------------------------*/
7962 static void
7963 AccSRsh (int shCount)
7964 {
7965   symbol *tlbl;
7966   if (shCount != 0)
7967     {
7968       if (shCount == 1)
7969         {
7970           emitcode ("mov", "c,acc.7");
7971           emitcode ("rrc", "a");
7972         }
7973       else if (shCount == 2)
7974         {
7975           emitcode ("mov", "c,acc.7");
7976           emitcode ("rrc", "a");
7977           emitcode ("mov", "c,acc.7");
7978           emitcode ("rrc", "a");
7979         }
7980       else
7981         {
7982           tlbl = newiTempLabel (NULL);
7983           /* rotate right accumulator */
7984           AccRol (8 - shCount);
7985           /* and kill the higher order bits */
7986           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7987           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7988           emitcode ("orl", "a,#!constbyte",
7989                     (unsigned char) ~SRMask[shCount]);
7990           emitcode ("", "!tlabeldef", tlbl->key + 100);
7991         }
7992     }
7993 }
7994 #endif
7995
7996 #ifdef BETTER_LITERAL_SHIFT
7997 /*-----------------------------------------------------------------*/
7998 /* shiftR1Left2Result - shift right one byte from left to result   */
7999 /*-----------------------------------------------------------------*/
8000 static void
8001 shiftR1Left2Result (operand * left, int offl,
8002                     operand * result, int offr,
8003                     int shCount, int sign)
8004 {
8005   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8006   /* shift right accumulator */
8007   if (sign)
8008     AccSRsh (shCount);
8009   else
8010     AccRsh (shCount);
8011   aopPut (AOP (result), "a", offr);
8012 }
8013 #endif
8014
8015 #ifdef BETTER_LITERAL_SHIFT
8016 /*-----------------------------------------------------------------*/
8017 /* shiftL1Left2Result - shift left one byte from left to result    */
8018 /*-----------------------------------------------------------------*/
8019 static void
8020 shiftL1Left2Result (operand * left, int offl,
8021                     operand * result, int offr, int shCount)
8022 {
8023   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8024   /* shift left accumulator */
8025   AccLsh (shCount);
8026   aopPut (AOP (result), "a", offr);
8027 }
8028 #endif
8029
8030 #ifdef BETTER_LITERAL_SHIFT
8031 /*-----------------------------------------------------------------*/
8032 /* movLeft2Result - move byte from left to result                  */
8033 /*-----------------------------------------------------------------*/
8034 static void
8035 movLeft2Result (operand * left, int offl,
8036                 operand * result, int offr, int sign)
8037 {
8038   char *l;
8039   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8040   {
8041       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
8042
8043       if (*l == '@' && (IS_AOP_PREG (result)))
8044       {
8045           emitcode ("mov", "a,%s", l);
8046           aopPut (AOP (result), "a", offr);
8047       }
8048       else
8049       {
8050           if (!sign)
8051           {
8052             aopPut (AOP (result), l, offr);
8053           }
8054           else
8055             {
8056               /* MSB sign in acc.7 ! */
8057               if (getDataSize (left) == offl + 1)
8058                 {
8059                   emitcode ("mov", "a,%s", l);
8060                   aopPut (AOP (result), "a", offr);
8061                 }
8062             }
8063       }
8064   }
8065 }
8066 #endif
8067
8068 #ifdef BETTER_LITERAL_SHIFT
8069 /*-----------------------------------------------------------------*/
8070 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8071 /*-----------------------------------------------------------------*/
8072 static void
8073 AccAXRrl1 (char *x)
8074 {
8075   emitcode ("rrc", "a");
8076   emitcode ("xch", "a,%s", x);
8077   emitcode ("rrc", "a");
8078   emitcode ("xch", "a,%s", x);
8079 }
8080 #endif
8081
8082 #ifdef BETTER_LITERAL_SHIFT
8083 //REMOVE ME!!!
8084 /*-----------------------------------------------------------------*/
8085 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8086 /*-----------------------------------------------------------------*/
8087 static void
8088 AccAXLrl1 (char *x)
8089 {
8090   emitcode ("xch", "a,%s", x);
8091   emitcode ("rlc", "a");
8092   emitcode ("xch", "a,%s", x);
8093   emitcode ("rlc", "a");
8094 }
8095 #endif
8096
8097 #ifdef BETTER_LITERAL_SHIFT
8098 /*-----------------------------------------------------------------*/
8099 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8100 /*-----------------------------------------------------------------*/
8101 static void
8102 AccAXLsh1 (char *x)
8103 {
8104   emitcode ("xch", "a,%s", x);
8105   emitcode ("add", "a,acc");
8106   emitcode ("xch", "a,%s", x);
8107   emitcode ("rlc", "a");
8108 }
8109 #endif
8110
8111 #ifdef BETTER_LITERAL_SHIFT
8112 /*-----------------------------------------------------------------*/
8113 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8114 /*-----------------------------------------------------------------*/
8115 static void
8116 AccAXLsh (char *x, int shCount)
8117 {
8118   switch (shCount)
8119     {
8120     case 0:
8121       break;
8122     case 1:
8123       AccAXLsh1 (x);
8124       break;
8125     case 2:
8126       AccAXLsh1 (x);
8127       AccAXLsh1 (x);
8128       break;
8129     case 3:
8130     case 4:
8131     case 5:                     // AAAAABBB:CCCCCDDD
8132
8133       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8134
8135       emitcode ("anl", "a,#!constbyte",
8136                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8137
8138       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8139
8140       AccRol (shCount);         // DDDCCCCC:BBB00000
8141
8142       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8143
8144       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8145
8146       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8147
8148       emitcode ("anl", "a,#!constbyte",
8149                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8150
8151       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8152
8153       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8154
8155       break;
8156     case 6:                     // AAAAAABB:CCCCCCDD
8157       emitcode ("anl", "a,#!constbyte",
8158                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8159       emitcode ("mov", "c,acc.0");      // c = B
8160       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8161 #if 0
8162       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8163       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8164 #else
8165       emitcode("rrc","a");
8166       emitcode("xch","a,%s", x);
8167       emitcode("rrc","a");
8168       emitcode("mov","c,acc.0"); //<< get correct bit
8169       emitcode("xch","a,%s", x);
8170
8171       emitcode("rrc","a");
8172       emitcode("xch","a,%s", x);
8173       emitcode("rrc","a");
8174       emitcode("xch","a,%s", x);
8175 #endif
8176       break;
8177     case 7:                     // a:x <<= 7
8178
8179       emitcode ("anl", "a,#!constbyte",
8180                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8181
8182       emitcode ("mov", "c,acc.0");      // c = B
8183
8184       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8185
8186       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8187
8188       break;
8189     default:
8190       break;
8191     }
8192 }
8193 #endif
8194
8195 #ifdef BETTER_LITERAL_SHIFT
8196 //REMOVE ME!!!
8197 /*-----------------------------------------------------------------*/
8198 /* AccAXRsh - right shift a:x known count (0..7)                   */
8199 /*-----------------------------------------------------------------*/
8200 static void
8201 AccAXRsh (char *x, int shCount)
8202 {
8203   switch (shCount)
8204     {
8205     case 0:
8206       break;
8207     case 1:
8208       CLRC;
8209       AccAXRrl1 (x);            // 0->a:x
8210
8211       break;
8212     case 2:
8213       CLRC;
8214       AccAXRrl1 (x);            // 0->a:x
8215
8216       CLRC;
8217       AccAXRrl1 (x);            // 0->a:x
8218
8219       break;
8220     case 3:
8221     case 4:
8222     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8223
8224       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8225
8226       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8227
8228       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8229
8230       emitcode ("anl", "a,#!constbyte",
8231                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8232
8233       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8234
8235       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8236
8237       emitcode ("anl", "a,#!constbyte",
8238                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8239
8240       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8241
8242       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8243
8244       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8245
8246       break;
8247     case 6:                     // AABBBBBB:CCDDDDDD
8248
8249       emitcode ("mov", "c,acc.7");
8250       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8251
8252       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8253
8254       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8255
8256       emitcode ("anl", "a,#!constbyte",
8257                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8258
8259       break;
8260     case 7:                     // ABBBBBBB:CDDDDDDD
8261
8262       emitcode ("mov", "c,acc.7");      // c = A
8263
8264       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8265
8266       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8267
8268       emitcode ("anl", "a,#!constbyte",
8269                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8270
8271       break;
8272     default:
8273       break;
8274     }
8275 }
8276 #endif
8277
8278 #ifdef BETTER_LITERAL_SHIFT
8279 /*-----------------------------------------------------------------*/
8280 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8281 /*-----------------------------------------------------------------*/
8282 static void
8283 AccAXRshS (char *x, int shCount)
8284 {
8285   symbol *tlbl;
8286   switch (shCount)
8287     {
8288     case 0:
8289       break;
8290     case 1:
8291       emitcode ("mov", "c,acc.7");
8292       AccAXRrl1 (x);            // s->a:x
8293
8294       break;
8295     case 2:
8296       emitcode ("mov", "c,acc.7");
8297       AccAXRrl1 (x);            // s->a:x
8298
8299       emitcode ("mov", "c,acc.7");
8300       AccAXRrl1 (x);            // s->a:x
8301
8302       break;
8303     case 3:
8304     case 4:
8305     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8306
8307       tlbl = newiTempLabel (NULL);
8308       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8309
8310       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8311
8312       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8313
8314       emitcode ("anl", "a,#!constbyte",
8315                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8316
8317       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8318
8319       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8320
8321       emitcode ("anl", "a,#!constbyte",
8322                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8323
8324       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8325
8326       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8327
8328       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8329
8330       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8331       emitcode ("orl", "a,#!constbyte",
8332                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8333
8334       emitcode ("", "!tlabeldef", tlbl->key + 100);
8335       break;                    // SSSSAAAA:BBBCCCCC
8336
8337     case 6:                     // AABBBBBB:CCDDDDDD
8338
8339       tlbl = newiTempLabel (NULL);
8340       emitcode ("mov", "c,acc.7");
8341       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8342
8343       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8344
8345       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8346
8347       emitcode ("anl", "a,#!constbyte",
8348                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8349
8350       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8351       emitcode ("orl", "a,#!constbyte",
8352                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8353
8354       emitcode ("", "!tlabeldef", tlbl->key + 100);
8355       break;
8356     case 7:                     // ABBBBBBB:CDDDDDDD
8357
8358       tlbl = newiTempLabel (NULL);
8359       emitcode ("mov", "c,acc.7");      // c = A
8360
8361       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8362
8363       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8364
8365       emitcode ("anl", "a,#!constbyte",
8366                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8367
8368       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8369       emitcode ("orl", "a,#!constbyte",
8370                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8371
8372       emitcode ("", "!tlabeldef", tlbl->key + 100);
8373       break;
8374     default:
8375       break;
8376     }
8377 }
8378 #endif
8379
8380 #ifdef BETTER_LITERAL_SHIFT
8381 static void
8382 _loadLeftIntoAx(char    **lsb,
8383                 operand *left,
8384                 operand *result,
8385                 int     offl,
8386                 int     offr)
8387 {
8388   // Get the initial value from left into a pair of registers.
8389   // MSB must be in A, LSB can be any register.
8390   //
8391   // If the result is held in registers, it is an optimization
8392   // if the LSB can be held in the register which will hold the,
8393   // result LSB since this saves us from having to copy it into
8394   // the result following AccAXLsh.
8395   //
8396   // If the result is addressed indirectly, this is not a gain.
8397   if (AOP_NEEDSACC(result))
8398   {
8399        char *leftByte;
8400
8401        _startLazyDPSEvaluation();
8402       if (AOP_TYPE(left) == AOP_DPTR2)
8403        {
8404            // Get MSB in A.
8405            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
8406            // get LSB in DP2_RESULT_REG.
8407            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
8408            assert(!strcmp(leftByte, DP2_RESULT_REG));
8409        }
8410        else
8411        {
8412            // get LSB into DP2_RESULT_REG
8413            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
8414            if (strcmp(leftByte, DP2_RESULT_REG))
8415            {
8416                TR_AP("#7");
8417                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8418            }
8419            // And MSB in A.
8420            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
8421            assert(strcmp(leftByte, DP2_RESULT_REG));
8422            MOVA(leftByte);
8423        }
8424        _endLazyDPSEvaluation();
8425        *lsb = DP2_RESULT_REG;
8426   }
8427   else
8428   {
8429       if (sameRegs (AOP (result), AOP (left)) &&
8430         ((offl + MSB16) == offr))
8431       {
8432           /* don't crash result[offr] */
8433           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
8434           emitcode ("xch", "a,%s",
8435                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8436       }
8437       else
8438       {
8439           movLeft2Result (left, offl, result, offr, 0);
8440           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
8441       }
8442       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
8443       assert(strcmp(*lsb,"a"));
8444   }
8445 }
8446
8447 static void
8448 _storeAxResults(char    *lsb,
8449                 operand *result,
8450                 int     offr)
8451 {
8452   _startLazyDPSEvaluation();
8453   if (AOP_NEEDSACC(result))
8454   {
8455       /* We have to explicitly update the result LSB.
8456        */
8457       emitcode("xch","a,%s", lsb);
8458       aopPut(AOP(result), "a", offr);
8459       emitcode("mov","a,%s", lsb);
8460   }
8461   if (getDataSize (result) > 1)
8462   {
8463       aopPut (AOP (result), "a", offr + MSB16);
8464   }
8465   _endLazyDPSEvaluation();
8466 }
8467
8468 /*-----------------------------------------------------------------*/
8469 /* shiftL2Left2Result - shift left two bytes from left to result   */
8470 /*-----------------------------------------------------------------*/
8471 static void
8472 shiftL2Left2Result (operand * left, int offl,
8473                     operand * result, int offr, int shCount)
8474 {
8475   char *lsb;
8476
8477   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8478
8479   AccAXLsh (lsb, shCount);
8480
8481   _storeAxResults(lsb, result, offr);
8482 }
8483 #endif
8484
8485 #ifdef BETTER_LITERAL_SHIFT
8486 /*-----------------------------------------------------------------*/
8487 /* shiftR2Left2Result - shift right two bytes from left to result  */
8488 /*-----------------------------------------------------------------*/
8489 static void
8490 shiftR2Left2Result (operand * left, int offl,
8491                     operand * result, int offr,
8492                     int shCount, int sign)
8493 {
8494   char *lsb;
8495
8496   _loadLeftIntoAx(&lsb, left, result, offl, offr);
8497
8498   /* a:x >> shCount (x = lsb(result)) */
8499   if (sign)
8500   {
8501      AccAXRshS(lsb, shCount);
8502   }
8503   else
8504   {
8505     AccAXRsh(lsb, shCount);
8506   }
8507
8508   _storeAxResults(lsb, result, offr);
8509 }
8510 #endif
8511
8512 /*-----------------------------------------------------------------*/
8513 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8514 /*-----------------------------------------------------------------*/
8515 static void
8516 shiftLLeftOrResult (operand * left, int offl,
8517                     operand * result, int offr, int shCount)
8518 {
8519   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8520   /* shift left accumulator */
8521   AccLsh (shCount);
8522   /* or with result */
8523   emitcode ("orl", "a,%s",
8524             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8525   /* back to result */
8526   aopPut (AOP (result), "a", offr);
8527 }
8528
8529 #if 0
8530 //REMOVE ME!!!
8531 /*-----------------------------------------------------------------*/
8532 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8533 /*-----------------------------------------------------------------*/
8534 static void
8535 shiftRLeftOrResult (operand * left, int offl,
8536                     operand * result, int offr, int shCount)
8537 {
8538   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
8539   /* shift right accumulator */
8540   AccRsh (shCount);
8541   /* or with result */
8542   emitcode ("orl", "a,%s",
8543             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
8544   /* back to result */
8545   aopPut (AOP (result), "a", offr);
8546 }
8547 #endif
8548
8549 #ifdef BETTER_LITERAL_SHIFT
8550 /*-----------------------------------------------------------------*/
8551 /* genlshOne - left shift a one byte quantity by known count       */
8552 /*-----------------------------------------------------------------*/
8553 static void
8554 genlshOne (operand * result, operand * left, int shCount)
8555 {
8556   D (emitcode (";", "genlshOne "););
8557   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8558 }
8559 #endif
8560
8561 #ifdef BETTER_LITERAL_SHIFT
8562 /*-----------------------------------------------------------------*/
8563 /* genlshTwo - left shift two bytes by known amount != 0           */
8564 /*-----------------------------------------------------------------*/
8565 static void
8566 genlshTwo (operand * result, operand * left, int shCount)
8567 {
8568   int size;
8569
8570   D (emitcode (";", "genlshTwo "););
8571
8572   size = getDataSize (result);
8573
8574   /* if shCount >= 8 */
8575   if (shCount >= 8)
8576   {
8577       shCount -= 8;
8578
8579       _startLazyDPSEvaluation();
8580
8581       if (size > 1)
8582         {
8583           if (shCount)
8584           {
8585             _endLazyDPSEvaluation();
8586             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8587             aopPut (AOP (result), zero, LSB);
8588           }
8589           else
8590           {
8591             movLeft2Result (left, LSB, result, MSB16, 0);
8592             aopPut (AOP (result), zero, LSB);
8593             _endLazyDPSEvaluation();
8594           }
8595         }
8596         else
8597         {
8598           aopPut (AOP (result), zero, LSB);
8599           _endLazyDPSEvaluation();
8600         }
8601   }
8602
8603   /*  1 <= shCount <= 7 */
8604   else
8605     {
8606       if (size == 1)
8607       {
8608         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8609       }
8610       else
8611       {
8612         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8613       }
8614     }
8615 }
8616 #endif
8617
8618 #if 0
8619 //REMOVE ME!!!
8620 /*-----------------------------------------------------------------*/
8621 /* shiftLLong - shift left one long from left to result            */
8622 /* offl = LSB or MSB16                                             */
8623 /*-----------------------------------------------------------------*/
8624 static void
8625 shiftLLong (operand * left, operand * result, int offr)
8626 {
8627   char *l;
8628   int size = AOP_SIZE (result);
8629
8630   if (size >= LSB + offr)
8631     {
8632       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8633       MOVA (l);
8634       emitcode ("add", "a,acc");
8635       if (sameRegs (AOP (left), AOP (result)) &&
8636           size >= MSB16 + offr && offr != LSB)
8637         emitcode ("xch", "a,%s",
8638                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8639       else
8640         aopPut (AOP (result), "a", LSB + offr);
8641     }
8642
8643   if (size >= MSB16 + offr)
8644     {
8645       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8646         {
8647           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8648         }
8649       emitcode ("rlc", "a");
8650       if (sameRegs (AOP (left), AOP (result)) &&
8651           size >= MSB24 + offr && offr != LSB)
8652         emitcode ("xch", "a,%s",
8653                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8654       else
8655         aopPut (AOP (result), "a", MSB16 + offr);
8656     }
8657
8658   if (size >= MSB24 + offr)
8659     {
8660       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8661         {
8662           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8663         }
8664       emitcode ("rlc", "a");
8665       if (sameRegs (AOP (left), AOP (result)) &&
8666           size >= MSB32 + offr && offr != LSB)
8667         emitcode ("xch", "a,%s",
8668                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8669       else
8670         aopPut (AOP (result), "a", MSB24 + offr);
8671     }
8672
8673   if (size > MSB32 + offr)
8674     {
8675       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8676         {
8677           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8678         }
8679       emitcode ("rlc", "a");
8680       aopPut (AOP (result), "a", MSB32 + offr);
8681     }
8682   if (offr != LSB)
8683     aopPut (AOP (result), zero, LSB);
8684 }
8685 #endif
8686
8687 #if 0
8688 //REMOVE ME!!!
8689 /*-----------------------------------------------------------------*/
8690 /* genlshFour - shift four byte by a known amount != 0             */
8691 /*-----------------------------------------------------------------*/
8692 static void
8693 genlshFour (operand * result, operand * left, int shCount)
8694 {
8695   int size;
8696
8697   D (emitcode (";", "genlshFour ");
8698     );
8699
8700   size = AOP_SIZE (result);
8701
8702   /* if shifting more that 3 bytes */
8703   if (shCount >= 24)
8704     {
8705       shCount -= 24;
8706       if (shCount)
8707         /* lowest order of left goes to the highest
8708            order of the destination */
8709         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8710       else
8711         movLeft2Result (left, LSB, result, MSB32, 0);
8712       aopPut (AOP (result), zero, LSB);
8713       aopPut (AOP (result), zero, MSB16);
8714       aopPut (AOP (result), zero, MSB24);
8715       return;
8716     }
8717
8718   /* more than two bytes */
8719   else if (shCount >= 16)
8720     {
8721       /* lower order two bytes goes to higher order two bytes */
8722       shCount -= 16;
8723       /* if some more remaining */
8724       if (shCount)
8725         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8726       else
8727         {
8728           movLeft2Result (left, MSB16, result, MSB32, 0);
8729           movLeft2Result (left, LSB, result, MSB24, 0);
8730         }
8731       aopPut (AOP (result), zero, MSB16);
8732       aopPut (AOP (result), zero, LSB);
8733       return;
8734     }
8735
8736   /* if more than 1 byte */
8737   else if (shCount >= 8)
8738     {
8739       /* lower order three bytes goes to higher order  three bytes */
8740       shCount -= 8;
8741       if (size == 2)
8742         {
8743           if (shCount)
8744             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8745           else
8746             movLeft2Result (left, LSB, result, MSB16, 0);
8747         }
8748       else
8749         {                       /* size = 4 */
8750           if (shCount == 0)
8751             {
8752               movLeft2Result (left, MSB24, result, MSB32, 0);
8753               movLeft2Result (left, MSB16, result, MSB24, 0);
8754               movLeft2Result (left, LSB, result, MSB16, 0);
8755               aopPut (AOP (result), zero, LSB);
8756             }
8757           else if (shCount == 1)
8758             shiftLLong (left, result, MSB16);
8759           else
8760             {
8761               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8762               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8763               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8764               aopPut (AOP (result), zero, LSB);
8765             }
8766         }
8767     }
8768
8769   /* 1 <= shCount <= 7 */
8770   else if (shCount <= 2)
8771     {
8772       shiftLLong (left, result, LSB);
8773       if (shCount == 2)
8774         shiftLLong (result, result, LSB);
8775     }
8776   /* 3 <= shCount <= 7, optimize */
8777   else
8778     {
8779       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8780       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8781       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8782     }
8783 }
8784 #endif
8785
8786 #ifdef BETTER_LITERAL_SHIFT
8787 /*-----------------------------------------------------------------*/
8788 /* genLeftShiftLiteral - left shifting by known count              */
8789 /*-----------------------------------------------------------------*/
8790 static bool
8791 genLeftShiftLiteral (operand * left,
8792                      operand * right,
8793                      operand * result,
8794                      iCode * ic)
8795 {
8796   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8797   int size;
8798
8799   size = getSize (operandType (result));
8800
8801   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8802
8803   /* We only handle certain easy cases so far. */
8804   if ((shCount != 0)
8805    && (shCount < (size * 8))
8806    && (size != 1)
8807    && (size != 2))
8808   {
8809       D(emitcode (";", "genLeftShiftLiteral wimping out"););
8810       return FALSE;
8811   }
8812
8813   freeAsmop (right, NULL, ic, TRUE);
8814
8815   aopOp(left, ic, FALSE, FALSE);
8816   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8817
8818 #if 0 // debug spew
8819   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8820   {
8821         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8822         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8823         {
8824            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8825         }
8826   }
8827   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8828   {
8829         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8830         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8831         {
8832            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8833         }
8834   }
8835 #endif
8836
8837 #if VIEW_SIZE
8838   emitcode ("; shift left ", "result %d, left %d", size,
8839             AOP_SIZE (left));
8840 #endif
8841
8842   /* I suppose that the left size >= result size */
8843   if (shCount == 0)
8844   {
8845         _startLazyDPSEvaluation();
8846         while (size--)
8847         {
8848           movLeft2Result (left, size, result, size, 0);
8849         }
8850         _endLazyDPSEvaluation();
8851   }
8852   else if (shCount >= (size * 8))
8853   {
8854     _startLazyDPSEvaluation();
8855     while (size--)
8856     {
8857       aopPut (AOP (result), zero, size);
8858     }
8859     _endLazyDPSEvaluation();
8860   }
8861   else
8862   {
8863       switch (size)
8864         {
8865         case 1:
8866           genlshOne (result, left, shCount);
8867           break;
8868
8869         case 2:
8870           genlshTwo (result, left, shCount);
8871           break;
8872 #if 0
8873         case 4:
8874           genlshFour (result, left, shCount);
8875           break;
8876 #endif
8877         default:
8878           fprintf(stderr, "*** ack! mystery literal shift!\n");
8879           break;
8880         }
8881     }
8882   freeAsmop (left, NULL, ic, TRUE);
8883   freeAsmop (result, NULL, ic, TRUE);
8884   return TRUE;
8885 }
8886 #endif
8887
8888 /*-----------------------------------------------------------------*/
8889 /* genLeftShift - generates code for left shifting                 */
8890 /*-----------------------------------------------------------------*/
8891 static void
8892 genLeftShift (iCode * ic)
8893 {
8894   operand *left, *right, *result;
8895   int size, offset;
8896   char *l;
8897   symbol *tlbl, *tlbl1;
8898
8899   D (emitcode (";", "genLeftShift "););
8900
8901   right = IC_RIGHT (ic);
8902   left = IC_LEFT (ic);
8903   result = IC_RESULT (ic);
8904
8905   aopOp (right, ic, FALSE, FALSE);
8906
8907
8908 #ifdef BETTER_LITERAL_SHIFT
8909   /* if the shift count is known then do it
8910      as efficiently as possible */
8911   if (AOP_TYPE (right) == AOP_LIT)
8912     {
8913       if (genLeftShiftLiteral (left, right, result, ic))
8914       {
8915         return;
8916       }
8917     }
8918 #endif
8919
8920   /* shift count is unknown then we have to form
8921      a loop get the loop count in B : Note: we take
8922      only the lower order byte since shifting
8923      more that 32 bits make no sense anyway, ( the
8924      largest size of an object can be only 32 bits ) */
8925
8926   if (AOP_TYPE (right) == AOP_LIT)
8927   {
8928       /* Really should be handled by genLeftShiftLiteral,
8929        * but since I'm too lazy to fix that today, at least we can make
8930        * some small improvement.
8931        */
8932        emitcode("mov", "b,#!constbyte",
8933                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8934   }
8935   else
8936   {
8937       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8938       emitcode ("inc", "b");
8939   }
8940   freeAsmop (right, NULL, ic, TRUE);
8941   aopOp (left, ic, FALSE, FALSE);
8942   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8943
8944   /* now move the left to the result if they are not the
8945      same */
8946   if (!sameRegs (AOP (left), AOP (result)) &&
8947       AOP_SIZE (result) > 1)
8948     {
8949
8950       size = AOP_SIZE (result);
8951       offset = 0;
8952       _startLazyDPSEvaluation ();
8953       while (size--)
8954         {
8955           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8956           if (*l == '@' && (IS_AOP_PREG (result)))
8957             {
8958
8959               emitcode ("mov", "a,%s", l);
8960               aopPut (AOP (result), "a", offset);
8961             }
8962           else
8963             aopPut (AOP (result), l, offset);
8964           offset++;
8965         }
8966       _endLazyDPSEvaluation ();
8967     }
8968
8969   tlbl = newiTempLabel (NULL);
8970   size = AOP_SIZE (result);
8971   offset = 0;
8972   tlbl1 = newiTempLabel (NULL);
8973
8974   /* if it is only one byte then */
8975   if (size == 1)
8976     {
8977       symbol *tlbl1 = newiTempLabel (NULL);
8978
8979       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8980       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8981       emitcode ("", "!tlabeldef", tlbl->key + 100);
8982       emitcode ("add", "a,acc");
8983       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8984       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8985       aopPut (AOP (result), "a", 0);
8986       goto release;
8987     }
8988
8989   reAdjustPreg (AOP (result));
8990
8991   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8992   emitcode ("", "!tlabeldef", tlbl->key + 100);
8993   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8994   emitcode ("add", "a,acc");
8995   aopPut (AOP (result), "a", offset++);
8996   _startLazyDPSEvaluation ();
8997   while (--size)
8998     {
8999       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9000       emitcode ("rlc", "a");
9001       aopPut (AOP (result), "a", offset++);
9002     }
9003   _endLazyDPSEvaluation ();
9004   reAdjustPreg (AOP (result));
9005
9006   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9007   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9008 release:
9009   freeAsmop (left, NULL, ic, TRUE);
9010   freeAsmop (result, NULL, ic, TRUE);
9011 }
9012
9013 #ifdef BETTER_LITERAL_SHIFT
9014 /*-----------------------------------------------------------------*/
9015 /* genrshOne - right shift a one byte quantity by known count      */
9016 /*-----------------------------------------------------------------*/
9017 static void
9018 genrshOne (operand * result, operand * left,
9019            int shCount, int sign)
9020 {
9021   D (emitcode (";", "genrshOne"););
9022   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9023 }
9024 #endif
9025
9026 #ifdef BETTER_LITERAL_SHIFT
9027 /*-----------------------------------------------------------------*/
9028 /* genrshTwo - right shift two bytes by known amount != 0          */
9029 /*-----------------------------------------------------------------*/
9030 static void
9031 genrshTwo (operand * result, operand * left,
9032            int shCount, int sign)
9033 {
9034   D (emitcode (";", "genrshTwo"););
9035
9036   /* if shCount >= 8 */
9037   if (shCount >= 8)
9038     {
9039       shCount -= 8;
9040       _startLazyDPSEvaluation();
9041       if (shCount)
9042       {
9043         shiftR1Left2Result (left, MSB16, result, LSB,
9044                             shCount, sign);
9045       }
9046       else
9047       {
9048         movLeft2Result (left, MSB16, result, LSB, sign);
9049       }
9050       addSign (result, MSB16, sign);
9051       _endLazyDPSEvaluation();
9052     }
9053
9054   /*  1 <= shCount <= 7 */
9055   else
9056   {
9057     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9058   }
9059 }
9060 #endif
9061
9062 /*-----------------------------------------------------------------*/
9063 /* shiftRLong - shift right one long from left to result           */
9064 /* offl = LSB or MSB16                                             */
9065 /*-----------------------------------------------------------------*/
9066 static void
9067 shiftRLong (operand * left, int offl,
9068             operand * result, int sign)
9069 {
9070   int isSameRegs=sameRegs(AOP(left),AOP(result));
9071
9072   if (isSameRegs && offl>1) {
9073     // we are in big trouble, but this shouldn't happen
9074     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9075   }
9076
9077   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
9078
9079   if (offl==MSB16) {
9080     // shift is > 8
9081     if (sign) {
9082       emitcode ("rlc", "a");
9083       emitcode ("subb", "a,acc");
9084       emitcode ("xch", "a,%s",
9085                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
9086     } else {
9087       aopPut (AOP(result), zero, MSB32);
9088     }
9089   }
9090
9091   if (!sign) {
9092     emitcode ("clr", "c");
9093   } else {
9094     emitcode ("mov", "c,acc.7");
9095   }
9096
9097   emitcode ("rrc", "a");
9098
9099   if (isSameRegs && offl==MSB16) {
9100     emitcode ("xch",
9101               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
9102   } else {
9103     aopPut (AOP (result), "a", MSB32);
9104     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
9105   }
9106
9107   emitcode ("rrc", "a");
9108   if (isSameRegs && offl==1) {
9109     emitcode ("xch", "a,%s",
9110               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
9111   } else {
9112     aopPut (AOP (result), "a", MSB24);
9113     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
9114   }
9115   emitcode ("rrc", "a");
9116   aopPut (AOP (result), "a", MSB16 - offl);
9117
9118   if (offl == LSB)
9119     {
9120       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
9121       emitcode ("rrc", "a");
9122       aopPut (AOP (result), "a", LSB);
9123     }
9124 }
9125
9126 /*-----------------------------------------------------------------*/
9127 /* genrshFour - shift four byte by a known amount != 0             */
9128 /*-----------------------------------------------------------------*/
9129 static void
9130 genrshFour (operand * result, operand * left,
9131             int shCount, int sign)
9132 {
9133   D (emitcode (";", "genrshFour"););
9134
9135   /* if shifting more that 3 bytes */
9136   if (shCount >= 24)
9137     {
9138       shCount -= 24;
9139       _startLazyDPSEvaluation();
9140       if (shCount)
9141         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9142       else
9143         movLeft2Result (left, MSB32, result, LSB, sign);
9144       addSign (result, MSB16, sign);
9145       _endLazyDPSEvaluation();
9146     }
9147   else if (shCount >= 16)
9148     {
9149       shCount -= 16;
9150       _startLazyDPSEvaluation();
9151       if (shCount)
9152         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9153       else
9154         {
9155           movLeft2Result (left, MSB24, result, LSB, 0);
9156           movLeft2Result (left, MSB32, result, MSB16, sign);
9157         }
9158       addSign (result, MSB24, sign);
9159       _endLazyDPSEvaluation();
9160     }
9161   else if (shCount >= 8)
9162     {
9163       shCount -= 8;
9164       _startLazyDPSEvaluation();
9165       if (shCount == 1)
9166         {
9167             shiftRLong (left, MSB16, result, sign);
9168         }
9169       else if (shCount == 0)
9170         {
9171           movLeft2Result (left, MSB16, result, LSB, 0);
9172           movLeft2Result (left, MSB24, result, MSB16, 0);
9173           movLeft2Result (left, MSB32, result, MSB24, sign);
9174           addSign (result, MSB32, sign);
9175         }
9176       else
9177         {
9178           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9179           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9180           /* the last shift is signed */
9181           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9182           addSign (result, MSB32, sign);
9183         }
9184         _endLazyDPSEvaluation();
9185     }
9186   else
9187     {
9188         /* 1 <= shCount <= 7 */
9189       if (shCount <= 2)
9190         {
9191           shiftRLong (left, LSB, result, sign);
9192           if (shCount == 2)
9193             shiftRLong (result, LSB, result, sign);
9194         }
9195       else
9196         {
9197           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9198           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9199           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9200         }
9201     }
9202 }
9203
9204 #ifdef BETTER_LITERAL_SHIFT
9205 /*-----------------------------------------------------------------*/
9206 /* genRightShiftLiteral - right shifting by known count            */
9207 /*-----------------------------------------------------------------*/
9208 static bool
9209 genRightShiftLiteral (operand * left,
9210                       operand * right,
9211                       operand * result,
9212                       iCode * ic,
9213                       int sign)
9214 {
9215   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9216   int size;
9217
9218   size = getSize (operandType (result));
9219
9220   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9221
9222   /* We only handle certain easy cases so far. */
9223   if ((shCount != 0)
9224    && (shCount < (size * 8))
9225    && (size != 1)
9226    && (size != 2)
9227    && (size != 4))
9228   {
9229       D(emitcode (";", "genRightShiftLiteral wimping out"););
9230       return FALSE;
9231   }
9232
9233   freeAsmop (right, NULL, ic, TRUE);
9234
9235   aopOp (left, ic, FALSE, FALSE);
9236   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9237
9238 #if VIEW_SIZE
9239   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9240             AOP_SIZE (left));
9241 #endif
9242
9243   /* test the LEFT size !!! */
9244
9245   /* I suppose that the left size >= result size */
9246   if (shCount == 0)
9247   {
9248       size = getDataSize (result);
9249       _startLazyDPSEvaluation();
9250       while (size--)
9251       {
9252         movLeft2Result (left, size, result, size, 0);
9253       }
9254       _endLazyDPSEvaluation();
9255   }
9256   else if (shCount >= (size * 8))
9257     {
9258       if (sign)
9259       {
9260         /* get sign in acc.7 */
9261         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
9262       }
9263       addSign (result, LSB, sign);
9264     }
9265   else
9266     {
9267       switch (size)
9268         {
9269         case 1:
9270           genrshOne (result, left, shCount, sign);
9271           break;
9272
9273         case 2:
9274           genrshTwo (result, left, shCount, sign);
9275           break;
9276 #if 1
9277         case 4:
9278           genrshFour (result, left, shCount, sign);
9279           break;
9280 #endif
9281         default:
9282           break;
9283         }
9284     }
9285   freeAsmop (left, NULL, ic, TRUE);
9286   freeAsmop (result, NULL, ic, TRUE);
9287
9288   return TRUE;
9289 }
9290 #endif
9291
9292 /*-----------------------------------------------------------------*/
9293 /* genSignedRightShift - right shift of signed number              */
9294 /*-----------------------------------------------------------------*/
9295 static void
9296 genSignedRightShift (iCode * ic)
9297 {
9298   operand *right, *left, *result;
9299   int size, offset;
9300   char *l;
9301   symbol *tlbl, *tlbl1;
9302
9303   D (emitcode (";", "genSignedRightShift "););
9304
9305   /* we do it the hard way put the shift count in b
9306      and loop thru preserving the sign */
9307
9308   right = IC_RIGHT (ic);
9309   left = IC_LEFT (ic);
9310   result = IC_RESULT (ic);
9311
9312   aopOp (right, ic, FALSE, FALSE);
9313
9314 #ifdef BETTER_LITERAL_SHIFT
9315   if (AOP_TYPE (right) == AOP_LIT)
9316     {
9317       if (genRightShiftLiteral (left, right, result, ic, 1))
9318       {
9319         return;
9320       }
9321     }
9322 #endif
9323   /* shift count is unknown then we have to form
9324      a loop get the loop count in B : Note: we take
9325      only the lower order byte since shifting
9326      more that 32 bits make no sense anyway, ( the
9327      largest size of an object can be only 32 bits ) */
9328
9329   if (AOP_TYPE (right) == AOP_LIT)
9330   {
9331       /* Really should be handled by genRightShiftLiteral,
9332        * but since I'm too lazy to fix that today, at least we can make
9333        * some small improvement.
9334        */
9335        emitcode("mov", "b,#!constbyte",
9336                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9337   }
9338   else
9339   {
9340         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9341         emitcode ("inc", "b");
9342   }
9343   freeAsmop (right, NULL, ic, TRUE);
9344   aopOp (left, ic, FALSE, FALSE);
9345   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9346
9347   /* now move the left to the result if they are not the
9348      same */
9349   if (!sameRegs (AOP (left), AOP (result)) &&
9350       AOP_SIZE (result) > 1)
9351     {
9352
9353       size = AOP_SIZE (result);
9354       offset = 0;
9355       _startLazyDPSEvaluation ();
9356       while (size--)
9357         {
9358           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9359           if (*l == '@' && IS_AOP_PREG (result))
9360             {
9361
9362               emitcode ("mov", "a,%s", l);
9363               aopPut (AOP (result), "a", offset);
9364             }
9365           else
9366             aopPut (AOP (result), l, offset);
9367           offset++;
9368         }
9369       _endLazyDPSEvaluation ();
9370     }
9371
9372   /* mov the highest order bit to OVR */
9373   tlbl = newiTempLabel (NULL);
9374   tlbl1 = newiTempLabel (NULL);
9375
9376   size = AOP_SIZE (result);
9377   offset = size - 1;
9378   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
9379   emitcode ("rlc", "a");
9380   emitcode ("mov", "ov,c");
9381   /* if it is only one byte then */
9382   if (size == 1)
9383     {
9384       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9385       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9386       emitcode ("", "!tlabeldef", tlbl->key + 100);
9387       emitcode ("mov", "c,ov");
9388       emitcode ("rrc", "a");
9389       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9390       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9391       aopPut (AOP (result), "a", 0);
9392       goto release;
9393     }
9394
9395   reAdjustPreg (AOP (result));
9396   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9397   emitcode ("", "!tlabeldef", tlbl->key + 100);
9398   emitcode ("mov", "c,ov");
9399   _startLazyDPSEvaluation ();
9400   while (size--)
9401     {
9402       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9403       emitcode ("rrc", "a");
9404       aopPut (AOP (result), "a", offset--);
9405     }
9406   _endLazyDPSEvaluation ();
9407   reAdjustPreg (AOP (result));
9408   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9409   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9410
9411 release:
9412   freeAsmop (left, NULL, ic, TRUE);
9413   freeAsmop (result, NULL, ic, TRUE);
9414 }
9415
9416 /*-----------------------------------------------------------------*/
9417 /* genRightShift - generate code for right shifting                */
9418 /*-----------------------------------------------------------------*/
9419 static void
9420 genRightShift (iCode * ic)
9421 {
9422   operand *right, *left, *result;
9423   sym_link *letype;
9424   int size, offset;
9425   char *l;
9426   symbol *tlbl, *tlbl1;
9427
9428   D (emitcode (";", "genRightShift "););
9429
9430   /* if signed then we do it the hard way preserve the
9431      sign bit moving it inwards */
9432   letype = getSpec (operandType (IC_LEFT (ic)));
9433
9434   if (!SPEC_USIGN (letype))
9435     {
9436       genSignedRightShift (ic);
9437       return;
9438     }
9439
9440   /* signed & unsigned types are treated the same : i.e. the
9441      signed is NOT propagated inwards : quoting from the
9442      ANSI - standard : "for E1 >> E2, is equivalent to division
9443      by 2**E2 if unsigned or if it has a non-negative value,
9444      otherwise the result is implementation defined ", MY definition
9445      is that the sign does not get propagated */
9446
9447   right = IC_RIGHT (ic);
9448   left = IC_LEFT (ic);
9449   result = IC_RESULT (ic);
9450
9451   aopOp (right, ic, FALSE, FALSE);
9452
9453 #ifdef BETTER_LITERAL_SHIFT
9454   /* if the shift count is known then do it
9455      as efficiently as possible */
9456   if (AOP_TYPE (right) == AOP_LIT)
9457     {
9458       if (genRightShiftLiteral (left, right, result, ic, 0))
9459       {
9460         return;
9461       }
9462     }
9463 #endif
9464
9465   /* shift count is unknown then we have to form
9466      a loop get the loop count in B : Note: we take
9467      only the lower order byte since shifting
9468      more that 32 bits make no sense anyway, ( the
9469      largest size of an object can be only 32 bits ) */
9470
9471   if (AOP_TYPE (right) == AOP_LIT)
9472   {
9473       /* Really should be handled by genRightShiftLiteral,
9474        * but since I'm too lazy to fix that today, at least we can make
9475        * some small improvement.
9476        */
9477        emitcode("mov", "b,#!constbyte",
9478                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9479   }
9480   else
9481   {
9482       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
9483       emitcode ("inc", "b");
9484   }
9485   freeAsmop (right, NULL, ic, TRUE);
9486   aopOp (left, ic, FALSE, FALSE);
9487   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9488
9489   /* now move the left to the result if they are not the
9490      same */
9491   if (!sameRegs (AOP (left), AOP (result)) &&
9492       AOP_SIZE (result) > 1)
9493     {
9494
9495       size = AOP_SIZE (result);
9496       offset = 0;
9497       _startLazyDPSEvaluation ();
9498       while (size--)
9499         {
9500           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
9501           if (*l == '@' && IS_AOP_PREG (result))
9502             {
9503
9504               emitcode ("mov", "a,%s", l);
9505               aopPut (AOP (result), "a", offset);
9506             }
9507           else
9508             aopPut (AOP (result), l, offset);
9509           offset++;
9510         }
9511       _endLazyDPSEvaluation ();
9512     }
9513
9514   tlbl = newiTempLabel (NULL);
9515   tlbl1 = newiTempLabel (NULL);
9516   size = AOP_SIZE (result);
9517   offset = size - 1;
9518
9519   /* if it is only one byte then */
9520   if (size == 1)
9521     {
9522       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9523       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9524       emitcode ("", "!tlabeldef", tlbl->key + 100);
9525       CLRC;
9526       emitcode ("rrc", "a");
9527       emitcode ("", "!tlabeldef", tlbl1->key + 100);
9528       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9529       aopPut (AOP (result), "a", 0);
9530       goto release;
9531     }
9532
9533   reAdjustPreg (AOP (result));
9534   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9535   emitcode ("", "!tlabeldef", tlbl->key + 100);
9536   CLRC;
9537   _startLazyDPSEvaluation ();
9538   while (size--)
9539     {
9540       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
9541       emitcode ("rrc", "a");
9542       aopPut (AOP (result), "a", offset--);
9543     }
9544   _endLazyDPSEvaluation ();
9545   reAdjustPreg (AOP (result));
9546
9547   emitcode ("", "!tlabeldef", tlbl1->key + 100);
9548   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9549
9550 release:
9551   freeAsmop (left, NULL, ic, TRUE);
9552   freeAsmop (result, NULL, ic, TRUE);
9553 }
9554
9555
9556 /*-----------------------------------------------------------------*/
9557 /* emitPtrByteGet - emits code to get a byte into A through a      */
9558 /*                  pointer register (R0, R1, or DPTR). The        */
9559 /*                  original value of A can be preserved in B.     */
9560 /*-----------------------------------------------------------------*/
9561 static void
9562 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9563 {
9564   switch (p_type)
9565     {
9566     case IPOINTER:
9567     case POINTER:
9568       if (preserveAinB)
9569         emitcode ("mov", "b,a");
9570       emitcode ("mov", "a,@%s", rname);
9571       break;
9572
9573     case PPOINTER:
9574       if (preserveAinB)
9575         emitcode ("mov", "b,a");
9576       emitcode ("movx", "a,@%s", rname);
9577       break;
9578
9579     case FPOINTER:
9580       if (preserveAinB)
9581         emitcode ("mov", "b,a");
9582       emitcode ("movx", "a,@dptr");
9583       break;
9584
9585     case CPOINTER:
9586       if (preserveAinB)
9587         emitcode ("mov", "b,a");
9588       emitcode ("clr", "a");
9589       emitcode ("movc", "a,@a+dptr");
9590       break;
9591
9592     case GPOINTER:
9593       if (preserveAinB)
9594         {
9595           emitcode ("push", "b");
9596           emitcode ("push", "acc");
9597         }
9598       emitcode ("lcall", "__gptrget");
9599       if (preserveAinB)
9600         emitcode ("pop", "b");
9601       break;
9602     }
9603 }
9604
9605 /*-----------------------------------------------------------------*/
9606 /* emitPtrByteSet - emits code to set a byte from src through a    */
9607 /*                  pointer register (R0, R1, or DPTR).            */
9608 /*-----------------------------------------------------------------*/
9609 static void
9610 emitPtrByteSet (char *rname, int p_type, char *src)
9611 {
9612   switch (p_type)
9613     {
9614     case IPOINTER:
9615     case POINTER:
9616       if (*src=='@')
9617         {
9618           MOVA (src);
9619           emitcode ("mov", "@%s,a", rname);
9620         }
9621       else
9622         emitcode ("mov", "@%s,%s", rname, src);
9623       break;
9624
9625     case PPOINTER:
9626       MOVA (src);
9627       emitcode ("movx", "@%s,a", rname);
9628       break;
9629
9630     case FPOINTER:
9631       MOVA (src);
9632       emitcode ("movx", "@dptr,a");
9633       break;
9634
9635     case GPOINTER:
9636       MOVA (src);
9637       emitcode ("lcall", "__gptrput");
9638       break;
9639     }
9640 }
9641
9642 /*-----------------------------------------------------------------*/
9643 /* genUnpackBits - generates code for unpacking bits               */
9644 /*-----------------------------------------------------------------*/
9645 static void
9646 genUnpackBits (operand * result, char *rname, int ptype)
9647 {
9648   int offset = 0;       /* result byte offset */
9649   int rsize;            /* result size */
9650   int rlen = 0;         /* remaining bitfield length */
9651   sym_link *etype;      /* bitfield type information */
9652   int blen;             /* bitfield length */
9653   int bstr;             /* bitfield starting bit within byte */
9654
9655   D(emitcode (";     genUnpackBits",""));
9656
9657   etype = getSpec (operandType (result));
9658   rsize = getSize (operandType (result));
9659   blen = SPEC_BLEN (etype);
9660   bstr = SPEC_BSTR (etype);
9661
9662   /* If the bitfield length is less than a byte */
9663   if (blen < 8)
9664     {
9665       emitPtrByteGet (rname, ptype, FALSE);
9666       AccRsh (bstr);
9667       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9668       aopPut (AOP (result), "a", offset++);
9669       goto finish;
9670     }
9671
9672   /* Bit field did not fit in a byte. Copy all
9673      but the partial byte at the end.  */
9674   for (rlen=blen;rlen>=8;rlen-=8)
9675     {
9676       emitPtrByteGet (rname, ptype, FALSE);
9677       aopPut (AOP (result), "a", offset++);
9678       if (rlen>8)
9679         emitcode ("inc", "%s", rname);
9680     }
9681
9682   /* Handle the partial byte at the end */
9683   if (rlen)
9684     {
9685       emitPtrByteGet (rname, ptype, FALSE);
9686       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9687       aopPut (AOP (result), "a", offset++);
9688     }
9689
9690 finish:
9691   if (offset < rsize)
9692     {
9693       rsize -= offset;
9694       while (rsize--)
9695         aopPut (AOP (result), zero, offset++);
9696     }
9697 }
9698
9699
9700 /*-----------------------------------------------------------------*/
9701 /* genDataPointerGet - generates code when ptr offset is known     */
9702 /*-----------------------------------------------------------------*/
9703 static void
9704 genDataPointerGet (operand * left,
9705                    operand * result,
9706                    iCode * ic)
9707 {
9708   char *l;
9709   char buff[256];
9710   int size, offset = 0;
9711   aopOp (result, ic, TRUE, FALSE);
9712
9713   /* get the string representation of the name */
9714   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9715   size = AOP_SIZE (result);
9716   _startLazyDPSEvaluation ();
9717   while (size--)
9718     {
9719         if (offset)
9720         {
9721             SNPRINTF (buff, sizeof(buff),
9722                       "(%s + %d)", l + 1, offset);
9723         }
9724         else
9725         {
9726             SNPRINTF (buff, sizeof(buff),
9727                       "%s", l + 1);
9728         }
9729       aopPut (AOP (result), buff, offset++);
9730     }
9731   _endLazyDPSEvaluation ();
9732
9733   freeAsmop (left, NULL, ic, TRUE);
9734   freeAsmop (result, NULL, ic, TRUE);
9735 }
9736
9737 /*-----------------------------------------------------------------*/
9738 /* genNearPointerGet - emitcode for near pointer fetch             */
9739 /*-----------------------------------------------------------------*/
9740 static void
9741 genNearPointerGet (operand * left,
9742                    operand * result,
9743                    iCode * ic,
9744                    iCode *pi)
9745 {
9746   asmop *aop = NULL;
9747   regs *preg;
9748   char *rname;
9749   sym_link *rtype, *retype, *letype;
9750   sym_link *ltype = operandType (left);
9751   char buff[80];
9752
9753   rtype = operandType (result);
9754   retype = getSpec (rtype);
9755   letype = getSpec (ltype);
9756
9757   aopOp (left, ic, FALSE, FALSE);
9758
9759   /* if left is rematerialisable and
9760      result is not bitfield variable type and
9761      the left is pointer to data space i.e
9762      lower 128 bytes of space */
9763   if (AOP_TYPE (left) == AOP_IMMD &&
9764       !IS_BITFIELD (retype) &&
9765       !IS_BITFIELD (letype) &&
9766       DCL_TYPE (ltype) == POINTER)
9767     {
9768       genDataPointerGet (left, result, ic);
9769       return;
9770     }
9771
9772   /* if the value is already in a pointer register
9773      then don't need anything more */
9774   if (!AOP_INPREG (AOP (left)))
9775     {
9776       /* otherwise get a free pointer register */
9777       aop = newAsmop (0);
9778       preg = getFreePtr (ic, &aop, FALSE);
9779       emitcode ("mov", "%s,%s",
9780                 preg->name,
9781                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9782       rname = preg->name;
9783     }
9784   else
9785     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9786
9787   freeAsmop (left, NULL, ic, TRUE);
9788   aopOp (result, ic, FALSE, FALSE);
9789
9790   /* if bitfield then unpack the bits */
9791   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9792     genUnpackBits (result, rname, POINTER);
9793   else
9794     {
9795       /* we have can just get the values */
9796       int size = AOP_SIZE (result);
9797       int offset = 0;
9798
9799       while (size--)
9800         {
9801           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9802             {
9803
9804               emitcode ("mov", "a,@%s", rname);
9805               aopPut (AOP (result), "a", offset);
9806             }
9807           else
9808             {
9809               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9810               aopPut (AOP (result), buff, offset);
9811             }
9812           offset++;
9813           if (size || pi)
9814             {
9815                 emitcode ("inc", "%s", rname);
9816             }
9817         }
9818     }
9819
9820   /* now some housekeeping stuff */
9821   if (aop)
9822     {
9823       /* we had to allocate for this iCode */
9824       if (pi) { /* post increment present */
9825         aopPut(AOP ( left ),rname,0);
9826       }
9827       freeAsmop (NULL, aop, ic, TRUE);
9828     }
9829   else
9830     {
9831       /* we did not allocate which means left
9832          already in a pointer register, then
9833          if size > 0 && this could be used again
9834          we have to point it back to where it
9835          belongs */
9836       if (AOP_SIZE (result) > 1 &&
9837           !OP_SYMBOL (left)->remat &&
9838           (OP_SYMBOL (left)->liveTo > ic->seq ||
9839            ic->depth) &&
9840           !pi)
9841         {
9842           int size = AOP_SIZE (result) - 1;
9843           while (size--)
9844             emitcode ("dec", "%s", rname);
9845         }
9846     }
9847
9848   /* done */
9849   freeAsmop (result, NULL, ic, TRUE);
9850   if (pi) pi->generated = 1;
9851 }
9852
9853 /*-----------------------------------------------------------------*/
9854 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9855 /*-----------------------------------------------------------------*/
9856 static void
9857 genPagedPointerGet (operand * left,
9858                     operand * result,
9859                     iCode * ic,
9860                     iCode * pi)
9861 {
9862   asmop *aop = NULL;
9863   regs *preg;
9864   char *rname;
9865   sym_link *rtype, *retype, *letype;
9866
9867   rtype = operandType (result);
9868   retype = getSpec (rtype);
9869   letype = getSpec (operandType (left));
9870   aopOp (left, ic, FALSE, FALSE);
9871
9872   /* if the value is already in a pointer register
9873      then don't need anything more */
9874   if (!AOP_INPREG (AOP (left)))
9875     {
9876       /* otherwise get a free pointer register */
9877       aop = newAsmop (0);
9878       preg = getFreePtr (ic, &aop, FALSE);
9879       emitcode ("mov", "%s,%s",
9880                 preg->name,
9881                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9882       rname = preg->name;
9883     }
9884   else
9885     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9886
9887   freeAsmop (left, NULL, ic, TRUE);
9888   aopOp (result, ic, FALSE, FALSE);
9889
9890   /* if bitfield then unpack the bits */
9891   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9892     genUnpackBits (result, rname, PPOINTER);
9893   else
9894     {
9895       /* we have can just get the values */
9896       int size = AOP_SIZE (result);
9897       int offset = 0;
9898
9899       while (size--)
9900         {
9901
9902           emitcode ("movx", "a,@%s", rname);
9903           aopPut (AOP (result), "a", offset);
9904
9905           offset++;
9906
9907           if (size || pi)
9908             emitcode ("inc", "%s", rname);
9909         }
9910     }
9911
9912   /* now some housekeeping stuff */
9913   if (aop)
9914     {
9915       /* we had to allocate for this iCode */
9916       if (pi) aopPut ( AOP (left), rname, 0);
9917       freeAsmop (NULL, aop, ic, TRUE);
9918     }
9919   else
9920     {
9921       /* we did not allocate which means left
9922          already in a pointer register, then
9923          if size > 0 && this could be used again
9924          we have to point it back to where it
9925          belongs */
9926       if (AOP_SIZE (result) > 1 &&
9927           !OP_SYMBOL (left)->remat &&
9928           (OP_SYMBOL (left)->liveTo > ic->seq ||
9929            ic->depth) &&
9930           !pi)
9931         {
9932           int size = AOP_SIZE (result) - 1;
9933           while (size--)
9934             emitcode ("dec", "%s", rname);
9935         }
9936     }
9937
9938   /* done */
9939   freeAsmop (result, NULL, ic, TRUE);
9940   if (pi) pi->generated = 1;
9941 }
9942
9943 /*-----------------------------------------------------------------*/
9944 /* genFarPointerGet - gget value from far space                    */
9945 /*-----------------------------------------------------------------*/
9946 static void
9947 genFarPointerGet (operand * left,
9948                   operand * result, iCode * ic, iCode *pi)
9949 {
9950     int size, offset, dopi=1;
9951   sym_link *retype = getSpec (operandType (result));
9952   sym_link *letype = getSpec (operandType (left));
9953   D (emitcode (";", "genFarPointerGet"););
9954
9955   aopOp (left, ic, FALSE, FALSE);
9956
9957   /* if the operand is already in dptr
9958      then we do nothing else we move the value to dptr */
9959   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9960     {
9961       /* if this is remateriazable */
9962       if (AOP_TYPE (left) == AOP_IMMD)
9963         {
9964           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9965         }
9966       else
9967         {
9968           /* we need to get it byte by byte */
9969           _startLazyDPSEvaluation ();
9970           if (AOP_TYPE (left) != AOP_DPTR)
9971             {
9972               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9973               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9974               if (options.model == MODEL_FLAT24)
9975                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9976             }
9977           else
9978             {
9979               /* We need to generate a load to DPTR indirect through DPTR. */
9980               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9981               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9982               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9983               if (options.model == MODEL_FLAT24)
9984                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9985               emitcode ("pop", "dph");
9986               emitcode ("pop", "dpl");
9987               dopi =0;
9988             }
9989           _endLazyDPSEvaluation ();
9990         }
9991     }
9992   /* so dptr know contains the address */
9993   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9994
9995   /* if bit then unpack */
9996   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9997       if (AOP_INDPTRn(left)) {
9998           genSetDPTR(AOP(left)->aopu.dptr);
9999       }
10000       genUnpackBits (result, "dptr", FPOINTER);
10001       if (AOP_INDPTRn(left)) {
10002           genSetDPTR(0);
10003       }
10004   } else
10005     {
10006       size = AOP_SIZE (result);
10007       offset = 0;
10008
10009       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10010           while (size--) {
10011               genSetDPTR(AOP(left)->aopu.dptr);
10012               emitcode ("movx", "a,@dptr");
10013               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10014                   emitcode ("inc", "dptr");
10015               genSetDPTR (0);
10016               aopPut (AOP (result), "a", offset++);
10017           }
10018       } else {
10019           _startLazyDPSEvaluation ();
10020           while (size--) {
10021               if (AOP_INDPTRn(left)) {
10022                   genSetDPTR(AOP(left)->aopu.dptr);
10023               } else {
10024                   genSetDPTR (0);
10025               }
10026               _flushLazyDPS ();
10027
10028               emitcode ("movx", "a,@dptr");
10029               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10030                   emitcode ("inc", "dptr");
10031
10032               aopPut (AOP (result), "a", offset++);
10033           }
10034           _endLazyDPSEvaluation ();
10035       }
10036     }
10037   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10038       if (!AOP_INDPTRn(left)) {
10039           _startLazyDPSEvaluation ();
10040           aopPut ( AOP (left), "dpl", 0);
10041           aopPut ( AOP (left), "dph", 1);
10042           if (options.model == MODEL_FLAT24)
10043               aopPut ( AOP (left), "dpx", 2);
10044           _endLazyDPSEvaluation ();
10045       }
10046     pi->generated = 1;
10047   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10048              AOP_SIZE(result) > 1 &&
10049              IS_SYMOP(left) &&
10050              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10051
10052       size = AOP_SIZE (result) - 1;
10053       if (AOP_INDPTRn(left)) {
10054           genSetDPTR(AOP(left)->aopu.dptr);
10055       }
10056       while (size--) emitcode ("lcall","__decdptr");
10057       if (AOP_INDPTRn(left)) {
10058           genSetDPTR(0);
10059       }
10060   }
10061
10062   freeAsmop (left, NULL, ic, TRUE);
10063   freeAsmop (result, NULL, ic, TRUE);
10064 }
10065
10066 /*-----------------------------------------------------------------*/
10067 /* genCodePointerGet - get value from code space                  */
10068 /*-----------------------------------------------------------------*/
10069 static void
10070 genCodePointerGet (operand * left,
10071                     operand * result, iCode * ic, iCode *pi)
10072 {
10073   int size, offset, dopi=1;
10074   sym_link *retype = getSpec (operandType (result));
10075
10076   aopOp (left, ic, FALSE, FALSE);
10077
10078   /* if the operand is already in dptr
10079      then we do nothing else we move the value to dptr */
10080   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10081     {
10082       /* if this is remateriazable */
10083       if (AOP_TYPE (left) == AOP_IMMD)
10084         {
10085           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10086         }
10087       else
10088         {                       /* we need to get it byte by byte */
10089           _startLazyDPSEvaluation ();
10090           if (AOP_TYPE (left) != AOP_DPTR)
10091             {
10092               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10093               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10094               if (options.model == MODEL_FLAT24)
10095                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10096             }
10097           else
10098             {
10099               /* We need to generate a load to DPTR indirect through DPTR. */
10100               D (emitcode (";", "gencodePointerGet -- indirection special case."););
10101               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
10102               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
10103               if (options.model == MODEL_FLAT24)
10104                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10105               emitcode ("pop", "dph");
10106               emitcode ("pop", "dpl");
10107               dopi=0;
10108             }
10109           _endLazyDPSEvaluation ();
10110         }
10111     }
10112   /* so dptr know contains the address */
10113   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10114
10115   /* if bit then unpack */
10116   if (IS_BITFIELD (retype)) {
10117       if (AOP_INDPTRn(left)) {
10118           genSetDPTR(AOP(left)->aopu.dptr);
10119       }
10120       genUnpackBits (result, "dptr", CPOINTER);
10121       if (AOP_INDPTRn(left)) {
10122           genSetDPTR(0);
10123       }
10124   } else
10125     {
10126       size = AOP_SIZE (result);
10127       offset = 0;
10128       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10129           while (size--) {
10130               genSetDPTR(AOP(left)->aopu.dptr);
10131               emitcode ("clr", "a");
10132               emitcode ("movc", "a,@a+dptr");
10133               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10134                   emitcode ("inc", "dptr");
10135               genSetDPTR (0);
10136               aopPut (AOP (result), "a", offset++);
10137           }
10138       } else {
10139           _startLazyDPSEvaluation ();
10140           while (size--)
10141               {
10142                   if (AOP_INDPTRn(left)) {
10143                       genSetDPTR(AOP(left)->aopu.dptr);
10144                   } else {
10145                       genSetDPTR (0);
10146                   }
10147                   _flushLazyDPS ();
10148
10149                   emitcode ("clr", "a");
10150                   emitcode ("movc", "a,@a+dptr");
10151                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10152                       emitcode ("inc", "dptr");
10153                   aopPut (AOP (result), "a", offset++);
10154               }
10155           _endLazyDPSEvaluation ();
10156       }
10157     }
10158   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10159       if (!AOP_INDPTRn(left)) {
10160           _startLazyDPSEvaluation ();
10161
10162           aopPut ( AOP (left), "dpl", 0);
10163           aopPut ( AOP (left), "dph", 1);
10164           if (options.model == MODEL_FLAT24)
10165               aopPut ( AOP (left), "dpx", 2);
10166
10167           _endLazyDPSEvaluation ();
10168       }
10169       pi->generated = 1;
10170   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10171              AOP_SIZE(result) > 1 &&
10172              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10173
10174       size = AOP_SIZE (result) - 1;
10175       if (AOP_INDPTRn(left)) {
10176           genSetDPTR(AOP(left)->aopu.dptr);
10177       }
10178       while (size--) emitcode ("lcall","__decdptr");
10179       if (AOP_INDPTRn(left)) {
10180           genSetDPTR(0);
10181       }
10182   }
10183
10184   freeAsmop (left, NULL, ic, TRUE);
10185   freeAsmop (result, NULL, ic, TRUE);
10186 }
10187
10188 /*-----------------------------------------------------------------*/
10189 /* genGenPointerGet - gget value from generic pointer space        */
10190 /*-----------------------------------------------------------------*/
10191 static void
10192 genGenPointerGet (operand * left,
10193                   operand * result, iCode * ic, iCode * pi)
10194 {
10195   int size, offset;
10196   sym_link *retype = getSpec (operandType (result));
10197   sym_link *letype = getSpec (operandType (left));
10198
10199   D (emitcode (";", "genGenPointerGet "); );
10200
10201   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10202
10203   /* if the operand is already in dptr
10204      then we do nothing else we move the value to dptr */
10205   if (AOP_TYPE (left) != AOP_STR)
10206     {
10207       /* if this is rematerializable */
10208       if (AOP_TYPE (left) == AOP_IMMD)
10209         {
10210           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
10211           if (AOP(left)->aopu.aop_immd.from_cast_remat)
10212             {
10213               MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10214             }
10215           else
10216             {
10217               emitcode ("mov", "b,#%d", pointerCode (retype));
10218             }
10219         }
10220       else
10221         {                       /* we need to get it byte by byte */
10222           _startLazyDPSEvaluation ();
10223           emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
10224           emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
10225           if (options.model == MODEL_FLAT24) {
10226               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10227               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
10228           } else {
10229               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
10230           }
10231           _endLazyDPSEvaluation ();
10232         }
10233     }
10234
10235   /* so dptr-b now contains the address */
10236   _G.bInUse++;
10237   aopOp (result, ic, FALSE, TRUE);
10238   _G.bInUse--;
10239
10240   /* if bit then unpack */
10241   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10242   {
10243     genUnpackBits (result, "dptr", GPOINTER);
10244   }
10245   else
10246     {
10247         size = AOP_SIZE (result);
10248         offset = 0;
10249
10250         while (size--)
10251         {
10252             if (size)
10253             {
10254                 // Get two bytes at a time, results in _AP & A.
10255                 // dptr will be incremented ONCE by __gptrgetWord.
10256                 //
10257                 // Note: any change here must be coordinated
10258                 // with the implementation of __gptrgetWord
10259                 // in device/lib/_gptrget.c
10260                 emitcode ("lcall", "__gptrgetWord");
10261                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
10262                 aopPut (AOP (result), "a", offset++);
10263                 size--;
10264             }
10265             else
10266             {
10267                 // Only one byte to get.
10268                 emitcode ("lcall", "__gptrget");
10269                 aopPut (AOP (result), "a", offset++);
10270             }
10271
10272             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10273             {
10274                 emitcode ("inc", "dptr");
10275             }
10276         }
10277     }
10278
10279   if (pi && AOP_TYPE (left) != AOP_IMMD) {
10280     _startLazyDPSEvaluation ();
10281
10282     aopPut ( AOP (left), "dpl", 0);
10283     aopPut ( AOP (left), "dph", 1);
10284     if (options.model == MODEL_FLAT24) {
10285         aopPut ( AOP (left), "dpx", 2);
10286         aopPut ( AOP (left), "b", 3);
10287     } else  aopPut ( AOP (left), "b", 2);
10288
10289     _endLazyDPSEvaluation ();
10290
10291     pi->generated = 1;
10292   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10293              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10294
10295       size = AOP_SIZE (result) - 1;
10296       while (size--) emitcode ("lcall","__decdptr");
10297   }
10298
10299   freeAsmop (left, NULL, ic, TRUE);
10300   freeAsmop (result, NULL, ic, TRUE);
10301 }
10302
10303 /*-----------------------------------------------------------------*/
10304 /* genPointerGet - generate code for pointer get                   */
10305 /*-----------------------------------------------------------------*/
10306 static void
10307 genPointerGet (iCode * ic, iCode *pi)
10308 {
10309   operand *left, *result;
10310   sym_link *type, *etype;
10311   int p_type;
10312
10313   D (emitcode (";", "genPointerGet ");
10314     );
10315
10316   left = IC_LEFT (ic);
10317   result = IC_RESULT (ic);
10318
10319   /* depending on the type of pointer we need to
10320      move it to the correct pointer register */
10321   type = operandType (left);
10322   etype = getSpec (type);
10323   /* if left is of type of pointer then it is simple */
10324   if (IS_PTR (type) && !IS_FUNC (type->next))
10325     p_type = DCL_TYPE (type);
10326   else
10327     {
10328       /* we have to go by the storage class */
10329       p_type = PTR_TYPE (SPEC_OCLS (etype));
10330     }
10331   /* special case when cast remat */
10332   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10333       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10334     {
10335       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10336       type = operandType (left);
10337       p_type = DCL_TYPE (type);
10338     }
10339   /* now that we have the pointer type we assign
10340      the pointer values */
10341   switch (p_type)
10342     {
10343
10344     case POINTER:
10345     case IPOINTER:
10346       genNearPointerGet (left, result, ic, pi);
10347       break;
10348
10349     case PPOINTER:
10350       genPagedPointerGet (left, result, ic, pi);
10351       break;
10352
10353     case FPOINTER:
10354       genFarPointerGet (left, result, ic, pi);
10355       break;
10356
10357     case CPOINTER:
10358       genCodePointerGet (left, result, ic, pi);
10359       break;
10360
10361     case GPOINTER:
10362       genGenPointerGet (left, result, ic, pi);
10363       break;
10364     }
10365
10366 }
10367
10368 /*-----------------------------------------------------------------*/
10369 /* genPackBits - generates code for packed bit storage             */
10370 /*-----------------------------------------------------------------*/
10371 static void
10372 genPackBits (sym_link * etype,
10373              operand * right,
10374              char *rname, int p_type)
10375 {
10376   int offset = 0;       /* source byte offset */
10377   int rlen = 0;         /* remaining bitfield length */
10378   int blen;             /* bitfield length */
10379   int bstr;             /* bitfield starting bit within byte */
10380   int litval;           /* source literal value (if AOP_LIT) */
10381   unsigned char mask;   /* bitmask within current byte */
10382
10383   D(emitcode (";     genPackBits",""));
10384
10385   blen = SPEC_BLEN (etype);
10386   bstr = SPEC_BSTR (etype);
10387
10388   /* If the bitfield length is less than a byte */
10389   if (blen < 8)
10390     {
10391       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10392               (unsigned char) (0xFF >> (8 - bstr)));
10393
10394       if (AOP_TYPE (right) == AOP_LIT)
10395         {
10396           /* Case with a bitfield length <8 and literal source
10397           */
10398           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10399           litval <<= bstr;
10400           litval &= (~mask) & 0xff;
10401           emitPtrByteGet (rname, p_type, FALSE);
10402           if ((mask|litval)!=0xff)
10403             emitcode ("anl","a,#!constbyte", mask);
10404           if (litval)
10405             emitcode ("orl","a,#!constbyte", litval);
10406         }
10407       else
10408         {
10409           if ((blen==1) && (p_type!=GPOINTER))
10410             {
10411               /* Case with a bitfield length == 1 and no generic pointer
10412               */
10413               if (AOP_TYPE (right) == AOP_CRY)
10414                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10415               else
10416                 {
10417                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10418                   emitcode ("rrc","a");
10419                 }
10420               emitPtrByteGet (rname, p_type, FALSE);
10421               emitcode ("mov","acc.%d,c",bstr);
10422             }
10423           else
10424             {
10425               /* Case with a bitfield length < 8 and arbitrary source
10426               */
10427               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
10428               /* shift and mask source value */
10429               AccLsh (bstr);
10430               emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10431
10432               /* transfer A to B and get next byte */
10433               emitPtrByteGet (rname, p_type, TRUE);
10434
10435               emitcode ("anl", "a,#!constbyte", mask);
10436               emitcode ("orl", "a,b");
10437               if (p_type == GPOINTER)
10438                 emitcode ("pop", "b");
10439            }
10440         }
10441
10442       emitPtrByteSet (rname, p_type, "a");
10443       return;
10444     }
10445
10446   /* Bit length is greater than 7 bits. In this case, copy  */
10447   /* all except the partial byte at the end                 */
10448   for (rlen=blen;rlen>=8;rlen-=8)
10449     {
10450       emitPtrByteSet (rname, p_type,
10451                       aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
10452       if (rlen>8)
10453         emitcode ("inc", "%s", rname);
10454     }
10455
10456   /* If there was a partial byte at the end */
10457   if (rlen)
10458     {
10459       mask = (((unsigned char) -1 << rlen) & 0xff);
10460
10461       if (AOP_TYPE (right) == AOP_LIT)
10462         {
10463           /* Case with partial byte and literal source
10464           */
10465           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10466           litval >>= (blen-rlen);
10467           litval &= (~mask) & 0xff;
10468           emitPtrByteGet (rname, p_type, FALSE);
10469           if ((mask|litval)!=0xff)
10470             emitcode ("anl","a,#!constbyte", mask);
10471           if (litval)
10472             emitcode ("orl","a,#!constbyte", litval);
10473         }
10474       else
10475         {
10476           /* Case with partial byte and arbitrary source
10477           */
10478           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10479           emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
10480
10481           /* transfer A to B and get next byte */
10482           emitPtrByteGet (rname, p_type, TRUE);
10483
10484           emitcode ("anl", "a,#!constbyte", mask);
10485           emitcode ("orl", "a,b");
10486           if (p_type == GPOINTER)
10487             emitcode ("pop", "b");
10488         }
10489       emitPtrByteSet (rname, p_type, "a");
10490     }
10491
10492 }
10493
10494
10495 /*-----------------------------------------------------------------*/
10496 /* genDataPointerSet - remat pointer to data space                 */
10497 /*-----------------------------------------------------------------*/
10498 static void
10499 genDataPointerSet (operand * right,
10500                    operand * result,
10501                    iCode * ic)
10502 {
10503   int size, offset = 0;
10504   char *l, buff[256];
10505
10506   aopOp (right, ic, FALSE, FALSE);
10507
10508   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
10509   size = AOP_SIZE (right);
10510   while (size--)
10511     {
10512       if (offset)
10513         {
10514             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
10515         }
10516       else
10517         {
10518             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
10519         }
10520
10521       emitcode ("mov", "%s,%s", buff,
10522                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10523     }
10524
10525   freeAsmop (right, NULL, ic, TRUE);
10526   freeAsmop (result, NULL, ic, TRUE);
10527 }
10528
10529 /*-----------------------------------------------------------------*/
10530 /* genNearPointerSet - emitcode for near pointer put                */
10531 /*-----------------------------------------------------------------*/
10532 static void
10533 genNearPointerSet (operand * right,
10534                    operand * result,
10535                    iCode * ic,
10536                    iCode * pi)
10537 {
10538   asmop *aop = NULL;
10539   char *rname, *l;
10540   sym_link *retype, *letype;
10541   sym_link *ptype = operandType (result);
10542
10543   retype = getSpec (operandType (right));
10544   letype = getSpec (ptype);
10545
10546   aopOp (result, ic, FALSE, FALSE);
10547
10548   /* if the result is rematerializable &
10549      in data space & not a bit variable */
10550   if (AOP_TYPE (result) == AOP_IMMD &&
10551       DCL_TYPE (ptype) == POINTER &&
10552       !IS_BITVAR (retype) &&
10553       !IS_BITVAR (letype))
10554     {
10555       genDataPointerSet (right, result, ic);
10556       return;
10557     }
10558
10559   /* if the value is already in a pointer register
10560      then don't need anything more */
10561   if (!AOP_INPREG (AOP (result)))
10562     {
10563       /* otherwise get a free pointer register */
10564       regs *preg;
10565
10566       aop = newAsmop (0);
10567       preg = getFreePtr (ic, &aop, FALSE);
10568       emitcode ("mov", "%s,%s",
10569                 preg->name,
10570                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10571       rname = preg->name;
10572     }
10573   else
10574     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10575
10576   aopOp (right, ic, FALSE, FALSE);
10577
10578   /* if bitfield then unpack the bits */
10579   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10580     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10581   else
10582     {
10583       /* we have can just get the values */
10584       int size = AOP_SIZE (right);
10585       int offset = 0;
10586
10587       while (size--)
10588         {
10589           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10590           if (*l == '@')
10591             {
10592               MOVA (l);
10593               emitcode ("mov", "@%s,a", rname);
10594             }
10595           else
10596             emitcode ("mov", "@%s,%s", rname, l);
10597           if (size || pi)
10598             emitcode ("inc", "%s", rname);
10599           offset++;
10600         }
10601     }
10602
10603   /* now some housekeeping stuff */
10604   if (aop)
10605     {
10606       /* we had to allocate for this iCode */
10607       if (pi) aopPut (AOP (result),rname,0);
10608       freeAsmop (NULL, aop, ic, TRUE);
10609     }
10610   else
10611     {
10612       /* we did not allocate which means left
10613          already in a pointer register, then
10614          if size > 0 && this could be used again
10615          we have to point it back to where it
10616          belongs */
10617       if (AOP_SIZE (right) > 1 &&
10618           !OP_SYMBOL (result)->remat &&
10619           (OP_SYMBOL (result)->liveTo > ic->seq ||
10620            ic->depth) &&
10621           !pi)
10622         {
10623           int size = AOP_SIZE (right) - 1;
10624           while (size--)
10625             emitcode ("dec", "%s", rname);
10626         }
10627     }
10628
10629   /* done */
10630   if (pi) pi->generated = 1;
10631   freeAsmop (result, NULL, ic, TRUE);
10632   freeAsmop (right, NULL, ic, TRUE);
10633
10634
10635 }
10636
10637 /*-----------------------------------------------------------------*/
10638 /* genPagedPointerSet - emitcode for Paged pointer put             */
10639 /*-----------------------------------------------------------------*/
10640 static void
10641 genPagedPointerSet (operand * right,
10642                     operand * result,
10643                     iCode * ic,
10644                     iCode *pi)
10645 {
10646   asmop *aop = NULL;
10647   char *rname;
10648   sym_link *retype, *letype;
10649
10650   retype = getSpec (operandType (right));
10651   letype = getSpec (operandType (result));
10652
10653   aopOp (result, ic, FALSE, FALSE);
10654
10655   /* if the value is already in a pointer register
10656      then don't need anything more */
10657   if (!AOP_INPREG (AOP (result)))
10658     {
10659       /* otherwise get a free pointer register */
10660       regs *preg;
10661
10662       aop = newAsmop (0);
10663       preg = getFreePtr (ic, &aop, FALSE);
10664       emitcode ("mov", "%s,%s",
10665                 preg->name,
10666                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10667       rname = preg->name;
10668     }
10669   else
10670     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10671
10672   aopOp (right, ic, FALSE, FALSE);
10673
10674   /* if bitfield then unpack the bits */
10675   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10676     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10677   else
10678     {
10679       /* we have can just get the values */
10680       int size = AOP_SIZE (right);
10681       int offset = 0;
10682
10683       while (size--)
10684         {
10685           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10686
10687           emitcode ("movx", "@%s,a", rname);
10688
10689           if (size || pi)
10690             emitcode ("inc", "%s", rname);
10691
10692           offset++;
10693         }
10694     }
10695
10696   /* now some housekeeping stuff */
10697   if (aop)
10698     {
10699       if (pi) aopPut (AOP (result),rname,0);
10700       /* we had to allocate for this iCode */
10701       freeAsmop (NULL, aop, ic, TRUE);
10702     }
10703   else
10704     {
10705       /* we did not allocate which means left
10706          already in a pointer register, then
10707          if size > 0 && this could be used again
10708          we have to point it back to where it
10709          belongs */
10710       if (AOP_SIZE (right) > 1 &&
10711           !OP_SYMBOL (result)->remat &&
10712           (OP_SYMBOL (result)->liveTo > ic->seq ||
10713            ic->depth) &&
10714           !pi)
10715         {
10716           int size = AOP_SIZE (right) - 1;
10717           while (size--)
10718             emitcode ("dec", "%s", rname);
10719         }
10720     }
10721
10722   /* done */
10723   if (pi) pi->generated = 1;
10724   freeAsmop (result, NULL, ic, TRUE);
10725   freeAsmop (right, NULL, ic, TRUE);
10726
10727
10728 }
10729
10730 /*-----------------------------------------------------------------*/
10731 /* genFarPointerSet - set value from far space                     */
10732 /*-----------------------------------------------------------------*/
10733 static void
10734 genFarPointerSet (operand * right,
10735                   operand * result, iCode * ic, iCode *pi)
10736 {
10737   int size, offset, dopi=1;
10738   sym_link *retype = getSpec (operandType (right));
10739   sym_link *letype = getSpec (operandType (result));
10740
10741   aopOp (result, ic, FALSE, FALSE);
10742
10743   /* if the operand is already in dptr
10744      then we do nothing else we move the value to dptr */
10745   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10746     {
10747       /* if this is remateriazable */
10748       if (AOP_TYPE (result) == AOP_IMMD)
10749         emitcode ("mov", "dptr,%s",
10750                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10751       else
10752         {
10753           /* we need to get it byte by byte */
10754           _startLazyDPSEvaluation ();
10755           if (AOP_TYPE (result) != AOP_DPTR)
10756             {
10757               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10758               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10759               if (options.model == MODEL_FLAT24)
10760                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10761             }
10762           else
10763             {
10764               /* We need to generate a load to DPTR indirect through DPTR. */
10765               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10766
10767               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10768               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10769               if (options.model == MODEL_FLAT24)
10770                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10771               emitcode ("pop", "dph");
10772               emitcode ("pop", "dpl");
10773               dopi=0;
10774             }
10775           _endLazyDPSEvaluation ();
10776         }
10777     }
10778   /* so dptr know contains the address */
10779   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10780
10781   /* if bit then unpack */
10782   if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10783       if (AOP_INDPTRn(result)) {
10784           genSetDPTR(AOP(result)->aopu.dptr);
10785       }
10786       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10787       if (AOP_INDPTRn(result)) {
10788           genSetDPTR(0);
10789       }
10790   } else {
10791       size = AOP_SIZE (right);
10792       offset = 0;
10793       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10794           while (size--) {
10795               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10796
10797               genSetDPTR(AOP(result)->aopu.dptr);
10798               emitcode ("movx", "@dptr,a");
10799               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10800                   emitcode ("inc", "dptr");
10801               genSetDPTR (0);
10802           }
10803       } else {
10804           _startLazyDPSEvaluation ();
10805           while (size--) {
10806               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10807
10808               if (AOP_INDPTRn(result)) {
10809                   genSetDPTR(AOP(result)->aopu.dptr);
10810               } else {
10811                   genSetDPTR (0);
10812               }
10813               _flushLazyDPS ();
10814
10815               emitcode ("movx", "@dptr,a");
10816               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10817                   emitcode ("inc", "dptr");
10818           }
10819           _endLazyDPSEvaluation ();
10820       }
10821   }
10822
10823   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10824       if (!AOP_INDPTRn(result)) {
10825           _startLazyDPSEvaluation ();
10826
10827           aopPut (AOP(result),"dpl",0);
10828           aopPut (AOP(result),"dph",1);
10829           if (options.model == MODEL_FLAT24)
10830               aopPut (AOP(result),"dpx",2);
10831
10832           _endLazyDPSEvaluation ();
10833       }
10834       pi->generated=1;
10835   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10836              AOP_SIZE(right) > 1 &&
10837              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10838
10839       size = AOP_SIZE (right) - 1;
10840       if (AOP_INDPTRn(result)) {
10841           genSetDPTR(AOP(result)->aopu.dptr);
10842       }
10843       while (size--) emitcode ("lcall","__decdptr");
10844       if (AOP_INDPTRn(result)) {
10845           genSetDPTR(0);
10846       }
10847   }
10848   freeAsmop (result, NULL, ic, TRUE);
10849   freeAsmop (right, NULL, ic, TRUE);
10850 }
10851
10852 /*-----------------------------------------------------------------*/
10853 /* genGenPointerSet - set value from generic pointer space         */
10854 /*-----------------------------------------------------------------*/
10855 static void
10856 genGenPointerSet (operand * right,
10857                   operand * result, iCode * ic, iCode *pi)
10858 {
10859   int size, offset;
10860   sym_link *retype = getSpec (operandType (right));
10861   sym_link *letype = getSpec (operandType (result));
10862
10863   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10864
10865   /* if the operand is already in dptr
10866      then we do nothing else we move the value to dptr */
10867   if (AOP_TYPE (result) != AOP_STR)
10868     {
10869       _startLazyDPSEvaluation ();
10870       /* if this is remateriazable */
10871       if (AOP_TYPE (result) == AOP_IMMD)
10872         {
10873           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10874           if (AOP(result)->aopu.aop_immd.from_cast_remat)
10875           {
10876               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10877           }
10878           else
10879           {
10880               emitcode ("mov",
10881                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10882           }
10883         }
10884       else
10885         {                       /* we need to get it byte by byte */
10886           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10887           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10888           if (options.model == MODEL_FLAT24) {
10889             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10890             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10891           } else {
10892             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10893           }
10894         }
10895       _endLazyDPSEvaluation ();
10896     }
10897   /* so dptr + b now contains the address */
10898   _G.bInUse++;
10899   aopOp (right, ic, FALSE, TRUE);
10900   _G.bInUse--;
10901
10902
10903   /* if bit then unpack */
10904   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10905     {
10906         genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10907     }
10908   else
10909     {
10910         size = AOP_SIZE (right);
10911         offset = 0;
10912
10913         _startLazyDPSEvaluation ();
10914         while (size--)
10915         {
10916             if (size)
10917             {
10918                 // Set two bytes at a time, passed in _AP & A.
10919                 // dptr will be incremented ONCE by __gptrputWord.
10920                 //
10921                 // Note: any change here must be coordinated
10922                 // with the implementation of __gptrputWord
10923                 // in device/lib/_gptrput.c
10924                 emitcode("mov", "_ap, %s",
10925                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10926                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10927
10928                 genSetDPTR (0);
10929                 _flushLazyDPS ();
10930                 emitcode ("lcall", "__gptrputWord");
10931                 size--;
10932             }
10933             else
10934             {
10935                 // Only one byte to put.
10936                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10937
10938                 genSetDPTR (0);
10939                 _flushLazyDPS ();
10940                 emitcode ("lcall", "__gptrput");
10941             }
10942
10943             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10944             {
10945                 emitcode ("inc", "dptr");
10946             }
10947         }
10948         _endLazyDPSEvaluation ();
10949     }
10950
10951   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10952       _startLazyDPSEvaluation ();
10953
10954       aopPut (AOP(result),"dpl",0);
10955       aopPut (AOP(result),"dph",1);
10956       if (options.model == MODEL_FLAT24) {
10957           aopPut (AOP(result),"dpx",2);
10958           aopPut (AOP(result),"b",3);
10959       } else {
10960           aopPut (AOP(result),"b",2);
10961       }
10962       _endLazyDPSEvaluation ();
10963
10964       pi->generated=1;
10965   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10966              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10967
10968       size = AOP_SIZE (right) - 1;
10969       while (size--) emitcode ("lcall","__decdptr");
10970   }
10971   freeAsmop (result, NULL, ic, TRUE);
10972   freeAsmop (right, NULL, ic, TRUE);
10973 }
10974
10975 /*-----------------------------------------------------------------*/
10976 /* genPointerSet - stores the value into a pointer location        */
10977 /*-----------------------------------------------------------------*/
10978 static void
10979 genPointerSet (iCode * ic, iCode *pi)
10980 {
10981   operand *right, *result;
10982   sym_link *type, *etype;
10983   int p_type;
10984
10985   D (emitcode (";", "genPointerSet "););
10986
10987   right = IC_RIGHT (ic);
10988   result = IC_RESULT (ic);
10989
10990   /* depending on the type of pointer we need to
10991      move it to the correct pointer register */
10992   type = operandType (result);
10993   etype = getSpec (type);
10994   /* if left is of type of pointer then it is simple */
10995   if (IS_PTR (type) && !IS_FUNC (type->next))
10996     {
10997       p_type = DCL_TYPE (type);
10998     }
10999   else
11000     {
11001       /* we have to go by the storage class */
11002       p_type = PTR_TYPE (SPEC_OCLS (etype));
11003     }
11004   /* special case when cast remat */
11005   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11006       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11007           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11008           type = operandType (result);
11009           p_type = DCL_TYPE (type);
11010   }
11011
11012   /* now that we have the pointer type we assign
11013      the pointer values */
11014   switch (p_type)
11015     {
11016
11017     case POINTER:
11018     case IPOINTER:
11019       genNearPointerSet (right, result, ic, pi);
11020       break;
11021
11022     case PPOINTER:
11023       genPagedPointerSet (right, result, ic, pi);
11024       break;
11025
11026     case FPOINTER:
11027       genFarPointerSet (right, result, ic, pi);
11028       break;
11029
11030     case GPOINTER:
11031       genGenPointerSet (right, result, ic, pi);
11032       break;
11033
11034     default:
11035       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11036               "genPointerSet: illegal pointer type");
11037     }
11038
11039 }
11040
11041 /*-----------------------------------------------------------------*/
11042 /* genIfx - generate code for Ifx statement                        */
11043 /*-----------------------------------------------------------------*/
11044 static void
11045 genIfx (iCode * ic, iCode * popIc)
11046 {
11047   operand *cond = IC_COND (ic);
11048   int isbit = 0;
11049
11050   D (emitcode (";", "genIfx "););
11051
11052   aopOp (cond, ic, FALSE, FALSE);
11053
11054   /* get the value into acc */
11055   if (AOP_TYPE (cond) != AOP_CRY)
11056     {
11057         toBoolean (cond);
11058     }
11059   else
11060     {
11061         isbit = 1;
11062     }
11063
11064   /* the result is now in the accumulator */
11065   freeAsmop (cond, NULL, ic, TRUE);
11066
11067   /* if there was something to be popped then do it */
11068   if (popIc)
11069     genIpop (popIc);
11070
11071   /* if the condition is  a bit variable */
11072   if (isbit && IS_ITEMP (cond) &&
11073       SPIL_LOC (cond))
11074     {
11075         genIfxJump (ic, SPIL_LOC (cond)->rname);
11076     }
11077   else if (isbit && !IS_ITEMP (cond))
11078     {
11079         genIfxJump (ic, OP_SYMBOL (cond)->rname);
11080     }
11081   else
11082     {
11083         genIfxJump (ic, "a");
11084     }
11085
11086   ic->generated = 1;
11087 }
11088
11089 /*-----------------------------------------------------------------*/
11090 /* genAddrOf - generates code for address of                       */
11091 /*-----------------------------------------------------------------*/
11092 static void
11093 genAddrOf (iCode * ic)
11094 {
11095   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11096   int size, offset;
11097
11098   D (emitcode (";", "genAddrOf ");
11099     );
11100
11101   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11102
11103   /* if the operand is on the stack then we
11104      need to get the stack offset of this
11105      variable */
11106   if (sym->onStack) {
11107
11108       /* if 10 bit stack */
11109       if (options.stack10bit) {
11110           char buff[10];
11111           int  offset;
11112
11113           tsprintf(buff, sizeof(buff),
11114                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
11115           /* if it has an offset then we need to compute it */
11116 /*        emitcode ("subb", "a,#!constbyte", */
11117 /*                  -((sym->stack < 0) ? */
11118 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
11119 /*                    ((short) sym->stack)) & 0xff); */
11120 /*        emitcode ("mov","b,a"); */
11121 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11122 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
11123 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
11124           if (sym->stack) {
11125               emitcode ("mov", "a,_bpx");
11126               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11127                                              ((char) (sym->stack - _G.nRegsSaved)) :
11128                                              ((char) sym->stack )) & 0xff);
11129               emitcode ("mov", "b,a");
11130               emitcode ("mov", "a,_bpx+1");
11131
11132               offset = (((sym->stack < 0) ?
11133                          ((short) (sym->stack - _G.nRegsSaved)) :
11134                          ((short) sym->stack )) >> 8) & 0xff;
11135
11136               emitcode ("addc","a,#!constbyte", offset);
11137
11138               aopPut (AOP (IC_RESULT (ic)), "b", 0);
11139               aopPut (AOP (IC_RESULT (ic)), "a", 1);
11140               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11141           } else {
11142               /* we can just move _bp */
11143               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
11144               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
11145               aopPut (AOP (IC_RESULT (ic)), buff, 2);
11146           }
11147       } else {
11148           /* if it has an offset then we need to compute it */
11149           if (sym->stack) {
11150               emitcode ("mov", "a,_bp");
11151               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11152               aopPut (AOP (IC_RESULT (ic)), "a", 0);
11153           } else {
11154               /* we can just move _bp */
11155               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
11156           }
11157           /* fill the result with zero */
11158           size = AOP_SIZE (IC_RESULT (ic)) - 1;
11159
11160
11161           if (options.stack10bit && size < (FPTRSIZE - 1)) {
11162               fprintf (stderr,
11163                        "*** warning: pointer to stack var truncated.\n");
11164           }
11165
11166           offset = 1;
11167           while (size--) {
11168               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
11169           }
11170       }
11171       goto release;
11172   }
11173
11174   /* object not on stack then we need the name */
11175   size = AOP_SIZE (IC_RESULT (ic));
11176   offset = 0;
11177
11178   while (size--)
11179     {
11180       char s[SDCC_NAME_MAX];
11181       if (offset) {
11182           switch (offset) {
11183           case 1:
11184               tsprintf(s, sizeof(s), "#!his",sym->rname);
11185               break;
11186           case 2:
11187               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11188               break;
11189           case 3:
11190               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11191               break;
11192           default: /* should not need this (just in case) */
11193               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11194                        sym->rname,
11195                        offset * 8);
11196           }
11197       }
11198       else
11199       {
11200           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11201       }
11202
11203       aopPut (AOP (IC_RESULT (ic)), s, offset++);
11204     }
11205
11206 release:
11207   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11208
11209 }
11210
11211 #if 0 // obsolete, and buggy for != xdata
11212 /*-----------------------------------------------------------------*/
11213 /* genArrayInit - generates code for address of                       */
11214 /*-----------------------------------------------------------------*/
11215 static void
11216 genArrayInit (iCode * ic)
11217 {
11218     literalList *iLoop;
11219     int         ix, count;
11220     int         elementSize = 0, eIndex;
11221     unsigned    val, lastVal;
11222     sym_link    *type;
11223     operand     *left=IC_LEFT(ic);
11224
11225     D (emitcode (";", "genArrayInit "););
11226
11227     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11228
11229     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11230     {
11231         // Load immediate value into DPTR.
11232         emitcode("mov", "dptr, %s",
11233              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
11234     }
11235     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11236     {
11237 #if 0
11238       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11239               "Unexpected operand to genArrayInit.\n");
11240       exit(1);
11241 #else
11242       // a regression because of SDCCcse.c:1.52
11243       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
11244       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
11245       if (options.model == MODEL_FLAT24)
11246         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
11247 #endif
11248     }
11249
11250     type = operandType(IC_LEFT(ic));
11251
11252     if (type && type->next)
11253     {
11254         elementSize = getSize(type->next);
11255     }
11256     else
11257     {
11258         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11259                                 "can't determine element size in genArrayInit.\n");
11260         exit(1);
11261     }
11262
11263     iLoop = IC_ARRAYILIST(ic);
11264     lastVal = 0xffff;
11265
11266     while (iLoop)
11267     {
11268         bool firstpass = TRUE;
11269
11270         emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11271                  iLoop->count, (int)iLoop->literalValue, elementSize);
11272
11273         ix = iLoop->count;
11274
11275         while (ix)
11276         {
11277             symbol *tlbl = NULL;
11278
11279             count = ix > 256 ? 256 : ix;
11280
11281             if (count > 1)
11282             {
11283                 tlbl = newiTempLabel (NULL);
11284                 if (firstpass || (count & 0xff))
11285                 {
11286                     emitcode("mov", "b, #!constbyte", count & 0xff);
11287                 }
11288
11289                 emitcode ("", "!tlabeldef", tlbl->key + 100);
11290             }
11291
11292             firstpass = FALSE;
11293
11294             for (eIndex = 0; eIndex < elementSize; eIndex++)
11295             {
11296                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11297                 if (val != lastVal)
11298                 {
11299                     emitcode("mov", "a, #!constbyte", val);
11300                     lastVal = val;
11301                 }
11302
11303                 emitcode("movx", "@dptr, a");
11304                 emitcode("inc", "dptr");
11305             }
11306
11307             if (count > 1)
11308             {
11309                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11310             }
11311
11312             ix -= count;
11313         }
11314
11315         iLoop = iLoop->next;
11316     }
11317
11318     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11319 }
11320 #endif
11321
11322 /*-----------------------------------------------------------------*/
11323 /* genFarFarAssign - assignment when both are in far space         */
11324 /*-----------------------------------------------------------------*/
11325 static void
11326 genFarFarAssign (operand * result, operand * right, iCode * ic)
11327 {
11328   int size = AOP_SIZE (right);
11329   int offset = 0;
11330   symbol *rSym = NULL;
11331
11332   if (size == 1)
11333   {
11334       /* quick & easy case. */
11335       D(emitcode(";","genFarFarAssign (1 byte case)"););
11336       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
11337       freeAsmop (right, NULL, ic, FALSE);
11338       /* now assign DPTR to result */
11339       _G.accInUse++;
11340       aopOp(result, ic, FALSE, FALSE);
11341       _G.accInUse--;
11342       aopPut(AOP(result), "a", 0);
11343       freeAsmop(result, NULL, ic, FALSE);
11344       return;
11345   }
11346
11347   /* See if we've got an underlying symbol to abuse. */
11348   if (IS_SYMOP(result) && OP_SYMBOL(result))
11349   {
11350       if (IS_TRUE_SYMOP(result))
11351       {
11352           rSym = OP_SYMBOL(result);
11353       }
11354       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11355       {
11356           rSym = OP_SYMBOL(result)->usl.spillLoc;
11357       }
11358   }
11359
11360   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11361   {
11362       /* We can use the '390 auto-toggle feature to good effect here. */
11363
11364       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11365       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
11366       emitcode ("mov", "dptr,#%s", rSym->rname);
11367       /* DP2 = result, DP1 = right, DP1 is current. */
11368       while (size)
11369       {
11370           emitcode("movx", "a,@dptr");
11371           emitcode("movx", "@dptr,a");
11372           if (--size)
11373           {
11374                emitcode("inc", "dptr");
11375                emitcode("inc", "dptr");
11376           }
11377       }
11378       emitcode("mov", "dps,#0");
11379       freeAsmop (right, NULL, ic, FALSE);
11380 #if 0
11381 some alternative code for processors without auto-toggle
11382 no time to test now, so later well put in...kpb
11383         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11384         emitcode("mov", "dps,#1");      /* Select DPTR2. */
11385         emitcode ("mov", "dptr,#%s", rSym->rname);
11386         /* DP2 = result, DP1 = right, DP1 is current. */
11387         while (size)
11388         {
11389           --size;
11390           emitcode("movx", "a,@dptr");
11391           if (size)
11392             emitcode("inc", "dptr");
11393           emitcode("inc", "dps");
11394           emitcode("movx", "@dptr,a");
11395           if (size)
11396             emitcode("inc", "dptr");
11397           emitcode("inc", "dps");
11398         }
11399         emitcode("mov", "dps,#0");
11400         freeAsmop (right, NULL, ic, FALSE);
11401 #endif
11402   }
11403   else
11404   {
11405       D (emitcode (";", "genFarFarAssign"););
11406       aopOp (result, ic, TRUE, TRUE);
11407
11408       _startLazyDPSEvaluation ();
11409
11410       while (size--)
11411         {
11412           aopPut (AOP (result),
11413                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
11414           offset++;
11415         }
11416       _endLazyDPSEvaluation ();
11417       freeAsmop (result, NULL, ic, FALSE);
11418       freeAsmop (right, NULL, ic, FALSE);
11419   }
11420 }
11421
11422 /*-----------------------------------------------------------------*/
11423 /* genAssign - generate code for assignment                        */
11424 /*-----------------------------------------------------------------*/
11425 static void
11426 genAssign (iCode * ic)
11427 {
11428   operand *result, *right;
11429   int size, offset;
11430   unsigned long lit = 0L;
11431
11432   D (emitcode (";", "genAssign ");
11433     );
11434
11435   result = IC_RESULT (ic);
11436   right = IC_RIGHT (ic);
11437
11438   /* if they are the same */
11439   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11440     return;
11441
11442   aopOp (right, ic, FALSE, FALSE);
11443
11444   emitcode (";", "genAssign: resultIsFar = %s",
11445             isOperandInFarSpace (result) ?
11446             "TRUE" : "FALSE");
11447
11448   /* special case both in far space */
11449   if ((AOP_TYPE (right) == AOP_DPTR ||
11450        AOP_TYPE (right) == AOP_DPTR2) &&
11451   /* IS_TRUE_SYMOP(result)       && */
11452       isOperandInFarSpace (result))
11453     {
11454       genFarFarAssign (result, right, ic);
11455       return;
11456     }
11457
11458   aopOp (result, ic, TRUE, FALSE);
11459
11460   /* if they are the same registers */
11461   if (sameRegs (AOP (right), AOP (result)))
11462     goto release;
11463
11464   /* if the result is a bit */
11465   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11466     {
11467       /* if the right size is a literal then
11468          we know what the value is */
11469       if (AOP_TYPE (right) == AOP_LIT)
11470         {
11471           if (((int) operandLitValue (right)))
11472             aopPut (AOP (result), one, 0);
11473           else
11474             aopPut (AOP (result), zero, 0);
11475           goto release;
11476         }
11477
11478       /* the right is also a bit variable */
11479       if (AOP_TYPE (right) == AOP_CRY)
11480         {
11481           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11482           aopPut (AOP (result), "c", 0);
11483           goto release;
11484         }
11485
11486       /* we need to or */
11487       toBoolean (right);
11488       aopPut (AOP (result), "a", 0);
11489       goto release;
11490     }
11491
11492   /* bit variables done */
11493   /* general case */
11494   size = AOP_SIZE (result);
11495   offset = 0;
11496   if (AOP_TYPE (right) == AOP_LIT)
11497     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11498
11499   if ((size > 1) &&
11500       (AOP_TYPE (result) != AOP_REG) &&
11501       (AOP_TYPE (right) == AOP_LIT) &&
11502       !IS_FLOAT (operandType (right)))
11503     {
11504       _startLazyDPSEvaluation ();
11505       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
11506         {
11507           aopPut (AOP (result),
11508                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11509                   offset);
11510           offset++;
11511           size--;
11512         }
11513       /* And now fill the rest with zeros. */
11514       if (size)
11515         {
11516           emitcode ("clr", "a");
11517         }
11518       while (size--)
11519         {
11520           aopPut (AOP (result), "a", offset++);
11521         }
11522       _endLazyDPSEvaluation ();
11523     }
11524   else
11525     {
11526       _startLazyDPSEvaluation ();
11527       while (size--)
11528         {
11529           aopPut (AOP (result),
11530                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11531                   offset);
11532           offset++;
11533         }
11534       _endLazyDPSEvaluation ();
11535     }
11536
11537 release:
11538   freeAsmop (right, NULL, ic, FALSE);
11539   freeAsmop (result, NULL, ic, TRUE);
11540 }
11541
11542 /*-----------------------------------------------------------------*/
11543 /* genJumpTab - generates code for jump table                      */
11544 /*-----------------------------------------------------------------*/
11545 static void
11546 genJumpTab (iCode * ic)
11547 {
11548   symbol *jtab;
11549   char *l;
11550
11551   D (emitcode (";", "genJumpTab ");
11552     );
11553
11554   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
11555   /* get the condition into accumulator */
11556   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
11557   MOVA (l);
11558   /* multiply by four! */
11559   emitcode ("add", "a,acc");
11560   emitcode ("add", "a,acc");
11561   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11562
11563   jtab = newiTempLabel (NULL);
11564   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11565   emitcode ("jmp", "@a+dptr");
11566   emitcode ("", "!tlabeldef", jtab->key + 100);
11567   /* now generate the jump labels */
11568   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11569        jtab = setNextItem (IC_JTLABELS (ic)))
11570     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11571
11572 }
11573
11574 /*-----------------------------------------------------------------*/
11575 /* genCast - gen code for casting                                  */
11576 /*-----------------------------------------------------------------*/
11577 static void
11578 genCast (iCode * ic)
11579 {
11580   operand *result = IC_RESULT (ic);
11581   sym_link *ctype = operandType (IC_LEFT (ic));
11582   sym_link *rtype = operandType (IC_RIGHT (ic));
11583   operand *right = IC_RIGHT (ic);
11584   int size, offset;
11585
11586   D (emitcode (";", "genCast "););
11587
11588   /* if they are equivalent then do nothing */
11589   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11590     return;
11591
11592   aopOp (right, ic, FALSE, AOP_IS_STR (result));
11593   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
11594
11595   /* if the result is a bit */
11596   if (IS_BITVAR (OP_SYMBOL (result)->type)
11597       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11598     {
11599       /* if the right size is a literal then
11600          we know what the value is */
11601       if (AOP_TYPE (right) == AOP_LIT)
11602         {
11603           if (((int) operandLitValue (right)))
11604             aopPut (AOP (result), one, 0);
11605           else
11606             aopPut (AOP (result), zero, 0);
11607
11608           goto release;
11609         }
11610
11611       /* the right is also a bit variable */
11612       if (AOP_TYPE (right) == AOP_CRY)
11613         {
11614           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11615           aopPut (AOP (result), "c", 0);
11616           goto release;
11617         }
11618
11619       /* we need to or */
11620       toBoolean (right);
11621       aopPut (AOP (result), "a", 0);
11622       goto release;
11623     }
11624
11625   /* if they are the same size : or less */
11626   if (AOP_SIZE (result) <= AOP_SIZE (right))
11627     {
11628
11629       /* if they are in the same place */
11630       if (sameRegs (AOP (right), AOP (result)))
11631         goto release;
11632
11633       /* if they in different places then copy */
11634       size = AOP_SIZE (result);
11635       offset = 0;
11636       _startLazyDPSEvaluation ();
11637       while (size--)
11638         {
11639           aopPut (AOP (result),
11640                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11641                   offset);
11642           offset++;
11643         }
11644       _endLazyDPSEvaluation ();
11645       goto release;
11646     }
11647
11648
11649   /* if the result is of type pointer */
11650   if (IS_PTR (ctype))
11651     {
11652
11653       int p_type;
11654       sym_link *type = operandType (right);
11655
11656       /* pointer to generic pointer */
11657       if (IS_GENPTR (ctype))
11658         {
11659           if (IS_PTR (type))
11660             {
11661               p_type = DCL_TYPE (type);
11662             }
11663           else
11664             {
11665 #if OLD_CAST_BEHAVIOR
11666               /* KV: we are converting a non-pointer type to
11667                * a generic pointer. This (ifdef'd out) code
11668                * says that the resulting generic pointer
11669                * should have the same class as the storage
11670                * location of the non-pointer variable.
11671                *
11672                * For example, converting an int (which happens
11673                * to be stored in DATA space) to a pointer results
11674                * in a DATA generic pointer; if the original int
11675                * in XDATA space, so will be the resulting pointer.
11676                *
11677                * I don't like that behavior, and thus this change:
11678                * all such conversions will be forced to XDATA and
11679                * throw a warning. If you want some non-XDATA
11680                * type, or you want to suppress the warning, you
11681                * must go through an intermediate cast, like so:
11682                *
11683                * char _generic *gp = (char _xdata *)(intVar);
11684                */
11685               sym_link *etype = getSpec (type);
11686
11687               /* we have to go by the storage class */
11688               if (SPEC_OCLS (etype) != generic)
11689                 {
11690                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11691                 }
11692               else
11693 #endif
11694                 {
11695                   /* Converting unknown class (i.e. register variable)
11696                    * to generic pointer. This is not good, but
11697                    * we'll make a guess (and throw a warning).
11698                    */
11699                   p_type = FPOINTER;
11700                   werror (W_INT_TO_GEN_PTR_CAST);
11701                 }
11702             }
11703
11704           /* the first two bytes are known */
11705           size = GPTRSIZE - 1;
11706           offset = 0;
11707           _startLazyDPSEvaluation ();
11708           while (size--)
11709             {
11710               aopPut (AOP (result),
11711                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11712                       offset);
11713               offset++;
11714             }
11715           _endLazyDPSEvaluation ();
11716
11717           /* the last byte depending on type */
11718             {
11719                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11720                 char gpValStr[10];
11721
11722                 if (gpVal == -1)
11723                 {
11724                     // pointerTypeToGPByte will have bitched.
11725                     exit(1);
11726                 }
11727
11728                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11729                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11730             }
11731           goto release;
11732         }
11733
11734       /* just copy the pointers */
11735       size = AOP_SIZE (result);
11736       offset = 0;
11737       _startLazyDPSEvaluation ();
11738       while (size--)
11739         {
11740           aopPut (AOP (result),
11741                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11742                   offset);
11743           offset++;
11744         }
11745       _endLazyDPSEvaluation ();
11746       goto release;
11747     }
11748
11749   /* so we now know that the size of destination is greater
11750      than the size of the source */
11751   /* we move to result for the size of source */
11752   size = AOP_SIZE (right);
11753   offset = 0;
11754   _startLazyDPSEvaluation ();
11755   while (size--)
11756     {
11757       aopPut (AOP (result),
11758               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11759               offset);
11760       offset++;
11761     }
11762   _endLazyDPSEvaluation ();
11763
11764   /* now depending on the sign of the source && destination */
11765   size = AOP_SIZE (result) - AOP_SIZE (right);
11766   /* if unsigned or not an integral type */
11767   /* also, if the source is a bit, we don't need to sign extend, because
11768    * it can't possibly have set the sign bit.
11769    */
11770   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11771     {
11772       while (size--)
11773         {
11774           aopPut (AOP (result), zero, offset++);
11775         }
11776     }
11777   else
11778     {
11779       /* we need to extend the sign :{ */
11780       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11781                         FALSE, FALSE, NULL));
11782       emitcode ("rlc", "a");
11783       emitcode ("subb", "a,acc");
11784       while (size--)
11785         aopPut (AOP (result), "a", offset++);
11786     }
11787
11788   /* we are done hurray !!!! */
11789
11790 release:
11791   freeAsmop (right, NULL, ic, TRUE);
11792   freeAsmop (result, NULL, ic, TRUE);
11793
11794 }
11795
11796 /*-----------------------------------------------------------------*/
11797 /* genDjnz - generate decrement & jump if not zero instrucion      */
11798 /*-----------------------------------------------------------------*/
11799 static int
11800 genDjnz (iCode * ic, iCode * ifx)
11801 {
11802   symbol *lbl, *lbl1;
11803   if (!ifx)
11804     return 0;
11805
11806   /* if the if condition has a false label
11807      then we cannot save */
11808   if (IC_FALSE (ifx))
11809     return 0;
11810
11811   /* if the minus is not of the form
11812      a = a - 1 */
11813   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11814       !IS_OP_LITERAL (IC_RIGHT (ic)))
11815     return 0;
11816
11817   if (operandLitValue (IC_RIGHT (ic)) != 1)
11818     return 0;
11819
11820   /* if the size of this greater than one then no
11821      saving */
11822   if (getSize (operandType (IC_RESULT (ic))) > 1)
11823     return 0;
11824
11825   /* otherwise we can save BIG */
11826   D(emitcode(";", "genDjnz"););
11827
11828   lbl = newiTempLabel (NULL);
11829   lbl1 = newiTempLabel (NULL);
11830
11831   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11832
11833   if (AOP_NEEDSACC(IC_RESULT(ic)))
11834   {
11835       /* If the result is accessed indirectly via
11836        * the accumulator, we must explicitly write
11837        * it back after the decrement.
11838        */
11839       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11840
11841       if (strcmp(rByte, "a"))
11842       {
11843            /* Something is hopelessly wrong */
11844            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11845                    __FILE__, __LINE__);
11846            /* We can just give up; the generated code will be inefficient,
11847             * but what the hey.
11848             */
11849            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11850            return 0;
11851       }
11852       emitcode ("dec", "%s", rByte);
11853       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11854       emitcode ("jnz", "!tlabel", lbl->key + 100);
11855   }
11856   else if (IS_AOP_PREG (IC_RESULT (ic)))
11857     {
11858       emitcode ("dec", "%s",
11859                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11860       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11861       emitcode ("jnz", "!tlabel", lbl->key + 100);
11862     }
11863   else
11864     {
11865       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11866                 lbl->key + 100);
11867     }
11868   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11869   emitcode ("", "!tlabeldef", lbl->key + 100);
11870   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11871   emitcode ("", "!tlabeldef", lbl1->key + 100);
11872
11873   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11874   ifx->generated = 1;
11875   return 1;
11876 }
11877
11878 /*-----------------------------------------------------------------*/
11879 /* genReceive - generate code for a receive iCode                  */
11880 /*-----------------------------------------------------------------*/
11881 static void
11882 genReceive (iCode * ic)
11883 {
11884     int size = getSize (operandType (IC_RESULT (ic)));
11885     int offset = 0;
11886     int rb1off ;
11887
11888     D (emitcode (";", "genReceive "););
11889
11890     if (ic->argreg == 1)
11891     {
11892         /* first parameter */
11893         if (AOP_IS_STR(IC_RESULT(ic)))
11894         {
11895             /* Nothing to do: it's already in the proper place. */
11896             return;
11897         }
11898         else
11899         {
11900             bool useDp2;
11901
11902             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11903                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11904                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11905
11906             _G.accInUse++;
11907             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11908             _G.accInUse--;
11909
11910             /* Sanity checking... */
11911             if (AOP_USESDPTR(IC_RESULT(ic)))
11912             {
11913                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11914                         "genReceive got unexpected DPTR.");
11915             }
11916             assignResultValue (IC_RESULT (ic));
11917         }
11918     }
11919     else
11920     {
11921         /* second receive onwards */
11922         /* this gets a little tricky since unused recevies will be
11923          eliminated, we have saved the reg in the type field . and
11924          we use that to figure out which register to use */
11925         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11926         rb1off = ic->argreg;
11927         while (size--)
11928         {
11929             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11930         }
11931     }
11932     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11933 }
11934
11935 /*-----------------------------------------------------------------*/
11936 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11937 /*-----------------------------------------------------------------*/
11938 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11939 {
11940     operand *from , *to , *count;
11941     symbol *lbl;
11942     bitVect *rsave;
11943     int i;
11944
11945     /* we know it has to be 3 parameters */
11946     assert (nparms == 3);
11947
11948     rsave = newBitVect(16);
11949     /* save DPTR if it needs to be saved */
11950     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11951             if (bitVectBitValue(ic->rMask,i))
11952                     rsave = bitVectSetBit(rsave,i);
11953     }
11954     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11955                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11956     savermask(rsave);
11957
11958     to = parms[0];
11959     from = parms[1];
11960     count = parms[2];
11961
11962     aopOp (from, ic->next, FALSE, FALSE);
11963
11964     /* get from into DPTR1 */
11965     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11966     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11967     if (options.model == MODEL_FLAT24) {
11968         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11969     }
11970
11971     freeAsmop (from, NULL, ic, FALSE);
11972     aopOp (to, ic, FALSE, FALSE);
11973     /* get "to" into DPTR */
11974     /* if the operand is already in dptr
11975        then we do nothing else we move the value to dptr */
11976     if (AOP_TYPE (to) != AOP_STR) {
11977         /* if already in DPTR then we need to push */
11978         if (AOP_TYPE(to) == AOP_DPTR) {
11979             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11980             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11981             if (options.model == MODEL_FLAT24)
11982                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11983             emitcode ("pop", "dph");
11984             emitcode ("pop", "dpl");
11985         } else {
11986             _startLazyDPSEvaluation ();
11987             /* if this is remateriazable */
11988             if (AOP_TYPE (to) == AOP_IMMD) {
11989                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11990             } else {                    /* we need to get it byte by byte */
11991                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11992                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11993                 if (options.model == MODEL_FLAT24) {
11994                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11995                 }
11996             }
11997             _endLazyDPSEvaluation ();
11998         }
11999     }
12000     freeAsmop (to, NULL, ic, FALSE);
12001     _G.dptrInUse = _G.dptr1InUse = 1;
12002     aopOp (count, ic->next->next, FALSE,FALSE);
12003     lbl =newiTempLabel(NULL);
12004
12005     /* now for the actual copy */
12006     if (AOP_TYPE(count) == AOP_LIT &&
12007         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12008         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12009         if (fromc) {
12010             emitcode ("lcall","__bi_memcpyc2x_s");
12011         } else {
12012             emitcode ("lcall","__bi_memcpyx2x_s");
12013         }
12014         freeAsmop (count, NULL, ic, FALSE);
12015     } else {
12016         symbol *lbl1 = newiTempLabel(NULL);
12017
12018         emitcode (";"," Auto increment but no djnz");
12019         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12020         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12021         freeAsmop (count, NULL, ic, FALSE);
12022         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
12023         emitcode ("","!tlabeldef",lbl->key+100);
12024         if (fromc) {
12025             emitcode ("clr","a");
12026             emitcode ("movc", "a,@a+dptr");
12027         } else
12028             emitcode ("movx", "a,@dptr");
12029         emitcode ("movx", "@dptr,a");
12030         emitcode ("inc", "dptr");
12031         emitcode ("inc", "dptr");
12032         emitcode ("mov","a,b");
12033         emitcode ("orl","a,_ap");
12034         emitcode ("jz","!tlabel",lbl1->key+100);
12035         emitcode ("mov","a,_ap");
12036         emitcode ("add","a,#!constbyte",0xFF);
12037         emitcode ("mov","_ap,a");
12038         emitcode ("mov","a,b");
12039         emitcode ("addc","a,#!constbyte",0xFF);
12040         emitcode ("mov","b,a");
12041         emitcode ("sjmp","!tlabel",lbl->key+100);
12042         emitcode ("","!tlabeldef",lbl1->key+100);
12043     }
12044     emitcode ("mov", "dps,#0");
12045     _G.dptrInUse = _G.dptr1InUse = 0;
12046     unsavermask(rsave);
12047
12048 }
12049
12050 /*-----------------------------------------------------------------*/
12051 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
12052 /*-----------------------------------------------------------------*/
12053 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12054 {
12055     operand *from , *to , *count;
12056     symbol *lbl,*lbl2;
12057     bitVect *rsave;
12058     int i;
12059
12060     /* we know it has to be 3 parameters */
12061     assert (nparms == 3);
12062
12063     rsave = newBitVect(16);
12064     /* save DPTR if it needs to be saved */
12065     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12066             if (bitVectBitValue(ic->rMask,i))
12067                     rsave = bitVectSetBit(rsave,i);
12068     }
12069     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12070                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12071     savermask(rsave);
12072
12073     to = parms[0];
12074     from = parms[1];
12075     count = parms[2];
12076
12077     aopOp (from, ic->next, FALSE, FALSE);
12078
12079     /* get from into DPTR1 */
12080     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12081     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12082     if (options.model == MODEL_FLAT24) {
12083         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12084     }
12085
12086     freeAsmop (from, NULL, ic, FALSE);
12087     aopOp (to, ic, FALSE, FALSE);
12088     /* get "to" into DPTR */
12089     /* if the operand is already in dptr
12090        then we do nothing else we move the value to dptr */
12091     if (AOP_TYPE (to) != AOP_STR) {
12092         /* if already in DPTR then we need to push */
12093         if (AOP_TYPE(to) == AOP_DPTR) {
12094             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12095             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12096             if (options.model == MODEL_FLAT24)
12097                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12098             emitcode ("pop", "dph");
12099             emitcode ("pop", "dpl");
12100         } else {
12101             _startLazyDPSEvaluation ();
12102             /* if this is remateriazable */
12103             if (AOP_TYPE (to) == AOP_IMMD) {
12104                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12105             } else {                    /* we need to get it byte by byte */
12106                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12107                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12108                 if (options.model == MODEL_FLAT24) {
12109                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12110                 }
12111             }
12112             _endLazyDPSEvaluation ();
12113         }
12114     }
12115     freeAsmop (to, NULL, ic, FALSE);
12116     _G.dptrInUse = _G.dptr1InUse = 1;
12117     aopOp (count, ic->next->next, FALSE,FALSE);
12118     lbl =newiTempLabel(NULL);
12119     lbl2 =newiTempLabel(NULL);
12120
12121     /* now for the actual compare */
12122     if (AOP_TYPE(count) == AOP_LIT &&
12123         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12124         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12125         if (fromc)
12126             emitcode("lcall","__bi_memcmpc2x_s");
12127         else
12128             emitcode("lcall","__bi_memcmpx2x_s");
12129         freeAsmop (count, NULL, ic, FALSE);
12130         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12131         aopPut(AOP(IC_RESULT(ic)),"a",0);
12132         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12133     } else {
12134         symbol *lbl1 = newiTempLabel(NULL);
12135
12136         emitcode("push","ar0");
12137         emitcode (";"," Auto increment but no djnz");
12138         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12139         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12140         freeAsmop (count, NULL, ic, FALSE);
12141         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
12142         emitcode ("","!tlabeldef",lbl->key+100);
12143         if (fromc) {
12144             emitcode ("clr","a");
12145             emitcode ("movc", "a,@a+dptr");
12146         } else
12147             emitcode ("movx", "a,@dptr");
12148         emitcode ("mov","r0,a");
12149         emitcode ("movx", "a,@dptr");
12150         emitcode ("clr","c");
12151         emitcode ("subb","a,r0");
12152         emitcode ("jnz","!tlabel",lbl2->key+100);
12153         emitcode ("inc", "dptr");
12154         emitcode ("inc", "dptr");
12155         emitcode ("mov","a,b");
12156         emitcode ("orl","a,_ap");
12157         emitcode ("jz","!tlabel",lbl1->key+100);
12158         emitcode ("mov","a,_ap");
12159         emitcode ("add","a,#!constbyte",0xFF);
12160         emitcode ("mov","_ap,a");
12161         emitcode ("mov","a,b");
12162         emitcode ("addc","a,#!constbyte",0xFF);
12163         emitcode ("mov","b,a");
12164         emitcode ("sjmp","!tlabel",lbl->key+100);
12165         emitcode ("","!tlabeldef",lbl1->key+100);
12166         emitcode ("clr","a");
12167         emitcode ("","!tlabeldef",lbl2->key+100);
12168         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12169         aopPut(AOP(IC_RESULT(ic)),"a",0);
12170         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12171         emitcode("pop","ar0");
12172         emitcode ("mov", "dps,#0");
12173     }
12174     _G.dptrInUse = _G.dptr1InUse = 0;
12175     unsavermask(rsave);
12176
12177 }
12178
12179 /*-----------------------------------------------------------------*/
12180 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12181 /* port, first parameter output area second parameter pointer to   */
12182 /* port third parameter count                                      */
12183 /*-----------------------------------------------------------------*/
12184 static void genInp( iCode *ic, int nparms, operand **parms)
12185 {
12186     operand *from , *to , *count;
12187     symbol *lbl;
12188     bitVect *rsave;
12189     int i;
12190
12191     /* we know it has to be 3 parameters */
12192     assert (nparms == 3);
12193
12194     rsave = newBitVect(16);
12195     /* save DPTR if it needs to be saved */
12196     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12197             if (bitVectBitValue(ic->rMask,i))
12198                     rsave = bitVectSetBit(rsave,i);
12199     }
12200     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12201                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12202     savermask(rsave);
12203
12204     to = parms[0];
12205     from = parms[1];
12206     count = parms[2];
12207
12208     aopOp (from, ic->next, FALSE, FALSE);
12209
12210     /* get from into DPTR1 */
12211     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12212     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12213     if (options.model == MODEL_FLAT24) {
12214         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12215     }
12216
12217     freeAsmop (from, NULL, ic, FALSE);
12218     aopOp (to, ic, FALSE, FALSE);
12219     /* get "to" into DPTR */
12220     /* if the operand is already in dptr
12221        then we do nothing else we move the value to dptr */
12222     if (AOP_TYPE (to) != AOP_STR) {
12223         /* if already in DPTR then we need to push */
12224         if (AOP_TYPE(to) == AOP_DPTR) {
12225             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12226             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12227             if (options.model == MODEL_FLAT24)
12228                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12229             emitcode ("pop", "dph");
12230             emitcode ("pop", "dpl");
12231         } else {
12232             _startLazyDPSEvaluation ();
12233             /* if this is remateriazable */
12234             if (AOP_TYPE (to) == AOP_IMMD) {
12235                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12236             } else {                    /* we need to get it byte by byte */
12237                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12238                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12239                 if (options.model == MODEL_FLAT24) {
12240                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12241                 }
12242             }
12243             _endLazyDPSEvaluation ();
12244         }
12245     }
12246     freeAsmop (to, NULL, ic, FALSE);
12247
12248     _G.dptrInUse = _G.dptr1InUse = 1;
12249     aopOp (count, ic->next->next, FALSE,FALSE);
12250     lbl =newiTempLabel(NULL);
12251
12252     /* now for the actual copy */
12253     if (AOP_TYPE(count) == AOP_LIT &&
12254         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12255         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12256         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12257         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12258         freeAsmop (count, NULL, ic, FALSE);
12259         emitcode ("","!tlabeldef",lbl->key+100);
12260         emitcode ("movx", "a,@dptr");   /* read data from port */
12261         emitcode ("dec","dps");         /* switch to DPTR */
12262         emitcode ("movx", "@dptr,a");   /* save into location */
12263         emitcode ("inc", "dptr");       /* point to next area */
12264         emitcode ("inc","dps");         /* switch to DPTR2 */
12265         emitcode ("djnz","b,!tlabel",lbl->key+100);
12266     } else {
12267         symbol *lbl1 = newiTempLabel(NULL);
12268
12269         emitcode (";"," Auto increment but no djnz");
12270         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12271         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12272         freeAsmop (count, NULL, ic, FALSE);
12273         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
12274         emitcode ("","!tlabeldef",lbl->key+100);
12275         emitcode ("movx", "a,@dptr");
12276         emitcode ("dec","dps");         /* switch to DPTR */
12277         emitcode ("movx", "@dptr,a");
12278         emitcode ("inc", "dptr");
12279         emitcode ("inc","dps");         /* switch to DPTR2 */
12280 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
12281 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12282         emitcode ("mov","a,b");
12283         emitcode ("orl","a,_ap");
12284         emitcode ("jz","!tlabel",lbl1->key+100);
12285         emitcode ("mov","a,_ap");
12286         emitcode ("add","a,#!constbyte",0xFF);
12287         emitcode ("mov","_ap,a");
12288         emitcode ("mov","a,b");
12289         emitcode ("addc","a,#!constbyte",0xFF);
12290         emitcode ("mov","b,a");
12291         emitcode ("sjmp","!tlabel",lbl->key+100);
12292         emitcode ("","!tlabeldef",lbl1->key+100);
12293     }
12294     emitcode ("mov", "dps,#0");
12295     _G.dptrInUse = _G.dptr1InUse = 0;
12296     unsavermask(rsave);
12297
12298 }
12299
12300 /*-----------------------------------------------------------------*/
12301 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12302 /* port, first parameter output area second parameter pointer to   */
12303 /* port third parameter count                                      */
12304 /*-----------------------------------------------------------------*/
12305 static void genOutp( iCode *ic, int nparms, operand **parms)
12306 {
12307     operand *from , *to , *count;
12308     symbol *lbl;
12309     bitVect *rsave;
12310     int i;
12311
12312     /* we know it has to be 3 parameters */
12313     assert (nparms == 3);
12314
12315     rsave = newBitVect(16);
12316     /* save DPTR if it needs to be saved */
12317     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12318             if (bitVectBitValue(ic->rMask,i))
12319                     rsave = bitVectSetBit(rsave,i);
12320     }
12321     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12322                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12323     savermask(rsave);
12324
12325     to = parms[0];
12326     from = parms[1];
12327     count = parms[2];
12328
12329     aopOp (from, ic->next, FALSE, FALSE);
12330
12331     /* get from into DPTR1 */
12332     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
12333     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
12334     if (options.model == MODEL_FLAT24) {
12335         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
12336     }
12337
12338     freeAsmop (from, NULL, ic, FALSE);
12339     aopOp (to, ic, FALSE, FALSE);
12340     /* get "to" into DPTR */
12341     /* if the operand is already in dptr
12342        then we do nothing else we move the value to dptr */
12343     if (AOP_TYPE (to) != AOP_STR) {
12344         /* if already in DPTR then we need to push */
12345         if (AOP_TYPE(to) == AOP_DPTR) {
12346             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12347             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12348             if (options.model == MODEL_FLAT24)
12349                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12350             emitcode ("pop", "dph");
12351             emitcode ("pop", "dpl");
12352         } else {
12353             _startLazyDPSEvaluation ();
12354             /* if this is remateriazable */
12355             if (AOP_TYPE (to) == AOP_IMMD) {
12356                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12357             } else {                    /* we need to get it byte by byte */
12358                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12359                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12360                 if (options.model == MODEL_FLAT24) {
12361                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12362                 }
12363             }
12364             _endLazyDPSEvaluation ();
12365         }
12366     }
12367     freeAsmop (to, NULL, ic, FALSE);
12368
12369     _G.dptrInUse = _G.dptr1InUse = 1;
12370     aopOp (count, ic->next->next, FALSE,FALSE);
12371     lbl =newiTempLabel(NULL);
12372
12373     /* now for the actual copy */
12374     if (AOP_TYPE(count) == AOP_LIT &&
12375         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12376         emitcode (";","OH  JOY auto increment with djnz (very fast)");
12377         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12378         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12379         emitcode ("","!tlabeldef",lbl->key+100);
12380         emitcode ("movx", "a,@dptr");   /* read data from port */
12381         emitcode ("inc","dps");         /* switch to DPTR2 */
12382         emitcode ("movx", "@dptr,a");   /* save into location */
12383         emitcode ("inc", "dptr");       /* point to next area */
12384         emitcode ("dec","dps");         /* switch to DPTR */
12385         emitcode ("djnz","b,!tlabel",lbl->key+100);
12386         freeAsmop (count, NULL, ic, FALSE);
12387     } else {
12388         symbol *lbl1 = newiTempLabel(NULL);
12389
12390         emitcode (";"," Auto increment but no djnz");
12391         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12392         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12393         freeAsmop (count, NULL, ic, FALSE);
12394         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
12395         emitcode ("","!tlabeldef",lbl->key+100);
12396         emitcode ("movx", "a,@dptr");
12397         emitcode ("inc", "dptr");
12398         emitcode ("inc","dps");         /* switch to DPTR2 */
12399         emitcode ("movx", "@dptr,a");
12400         emitcode ("dec","dps");         /* switch to DPTR */
12401         emitcode ("mov","a,b");
12402         emitcode ("orl","a,_ap");
12403         emitcode ("jz","!tlabel",lbl1->key+100);
12404         emitcode ("mov","a,_ap");
12405         emitcode ("add","a,#!constbyte",0xFF);
12406         emitcode ("mov","_ap,a");
12407         emitcode ("mov","a,b");
12408         emitcode ("addc","a,#!constbyte",0xFF);
12409         emitcode ("mov","b,a");
12410         emitcode ("sjmp","!tlabel",lbl->key+100);
12411         emitcode ("","!tlabeldef",lbl1->key+100);
12412     }
12413     emitcode ("mov", "dps,#0");
12414     _G.dptrInUse = _G.dptr1InUse = 0;
12415     unsavermask(rsave);
12416
12417 }
12418
12419 /*-----------------------------------------------------------------*/
12420 /* genSwapW - swap lower & high order bytes                        */
12421 /*-----------------------------------------------------------------*/
12422 static void genSwapW(iCode *ic, int nparms, operand **parms)
12423 {
12424     operand *dest;
12425     operand *src;
12426     assert (nparms==1);
12427
12428     src = parms[0];
12429     dest=IC_RESULT(ic);
12430
12431     assert(getSize(operandType(src))==2);
12432
12433     aopOp (src, ic, FALSE, FALSE);
12434     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
12435     _G.accInUse++;
12436     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
12437     _G.accInUse--;
12438     freeAsmop (src, NULL, ic, FALSE);
12439
12440     aopOp (dest,ic, FALSE, FALSE);
12441     aopPut(AOP(dest),"b",0);
12442     aopPut(AOP(dest),"a",1);
12443     freeAsmop (dest, NULL, ic, FALSE);
12444 }
12445
12446 /*-----------------------------------------------------------------*/
12447 /* genMemsetX - gencode for memSetX data                           */
12448 /*-----------------------------------------------------------------*/
12449 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12450 {
12451     operand *to , *val , *count;
12452     symbol *lbl;
12453     char *l;
12454     int i;
12455     bitVect *rsave;
12456
12457     /* we know it has to be 3 parameters */
12458     assert (nparms == 3);
12459
12460     to = parms[0];
12461     val = parms[1];
12462     count = parms[2];
12463
12464     /* save DPTR if it needs to be saved */
12465     rsave = newBitVect(16);
12466     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12467             if (bitVectBitValue(ic->rMask,i))
12468                     rsave = bitVectSetBit(rsave,i);
12469     }
12470     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12471                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
12472     savermask(rsave);
12473
12474     aopOp (to, ic, FALSE, FALSE);
12475     /* get "to" into DPTR */
12476     /* if the operand is already in dptr
12477        then we do nothing else we move the value to dptr */
12478     if (AOP_TYPE (to) != AOP_STR) {
12479         /* if already in DPTR then we need to push */
12480         if (AOP_TYPE(to) == AOP_DPTR) {
12481             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
12482             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
12483             if (options.model == MODEL_FLAT24)
12484                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12485             emitcode ("pop", "dph");
12486             emitcode ("pop", "dpl");
12487         } else {
12488             _startLazyDPSEvaluation ();
12489             /* if this is remateriazable */
12490             if (AOP_TYPE (to) == AOP_IMMD) {
12491                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
12492             } else {                    /* we need to get it byte by byte */
12493                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
12494                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
12495                 if (options.model == MODEL_FLAT24) {
12496                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
12497                 }
12498             }
12499             _endLazyDPSEvaluation ();
12500         }
12501     }
12502     freeAsmop (to, NULL, ic, FALSE);
12503
12504     aopOp (val, ic->next->next, FALSE,FALSE);
12505     aopOp (count, ic->next->next, FALSE,FALSE);
12506     lbl =newiTempLabel(NULL);
12507     /* now for the actual copy */
12508     if (AOP_TYPE(count) == AOP_LIT &&
12509         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12510         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
12511         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
12512         MOVA(l);
12513         emitcode ("","!tlabeldef",lbl->key+100);
12514         emitcode ("movx", "@dptr,a");
12515         emitcode ("inc", "dptr");
12516         emitcode ("djnz","b,!tlabel",lbl->key+100);
12517     } else {
12518         symbol *lbl1 = newiTempLabel(NULL);
12519
12520         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
12521         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
12522         emitcode ("","!tlabeldef",lbl->key+100);
12523         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
12524         emitcode ("movx", "@dptr,a");
12525         emitcode ("inc", "dptr");
12526         emitcode ("mov","a,b");
12527         emitcode ("orl","a,_ap");
12528         emitcode ("jz","!tlabel",lbl1->key+100);
12529         emitcode ("mov","a,_ap");
12530         emitcode ("add","a,#!constbyte",0xFF);
12531         emitcode ("mov","_ap,a");
12532         emitcode ("mov","a,b");
12533         emitcode ("addc","a,#!constbyte",0xFF);
12534         emitcode ("mov","b,a");
12535         emitcode ("sjmp","!tlabel",lbl->key+100);
12536         emitcode ("","!tlabeldef",lbl1->key+100);
12537     }
12538     freeAsmop (count, NULL, ic, FALSE);
12539     unsavermask(rsave);
12540 }
12541
12542 /*-----------------------------------------------------------------*/
12543 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
12544 /*-----------------------------------------------------------------*/
12545 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
12546 {
12547         bitVect *rsave ;
12548         operand *pnum, *result;
12549         int i;
12550
12551         assert (nparms==1);
12552         /* save registers that need to be saved */
12553         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12554                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12555
12556         pnum = parms[0];
12557         aopOp (pnum, ic, FALSE, FALSE);
12558         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12559         freeAsmop (pnum, NULL, ic, FALSE);
12560         emitcode ("lcall","NatLib_LoadPrimitive");
12561         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12562         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12563             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12564                 for (i = (size-1) ; i >= 0 ; i-- ) {
12565                         emitcode ("push","a%s",javaRet[i]);
12566                 }
12567                 for (i=0; i < size ; i++ ) {
12568                         emitcode ("pop","a%s",
12569                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12570                 }
12571         } else {
12572                 for (i = 0 ; i < size ; i++ ) {
12573                         aopPut(AOP(result),javaRet[i],i);
12574                 }
12575         }
12576         freeAsmop (result, NULL, ic, FALSE);
12577         unsavermask(rsave);
12578 }
12579
12580 /*-----------------------------------------------------------------*/
12581 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12582 /*-----------------------------------------------------------------*/
12583 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12584 {
12585         bitVect *rsave ;
12586         operand *pnum, *result;
12587         int size = 3;
12588         int i;
12589
12590         assert (nparms==1);
12591         /* save registers that need to be saved */
12592         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12593                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12594
12595         pnum = parms[0];
12596         aopOp (pnum, ic, FALSE, FALSE);
12597         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12598         freeAsmop (pnum, NULL, ic, FALSE);
12599         emitcode ("lcall","NatLib_LoadPointer");
12600         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12601         if (AOP_TYPE(result)!=AOP_STR) {
12602                 for (i = 0 ; i < size ; i++ ) {
12603                         aopPut(AOP(result),fReturn[i],i);
12604                 }
12605         }
12606         freeAsmop (result, NULL, ic, FALSE);
12607         unsavermask(rsave);
12608 }
12609
12610 /*-----------------------------------------------------------------*/
12611 /* genNatLibInstallStateBlock -                                    */
12612 /*-----------------------------------------------------------------*/
12613 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12614                                        operand **parms, const char *name)
12615 {
12616         bitVect *rsave ;
12617         operand *psb, *handle;
12618         assert (nparms==2);
12619
12620         /* save registers that need to be saved */
12621         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12622                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12623         psb = parms[0];
12624         handle = parms[1];
12625
12626         /* put pointer to state block into DPTR1 */
12627         aopOp (psb, ic, FALSE, FALSE);
12628         if (AOP_TYPE (psb) == AOP_IMMD) {
12629                 emitcode ("mov","dps,#1");
12630                 emitcode ("mov", "dptr,%s",
12631                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12632                 emitcode ("mov","dps,#0");
12633         } else {
12634                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12635                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12636                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12637         }
12638         freeAsmop (psb, NULL, ic, FALSE);
12639
12640         /* put libraryID into DPTR */
12641         emitcode ("mov","dptr,#LibraryID");
12642
12643         /* put handle into r3:r2 */
12644         aopOp (handle, ic, FALSE, FALSE);
12645         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12646                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12647                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12648                 emitcode ("pop","ar3");
12649                 emitcode ("pop","ar2");
12650         } else {
12651                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12652                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12653         }
12654         freeAsmop (psb, NULL, ic, FALSE);
12655
12656         /* make the call */
12657         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12658
12659         /* put return value into place*/
12660         _G.accInUse++;
12661         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12662         _G.accInUse--;
12663         aopPut(AOP(IC_RESULT(ic)),"a",0);
12664         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12665         unsavermask(rsave);
12666 }
12667
12668 /*-----------------------------------------------------------------*/
12669 /* genNatLibRemoveStateBlock -                                     */
12670 /*-----------------------------------------------------------------*/
12671 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12672 {
12673         bitVect *rsave ;
12674
12675         assert(nparms==0);
12676
12677         /* save registers that need to be saved */
12678         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12679                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12680
12681         /* put libraryID into DPTR */
12682         emitcode ("mov","dptr,#LibraryID");
12683         /* make the call */
12684         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12685         unsavermask(rsave);
12686 }
12687
12688 /*-----------------------------------------------------------------*/
12689 /* genNatLibGetStateBlock -                                        */
12690 /*-----------------------------------------------------------------*/
12691 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12692                                    operand **parms,const char *name)
12693 {
12694         bitVect *rsave ;
12695         symbol *lbl = newiTempLabel(NULL);
12696
12697         assert(nparms==0);
12698         /* save registers that need to be saved */
12699         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12700                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12701
12702         /* put libraryID into DPTR */
12703         emitcode ("mov","dptr,#LibraryID");
12704         /* make the call */
12705         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12706         emitcode ("jnz","!tlabel",lbl->key+100);
12707
12708         /* put return value into place */
12709         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12710         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12711                 emitcode ("push","ar3");
12712                 emitcode ("push","ar2");
12713                 emitcode ("pop","%s",
12714                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12715                 emitcode ("pop","%s",
12716                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12717         } else {
12718                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12719                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12720         }
12721         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12722         emitcode ("","!tlabeldef",lbl->key+100);
12723         unsavermask(rsave);
12724 }
12725
12726 /*-----------------------------------------------------------------*/
12727 /* genMMMalloc -                                                   */
12728 /*-----------------------------------------------------------------*/
12729 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12730                          int size, const char *name)
12731 {
12732         bitVect *rsave ;
12733         operand *bsize;
12734         symbol *rsym;
12735         symbol *lbl = newiTempLabel(NULL);
12736
12737         assert (nparms == 1);
12738         /* save registers that need to be saved */
12739         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12740                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12741
12742         bsize=parms[0];
12743         aopOp (bsize,ic,FALSE,FALSE);
12744
12745         /* put the size in R4-R2 */
12746         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12747                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12748                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12749                 if (size==3) {
12750                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12751                         emitcode("pop","ar4");
12752                 }
12753                 emitcode("pop","ar3");
12754                 emitcode("pop","ar2");
12755         } else {
12756                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12757                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12758                 if (size==3) {
12759                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12760                 }
12761         }
12762         freeAsmop (bsize, NULL, ic, FALSE);
12763
12764         /* make the call */
12765         emitcode ("lcall","MM_%s",name);
12766         emitcode ("jz","!tlabel",lbl->key+100);
12767         emitcode ("mov","r2,#!constbyte",0xff);
12768         emitcode ("mov","r3,#!constbyte",0xff);
12769         emitcode ("","!tlabeldef",lbl->key+100);
12770         /* we don't care about the pointer : we just save the handle */
12771         rsym = OP_SYMBOL(IC_RESULT(ic));
12772         if (rsym->liveFrom != rsym->liveTo) {
12773                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12774                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12775                         emitcode ("push","ar3");
12776                         emitcode ("push","ar2");
12777                         emitcode ("pop","%s",
12778                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12779                         emitcode ("pop","%s",
12780                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12781                 } else {
12782                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12783                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12784                 }
12785                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12786         }
12787         unsavermask(rsave);
12788 }
12789
12790 /*-----------------------------------------------------------------*/
12791 /* genMMDeref -                                                    */
12792 /*-----------------------------------------------------------------*/
12793 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12794 {
12795         bitVect *rsave ;
12796         operand *handle;
12797
12798         assert (nparms == 1);
12799         /* save registers that need to be saved */
12800         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12801                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12802
12803         handle=parms[0];
12804         aopOp (handle,ic,FALSE,FALSE);
12805
12806         /* put the size in R4-R2 */
12807         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12808                 emitcode("push","%s",
12809                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12810                 emitcode("push","%s",
12811                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12812                 emitcode("pop","ar3");
12813                 emitcode("pop","ar2");
12814         } else {
12815                 emitcode ("mov","r2,%s",
12816                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12817                 emitcode ("mov","r3,%s",
12818                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12819         }
12820         freeAsmop (handle, NULL, ic, FALSE);
12821
12822         /* make the call */
12823         emitcode ("lcall","MM_Deref");
12824
12825         {
12826                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12827                 if (rsym->liveFrom != rsym->liveTo) {
12828                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12829                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12830                             _startLazyDPSEvaluation ();
12831
12832                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12833                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12834                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12835
12836                             _endLazyDPSEvaluation ();
12837
12838                         }
12839                 }
12840         }
12841         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12842         unsavermask(rsave);
12843 }
12844
12845 /*-----------------------------------------------------------------*/
12846 /* genMMUnrestrictedPersist -                                      */
12847 /*-----------------------------------------------------------------*/
12848 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12849 {
12850         bitVect *rsave ;
12851         operand *handle;
12852
12853         assert (nparms == 1);
12854         /* save registers that need to be saved */
12855         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12856                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12857
12858         handle=parms[0];
12859         aopOp (handle,ic,FALSE,FALSE);
12860
12861         /* put the size in R3-R2 */
12862         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12863                 emitcode("push","%s",
12864                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12865                 emitcode("push","%s",
12866                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12867                 emitcode("pop","ar3");
12868                 emitcode("pop","ar2");
12869         } else {
12870                 emitcode ("mov","r2,%s",
12871                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12872                 emitcode ("mov","r3,%s",
12873                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12874         }
12875         freeAsmop (handle, NULL, ic, FALSE);
12876
12877         /* make the call */
12878         emitcode ("lcall","MM_UnrestrictedPersist");
12879
12880         {
12881                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12882                 if (rsym->liveFrom != rsym->liveTo) {
12883                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12884                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12885                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12886                 }
12887         }
12888         unsavermask(rsave);
12889 }
12890
12891 /*-----------------------------------------------------------------*/
12892 /* genSystemExecJavaProcess -                                      */
12893 /*-----------------------------------------------------------------*/
12894 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12895 {
12896         bitVect *rsave ;
12897         operand *handle, *pp;
12898
12899         assert (nparms==2);
12900         /* save registers that need to be saved */
12901         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12902                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12903
12904         pp = parms[0];
12905         handle = parms[1];
12906
12907         /* put the handle in R3-R2 */
12908         aopOp (handle,ic,FALSE,FALSE);
12909         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12910                 emitcode("push","%s",
12911                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12912                 emitcode("push","%s",
12913                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12914                 emitcode("pop","ar3");
12915                 emitcode("pop","ar2");
12916         } else {
12917                 emitcode ("mov","r2,%s",
12918                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12919                 emitcode ("mov","r3,%s",
12920                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12921         }
12922         freeAsmop (handle, NULL, ic, FALSE);
12923
12924         /* put pointer in DPTR */
12925         aopOp (pp,ic,FALSE,FALSE);
12926         if (AOP_TYPE(pp) == AOP_IMMD) {
12927                 emitcode ("mov", "dptr,%s",
12928                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12929         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12930                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12931                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12932                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12933         }
12934         freeAsmop (handle, NULL, ic, FALSE);
12935
12936         /* make the call */
12937         emitcode ("lcall","System_ExecJavaProcess");
12938
12939         /* put result in place */
12940         {
12941                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12942                 if (rsym->liveFrom != rsym->liveTo) {
12943                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12944                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12945                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12946                 }
12947         }
12948
12949         unsavermask(rsave);
12950 }
12951
12952 /*-----------------------------------------------------------------*/
12953 /* genSystemRTCRegisters -                                         */
12954 /*-----------------------------------------------------------------*/
12955 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12956                                   char *name)
12957 {
12958         bitVect *rsave ;
12959         operand *pp;
12960
12961         assert (nparms==1);
12962         /* save registers that need to be saved */
12963         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12964                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12965
12966         pp=parms[0];
12967         /* put pointer in DPTR */
12968         aopOp (pp,ic,FALSE,FALSE);
12969         if (AOP_TYPE (pp) == AOP_IMMD) {
12970                 emitcode ("mov","dps,#1");
12971                 emitcode ("mov", "dptr,%s",
12972                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12973                 emitcode ("mov","dps,#0");
12974         } else {
12975                 emitcode ("mov","dpl1,%s",
12976                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12977                 emitcode ("mov","dph1,%s",
12978                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12979                 emitcode ("mov","dpx1,%s",
12980                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12981         }
12982         freeAsmop (pp, NULL, ic, FALSE);
12983
12984         /* make the call */
12985         emitcode ("lcall","System_%sRTCRegisters",name);
12986
12987         unsavermask(rsave);
12988 }
12989
12990 /*-----------------------------------------------------------------*/
12991 /* genSystemThreadSleep -                                          */
12992 /*-----------------------------------------------------------------*/
12993 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12994 {
12995         bitVect *rsave ;
12996         operand *to, *s;
12997
12998         assert (nparms==1);
12999         /* save registers that need to be saved */
13000         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13001                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13002
13003         to = parms[0];
13004         aopOp(to,ic,FALSE,FALSE);
13005         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13006             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13007                 emitcode ("push","%s",
13008                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13009                 emitcode ("push","%s",
13010                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13011                 emitcode ("push","%s",
13012                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13013                 emitcode ("push","%s",
13014                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13015                 emitcode ("pop","ar3");
13016                 emitcode ("pop","ar2");
13017                 emitcode ("pop","ar1");
13018                 emitcode ("pop","ar0");
13019         } else {
13020                 emitcode ("mov","r0,%s",
13021                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
13022                 emitcode ("mov","r1,%s",
13023                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
13024                 emitcode ("mov","r2,%s",
13025                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
13026                 emitcode ("mov","r3,%s",
13027                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
13028         }
13029         freeAsmop (to, NULL, ic, FALSE);
13030
13031         /* suspend in acc */
13032         s = parms[1];
13033         aopOp(s,ic,FALSE,FALSE);
13034         emitcode ("mov","a,%s",
13035                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
13036         freeAsmop (s, NULL, ic, FALSE);
13037
13038         /* make the call */
13039         emitcode ("lcall","System_%s",name);
13040
13041         unsavermask(rsave);
13042 }
13043
13044 /*-----------------------------------------------------------------*/
13045 /* genSystemThreadResume -                                         */
13046 /*-----------------------------------------------------------------*/
13047 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13048 {
13049         bitVect *rsave ;
13050         operand *tid,*pid;
13051
13052         assert (nparms==2);
13053         /* save registers that need to be saved */
13054         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13055                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13056
13057         tid = parms[0];
13058         pid = parms[1];
13059
13060         /* PID in R0 */
13061         aopOp(pid,ic,FALSE,FALSE);
13062         emitcode ("mov","r0,%s",
13063                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13064         freeAsmop (pid, NULL, ic, FALSE);
13065
13066         /* tid into ACC */
13067         aopOp(tid,ic,FALSE,FALSE);
13068         emitcode ("mov","a,%s",
13069                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
13070         freeAsmop (tid, NULL, ic, FALSE);
13071
13072         emitcode ("lcall","System_ThreadResume");
13073
13074         /* put result into place */
13075         {
13076                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13077                 if (rsym->liveFrom != rsym->liveTo) {
13078                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13079                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13080                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13081                 }
13082         }
13083         unsavermask(rsave);
13084 }
13085
13086 /*-----------------------------------------------------------------*/
13087 /* genSystemProcessResume -                                        */
13088 /*-----------------------------------------------------------------*/
13089 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13090 {
13091         bitVect *rsave ;
13092         operand *pid;
13093
13094         assert (nparms==1);
13095         /* save registers that need to be saved */
13096         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13097                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13098
13099         pid = parms[0];
13100
13101         /* pid into ACC */
13102         aopOp(pid,ic,FALSE,FALSE);
13103         emitcode ("mov","a,%s",
13104                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
13105         freeAsmop (pid, NULL, ic, FALSE);
13106
13107         emitcode ("lcall","System_ProcessResume");
13108
13109         unsavermask(rsave);
13110 }
13111
13112 /*-----------------------------------------------------------------*/
13113 /* genSystem -                                                     */
13114 /*-----------------------------------------------------------------*/
13115 static void genSystem (iCode *ic,int nparms,char *name)
13116 {
13117         assert(nparms == 0);
13118
13119         emitcode ("lcall","System_%s",name);
13120 }
13121
13122 /*-----------------------------------------------------------------*/
13123 /* genSystemPoll -                                                  */
13124 /*-----------------------------------------------------------------*/
13125 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13126 {
13127         bitVect *rsave ;
13128         operand *fp;
13129
13130         assert (nparms==1);
13131         /* save registers that need to be saved */
13132         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13133                                          ds390_rUmaskForOp (IC_RESULT(ic))));
13134
13135         fp = parms[0];
13136         aopOp (fp,ic,FALSE,FALSE);
13137         if (AOP_TYPE (fp) == AOP_IMMD) {
13138                 emitcode ("mov", "dptr,%s",
13139                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
13140         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13141                 emitcode ("mov","dpl,%s",
13142                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
13143                 emitcode ("mov","dph,%s",
13144                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
13145                 emitcode ("mov","dpx,%s",
13146                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
13147         }
13148         freeAsmop (fp, NULL, ic, FALSE);
13149
13150         emitcode ("lcall","System_%sPoll",name);
13151
13152         /* put result into place */
13153         {
13154                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13155                 if (rsym->liveFrom != rsym->liveTo) {
13156                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13157                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13158                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13159                 }
13160         }
13161         unsavermask(rsave);
13162 }
13163
13164 /*-----------------------------------------------------------------*/
13165 /* genSystemGetCurrentID -                                         */
13166 /*-----------------------------------------------------------------*/
13167 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13168 {
13169         assert (nparms==0);
13170
13171         emitcode ("lcall","System_GetCurrent%sId",name);
13172         /* put result into place */
13173         {
13174                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13175                 if (rsym->liveFrom != rsym->liveTo) {
13176                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13177                         aopPut(AOP(IC_RESULT(ic)),"a",0);
13178                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13179                 }
13180         }
13181 }
13182
13183 /*-----------------------------------------------------------------*/
13184 /* genDummyRead - generate code for dummy read of volatiles        */
13185 /*-----------------------------------------------------------------*/
13186 static void
13187 genDummyRead (iCode * ic)
13188 {
13189   operand *op;
13190   int size, offset;
13191
13192   D(emitcode(";     genDummyRead",""));
13193
13194   op = IC_RIGHT (ic);
13195   if (op && IS_SYMOP (op))
13196     {
13197       aopOp (op, ic, FALSE, FALSE);
13198
13199       /* if the result is a bit */
13200       if (AOP_TYPE (op) == AOP_CRY)
13201         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13202       else
13203         {
13204           /* bit variables done */
13205           /* general case */
13206           size = AOP_SIZE (op);
13207           offset = 0;
13208           while (size--)
13209           {
13210             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13211             offset++;
13212           }
13213         }
13214
13215       freeAsmop (op, NULL, ic, TRUE);
13216     }
13217
13218   op = IC_LEFT (ic);
13219   if (op && IS_SYMOP (op))
13220     {
13221       aopOp (op, ic, FALSE, FALSE);
13222
13223       /* if the result is a bit */
13224       if (AOP_TYPE (op) == AOP_CRY)
13225         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13226       else
13227         {
13228           /* bit variables done */
13229           /* general case */
13230           size = AOP_SIZE (op);
13231           offset = 0;
13232           while (size--)
13233           {
13234             MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE));
13235             offset++;
13236           }
13237         }
13238
13239       freeAsmop (op, NULL, ic, TRUE);
13240     }
13241
13242 }
13243
13244 /*-----------------------------------------------------------------*/
13245 /* genCritical - generate code for start of a critical sequence    */
13246 /*-----------------------------------------------------------------*/
13247 static void
13248 genCritical (iCode *ic)
13249 {
13250   symbol *tlbl = newiTempLabel (NULL);
13251
13252   D(emitcode(";     genCritical",""));
13253
13254   if (IC_RESULT (ic))
13255     aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13256
13257   emitcode ("setb", "c");
13258   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13259   emitcode ("clr", "c");
13260   emitcode ("", "%05d$:", (tlbl->key + 100));
13261
13262   if (IC_RESULT (ic))
13263     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13264   else
13265     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13266
13267   if (IC_RESULT (ic))
13268     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13269 }
13270
13271 /*-----------------------------------------------------------------*/
13272 /* genEndCritical - generate code for end of a critical sequence   */
13273 /*-----------------------------------------------------------------*/
13274 static void
13275 genEndCritical (iCode *ic)
13276 {
13277   D(emitcode(";     genEndCritical",""));
13278
13279   if (IC_RIGHT (ic))
13280     {
13281       aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13282       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13283         {
13284           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13285           emitcode ("mov", "ea,c");
13286         }
13287       else
13288         {
13289           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
13290           emitcode ("rrc", "a");
13291           emitcode ("mov", "ea,c");
13292         }
13293       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13294     }
13295   else
13296     {
13297       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13298       emitcode ("mov", "ea,c");
13299     }
13300 }
13301
13302
13303
13304 /*-----------------------------------------------------------------*/
13305 /* genBuiltIn - calls the appropriate function to  generating code */
13306 /* for a built in function                                         */
13307 /*-----------------------------------------------------------------*/
13308 static void genBuiltIn (iCode *ic)
13309 {
13310         operand *bi_parms[MAX_BUILTIN_ARGS];
13311         int nbi_parms;
13312         iCode *bi_iCode;
13313         symbol *bif;
13314
13315         /* get all the arguments for a built in function */
13316         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13317
13318         /* which function is it */
13319         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13320         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13321                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13322         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13323                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13324         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13325                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13326         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13327                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13328         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13329                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13330         } else if (strcmp(bif->name,"__builtin_inp")==0) {
13331                 genInp(bi_iCode,nbi_parms,bi_parms);
13332         } else if (strcmp(bif->name,"__builtin_outp")==0) {
13333                 genOutp(bi_iCode,nbi_parms,bi_parms);
13334         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13335                 genSwapW(bi_iCode,nbi_parms,bi_parms);
13336                 /* JavaNative builtIns */
13337         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13338                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13339         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13340                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13341         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13342                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13343         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13344                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13345         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13346                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13347         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13348                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13349         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13350                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13351         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13352                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13353         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13354                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13355         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13356                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13357         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13358                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13359         } else if (strcmp(bif->name,"MM_Malloc")==0) {
13360                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13361         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13362                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13363         } else if (strcmp(bif->name,"MM_Free")==0) {
13364                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13365         } else if (strcmp(bif->name,"MM_Deref")==0) {
13366                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13367         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13368                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13369         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13370                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13371         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13372                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13373         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13374                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13375         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13376                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13377         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13378                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13379         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13380                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13381         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13382                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13383         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13384                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13385         } else if (strcmp(bif->name,"System_SaveThread")==0) {
13386                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13387         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13388                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13389         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13390                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
13391         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
13392                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
13393         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
13394                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
13395         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
13396                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
13397         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
13398                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
13399         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
13400                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
13401         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
13402                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
13403         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
13404                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
13405         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
13406                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
13407         } else {
13408                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
13409                 return ;
13410         }
13411         return ;
13412 }
13413
13414 /*-----------------------------------------------------------------*/
13415 /* gen390Code - generate code for Dallas 390 based controllers     */
13416 /*-----------------------------------------------------------------*/
13417 void
13418 gen390Code (iCode * lic)
13419 {
13420   iCode *ic;
13421   int cln = 0;
13422
13423   lineHead = lineCurr = NULL;
13424   dptrn[1][0] = "dpl1";
13425   dptrn[1][1] = "dph1";
13426   dptrn[1][2] = "dpx1";
13427
13428   if (options.model == MODEL_FLAT24) {
13429     fReturnSizeDS390 = 5;
13430     fReturn = fReturn24;
13431   } else {
13432     fReturnSizeDS390 = 4;
13433     fReturn = fReturn16;
13434     options.stack10bit=0;
13435   }
13436 #if 1
13437   /* print the allocation information */
13438   if (allocInfo && currFunc)
13439     printAllocInfo (currFunc, codeOutFile);
13440 #endif
13441   /* if debug information required */
13442   if (options.debug && currFunc)
13443     {
13444       debugFile->writeFunction (currFunc, lic);
13445     }
13446   /* stack pointer name */
13447   if (options.useXstack)
13448     spname = "_spx";
13449   else
13450     spname = "sp";
13451
13452
13453   for (ic = lic; ic; ic = ic->next)
13454     {
13455       _G.current_iCode = ic;
13456
13457       if (ic->lineno && cln != ic->lineno)
13458         {
13459           if (options.debug)
13460             {
13461               debugFile->writeCLine (ic);
13462             }
13463           if (!options.noCcodeInAsm) {
13464             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
13465                       printCLine(ic->filename, ic->lineno));
13466           }
13467           cln = ic->lineno;
13468         }
13469       if (options.iCodeInAsm) {
13470         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
13471       }
13472       /* if the result is marked as
13473          spilt and rematerializable or code for
13474          this has already been generated then
13475          do nothing */
13476       if (resultRemat (ic) || ic->generated)
13477         continue;
13478
13479       /* depending on the operation */
13480       switch (ic->op)
13481         {
13482         case '!':
13483           genNot (ic);
13484           break;
13485
13486         case '~':
13487           genCpl (ic);
13488           break;
13489
13490         case UNARYMINUS:
13491           genUminus (ic);
13492           break;
13493
13494         case IPUSH:
13495           genIpush (ic);
13496           break;
13497
13498         case IPOP:
13499           /* IPOP happens only when trying to restore a
13500              spilt live range, if there is an ifx statement
13501              following this pop then the if statement might
13502              be using some of the registers being popped which
13503              would destory the contents of the register so
13504              we need to check for this condition and handle it */
13505           if (ic->next &&
13506               ic->next->op == IFX &&
13507               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
13508             genIfx (ic->next, ic);
13509           else
13510             genIpop (ic);
13511           break;
13512
13513         case CALL:
13514           genCall (ic);
13515           break;
13516
13517         case PCALL:
13518           genPcall (ic);
13519           break;
13520
13521         case FUNCTION:
13522           genFunction (ic);
13523           break;
13524
13525         case ENDFUNCTION:
13526           genEndFunction (ic);
13527           break;
13528
13529         case RETURN:
13530           genRet (ic);
13531           break;
13532
13533         case LABEL:
13534           genLabel (ic);
13535           break;
13536
13537         case GOTO:
13538           genGoto (ic);
13539           break;
13540
13541         case '+':
13542           genPlus (ic);
13543           break;
13544
13545         case '-':
13546           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
13547             genMinus (ic);
13548           break;
13549
13550         case '*':
13551           genMult (ic);
13552           break;
13553
13554         case '/':
13555           genDiv (ic);
13556           break;
13557
13558         case '%':
13559           genMod (ic);
13560           break;
13561
13562         case '>':
13563           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
13564           break;
13565
13566         case '<':
13567           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
13568           break;
13569
13570         case LE_OP:
13571         case GE_OP:
13572         case NE_OP:
13573
13574           /* note these two are xlated by algebraic equivalence
13575              during parsing SDCC.y */
13576           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13577                   "got '>=' or '<=' shouldn't have come here");
13578           break;
13579
13580         case EQ_OP:
13581           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
13582           break;
13583
13584         case AND_OP:
13585           genAndOp (ic);
13586           break;
13587
13588         case OR_OP:
13589           genOrOp (ic);
13590           break;
13591
13592         case '^':
13593           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
13594           break;
13595
13596         case '|':
13597           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
13598           break;
13599
13600         case BITWISEAND:
13601           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
13602           break;
13603
13604         case INLINEASM:
13605           genInline (ic);
13606           break;
13607
13608         case RRC:
13609           genRRC (ic);
13610           break;
13611
13612         case RLC:
13613           genRLC (ic);
13614           break;
13615
13616         case GETHBIT:
13617           genGetHbit (ic);
13618           break;
13619
13620         case LEFT_OP:
13621           genLeftShift (ic);
13622           break;
13623
13624         case RIGHT_OP:
13625           genRightShift (ic);
13626           break;
13627
13628         case GET_VALUE_AT_ADDRESS:
13629           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
13630           break;
13631
13632         case '=':
13633           if (POINTER_SET (ic))
13634             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13635           else
13636             genAssign (ic);
13637           break;
13638
13639         case IFX:
13640           genIfx (ic, NULL);
13641           break;
13642
13643         case ADDRESS_OF:
13644           genAddrOf (ic);
13645           break;
13646
13647         case JUMPTABLE:
13648           genJumpTab (ic);
13649           break;
13650
13651         case CAST:
13652           genCast (ic);
13653           break;
13654
13655         case RECEIVE:
13656           genReceive (ic);
13657           break;
13658
13659         case SEND:
13660           if (ic->builtinSEND) genBuiltIn(ic);
13661           else addSet (&_G.sendSet, ic);
13662           break;
13663
13664         case DUMMY_READ_VOLATILE:
13665           genDummyRead (ic);
13666           break;
13667
13668         case CRITICAL:
13669           genCritical (ic);
13670           break;
13671
13672         case ENDCRITICAL:
13673           genEndCritical (ic);
13674           break;
13675
13676         case SWAP:
13677           genSwap (ic);
13678           break;
13679
13680 #if 0 // obsolete, and buggy for != xdata
13681         case ARRAYINIT:
13682             genArrayInit(ic);
13683             break;
13684 #endif
13685
13686         default:
13687           ic = ic;
13688         }
13689     }
13690
13691
13692   /* now we are ready to call the
13693      peep hole optimizer */
13694   if (!options.nopeep)
13695     peepHole (&lineHead);
13696
13697   /* now do the actual printing */
13698   printLine (lineHead, codeOutFile);
13699   return;
13700 }