cleanup fp fix to pop directly instead of pop acc/mov x,acc; what was I thinking?
[fw/sdcc] / src / ds390 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for 8051
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   
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12   
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17   
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21   
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25   
26   Notes:
27   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
28                 Made everything static
29 -------------------------------------------------------------------------*/
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "SDCCglobl.h"
36
37 #ifdef HAVE_SYS_ISA_DEFS_H
38 #include <sys/isa_defs.h>
39 #else
40 #ifdef HAVE_ENDIAN_H
41 #include <endian.h>
42 #else
43 #ifndef __BORLANDC__
44 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
45 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
46 #endif
47 #endif
48 #endif
49
50 #include "common.h"
51 #include "SDCCpeeph.h"
52 #include "ralloc.h"
53 #include "gen.h"
54
55 char *aopLiteral (value *val, int offset);
56 extern int allocInfo;
57
58 /* this is the down and dirty file with all kinds of 
59    kludgy & hacky stuff. This is what it is all about
60    CODE GENERATION for a specific MCU . some of the
61    routines may be reusable, will have to see */
62
63 static char *zero = "#0x00";
64 static char *one  = "#0x01";
65 static char *spname ;
66
67 #define D(x) x
68
69 unsigned fReturnSize_390 = 5; /* shared with ralloc.c */
70 static char *fReturn[] = {"dpl","dph","dpx", "b","a" };
71 static char *accUse[] = {"a","b"};
72
73 static short rbank = -1;
74
75 static struct {
76     short r0Pushed;
77     short r1Pushed;
78     short accInUse;
79     short inLine;
80     short debugLine;
81     short nRegsSaved;
82     set *sendSet;
83 } _G;
84
85 extern int ds390_ptrRegReq ;
86 extern int ds390_nRegs;
87 extern FILE *codeOutFile;
88 static void saverbank (int, iCode *,bool);
89 #define RESULTONSTACK(x) \
90                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
91                          IC_RESULT(x)->aop->type == AOP_STK )
92
93 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
94 #define MOVA(x) { char *_mova_tmp = strdup(x); \
95                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
96                  { \
97                     emitcode("mov","a,%s",_mova_tmp); \
98                  } \
99                  free(_mova_tmp); \
100                 }
101 #define CLRC    emitcode("clr","c")
102 #define SETC    emitcode("setb","c")
103
104 static lineNode *lineHead = NULL;
105 static lineNode *lineCurr = NULL;
106
107 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
108 0xE0, 0xC0, 0x80, 0x00};
109 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
110 0x07, 0x03, 0x01, 0x00};
111
112 #define LSB     0
113 #define MSB16   1
114 #define MSB24   2
115 #define MSB32   3
116
117 /*-----------------------------------------------------------------*/
118 /* emitcode - writes the code into a file : for now it is simple    */
119 /*-----------------------------------------------------------------*/
120 static void emitcode (char *inst,char *fmt, ...)
121 {
122     va_list ap;
123     char lb[MAX_INLINEASM];  
124     char *lbp = lb;
125
126     va_start(ap,fmt);   
127
128     if (inst && *inst) {
129         if (fmt && *fmt)
130             sprintf(lb,"%s\t",inst);
131         else
132             sprintf(lb,"%s",inst);
133         vsprintf(lb+(strlen(lb)),fmt,ap);
134     }  else
135         vsprintf(lb,fmt,ap);
136
137     while (isspace(*lbp)) lbp++;
138
139     if (lbp && *lbp) 
140         lineCurr = (lineCurr ?
141                     connectLine(lineCurr,newLineNode(lb)) :
142                     (lineHead = newLineNode(lb)));
143     lineCurr->isInline = _G.inLine;
144     lineCurr->isDebug  = _G.debugLine;
145     va_end(ap);
146 }
147
148 /*-----------------------------------------------------------------*/
149 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
150 /*-----------------------------------------------------------------*/
151 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
152 {
153     bool r0iu = FALSE , r1iu = FALSE;
154     bool r0ou = FALSE , r1ou = FALSE;
155
156     /* the logic: if r0 & r1 used in the instruction
157     then we are in trouble otherwise */
158
159     /* first check if r0 & r1 are used by this
160     instruction, in which case we are in trouble */
161     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
162         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
163     {
164         goto endOfWorld;      
165     }
166
167     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
168     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
169
170     /* if no usage of r0 then return it */
171     if (!r0iu && !r0ou) {
172         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
173         (*aopp)->type = AOP_R0;
174         
175         return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
176     }
177
178     /* if no usage of r1 then return it */
179     if (!r1iu && !r1ou) {
180         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
181         (*aopp)->type = AOP_R1;
182
183         return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R1_IDX);
184     }    
185
186     /* now we know they both have usage */
187     /* if r0 not used in this instruction */
188     if (!r0iu) {
189         /* push it if not already pushed */
190         if (!_G.r0Pushed) {
191             emitcode ("push","%s",
192                       ds390_regWithIdx(R0_IDX)->dname);
193             _G.r0Pushed++ ;
194         }
195         
196         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
197         (*aopp)->type = AOP_R0;
198
199         return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
200     }
201
202     /* if r1 not used then */
203
204     if (!r1iu) {
205         /* push it if not already pushed */
206         if (!_G.r1Pushed) {
207             emitcode ("push","%s",
208                       ds390_regWithIdx(R1_IDX)->dname);
209             _G.r1Pushed++ ;
210         }
211         
212         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
213         (*aopp)->type = AOP_R1;
214         return ds390_regWithIdx(R1_IDX);
215     }
216
217 endOfWorld :
218     /* I said end of world but not quite end of world yet */
219     /* if this is a result then we can push it on the stack*/
220     if (result) {
221         (*aopp)->type = AOP_STK;    
222         return NULL;
223     }
224
225     piCode(ic,stdout);
226     /* other wise this is true end of the world */
227     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
228            "getFreePtr should never reach here");
229     exit(0);
230 }
231
232 /*-----------------------------------------------------------------*/
233 /* newAsmop - creates a new asmOp                                  */
234 /*-----------------------------------------------------------------*/
235 static asmop *newAsmop (short type)
236 {
237     asmop *aop;
238
239     ALLOC(aop,sizeof(asmop));
240     aop->type = type;
241     return aop;
242 }
243
244 static void genSetDPTR(int n)
245 {
246     if (!n)
247     {
248         emitcode(";", "Select standard DPTR");
249         emitcode("mov", "dps, #0x00");
250     }
251     else
252     {
253         emitcode(";", "Select alternate DPTR");
254         emitcode("mov", "dps, #0x01");
255     }
256 }
257
258 /*-----------------------------------------------------------------*/
259 /* pointerCode - returns the code for a pointer type               */
260 /*-----------------------------------------------------------------*/
261 static int pointerCode (link *etype)
262 {
263
264     return PTR_TYPE(SPEC_OCLS(etype));
265
266 }
267
268 /*-----------------------------------------------------------------*/
269 /* aopForSym - for a true symbol                                   */
270 /*-----------------------------------------------------------------*/
271 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool useDP2)
272 {
273     asmop *aop;
274     memmap *space= SPEC_OCLS(sym->etype);
275
276     /* if already has one */
277     if (sym->aop)
278         return sym->aop;
279
280     /* assign depending on the storage class */
281     /* if it is on the stack or indirectly addressable */
282     /* space we need to assign either r0 or r1 to it   */    
283     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
284         sym->aop = aop = newAsmop(0);
285         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
286         aop->size = getSize(sym->type);
287
288         /* now assign the address of the variable to 
289         the pointer register */
290         if (aop->type != AOP_STK) {
291
292             if (sym->onStack) {
293                     if ( _G.accInUse )
294                         emitcode("push","acc");
295
296                     emitcode("mov","a,_bp");
297                     emitcode("add","a,#0x%02x",
298                              ((sym->stack < 0) ?
299                               ((char)(sym->stack - _G.nRegsSaved )) :
300                               ((char)sym->stack)) & 0xff);
301                     emitcode("mov","%s,a",
302                              aop->aopu.aop_ptr->name);
303
304                     if ( _G.accInUse )
305                         emitcode("pop","acc");
306             } else
307                 emitcode("mov","%s,#%s",
308                          aop->aopu.aop_ptr->name,
309                          sym->rname);
310             aop->paged = space->paged;
311         } else
312             aop->aopu.aop_stk = sym->stack;
313         return aop;
314     }
315     
316     if (sym->onStack && options.stack10bit)
317     {
318         /* It's on the 10 bit stack, which is located in
319          * far data space.
320          */
321          
322         if ( _G.accInUse )
323                 emitcode("push","acc");
324
325         emitcode("mov","a,_bp");
326         emitcode("add","a,#0x%02x",
327                  ((sym->stack < 0) ?
328                    ((char)(sym->stack - _G.nRegsSaved )) :
329                    ((char)sym->stack)) & 0xff);
330         
331         if (useDP2)
332         {        
333         genSetDPTR(1);
334         emitcode ("mov","dpx1,#0x40");
335         emitcode ("mov","dph1,#0x00");
336         emitcode ("mov","dpl1, a");
337         genSetDPTR(0);
338         }
339         else
340         {
341             emitcode ("mov","dpx,#0x40");
342             emitcode ("mov","dph,#0x00");
343             emitcode ("mov","dpl, a");           
344         }
345         
346         if ( _G.accInUse )
347             emitcode("pop","acc");
348             
349         sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
350         aop->size = getSize(sym->type); 
351         return aop;
352     }
353
354     /* if in bit space */
355     if (IN_BITSPACE(space)) {
356         sym->aop = aop = newAsmop (AOP_CRY);
357         aop->aopu.aop_dir = sym->rname ;
358         aop->size = getSize(sym->type);
359         return aop;
360     }
361     /* if it is in direct space */
362     if (IN_DIRSPACE(space)) {
363         sym->aop = aop = newAsmop (AOP_DIR);
364         aop->aopu.aop_dir = sym->rname ;
365         aop->size = getSize(sym->type);
366         return aop;
367     }
368
369     /* special case for a function */
370     if (IS_FUNC(sym->type)) {   
371         sym->aop = aop = newAsmop(AOP_IMMD);    
372         ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
373         strcpy(aop->aopu.aop_immd,sym->rname);
374         aop->size = FPTRSIZE; 
375         return aop;
376     }
377
378     /* only remaining is far space */
379     /* in which case DPTR gets the address */
380     sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
381     if (useDP2)
382     {        
383         genSetDPTR(1);
384     emitcode ("mov","dptr,#%s", sym->rname);
385         genSetDPTR(0);
386     }    
387     else
388     {
389         emitcode ("mov","dptr,#%s", sym->rname);
390     }
391     aop->size = getSize(sym->type);
392
393     /* if it is in code space */
394     if (IN_CODESPACE(space))
395         aop->code = 1;
396
397     return aop;     
398 }
399
400 /*-----------------------------------------------------------------*/
401 /* aopForRemat - rematerialzes an object                           */
402 /*-----------------------------------------------------------------*/
403 static asmop *aopForRemat (symbol *sym)
404 {
405     iCode *ic = sym->rematiCode;
406     asmop *aop = newAsmop(AOP_IMMD);
407
408     int val = 0;
409
410     for (;;) {
411         if (ic->op == '+')
412             val += operandLitValue(IC_RIGHT(ic));
413         else if (ic->op == '-')
414             val -= operandLitValue(IC_RIGHT(ic));
415         else
416             break;
417         
418         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
419     }
420
421     if (val)
422         sprintf(buffer,"(%s %c 0x%04x)",
423                 OP_SYMBOL(IC_LEFT(ic))->rname, 
424                 val >= 0 ? '+' : '-',
425                 abs(val) & 0xffff);
426     else
427         strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
428
429     ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
430     strcpy(aop->aopu.aop_immd,buffer);    
431     return aop;        
432 }
433
434 /*-----------------------------------------------------------------*/
435 /* regsInCommon - two operands have some registers in common       */
436 /*-----------------------------------------------------------------*/
437 static bool regsInCommon (operand *op1, operand *op2)
438 {
439     symbol *sym1, *sym2;
440     int i;
441
442     /* if they have registers in common */
443     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
444         return FALSE ;
445
446     sym1 = OP_SYMBOL(op1);
447     sym2 = OP_SYMBOL(op2);
448
449     if (sym1->nRegs == 0 || sym2->nRegs == 0)
450         return FALSE ;
451
452     for (i = 0 ; i < sym1->nRegs ; i++) {
453         int j;
454         if (!sym1->regs[i])
455             continue ;
456
457         for (j = 0 ; j < sym2->nRegs ;j++ ) {
458             if (!sym2->regs[j])
459                 continue ;
460
461             if (sym2->regs[j] == sym1->regs[i])
462                 return TRUE ;
463         }
464     }
465
466     return FALSE ;
467 }
468
469 /*-----------------------------------------------------------------*/
470 /* operandsEqu - equivalent                                        */
471 /*-----------------------------------------------------------------*/
472 static bool operandsEqu ( operand *op1, operand *op2)
473 {
474     symbol *sym1, *sym2;
475
476     /* if they not symbols */
477     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
478         return FALSE;
479
480     sym1 = OP_SYMBOL(op1);
481     sym2 = OP_SYMBOL(op2);
482
483     /* if both are itemps & one is spilt
484        and the other is not then false */
485     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
486         sym1->isspilt != sym2->isspilt )
487         return FALSE ;
488
489     /* if they are the same */
490     if (sym1 == sym2)
491         return TRUE ;
492
493     if (strcmp(sym1->rname,sym2->rname) == 0)
494         return TRUE;
495
496
497     /* if left is a tmp & right is not */
498     if (IS_ITEMP(op1)  && 
499         !IS_ITEMP(op2) &&
500         sym1->isspilt  &&
501         (sym1->usl.spillLoc == sym2))
502         return TRUE;
503
504     if (IS_ITEMP(op2)  && 
505         !IS_ITEMP(op1) &&
506         sym2->isspilt  &&
507         sym1->level > 0 &&
508         (sym2->usl.spillLoc == sym1))
509         return TRUE ;
510
511     return FALSE ;
512 }
513
514 /*-----------------------------------------------------------------*/
515 /* sameRegs - two asmops have the same registers                   */
516 /*-----------------------------------------------------------------*/
517 static bool sameRegs (asmop *aop1, asmop *aop2 )
518 {
519     int i;
520
521     if (aop1 == aop2)
522     {
523         if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
524         {
525             return FALSE;
526         }
527         return TRUE ;
528     }
529
530     if (aop1->type != AOP_REG ||
531         aop2->type != AOP_REG )
532         return FALSE ;
533
534     if (aop1->size != aop2->size )
535         return FALSE ;
536
537     for (i = 0 ; i < aop1->size ; i++ )
538         if (aop1->aopu.aop_reg[i] !=
539             aop2->aopu.aop_reg[i] )
540             return FALSE ;
541
542     return TRUE ;
543 }
544
545 /*-----------------------------------------------------------------*/
546 /* aopOp - allocates an asmop for an operand  :                    */
547 /*-----------------------------------------------------------------*/
548 static void aopOp (operand *op, iCode *ic, bool result, bool useDP2)
549 {
550     asmop *aop;
551     symbol *sym;
552     int i;
553
554     if (!op)
555         return ;
556
557     /* if this a literal */
558     if (IS_OP_LITERAL(op)) {
559         op->aop = aop = newAsmop(AOP_LIT);
560         aop->aopu.aop_lit = op->operand.valOperand;
561         aop->size = getSize(operandType(op));
562         return;
563     }
564
565     /* if already has a asmop then continue */
566     if (op->aop)
567         return ;
568
569     /* if the underlying symbol has a aop */
570     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
571         op->aop = OP_SYMBOL(op)->aop;
572         return;
573     }
574
575     /* if this is a true symbol */
576     if (IS_TRUE_SYMOP(op)) {    
577         op->aop = aopForSym(ic,OP_SYMBOL(op),result, useDP2);
578         return ;
579     }
580
581     /* this is a temporary : this has
582     only four choices :
583     a) register
584     b) spillocation
585     c) rematerialize 
586     d) conditional   
587     e) can be a return use only */
588
589     sym = OP_SYMBOL(op);
590
591
592     /* if the type is a conditional */
593     if (sym->regType == REG_CND) {
594         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
595         aop->size = 0;
596         return;
597     }
598
599     /* if it is spilt then two situations
600     a) is rematerialize 
601     b) has a spill location */
602     if (sym->isspilt || sym->nRegs == 0) {
603
604         /* rematerialize it NOW */
605         if (sym->remat) {
606             sym->aop = op->aop = aop =
607                                       aopForRemat (sym);
608             aop->size = getSize(sym->type);
609             return;
610         }
611
612         if (sym->accuse) {
613             int i;
614             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
615             aop->size = getSize(sym->type);
616             for ( i = 0 ; i < 2 ; i++ )
617                 aop->aopu.aop_str[i] = accUse[i];
618             return;  
619         }
620
621         if (sym->ruonly ) {
622             int i;
623             aop = op->aop = sym->aop = newAsmop(AOP_STR);
624             aop->size = getSize(sym->type);
625             for ( i = 0 ; i < fReturnSize_390 ; i++ )
626                 aop->aopu.aop_str[i] = fReturn[i];
627             return;
628         }
629
630         /* else spill location  */
631         sym->aop = op->aop = aop = 
632                 aopForSym(ic,sym->usl.spillLoc,result, useDP2);
633         aop->size = getSize(sym->type);
634         return;
635     }
636
637     /* must be in a register */
638     sym->aop = op->aop = aop = newAsmop(AOP_REG);
639     aop->size = sym->nRegs;
640     for ( i = 0 ; i < sym->nRegs ;i++)
641         aop->aopu.aop_reg[i] = sym->regs[i];
642 }
643
644 /*-----------------------------------------------------------------*/
645 /* freeAsmop - free up the asmop given to an operand               */
646 /*----------------------------------------------------------------*/
647 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
648 {   
649     asmop *aop ;
650
651     if (!op)
652         aop = aaop;
653     else 
654         aop = op->aop;
655
656     if (!aop)
657         return ;
658
659     if (aop->freed)
660         goto dealloc; 
661
662     aop->freed = 1;
663
664     /* depending on the asmop type only three cases need work AOP_RO
665        , AOP_R1 && AOP_STK */
666     switch (aop->type) {
667         case AOP_R0 :
668             if (_G.r0Pushed ) {
669                 if (pop) {
670                     emitcode ("pop","ar0");     
671                     _G.r0Pushed--;
672                 }
673             }
674             bitVectUnSetBit(ic->rUsed,R0_IDX);
675             break;
676
677         case AOP_R1 :
678             if (_G.r1Pushed ) {
679                 if (pop) {
680                     emitcode ("pop","ar1");
681                     _G.r1Pushed--;
682                 }
683             }
684             bitVectUnSetBit(ic->rUsed,R1_IDX);          
685             break;
686
687         case AOP_STK :
688         {
689             int sz = aop->size;    
690             int stk = aop->aopu.aop_stk + aop->size;
691             bitVectUnSetBit(ic->rUsed,R0_IDX);
692             bitVectUnSetBit(ic->rUsed,R1_IDX);          
693
694             getFreePtr(ic,&aop,FALSE);
695             
696             if (options.stack10bit)
697             {
698                 /* I'm not sure what to do here yet... */
699                 /* #STUB */
700                 fprintf(stderr, 
701                         "*** Warning: probably generating bad code for "
702                         "10 bit stack mode.\n");
703             }
704             
705             if (stk) {
706                 emitcode ("mov","a,_bp");
707                 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
708                 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
709             } else {
710                 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
711             }
712
713             while (sz--) {
714                 emitcode("pop","acc");
715                 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
716                 if (!sz) break;
717                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
718             }
719             op->aop = aop;
720             freeAsmop(op,NULL,ic,TRUE);
721             if (_G.r0Pushed) {
722                 emitcode("pop","ar0");
723                 _G.r0Pushed--;
724             }
725
726             if (_G.r1Pushed) {
727                 emitcode("pop","ar1");
728                 _G.r1Pushed--;
729             }       
730         }
731     }
732
733 dealloc:
734     /* all other cases just dealloc */
735     if (op ) {
736         op->aop = NULL;
737         if (IS_SYMOP(op)) {
738             OP_SYMBOL(op)->aop = NULL;    
739             /* if the symbol has a spill */
740             if (SPIL_LOC(op))
741                 SPIL_LOC(op)->aop = NULL;
742         }
743     }
744 }
745
746 /*-----------------------------------------------------------------*/
747 /* aopGet - for fetching value of the aop                          */
748 /*-----------------------------------------------------------------*/
749 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
750 {
751     char *s = buffer ;
752     char *rs;
753
754     /* offset is greater than
755     size then zero */
756     if (offset > (aop->size - 1) &&
757         aop->type != AOP_LIT)
758         return zero;
759
760     /* depending on type */
761     switch (aop->type) {
762         
763     case AOP_R0:
764     case AOP_R1:
765         /* if we need to increment it */       
766         while (offset > aop->coff) {        
767             emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
768             aop->coff++;
769         }
770         
771         while (offset < aop->coff) {
772             emitcode("dec","%s",aop->aopu.aop_ptr->name);
773             aop->coff--;
774         }
775         
776         aop->coff = offset ;
777         if (aop->paged) {
778             emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
779             return (dname ? "acc" : "a");
780         }       
781         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
782         ALLOC_ATOMIC(rs,strlen(s)+1);
783         strcpy(rs,s);   
784         return rs;
785         
786     case AOP_DPTR:
787     case AOP_DPTR2:
788     
789     if (aop->type == AOP_DPTR2)
790     {
791         genSetDPTR(1);
792         emitcode("xch", "a, ap");
793     }
794     
795         while (offset > aop->coff) {
796             emitcode ("inc","dptr");
797             aop->coff++;
798         }
799         
800         while (offset < aop->coff) {        
801             emitcode("lcall","__decdptr");
802             aop->coff--;
803         }
804         
805         aop->coff = offset;
806         if (aop->code) {
807             emitcode("clr","a");
808             emitcode("movc","a,@a+dptr");
809         }
810     else {
811             emitcode("movx","a,@dptr");
812     }
813             
814     if (aop->type == AOP_DPTR2)
815     {
816         emitcode("xch", "a, ap");
817         genSetDPTR(0);
818         return "ap";
819     }
820             
821     return (dname ? "acc" : "a");
822         
823         
824     case AOP_IMMD:
825         if (bit16) 
826             sprintf (s,"#%s",aop->aopu.aop_immd);
827         else
828             if (offset) 
829                 sprintf(s,"#(%s >> %d)",
830                         aop->aopu.aop_immd,
831                         offset*8);
832             else
833                 sprintf(s,"#%s",
834                         aop->aopu.aop_immd);
835         ALLOC_ATOMIC(rs,strlen(s)+1);
836         strcpy(rs,s);   
837         return rs;
838         
839     case AOP_DIR:
840         if (offset)
841             sprintf(s,"(%s + %d)",
842                     aop->aopu.aop_dir,
843                     offset);
844         else
845             sprintf(s,"%s",aop->aopu.aop_dir);
846         ALLOC_ATOMIC(rs,strlen(s)+1);
847         strcpy(rs,s);   
848         return rs;
849         
850     case AOP_REG:
851         if (dname) 
852             return aop->aopu.aop_reg[offset]->dname;
853         else
854             return aop->aopu.aop_reg[offset]->name;
855         
856     case AOP_CRY:
857         emitcode("clr","a");
858         emitcode("mov","c,%s",aop->aopu.aop_dir);
859         emitcode("rlc","a") ;
860         return (dname ? "acc" : "a");
861         
862     case AOP_ACC:
863         if (!offset && dname)
864             return "acc";
865         return aop->aopu.aop_str[offset];
866
867     case AOP_LIT:
868         return aopLiteral (aop->aopu.aop_lit,offset);
869         
870     case AOP_STR:
871         aop->coff = offset ;
872         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
873             dname)
874             return "acc";
875         
876         return aop->aopu.aop_str[offset];
877         
878     }
879
880     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
881            "aopget got unsupported aop->type");
882     exit(0);
883 }
884 /*-----------------------------------------------------------------*/
885 /* aopPut - puts a string for a aop                                */
886 /*-----------------------------------------------------------------*/
887 static void aopPut (asmop *aop, char *s, int offset)
888 {
889     char *d = buffer ;
890     symbol *lbl ;
891
892     if (aop->size && offset > ( aop->size - 1)) {
893         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
894                "aopPut got offset > aop->size");
895         exit(0);
896     }
897
898     /* will assign value to value */
899     /* depending on where it is ofcourse */
900     switch (aop->type) {
901     case AOP_DIR:
902         if (offset)
903             sprintf(d,"(%s + %d)",
904                     aop->aopu.aop_dir,offset);
905         else
906             sprintf(d,"%s",aop->aopu.aop_dir);
907         
908         if (strcmp(d,s))
909             emitcode("mov","%s,%s",d,s);
910         
911         break;
912         
913     case AOP_REG:
914         if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
915             strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
916             if (*s == '@'           ||
917                 strcmp(s,"r0") == 0 ||
918                 strcmp(s,"r1") == 0 ||
919                 strcmp(s,"r2") == 0 ||
920                 strcmp(s,"r3") == 0 ||
921                 strcmp(s,"r4") == 0 ||
922                 strcmp(s,"r5") == 0 ||
923                 strcmp(s,"r6") == 0 || 
924                 strcmp(s,"r7") == 0 )
925                 emitcode("mov","%s,%s",
926                          aop->aopu.aop_reg[offset]->dname,s);
927             else
928                 emitcode("mov","%s,%s",
929                          aop->aopu.aop_reg[offset]->name,s);
930         }
931         break;
932         
933     case AOP_DPTR:
934     case AOP_DPTR2:
935     
936     if (aop->type == AOP_DPTR2)
937     {
938         genSetDPTR(1);
939     }
940     
941         if (aop->code) {
942             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
943                    "aopPut writting to code space");
944             exit(0);
945         }
946         
947         while (offset > aop->coff) {
948             aop->coff++;
949             emitcode ("inc","dptr");
950         }
951         
952         while (offset < aop->coff) {
953             aop->coff-- ;
954             emitcode("lcall","__decdptr");
955         }
956         
957         aop->coff = offset;
958         
959         /* if not in accumulater */
960         MOVA(s);        
961         
962         emitcode ("movx","@dptr,a");
963         
964     if (aop->type == AOP_DPTR2)
965     {
966         genSetDPTR(0);
967     }
968         break;
969         
970     case AOP_R0:
971     case AOP_R1:
972         while (offset > aop->coff) {
973             aop->coff++;
974             emitcode("inc","%s",aop->aopu.aop_ptr->name);
975         }
976         while (offset < aop->coff) {
977             aop->coff-- ;
978             emitcode ("dec","%s",aop->aopu.aop_ptr->name);
979         }
980         aop->coff = offset;
981         
982         if (aop->paged) {
983             MOVA(s);           
984             emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
985             
986         } else
987             if (*s == '@') {
988                 MOVA(s);
989                 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
990             } else
991                 if (strcmp(s,"r0") == 0 ||
992                     strcmp(s,"r1") == 0 ||
993                     strcmp(s,"r2") == 0 ||
994                     strcmp(s,"r3") == 0 ||
995                     strcmp(s,"r4") == 0 ||
996                     strcmp(s,"r5") == 0 ||
997                     strcmp(s,"r6") == 0 || 
998                     strcmp(s,"r7") == 0 ) {
999                     char buffer[10];
1000                     sprintf(buffer,"a%s",s);
1001                     emitcode("mov","@%s,%s",
1002                              aop->aopu.aop_ptr->name,buffer);
1003                 } else
1004                     emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1005         
1006         break;
1007         
1008     case AOP_STK:
1009         if (strcmp(s,"a") == 0)
1010             emitcode("push","acc");
1011         else
1012             emitcode("push","%s",s);
1013         
1014         break;
1015         
1016     case AOP_CRY:
1017         /* if bit variable */
1018         if (!aop->aopu.aop_dir) {
1019             emitcode("clr","a");
1020             emitcode("rlc","a");
1021         } else {
1022             if (s == zero) 
1023                 emitcode("clr","%s",aop->aopu.aop_dir);
1024             else
1025                 if (s == one)
1026                     emitcode("setb","%s",aop->aopu.aop_dir);
1027                 else
1028                     if (!strcmp(s,"c"))
1029                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1030                     else {
1031                         lbl = newiTempLabel(NULL);
1032                         
1033                         if (strcmp(s,"a")) {
1034                             MOVA(s);
1035                         }
1036                         emitcode("clr","c");
1037                         emitcode("jz","%05d$",lbl->key+100);
1038                         emitcode("cpl","c");
1039                         emitcode("","%05d$:",lbl->key+100);
1040                         emitcode("mov","%s,c",aop->aopu.aop_dir);
1041                     }
1042         }
1043         break;
1044         
1045     case AOP_STR:
1046         aop->coff = offset;
1047         if (strcmp(aop->aopu.aop_str[offset],s))
1048             emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1049         break;
1050         
1051     case AOP_ACC:
1052         aop->coff = offset;
1053         if (!offset && (strcmp(s,"acc") == 0))
1054             break;
1055         
1056         if (strcmp(aop->aopu.aop_str[offset],s))
1057             emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1058         break;
1059
1060     default :
1061         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1062                "aopPut got unsupported aop->type");
1063         exit(0);    
1064     }    
1065
1066 }
1067
1068
1069 #if 0
1070 /*-----------------------------------------------------------------*/
1071 /* pointToEnd :- points to the last byte of the operand            */
1072 /*-----------------------------------------------------------------*/
1073 static void pointToEnd (asmop *aop)
1074 {
1075     int count ;
1076     if (!aop)
1077         return ;
1078
1079     aop->coff = count = (aop->size - 1);
1080     switch (aop->type) {
1081         case AOP_R0 :
1082         case AOP_R1 :
1083             while (count--)
1084                 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1085             break;
1086         case AOP_DPTR :
1087             while (count--)
1088                 emitcode("inc","dptr");
1089             break;
1090     }
1091
1092 }
1093 #endif
1094
1095 /*-----------------------------------------------------------------*/
1096 /* reAdjustPreg - points a register back to where it should        */
1097 /*-----------------------------------------------------------------*/
1098 static void reAdjustPreg (asmop *aop)
1099 {
1100     int size ;
1101
1102     aop->coff = 0;
1103     if ((size = aop->size) <= 1)
1104         return ;
1105     size-- ;
1106     switch (aop->type) {
1107         case AOP_R0 :
1108         case AOP_R1 :
1109             while (size--)
1110                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1111             break;          
1112         case AOP_DPTR :
1113         case AOP_DPTR2:
1114             if (aop->type == AOP_DPTR2)
1115             {
1116                 genSetDPTR(1);
1117             } 
1118             while (size--)
1119             {
1120                 emitcode("lcall","__decdptr");
1121             }
1122                 
1123             if (aop->type == AOP_DPTR2)
1124             {
1125                 genSetDPTR(0);
1126             }                
1127             break;  
1128
1129     }   
1130
1131 }
1132
1133 #define AOP(op) op->aop
1134 #define AOP_TYPE(op) AOP(op)->type
1135 #define AOP_SIZE(op) AOP(op)->size
1136 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1137                        AOP_TYPE(x) == AOP_R0))
1138
1139 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1140                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1141                          AOP(x)->paged)) 
1142
1143 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1144                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1145                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1146
1147 /* Workaround for DS80C390 bug: div ab may return bogus results
1148  * if A is accessed in instruction immediately before the div.
1149  *
1150  * Will be fixed in B4 rev of processor, Dallas claims.
1151  */
1152  
1153 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)                         \
1154     if (!AOP_NEEDSACC(RIGHT))                                   \
1155     {                                                           \
1156         /* We can load A first, then B, since                   \
1157          * B (the RIGHT operand) won't clobber A,               \
1158          * thus avoiding touching A right before the div.       \
1159          */                                                     \
1160         D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1161         L = aopGet(AOP(LEFT),0,FALSE,FALSE);                    \
1162         MOVA(L);                                                \
1163         emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE));\
1164     }                                                           \
1165     else                                                        \
1166     {                                                           \
1167         /* Just stuff in a nop after loading A. */              \
1168         emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE));\
1169         L = aopGet(AOP(LEFT),0,FALSE,FALSE);                    \
1170         MOVA(L);                                                \
1171         emitcode("nop", "; workaround for DS80C390 div bug.");  \
1172     }
1173
1174 /*-----------------------------------------------------------------*/
1175 /* genNotFloat - generates not for float operations              */
1176 /*-----------------------------------------------------------------*/
1177 static void genNotFloat (operand *op, operand *res)
1178 {
1179     int size, offset;
1180     char *l;
1181     symbol *tlbl ;
1182
1183     D(emitcode(";", "genNotFloat "););
1184
1185     /* we will put 127 in the first byte of 
1186     the result */
1187     aopPut(AOP(res),"#127",0);
1188     size = AOP_SIZE(op) - 1;
1189     offset = 1;
1190
1191     l = aopGet(op->aop,offset++,FALSE,FALSE);
1192     MOVA(l);    
1193
1194     while(size--) {
1195         emitcode("orl","a,%s",
1196                  aopGet(op->aop,
1197                         offset++,FALSE,FALSE));
1198     }
1199     tlbl = newiTempLabel(NULL);
1200
1201     tlbl = newiTempLabel(NULL);
1202     aopPut(res->aop,one,1);
1203     emitcode("jz","%05d$",(tlbl->key+100));
1204     aopPut(res->aop,zero,1);
1205     emitcode("","%05d$:",(tlbl->key+100));
1206
1207     size = res->aop->size - 2;
1208     offset = 2;    
1209     /* put zeros in the rest */
1210     while (size--) 
1211         aopPut(res->aop,zero,offset++);
1212 }
1213
1214 /*-----------------------------------------------------------------*/
1215 /* opIsGptr: returns non-zero if the passed operand is             */   
1216 /* a generic pointer type.                                         */
1217 /*-----------------------------------------------------------------*/ 
1218 static int opIsGptr(operand *op)
1219 {
1220     link *type = operandType(op);
1221     
1222     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1223     {
1224         return 1;
1225     }
1226     return 0;        
1227 }
1228
1229 /*-----------------------------------------------------------------*/
1230 /* getDataSize - get the operand data size                         */
1231 /*-----------------------------------------------------------------*/
1232 static int getDataSize(operand *op)
1233 {
1234     int size;
1235     size = AOP_SIZE(op);
1236     if (size == GPTRSIZE)
1237     {
1238         link *type = operandType(op);
1239         if (IS_GENPTR(type))
1240         {
1241             /* generic pointer; arithmetic operations
1242              * should ignore the high byte (pointer type).
1243              */
1244             size--;
1245         }
1246     }
1247     return size;
1248 }
1249
1250 /*-----------------------------------------------------------------*/
1251 /* outAcc - output Acc                                             */
1252 /*-----------------------------------------------------------------*/
1253 static void outAcc(operand *result)
1254 {
1255     int size, offset;
1256     size = getDataSize(result);
1257     if(size){
1258         aopPut(AOP(result),"a",0);
1259         size--;
1260         offset = 1;
1261         /* unsigned or positive */
1262         while(size--){
1263             aopPut(AOP(result),zero,offset++);
1264         }
1265     }
1266 }
1267
1268 /*-----------------------------------------------------------------*/
1269 /* outBitC - output a bit C                                        */
1270 /*-----------------------------------------------------------------*/
1271 static void outBitC(operand *result)
1272 {
1273     /* if the result is bit */
1274     if (AOP_TYPE(result) == AOP_CRY) 
1275         aopPut(AOP(result),"c",0);
1276     else {
1277         emitcode("clr","a");
1278         emitcode("rlc","a");
1279         outAcc(result);
1280     }
1281 }
1282
1283 /*-----------------------------------------------------------------*/
1284 /* toBoolean - emit code for orl a,operator(sizeop)                */
1285 /*-----------------------------------------------------------------*/
1286 static void toBoolean(operand *oper)
1287 {
1288     int size = AOP_SIZE(oper) - 1;
1289     int offset = 1;
1290
1291     if (AOP_NEEDSACC(oper))
1292     {
1293         emitcode("push", "b");
1294         emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE));
1295     }
1296     else
1297     {
1298     MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1299     }
1300     while (size--) 
1301     {
1302         if (AOP_NEEDSACC(oper))
1303         {
1304             emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1305         }
1306         else
1307         {
1308         emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1309 }
1310     }
1311     
1312     if (AOP_NEEDSACC(oper))
1313     {
1314         emitcode("mov", "a,b");
1315         emitcode("pop", "b");
1316     }
1317 }
1318
1319
1320 /*-----------------------------------------------------------------*/
1321 /* genNot - generate code for ! operation                          */
1322 /*-----------------------------------------------------------------*/
1323 static void genNot (iCode *ic)
1324 {
1325     symbol *tlbl;
1326     link *optype = operandType(IC_LEFT(ic));
1327
1328     D(emitcode(";", "genNot "););
1329
1330     /* assign asmOps to operand & result */
1331     aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1332     aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1333
1334     /* if in bit space then a special case */
1335     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1336         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1337         emitcode("cpl","c"); 
1338         outBitC(IC_RESULT(ic));
1339         goto release;
1340     }
1341
1342     /* if type float then do float */
1343     if (IS_FLOAT(optype)) {
1344         genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1345         goto release;
1346     }
1347
1348     toBoolean(IC_LEFT(ic));
1349
1350     tlbl = newiTempLabel(NULL);
1351     emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1352     emitcode("","%05d$:",tlbl->key+100);
1353     outBitC(IC_RESULT(ic));
1354
1355 release:    
1356     /* release the aops */
1357     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1358     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1359 }
1360
1361
1362 /*-----------------------------------------------------------------*/
1363 /* genCpl - generate code for complement                           */
1364 /*-----------------------------------------------------------------*/
1365 static void genCpl (iCode *ic)
1366 {
1367     int offset = 0;
1368     int size ;
1369
1370     D(emitcode(";", "genCpl "););
1371
1372
1373     /* assign asmOps to operand & result */
1374     aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1375     aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1376
1377     /* if both are in bit space then 
1378     a special case */
1379     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1380         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1381
1382         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1383         emitcode("cpl","c"); 
1384         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1385         goto release; 
1386     } 
1387
1388     size = AOP_SIZE(IC_RESULT(ic));
1389     while (size--) {
1390         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1391         MOVA(l);       
1392         emitcode("cpl","a");
1393         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1394     }
1395
1396
1397 release:
1398     /* release the aops */
1399     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1400     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1401 }
1402
1403 /*-----------------------------------------------------------------*/
1404 /* genUminusFloat - unary minus for floating points                */
1405 /*-----------------------------------------------------------------*/
1406 static void genUminusFloat(operand *op,operand *result)
1407 {
1408     int size ,offset =0 ;
1409     char *l;
1410     /* for this we just need to flip the 
1411     first it then copy the rest in place */
1412     size = AOP_SIZE(op) - 1;
1413     l = aopGet(AOP(op),3,FALSE,FALSE);
1414
1415     D(emitcode(";", "genUminusFloat"););
1416
1417     MOVA(l);    
1418
1419     emitcode("cpl","acc.7");
1420     aopPut(AOP(result),"a",3);    
1421
1422     while(size--) {
1423         aopPut(AOP(result),
1424                aopGet(AOP(op),offset,FALSE,FALSE),
1425                offset);
1426         offset++;
1427     }          
1428 }
1429
1430 /*-----------------------------------------------------------------*/
1431 /* genUminus - unary minus code generation                         */
1432 /*-----------------------------------------------------------------*/
1433 static void genUminus (iCode *ic)
1434 {
1435     int offset ,size ;
1436     link *optype, *rtype;
1437
1438     D(emitcode(";", "genUminus "););
1439
1440
1441     /* assign asmops */
1442     aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1443     aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1444
1445     /* if both in bit space then special
1446     case */
1447     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1448         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1449
1450         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1451         emitcode("cpl","c"); 
1452         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1453         goto release; 
1454     } 
1455
1456     optype = operandType(IC_LEFT(ic));
1457     rtype = operandType(IC_RESULT(ic));
1458
1459     /* if float then do float stuff */
1460     if (IS_FLOAT(optype)) {
1461         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1462         goto release;
1463     }
1464
1465     /* otherwise subtract from zero */
1466     size = AOP_SIZE(IC_LEFT(ic));
1467     offset = 0 ;
1468     //CLRC ;
1469     while(size--) {
1470         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1471         if (!strcmp(l,"a")) {
1472           if (offset==0)
1473             SETC;
1474           emitcode("cpl","a");
1475           emitcode("addc", "a,#0");
1476         } else {
1477           if (offset==0)
1478             CLRC;
1479           emitcode("clr","a");
1480           emitcode("subb","a,%s",l);
1481         }       
1482         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1483     }
1484
1485     /* if any remaining bytes in the result */
1486     /* we just need to propagate the sign   */
1487     if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1488         emitcode("rlc","a");
1489         emitcode("subb","a,acc");
1490         while (size--) 
1491             aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1492     }       
1493
1494 release:
1495     /* release the aops */
1496     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1497     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1498 }
1499
1500 /*-----------------------------------------------------------------*/
1501 /* saveRegisters - will look for a call and save the registers     */
1502 /*-----------------------------------------------------------------*/
1503 static void saveRegisters(iCode *lic) 
1504 {
1505     int i;
1506     iCode *ic;
1507     bitVect *rsave;
1508     link *detype;
1509
1510     /* look for call */
1511     for (ic = lic ; ic ; ic = ic->next) 
1512         if (ic->op == CALL || ic->op == PCALL)
1513             break;
1514
1515     if (!ic) {
1516         fprintf(stderr,"found parameter push with no function call\n");
1517         return ;
1518     }
1519
1520     /* if the registers have been saved already then
1521     do nothing */
1522     if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1523         return ;
1524
1525     /* find the registers in use at this time 
1526     and push them away to safety */
1527     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1528                           ic->rUsed);
1529
1530     ic->regsSaved = 1;
1531     if (options.useXstack) {
1532         if (bitVectBitValue(rsave,R0_IDX))
1533             emitcode("mov","b,r0");
1534         emitcode("mov","r0,%s",spname);
1535         for (i = 0 ; i < ds390_nRegs ; i++) {
1536             if (bitVectBitValue(rsave,i)) {
1537                 if (i == R0_IDX)
1538                     emitcode("mov","a,b");
1539                 else
1540                     emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1541                 emitcode("movx","@r0,a");
1542                 emitcode("inc","r0");
1543             }
1544         }
1545         emitcode("mov","%s,r0",spname);
1546         if (bitVectBitValue(rsave,R0_IDX))
1547             emitcode("mov","r0,b");         
1548     } else
1549         for (i = 0 ; i < ds390_nRegs ; i++) {
1550             if (bitVectBitValue(rsave,i))
1551                 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1552         }
1553
1554     detype = getSpec(operandType(IC_LEFT(ic)));
1555     if (detype        && 
1556         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1557         IS_ISR(currFunc->etype) &&
1558         !ic->bankSaved) 
1559
1560         saverbank(SPEC_BANK(detype),ic,TRUE);
1561
1562 }
1563 /*-----------------------------------------------------------------*/
1564 /* unsaveRegisters - pop the pushed registers                      */
1565 /*-----------------------------------------------------------------*/
1566 static void unsaveRegisters (iCode *ic)
1567 {
1568     int i;
1569     bitVect *rsave;
1570     /* find the registers in use at this time 
1571     and push them away to safety */
1572     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1573                           ic->rUsed);
1574     
1575     if (options.useXstack) {
1576         emitcode("mov","r0,%s",spname); 
1577         for (i =  ds390_nRegs ; i >= 0 ; i--) {
1578             if (bitVectBitValue(rsave,i)) {
1579                 emitcode("dec","r0");
1580                 emitcode("movx","a,@r0");
1581                 if (i == R0_IDX)
1582                     emitcode("mov","b,a");
1583                 else
1584                     emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1585             }       
1586
1587         }
1588         emitcode("mov","%s,r0",spname);
1589         if (bitVectBitValue(rsave,R0_IDX))
1590             emitcode("mov","r0,b");
1591     } else
1592         for (i =  ds390_nRegs ; i >= 0 ; i--) {
1593             if (bitVectBitValue(rsave,i))
1594                 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1595         }
1596
1597 }  
1598
1599
1600 /*-----------------------------------------------------------------*/
1601 /* pushSide -                                                      */
1602 /*-----------------------------------------------------------------*/
1603 static void pushSide(operand * oper, int size)
1604 {
1605         int offset = 0;
1606         while (size--) {
1607                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1608                 if (AOP_TYPE(oper) != AOP_REG &&
1609                     AOP_TYPE(oper) != AOP_DIR &&
1610                     strcmp(l,"a") ) {
1611                         emitcode("mov","a,%s",l);
1612                         emitcode("push","acc");
1613                 } else
1614                         emitcode("push","%s",l);
1615         }
1616 }
1617
1618 /*-----------------------------------------------------------------*/
1619 /* assignResultValue -                                             */
1620 /*-----------------------------------------------------------------*/
1621 static void assignResultValue(operand * oper)
1622 {
1623         int offset = 0;
1624         int size = AOP_SIZE(oper);
1625         while (size--) {
1626                 aopPut(AOP(oper),fReturn[offset],offset);
1627                 offset++;
1628         }
1629 }
1630
1631
1632 /*-----------------------------------------------------------------*/
1633 /* genXpush - pushes onto the external stack                       */
1634 /*-----------------------------------------------------------------*/
1635 static void genXpush (iCode *ic)
1636 {
1637     asmop *aop = newAsmop(0);
1638     regs *r ;
1639     int size,offset = 0;
1640
1641     D(emitcode(";", "genXpush "););
1642
1643     aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1644     r = getFreePtr(ic,&aop,FALSE);
1645
1646     
1647     emitcode("mov","%s,_spx",r->name);
1648
1649     size = AOP_SIZE(IC_LEFT(ic));
1650     while(size--) {
1651
1652         char *l = aopGet(AOP(IC_LEFT(ic)),
1653                          offset++,FALSE,FALSE); 
1654         MOVA(l);            
1655         emitcode("movx","@%s,a",r->name);       
1656         emitcode("inc","%s",r->name);
1657
1658     }
1659
1660         
1661     emitcode("mov","_spx,%s",r->name);
1662
1663     freeAsmop(NULL,aop,ic,TRUE);
1664     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1665 }
1666
1667 /*-----------------------------------------------------------------*/
1668 /* genIpush - genrate code for pushing this gets a little complex  */
1669 /*-----------------------------------------------------------------*/
1670 static void genIpush (iCode *ic)
1671 {
1672     int size, offset = 0 ;
1673     char *l;
1674
1675     D(emitcode(";", "genIpush "););
1676
1677
1678     /* if this is not a parm push : ie. it is spill push 
1679     and spill push is always done on the local stack */
1680     if (!ic->parmPush) {
1681
1682         /* and the item is spilt then do nothing */
1683         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1684             return ;
1685
1686         aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1687         size = AOP_SIZE(IC_LEFT(ic));
1688         /* push it on the stack */
1689         while(size--) {
1690             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1691             if (*l == '#') {
1692                 MOVA(l);
1693                 l = "acc";
1694             }
1695             emitcode("push","%s",l);
1696         }
1697         return ;        
1698     }
1699
1700     /* this is a paramter push: in this case we call
1701     the routine to find the call and save those
1702     registers that need to be saved */   
1703     saveRegisters(ic);
1704
1705     /* if use external stack then call the external
1706     stack pushing routine */
1707     if (options.useXstack) {
1708         genXpush(ic);
1709         return ;
1710     }
1711
1712     /* then do the push */
1713     aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1714
1715
1716         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1717     size = AOP_SIZE(IC_LEFT(ic));
1718
1719     while (size--) {
1720         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1721         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
1722             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1723             strcmp(l,"a") ) {
1724             emitcode("mov","a,%s",l);
1725             emitcode("push","acc");
1726         } else
1727             emitcode("push","%s",l);
1728     }       
1729
1730     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1731 }
1732
1733 /*-----------------------------------------------------------------*/
1734 /* genIpop - recover the registers: can happen only for spilling   */
1735 /*-----------------------------------------------------------------*/
1736 static void genIpop (iCode *ic)
1737 {
1738     int size,offset ;
1739
1740     D(emitcode(";", "genIpop "););
1741
1742
1743     /* if the temp was not pushed then */
1744     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1745         return ;
1746
1747     aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1748     size = AOP_SIZE(IC_LEFT(ic));
1749     offset = (size-1);
1750     while (size--) 
1751         emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1752                                    FALSE,TRUE));
1753
1754     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1755 }
1756
1757 /*-----------------------------------------------------------------*/
1758 /* unsaverbank - restores the resgister bank from stack            */
1759 /*-----------------------------------------------------------------*/
1760 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1761 {
1762     int i;
1763     asmop *aop ;
1764     regs *r = NULL;
1765
1766     if (popPsw) {
1767         if (options.useXstack) {
1768             aop = newAsmop(0);
1769             r = getFreePtr(ic,&aop,FALSE);
1770             
1771             
1772             emitcode("mov","%s,_spx",r->name);
1773             emitcode("movx","a,@%s",r->name);
1774             emitcode("mov","psw,a");
1775             emitcode("dec","%s",r->name);
1776             
1777         }else
1778             emitcode ("pop","psw");
1779     }
1780
1781     for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1782         if (options.useXstack) {       
1783             emitcode("movx","a,@%s",r->name);
1784             emitcode("mov","(%s+%d),a",
1785                      regs390[i].base,8*bank+regs390[i].offset);
1786             emitcode("dec","%s",r->name);
1787
1788         } else 
1789             emitcode("pop","(%s+%d)",
1790                      regs390[i].base,8*bank+regs390[i].offset);
1791     }
1792
1793     if (options.useXstack) {
1794
1795         emitcode("mov","_spx,%s",r->name);
1796         freeAsmop(NULL,aop,ic,TRUE);
1797
1798     } 
1799 }
1800
1801 /*-----------------------------------------------------------------*/
1802 /* saverbank - saves an entire register bank on the stack          */
1803 /*-----------------------------------------------------------------*/
1804 static void saverbank (int bank, iCode *ic, bool pushPsw)
1805 {
1806     int i;
1807     asmop *aop ;
1808     regs *r = NULL;
1809
1810     if (options.useXstack) {
1811
1812         aop = newAsmop(0);
1813         r = getFreePtr(ic,&aop,FALSE);  
1814         emitcode("mov","%s,_spx",r->name);
1815
1816     }
1817
1818     for (i = 0 ; i < ds390_nRegs ;i++) {
1819         if (options.useXstack) {
1820             emitcode("inc","%s",r->name);
1821             emitcode("mov","a,(%s+%d)",
1822                      regs390[i].base,8*bank+regs390[i].offset);
1823             emitcode("movx","@%s,a",r->name);           
1824         } else 
1825             emitcode("push","(%s+%d)",
1826                      regs390[i].base,8*bank+regs390[i].offset);
1827     }
1828     
1829     if (pushPsw) {
1830         if (options.useXstack) {
1831             emitcode("mov","a,psw");
1832             emitcode("movx","@%s,a",r->name);   
1833             emitcode("inc","%s",r->name);
1834             emitcode("mov","_spx,%s",r->name);       
1835             freeAsmop (NULL,aop,ic,TRUE);
1836             
1837         } else
1838             emitcode("push","psw");
1839         
1840         emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1841     }
1842     ic->bankSaved = 1;
1843
1844 }
1845
1846 /*-----------------------------------------------------------------*/
1847 /* genCall - generates a call statement                            */
1848 /*-----------------------------------------------------------------*/
1849 static void genCall (iCode *ic)
1850 {
1851     link *detype;   
1852
1853     D(emitcode(";", "genCall "););
1854
1855     /* if caller saves & we have not saved then */
1856     if (!ic->regsSaved)
1857         saveRegisters(ic);
1858
1859     /* if we are calling a function that is not using
1860     the same register bank then we need to save the
1861     destination registers on the stack */
1862     detype = getSpec(operandType(IC_LEFT(ic)));
1863     if (detype        && 
1864         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1865         IS_ISR(currFunc->etype) &&
1866         !ic->bankSaved) 
1867
1868         saverbank(SPEC_BANK(detype),ic,TRUE);
1869
1870     /* if send set is not empty the assign */
1871     if (_G.sendSet) {
1872         iCode *sic ;
1873
1874         for (sic = setFirstItem(_G.sendSet) ; sic ; 
1875              sic = setNextItem(_G.sendSet)) {
1876             int size, offset = 0;
1877         aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
1878             size = AOP_SIZE(IC_LEFT(sic));
1879             while (size--) {
1880                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1881                                 FALSE, FALSE);
1882                 if (strcmp(l,fReturn[offset]))
1883                     emitcode("mov","%s,%s",
1884                              fReturn[offset],
1885                              l);
1886                 offset++;
1887             }
1888             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1889         }
1890         _G.sendSet = NULL;
1891     }
1892     /* make the call */
1893     emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1894                            OP_SYMBOL(IC_LEFT(ic))->rname :
1895                            OP_SYMBOL(IC_LEFT(ic))->name));
1896
1897     /* if we need assign a result value */
1898     if ((IS_ITEMP(IC_RESULT(ic)) && 
1899          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1900           OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1901         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1902
1903         if (!isOperandInFarSpace(IC_RESULT(ic)))
1904         {
1905         _G.accInUse++;
1906             aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1907         _G.accInUse--;
1908
1909         assignResultValue(IC_RESULT(ic));
1910                 
1911         freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1912     }
1913         else
1914         {
1915             /* Result is in far space, and requires DPTR to access
1916              * it. Push the result onto the stack and restore from
1917              * there.
1918              */
1919             int size = getSize(operandType(IC_RESULT(ic)));
1920             int offset = size - 1;
1921             char *l;
1922             
1923             emitcode(";", "Kevin function call abuse #1");
1924
1925             /* first push the right side on to the stack */
1926             /* NB: this relies on the fact that "a" is the last
1927              * register in fReturn. If it were not, the MOVA
1928              * would potentially clobber a returned byte in A.
1929              */
1930             while (size--) {
1931                 l = fReturn[offset--];
1932                 MOVA(l);
1933                 emitcode ("push","acc");
1934             }
1935     
1936             /* now assign DPTR to result */
1937             aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1938             size = AOP_SIZE(IC_RESULT(ic));
1939             aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
1940             while (size--) {
1941                 emitcode ("pop","acc");
1942                 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
1943             }
1944             freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1945         }
1946     }
1947
1948     /* adjust the stack for parameters if 
1949     required */
1950     if (IC_LEFT(ic)->parmBytes) {
1951         int i;
1952         if (IC_LEFT(ic)->parmBytes > 3) {
1953             emitcode("mov","a,%s",spname);
1954             emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1955             emitcode("mov","%s,a",spname);
1956         } else 
1957             for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
1958                 emitcode("dec","%s",spname);
1959
1960     }
1961
1962     /* if register bank was saved then pop them */
1963     if (ic->bankSaved)
1964         unsaverbank(SPEC_BANK(detype),ic,TRUE);
1965
1966     /* if we hade saved some registers then unsave them */
1967     if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1968         unsaveRegisters (ic);
1969
1970
1971 }
1972
1973 /*-----------------------------------------------------------------*/
1974 /* genPcall - generates a call by pointer statement                */
1975 /*-----------------------------------------------------------------*/
1976 static void genPcall (iCode *ic)
1977 {
1978     link *detype;
1979     symbol *rlbl = newiTempLabel(NULL);
1980
1981     D(emitcode(";", "genPcall "););
1982
1983
1984     /* if caller saves & we have not saved then */
1985     if (!ic->regsSaved)
1986         saveRegisters(ic);
1987
1988     /* if we are calling a function that is not using
1989     the same register bank then we need to save the
1990     destination registers on the stack */
1991     detype = getSpec(operandType(IC_LEFT(ic)));
1992     if (detype        && 
1993         IS_ISR(currFunc->etype) &&
1994         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1995         saverbank(SPEC_BANK(detype),ic,TRUE);
1996
1997
1998     /* push the return address on to the stack */
1999     emitcode("mov","a,#%05d$",(rlbl->key+100));
2000     emitcode("push","acc");    
2001     emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2002     emitcode("push","acc");
2003     
2004     if (options.model == MODEL_FLAT24)
2005     {
2006         emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2007         emitcode("push","acc");    
2008     }
2009
2010     /* now push the calling address */
2011     aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2012
2013     pushSide(IC_LEFT(ic), FPTRSIZE);
2014
2015     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2016
2017     /* if send set is not empty the assign */
2018     if (_G.sendSet) {
2019         iCode *sic ;
2020
2021         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2022              sic = setNextItem(_G.sendSet)) {
2023             int size, offset = 0;
2024             aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2025             size = AOP_SIZE(IC_LEFT(sic));
2026             while (size--) {
2027                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2028                                 FALSE,FALSE);
2029                 if (strcmp(l,fReturn[offset]))
2030                     emitcode("mov","%s,%s",
2031                              fReturn[offset],
2032                              l);
2033                 offset++;
2034             }
2035             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2036         }
2037         _G.sendSet = NULL;
2038     }
2039
2040     emitcode("ret","");
2041     emitcode("","%05d$:",(rlbl->key+100));
2042
2043
2044     /* if we need assign a result value */
2045     if ((IS_ITEMP(IC_RESULT(ic)) &&
2046          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2047           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2048         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2049
2050         _G.accInUse++;
2051         aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2052         _G.accInUse--;
2053         
2054         assignResultValue(IC_RESULT(ic));
2055
2056         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2057     }
2058
2059     /* adjust the stack for parameters if 
2060     required */
2061     if (IC_LEFT(ic)->parmBytes) {
2062         int i;
2063         if (IC_LEFT(ic)->parmBytes > 3) {
2064             emitcode("mov","a,%s",spname);
2065             emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2066             emitcode("mov","%s,a",spname);
2067         } else 
2068             for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
2069                 emitcode("dec","%s",spname);
2070
2071     }
2072
2073     /* if register bank was saved then unsave them */
2074     if (detype        && 
2075         (SPEC_BANK(currFunc->etype) != 
2076          SPEC_BANK(detype)))
2077         unsaverbank(SPEC_BANK(detype),ic,TRUE);
2078
2079     /* if we hade saved some registers then
2080     unsave them */
2081     if (ic->regsSaved)
2082         unsaveRegisters (ic);
2083
2084 }
2085
2086 /*-----------------------------------------------------------------*/
2087 /* resultRemat - result  is rematerializable                       */
2088 /*-----------------------------------------------------------------*/
2089 static int resultRemat (iCode *ic)
2090 {
2091     if (SKIP_IC(ic) || ic->op == IFX)
2092         return 0;
2093
2094     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2095         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2096         if (sym->remat && !POINTER_SET(ic)) 
2097             return 1;
2098     }
2099
2100     return 0;
2101 }
2102
2103 #ifdef __BORLANDC__
2104 #define STRCASECMP stricmp
2105 #else
2106 #define STRCASECMP strcasecmp
2107 #endif
2108
2109 /*-----------------------------------------------------------------*/
2110 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2111 /*-----------------------------------------------------------------*/
2112 static bool inExcludeList(char *s)
2113 {
2114     int i =0;
2115     
2116     if (options.excludeRegs[i] &&
2117     STRCASECMP(options.excludeRegs[i],"none") == 0)
2118         return FALSE ;
2119
2120     for ( i = 0 ; options.excludeRegs[i]; i++) {
2121         if (options.excludeRegs[i] &&
2122         STRCASECMP(s,options.excludeRegs[i]) == 0)
2123             return TRUE;
2124     }
2125     return FALSE ;
2126 }
2127
2128 /*-----------------------------------------------------------------*/
2129 /* genFunction - generated code for function entry                 */
2130 /*-----------------------------------------------------------------*/
2131 static void genFunction (iCode *ic)
2132 {
2133     symbol *sym;
2134     link *fetype;
2135
2136     D(emitcode(";", "genFunction "););
2137
2138     _G.nRegsSaved = 0;
2139     /* create the function header */
2140     emitcode(";","-----------------------------------------");
2141     emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2142     emitcode(";","-----------------------------------------");
2143
2144     emitcode("","%s:",sym->rname);
2145     fetype = getSpec(operandType(IC_LEFT(ic)));
2146
2147     /* if critical function then turn interrupts off */
2148     if (SPEC_CRTCL(fetype))
2149         emitcode("clr","ea");
2150
2151     /* here we need to generate the equates for the
2152        register bank if required */
2153     if (SPEC_BANK(fetype) != rbank) {
2154         int i ;
2155
2156         rbank = SPEC_BANK(fetype);
2157         for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2158             if (strcmp(regs390[i].base,"0") == 0)
2159                 emitcode("","%s = 0x%02x",
2160                          regs390[i].dname,
2161                          8*rbank+regs390[i].offset);
2162             else
2163                 emitcode ("","%s = %s + 0x%02x",
2164                           regs390[i].dname,
2165                           regs390[i].base,
2166                           8*rbank+regs390[i].offset);
2167         }
2168     }
2169
2170     /* if this is an interrupt service routine then
2171     save acc, b, dpl, dph  */
2172     if (IS_ISR(sym->etype)) {
2173         
2174         if (!inExcludeList("acc"))          
2175             emitcode ("push","acc");    
2176         if (!inExcludeList("b"))
2177             emitcode ("push","b");
2178         if (!inExcludeList("dpl"))
2179             emitcode ("push","dpl");
2180         if (!inExcludeList("dph"))
2181             emitcode ("push","dph");
2182         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2183         {
2184             emitcode ("push", "dpx");
2185             /* Make sure we're using standard DPTR */
2186             emitcode ("push", "dps");
2187             emitcode ("mov", "dps, #0x00");
2188             if (options.stack10bit)
2189             {   
2190                 /* This ISR could conceivably use DPTR2. Better save it. */
2191                 emitcode ("push", "dpl1");
2192                 emitcode ("push", "dph1");
2193                 emitcode ("push", "dpx1");
2194             emitcode ("push", "ap");
2195             }
2196         }
2197         /* if this isr has no bank i.e. is going to
2198            run with bank 0 , then we need to save more
2199            registers :-) */
2200         if (!SPEC_BANK(sym->etype)) {
2201
2202             /* if this function does not call any other
2203                function then we can be economical and
2204                save only those registers that are used */
2205             if (! sym->hasFcall) {
2206                 int i;
2207
2208                 /* if any registers used */
2209                 if (sym->regsUsed) {
2210                     /* save the registers used */
2211                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2212                         if (bitVectBitValue(sym->regsUsed,i) ||
2213                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2214                             emitcode("push","%s",ds390_regWithIdx(i)->dname);                       
2215                     }
2216                 }
2217                 
2218             } else {
2219                 /* this function has  a function call cannot
2220                    determines register usage so we will have the
2221                    entire bank */
2222                 saverbank(0,ic,FALSE);
2223             }       
2224         }
2225     } else {
2226         /* if callee-save to be used for this function
2227            then save the registers being used in this function */
2228         if (sym->calleeSave) {
2229             int i;
2230             
2231             /* if any registers used */
2232             if (sym->regsUsed) {
2233                 /* save the registers used */
2234                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2235                     if (bitVectBitValue(sym->regsUsed,i) ||
2236                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2237                         emitcode("push","%s",ds390_regWithIdx(i)->dname);
2238                         _G.nRegsSaved++;
2239                     }
2240                 }
2241             }
2242         }
2243     }
2244
2245     /* set the register bank to the desired value */
2246     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2247         emitcode("push","psw");
2248         emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);   
2249     }
2250
2251     if (IS_RENT(sym->etype) || options.stackAuto) {
2252
2253         if (options.useXstack) {
2254             emitcode("mov","r0,%s",spname);
2255             emitcode("mov","a,_bp");
2256             emitcode("movx","@r0,a");
2257             emitcode("inc","%s",spname);
2258         }
2259         else
2260         {
2261             /* set up the stack */
2262             emitcode ("push","_bp");     /* save the callers stack  */
2263         }
2264         emitcode ("mov","_bp,%s",spname);
2265     }
2266
2267     /* adjust the stack for the function */
2268     if (sym->stack) {
2269
2270         int i = sym->stack;
2271         if (i > 256 ) 
2272             werror(W_STACK_OVERFLOW,sym->name);
2273
2274         if (i > 3 && sym->recvSize < 4) {              
2275
2276             emitcode ("mov","a,sp");
2277             emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2278             emitcode ("mov","sp,a");
2279            
2280         }
2281         else
2282             while(i--)
2283                 emitcode("inc","sp");
2284     }
2285
2286      if (sym->xstack) {
2287
2288         emitcode ("mov","a,_spx");
2289         emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2290         emitcode ("mov","_spx,a");
2291     }    
2292
2293 }
2294
2295 /*-----------------------------------------------------------------*/
2296 /* genEndFunction - generates epilogue for functions               */
2297 /*-----------------------------------------------------------------*/
2298 static void genEndFunction (iCode *ic)
2299 {
2300     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2301
2302     D(emitcode(";", "genEndFunction "););
2303
2304     if (IS_RENT(sym->etype) || options.stackAuto)
2305     {
2306         emitcode ("mov","%s,_bp",spname);
2307     }
2308
2309     /* if use external stack but some variables were
2310     added to the local stack then decrement the
2311     local stack */
2312     if (options.useXstack && sym->stack) {      
2313         emitcode("mov","a,sp");
2314         emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2315         emitcode("mov","sp,a");
2316     }
2317
2318
2319     if ((IS_RENT(sym->etype) || options.stackAuto)) {
2320         if (options.useXstack) {
2321             emitcode("mov","r0,%s",spname);
2322             emitcode("movx","a,@r0");
2323             emitcode("mov","_bp,a");
2324             emitcode("dec","%s",spname);
2325         }
2326         else
2327         {
2328             emitcode ("pop","_bp");
2329         }
2330     }
2331
2332     /* restore the register bank  */    
2333     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2334         emitcode ("pop","psw");
2335
2336     if (IS_ISR(sym->etype)) {
2337
2338         /* now we need to restore the registers */
2339         /* if this isr has no bank i.e. is going to
2340            run with bank 0 , then we need to save more
2341            registers :-) */
2342         if (!SPEC_BANK(sym->etype)) {
2343             
2344             /* if this function does not call any other
2345                function then we can be economical and
2346                save only those registers that are used */
2347             if (! sym->hasFcall) {
2348                 int i;
2349                 
2350                 /* if any registers used */
2351                 if (sym->regsUsed) {
2352                     /* save the registers used */
2353                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2354                         if (bitVectBitValue(sym->regsUsed,i) ||
2355                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2356                             emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2357                     }
2358                 }
2359                 
2360             } else {
2361                 /* this function has  a function call cannot
2362                    determines register usage so we will have the
2363                    entire bank */
2364                 unsaverbank(0,ic,FALSE);
2365             }       
2366         }
2367
2368         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2369         {
2370             if (options.stack10bit)
2371             {
2372             emitcode ("pop", "ap");
2373                 emitcode ("pop", "dpx1");
2374                 emitcode ("pop", "dph1");
2375                 emitcode ("pop", "dpl1");
2376             }   
2377             emitcode ("pop", "dps");
2378             emitcode ("pop", "dpx");
2379         }
2380         if (!inExcludeList("dph"))
2381             emitcode ("pop","dph");
2382         if (!inExcludeList("dpl"))
2383             emitcode ("pop","dpl");
2384         if (!inExcludeList("b"))
2385             emitcode ("pop","b");
2386         if (!inExcludeList("acc"))
2387             emitcode ("pop","acc");
2388
2389         if (SPEC_CRTCL(sym->etype))
2390             emitcode("setb","ea");
2391
2392         /* if debug then send end of function */
2393 /*      if (options.debug && currFunc) { */
2394         if (currFunc) {
2395             _G.debugLine = 1;
2396             emitcode("","C$%s$%d$%d$%d ==.",
2397                      ic->filename,currFunc->lastLine,
2398                      ic->level,ic->block); 
2399             if (IS_STATIC(currFunc->etype))         
2400                 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2401             else
2402                 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2403             _G.debugLine = 0;
2404         }
2405         
2406         emitcode ("reti","");
2407     }
2408     else {
2409         if (SPEC_CRTCL(sym->etype))
2410             emitcode("setb","ea");
2411         
2412         if (sym->calleeSave) {
2413             int i;
2414             
2415             /* if any registers used */
2416             if (sym->regsUsed) {
2417                 /* save the registers used */
2418                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2419                     if (bitVectBitValue(sym->regsUsed,i) ||
2420                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2421                         emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2422                 }
2423             }
2424             
2425         }
2426
2427         /* if debug then send end of function */
2428         if (currFunc) {
2429             _G.debugLine = 1;
2430             emitcode("","C$%s$%d$%d$%d ==.",
2431                      ic->filename,currFunc->lastLine,
2432                      ic->level,ic->block); 
2433             if (IS_STATIC(currFunc->etype))         
2434                 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2435             else
2436                 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2437             _G.debugLine = 0;
2438         }
2439
2440         emitcode ("ret","");
2441     }
2442
2443 }
2444
2445 /*-----------------------------------------------------------------*/
2446 /* genRet - generate code for return statement                     */
2447 /*-----------------------------------------------------------------*/
2448 static void genRet (iCode *ic)
2449 {
2450     int size,offset = 0 , pushed = 0;
2451     
2452     D(emitcode(";", "genRet "););
2453
2454     /* if we have no return value then
2455        just generate the "ret" */
2456     if (!IC_LEFT(ic)) 
2457         goto jumpret;       
2458     
2459     /* we have something to return then
2460        move the return value into place */
2461     aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2462     size = AOP_SIZE(IC_LEFT(ic));
2463     
2464     while (size--) {
2465             char *l ;
2466             if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2467                     /* #NOCHANGE */
2468                     l = aopGet(AOP(IC_LEFT(ic)),offset++,
2469                            FALSE,TRUE);
2470                     emitcode("push","%s",l);
2471                     pushed++;
2472             } else {
2473                     l = aopGet(AOP(IC_LEFT(ic)),offset,
2474                                FALSE,FALSE);
2475                     if (strcmp(fReturn[offset],l))
2476                             emitcode("mov","%s,%s",fReturn[offset++],l);
2477             }
2478     }    
2479
2480     if (pushed) {
2481         while(pushed) {
2482             pushed--;
2483             if (strcmp(fReturn[pushed],"a"))
2484                 emitcode("pop",fReturn[pushed]);
2485             else
2486                 emitcode("pop","acc");
2487         }
2488     }
2489     freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2490     
2491  jumpret:
2492         /* generate a jump to the return label
2493            if the next is not the return statement */
2494     if (!(ic->next && ic->next->op == LABEL &&
2495           IC_LABEL(ic->next) == returnLabel))
2496         
2497         emitcode("ljmp","%05d$",(returnLabel->key+100));
2498     
2499 }
2500
2501 /*-----------------------------------------------------------------*/
2502 /* genLabel - generates a label                                    */
2503 /*-----------------------------------------------------------------*/
2504 static void genLabel (iCode *ic)
2505 {
2506     /* special case never generate */
2507     if (IC_LABEL(ic) == entryLabel)
2508         return ;
2509
2510     D(emitcode(";", "genLabel "););
2511
2512     emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2513 }
2514
2515 /*-----------------------------------------------------------------*/
2516 /* genGoto - generates a ljmp                                      */
2517 /*-----------------------------------------------------------------*/
2518 static void genGoto (iCode *ic)
2519 {
2520     D(emitcode(";", "genGoto "););
2521     emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2522 }
2523
2524 /*-----------------------------------------------------------------*/
2525 /* findLabelBackwards: walks back through the iCode chain looking  */
2526 /* for the given label. Returns number of iCode instructions       */
2527 /* between that label and given ic.                                */
2528 /* Returns zero if label not found.                                */
2529 /*-----------------------------------------------------------------*/
2530 static int findLabelBackwards(iCode *ic, int key)
2531 {
2532     int count = 0;
2533     
2534     while (ic->prev)
2535     {
2536         ic = ic->prev;
2537         count++;
2538         
2539         if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2540         {
2541             /* printf("findLabelBackwards = %d\n", count); */
2542             return count;
2543         }
2544     }
2545     
2546     return 0;
2547 }
2548
2549 /*-----------------------------------------------------------------*/
2550 /* genPlusIncr :- does addition with increment if possible         */
2551 /*-----------------------------------------------------------------*/
2552 static bool genPlusIncr (iCode *ic)
2553 {
2554     unsigned int icount ;
2555     unsigned int size = getDataSize(IC_RESULT(ic));
2556     
2557     /* will try to generate an increment */
2558     /* if the right side is not a literal 
2559        we cannot */
2560     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2561         return FALSE ;
2562     
2563     /* if the literal value of the right hand side
2564        is greater than 4 then it is not worth it */
2565     if ((icount =  floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2566         return FALSE ;
2567     
2568     /* if increment 16 bits in register */
2569     if (
2570         AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2571         AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2572         sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2573         (size > 1) &&
2574         (icount == 1)) {
2575         symbol *tlbl;
2576         int emitTlbl;
2577         int labelRange;
2578
2579         /* If the next instruction is a goto and the goto target
2580          * is < 10 instructions previous to this, we can generate
2581          * jumps straight to that target.
2582          */
2583         if (ic->next && ic->next->op == GOTO
2584             && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2585             && labelRange <= 10 )
2586         {
2587            emitcode(";", "tail increment optimized");
2588            tlbl = IC_LABEL(ic->next);
2589            emitTlbl = 0;
2590         }
2591         else
2592         {
2593             tlbl = newiTempLabel(NULL);
2594             emitTlbl = 1;
2595         }
2596         emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2597         if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2598            IS_AOP_PREG(IC_RESULT(ic)))
2599             emitcode("cjne","%s,#0x00,%05d$"
2600                      ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2601                      ,tlbl->key+100);
2602         else {
2603             emitcode("clr","a");
2604             emitcode("cjne","a,%s,%05d$"
2605                      ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2606                      ,tlbl->key+100);
2607         }
2608     
2609         emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2610         if (size > 2)
2611         {
2612             if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2613                IS_AOP_PREG(IC_RESULT(ic)))
2614                 emitcode("cjne","%s,#0x00,%05d$"
2615                          ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2616                          ,tlbl->key+100);
2617             else
2618                 emitcode("cjne","a,%s,%05d$"
2619                          ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2620                          ,tlbl->key+100);
2621             
2622             emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2623        }
2624        if (size > 3)
2625        {
2626             if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2627                IS_AOP_PREG(IC_RESULT(ic)))
2628                 emitcode("cjne","%s,#0x00,%05d$"
2629                          ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2630                          ,tlbl->key+100);
2631             else{
2632                 emitcode("cjne","a,%s,%05d$"
2633                          ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2634                          ,tlbl->key+100);
2635             }
2636             emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2637         }
2638         
2639         if (emitTlbl)
2640         {
2641             emitcode("","%05d$:",tlbl->key+100);
2642         }
2643         return TRUE;
2644     }
2645     
2646     /* if the sizes are greater than 1 then we cannot */
2647     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2648         AOP_SIZE(IC_LEFT(ic)) > 1   )
2649         return FALSE ;
2650     
2651     /* we can if the aops of the left & result match or
2652        if they are in registers and the registers are the
2653        same */
2654     if (
2655         AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2656         AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2657         sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2658         
2659         if (icount > 3) {
2660             MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));       
2661             emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2662             aopPut(AOP(IC_RESULT(ic)),"a",0);
2663         } else {
2664             
2665             while (icount--) 
2666                 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2667         }
2668         
2669         return TRUE ;
2670     }
2671     
2672     return FALSE ;
2673 }
2674
2675 /*-----------------------------------------------------------------*/
2676 /* outBitAcc - output a bit in acc                                 */
2677 /*-----------------------------------------------------------------*/
2678 static void outBitAcc(operand *result)
2679 {
2680     symbol *tlbl = newiTempLabel(NULL);
2681     /* if the result is a bit */
2682     if (AOP_TYPE(result) == AOP_CRY){
2683         aopPut(AOP(result),"a",0);
2684     }
2685     else {
2686         emitcode("jz","%05d$",tlbl->key+100);
2687         emitcode("mov","a,%s",one);
2688         emitcode("","%05d$:",tlbl->key+100);
2689         outAcc(result);
2690     }
2691 }
2692
2693 /*-----------------------------------------------------------------*/
2694 /* genPlusBits - generates code for addition of two bits           */
2695 /*-----------------------------------------------------------------*/
2696 static void genPlusBits (iCode *ic)
2697 {
2698     D(emitcode(";", "genPlusBits "););
2699     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2700         symbol *lbl = newiTempLabel(NULL);
2701         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2702         emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2703         emitcode("cpl","c");
2704         emitcode("","%05d$:",(lbl->key+100));
2705         outBitC(IC_RESULT(ic));
2706     }
2707     else{
2708         emitcode("clr","a");
2709         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2710         emitcode("rlc","a");
2711         emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2712         emitcode("addc","a,#0x00");
2713         outAcc(IC_RESULT(ic));
2714     }
2715 }
2716
2717
2718
2719 #if 0
2720 /* This is the original version of this code.
2721  *
2722  * This is being kept around for reference, 
2723  * because I am not entirely sure I got it right...
2724  */
2725 static void adjustArithmeticResult(iCode *ic)
2726 {
2727     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
2728         AOP_SIZE(IC_LEFT(ic)) == 3   &&
2729         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2730         aopPut(AOP(IC_RESULT(ic)),
2731                aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2732                2);
2733
2734     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
2735         AOP_SIZE(IC_RIGHT(ic)) == 3   &&
2736         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2737         aopPut(AOP(IC_RESULT(ic)),
2738                aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2739                2);
2740     
2741     if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2742         AOP_SIZE(IC_LEFT(ic)) < 3    &&
2743         AOP_SIZE(IC_RIGHT(ic)) < 3   &&
2744         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2745         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2746         char buffer[5];
2747         sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2748         aopPut(AOP(IC_RESULT(ic)),buffer,2);
2749     }
2750 }
2751 #else
2752 /* This is the pure and virtuous version of this code.
2753  * I'm pretty certain it's right, but not enough to toss the old 
2754  * code just yet...
2755  */
2756 static void adjustArithmeticResult(iCode *ic)
2757 {
2758     if (opIsGptr(IC_RESULT(ic)) &&
2759         opIsGptr(IC_LEFT(ic))   &&
2760         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2761     {
2762         aopPut(AOP(IC_RESULT(ic)),
2763                aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2764                GPTRSIZE - 1);
2765     }
2766
2767     if (opIsGptr(IC_RESULT(ic)) &&
2768         opIsGptr(IC_RIGHT(ic))   &&
2769         !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2770     {
2771         aopPut(AOP(IC_RESULT(ic)),
2772                aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2773                GPTRSIZE - 1);
2774     }
2775
2776     if (opIsGptr(IC_RESULT(ic))            &&
2777         AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
2778         AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
2779          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2780          !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2781          char buffer[5];
2782          sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2783          aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2784      }
2785 }
2786 #endif
2787
2788 #define AOP_OP_3(ic) \
2789     aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2790     aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2791     aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2792     if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2793         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2794     { \
2795         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2796         fprintf(stderr,                                  \
2797                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
2798     }
2799
2800 #define AOP_SET_LOCALS(ic) \
2801     left = IC_LEFT(ic); \
2802     right = IC_RIGHT(ic); \
2803     result = IC_RESULT(ic);
2804
2805 /*-----------------------------------------------------------------*/
2806 /* genPlus - generates code for addition                           */
2807 /*-----------------------------------------------------------------*/
2808 static void genPlus (iCode *ic)
2809 {
2810     int size, offset = 0;
2811     bool pushResult = FALSE;
2812
2813     D(emitcode(";", "genPlus "););
2814
2815     /* special cases :- */
2816
2817     aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
2818     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2819     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
2820         (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
2821     {
2822         pushResult = TRUE;
2823     }
2824     else
2825     {
2826         aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR);
2827
2828     /* if literal, literal on the right or
2829        if left requires ACC or right is already
2830        in ACC */
2831     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2832         (AOP_NEEDSACC(IC_LEFT(ic))) ||
2833         AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2834         operand *t = IC_RIGHT(ic);
2835         IC_RIGHT(ic) = IC_LEFT(ic);
2836         IC_LEFT(ic) = t;
2837     }
2838
2839     /* if both left & right are in bit
2840     space */
2841     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2842         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2843         genPlusBits (ic);
2844         goto release ;
2845     }
2846
2847     /* if left in bit space & right literal */
2848     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2849         AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2850         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2851         /* if result in bit space */
2852         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2853             if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2854                 emitcode("cpl","c");
2855             outBitC(IC_RESULT(ic));
2856         } else {
2857             size = getDataSize(IC_RESULT(ic));
2858             while (size--) {
2859                 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));  
2860                 emitcode("addc","a,#00");
2861                 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2862             }
2863         }
2864         goto release ;
2865     }
2866
2867     /* if I can do an increment instead
2868     of add then GOOD for ME */
2869     if (genPlusIncr (ic) == TRUE)
2870         goto release;   
2871
2872     }
2873     size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
2874
2875     while(size--){
2876         if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2877             MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2878             if(offset == 0)
2879                 emitcode("add","a,%s",
2880                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2881             else
2882                 emitcode("addc","a,%s",
2883                          aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2884         } else {
2885             MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2886             if(offset == 0)
2887                 emitcode("add","a,%s",
2888                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2889             else
2890                 emitcode("addc","a,%s",
2891                          aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2892         }
2893         if (!pushResult)
2894         {
2895             aopPut(AOP(IC_RESULT(ic)),"a",offset);
2896         }
2897         else
2898         {
2899             emitcode("push", "acc");
2900         }
2901         offset++;
2902     }
2903
2904     if (pushResult)
2905     {
2906         aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2907
2908         size = getDataSize(IC_LEFT(ic));
2909
2910         while(size--)
2911         {
2912             emitcode("pop", "acc");
2913             aopPut(AOP(IC_RESULT(ic)), "a", --offset);
2914         }
2915     }
2916
2917     adjustArithmeticResult(ic);
2918
2919 release:
2920     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2921     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2922     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2923 }
2924
2925 /*-----------------------------------------------------------------*/
2926 /* genMinusDec :- does subtraction with deccrement if possible     */
2927 /*-----------------------------------------------------------------*/
2928 static bool genMinusDec (iCode *ic)
2929 {
2930     unsigned int icount ;
2931     unsigned int size = getDataSize(IC_RESULT(ic));
2932
2933     /* will try to generate an increment */
2934     /* if the right side is not a literal 
2935     we cannot */
2936     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2937         return FALSE ;
2938
2939     /* if the literal value of the right hand side
2940     is greater than 4 then it is not worth it */
2941     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2942         return FALSE ;
2943
2944     /* if decrement 16 bits in register */
2945     if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2946         AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2947         sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2948         (size > 1) &&
2949         (icount == 1)) {
2950             symbol *tlbl;
2951             int emitTlbl;
2952             int labelRange;
2953
2954             /* If the next instruction is a goto and the goto target
2955              * is <= 10 instructions previous to this, we can generate
2956              * jumps straight to that target.
2957              */
2958             if (ic->next && ic->next->op == GOTO
2959                 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2960                 && labelRange <= 10 )
2961             {        
2962                emitcode(";", "tail decrement optimized");
2963                tlbl = IC_LABEL(ic->next);
2964                emitTlbl = 0;
2965             }
2966             else
2967             {
2968                 tlbl = newiTempLabel(NULL);
2969                 emitTlbl = 1;
2970             }
2971         
2972                 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2973                 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2974                    AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2975                    IS_AOP_PREG(IC_RESULT(ic)))
2976                         emitcode("cjne","%s,#0xff,%05d$"
2977                                          ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2978                                          ,tlbl->key+100);
2979                 else{
2980                         emitcode("mov","a,#0xff");
2981                         emitcode("cjne","a,%s,%05d$"
2982                                          ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2983                                          ,tlbl->key+100);
2984                 }
2985                 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2986                 if (size > 2)
2987                 {
2988                         if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2989                            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2990                            IS_AOP_PREG(IC_RESULT(ic)))
2991                                 emitcode("cjne","%s,#0xff,%05d$"
2992                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2993                                                  ,tlbl->key+100);
2994                         else{
2995                                 emitcode("cjne","a,%s,%05d$"
2996                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2997                                                  ,tlbl->key+100);
2998                         }
2999                         emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
3000                 }
3001                 if (size > 3)
3002                 {
3003                         if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3004                            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3005                            IS_AOP_PREG(IC_RESULT(ic)))
3006                                 emitcode("cjne","%s,#0xff,%05d$"
3007                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
3008                                                  ,tlbl->key+100);
3009                         else{
3010                                 emitcode("cjne","a,%s,%05d$"
3011                                                  ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
3012                                                  ,tlbl->key+100);
3013                         }
3014                         emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3015                 }
3016                 if (emitTlbl)
3017                 {
3018                     emitcode("","%05d$:",tlbl->key+100);
3019                 }
3020         return TRUE;
3021     }
3022
3023     /* if the sizes are greater than 1 then we cannot */
3024     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3025         AOP_SIZE(IC_LEFT(ic)) > 1   )
3026         return FALSE ;
3027
3028     /* we can if the aops of the left & result match or
3029     if they are in registers and the registers are the
3030     same */
3031     if (
3032         AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3033         AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3034         sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3035
3036         while (icount--) 
3037             emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3038
3039         return TRUE ;
3040     }
3041
3042     return FALSE ;
3043 }
3044
3045 /*-----------------------------------------------------------------*/
3046 /* addSign - complete with sign                                    */
3047 /*-----------------------------------------------------------------*/
3048 static void addSign(operand *result, int offset, int sign)
3049 {
3050     int size = (getDataSize(result) - offset);
3051     if(size > 0){
3052         if(sign){
3053             emitcode("rlc","a");
3054             emitcode("subb","a,acc");
3055             while(size--)
3056                 aopPut(AOP(result),"a",offset++); 
3057         } else
3058             while(size--)
3059                 aopPut(AOP(result),zero,offset++);
3060     }
3061 }
3062
3063 /*-----------------------------------------------------------------*/
3064 /* genMinusBits - generates code for subtraction  of two bits      */
3065 /*-----------------------------------------------------------------*/
3066 static void genMinusBits (iCode *ic)
3067 {
3068     symbol *lbl = newiTempLabel(NULL);
3069     
3070     D(emitcode(";", "genMinusBits "););    
3071
3072     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3073         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3074         emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3075         emitcode("cpl","c");
3076         emitcode("","%05d$:",(lbl->key+100));
3077         outBitC(IC_RESULT(ic));
3078     }
3079     else{
3080         emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3081         emitcode("subb","a,acc");
3082         emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3083         emitcode("inc","a");
3084         emitcode("","%05d$:",(lbl->key+100));
3085         aopPut(AOP(IC_RESULT(ic)),"a",0);
3086         addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3087     }
3088 }
3089
3090 /*-----------------------------------------------------------------*/
3091 /* genMinus - generates code for subtraction                       */
3092 /*-----------------------------------------------------------------*/
3093 static void genMinus (iCode *ic)
3094 {
3095     int size, offset = 0;
3096     unsigned long lit = 0L;
3097     bool pushResult = FALSE;
3098
3099     D(emitcode(";", "genMinus "););
3100
3101     aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3102     aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3103     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3104         (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3105     {
3106         pushResult = TRUE;
3107     }
3108     else
3109     {
3110         aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3111
3112     /* special cases :- */
3113     /* if both left & right are in bit space */
3114     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3115         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3116         genMinusBits (ic);
3117         goto release ;
3118     }
3119
3120     /* if I can do an decrement instead
3121     of subtract then GOOD for ME */
3122     if (genMinusDec (ic) == TRUE)
3123         goto release;
3124
3125     }
3126
3127     size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3128
3129     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3130         CLRC;
3131     }
3132     else{
3133         lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3134         lit = - (long)lit;
3135     }
3136
3137
3138     /* if literal, add a,#-lit, else normal subb */
3139     while (size--) {
3140         MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));    
3141         if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)  
3142             emitcode("subb","a,%s",
3143                      aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3144         else{
3145             /* first add without previous c */
3146             if(!offset)
3147                 emitcode("add","a,#0x%02x",
3148                          (unsigned int)(lit & 0x0FFL));
3149             else
3150                 emitcode("addc","a,#0x%02x",
3151                          (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3152         }
3153
3154         if (pushResult)
3155         {
3156             emitcode("push", "acc");
3157         }
3158         else
3159         {
3160             aopPut(AOP(IC_RESULT(ic)),"a",offset);
3161         }
3162         offset++;
3163     }
3164
3165     if (pushResult)
3166     {
3167         aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3168
3169         size = getDataSize(IC_LEFT(ic));
3170
3171         while(size--)
3172         {
3173             emitcode("pop", "acc");
3174             aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3175         }
3176     }
3177
3178     adjustArithmeticResult(ic);
3179         
3180 release:
3181     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3182     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3183     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3184 }
3185
3186
3187 /*-----------------------------------------------------------------*/
3188 /* genMultbits :- multiplication of bits                           */
3189 /*-----------------------------------------------------------------*/
3190 static void genMultbits (operand *left, 
3191                          operand *right, 
3192                          operand *result)
3193 {
3194     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3195     emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3196     outBitC(result);
3197 }
3198
3199
3200 /*-----------------------------------------------------------------*/
3201 /* genMultOneByte : 8 bit multiplication & division                */
3202 /*-----------------------------------------------------------------*/
3203 static void genMultOneByte (operand *left,
3204                             operand *right,
3205                             operand *result)
3206 {
3207     link *opetype = operandType(result);
3208     char *l ;
3209     symbol *lbl ;
3210     int size,offset;
3211
3212     /* (if two literals, the value is computed before) */
3213     /* if one literal, literal on the right */
3214     if (AOP_TYPE(left) == AOP_LIT){
3215         operand *t = right;
3216         right = left;
3217         left = t;
3218     }
3219
3220     size = AOP_SIZE(result);
3221     /* signed or unsigned */
3222     emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3223     l = aopGet(AOP(left),0,FALSE,FALSE);
3224     MOVA(l);       
3225     emitcode("mul","ab");
3226     /* if result size = 1, mul signed = mul unsigned */
3227     aopPut(AOP(result),"a",0);
3228     if (size > 1){
3229         if (SPEC_USIGN(opetype)){
3230             aopPut(AOP(result),"b",1);
3231             if (size > 2)
3232                 /* for filling the MSBs */
3233                 emitcode("clr","a");
3234         }
3235         else{
3236             emitcode("mov","a,b");
3237
3238             /* adjust the MSB if left or right neg */
3239
3240             /* if one literal */
3241             if (AOP_TYPE(right) == AOP_LIT){
3242                 /* AND literal negative */
3243                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3244                     /* adjust MSB (c==0 after mul) */
3245                     emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3246                 }
3247             }
3248             else{
3249                 lbl = newiTempLabel(NULL);
3250                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3251                 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3252                 emitcode("","%05d$:",(lbl->key+100));
3253                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3254                 lbl = newiTempLabel(NULL);      
3255                 emitcode("jc","%05d$",(lbl->key+100));          
3256                 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3257                 emitcode("","%05d$:",(lbl->key+100));
3258             }
3259
3260             lbl = newiTempLabel(NULL);
3261             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3262             emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3263             emitcode("","%05d$:",(lbl->key+100));
3264             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3265             lbl = newiTempLabel(NULL);      
3266             emitcode("jc","%05d$",(lbl->key+100));          
3267             emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3268             emitcode("","%05d$:",(lbl->key+100));
3269
3270             aopPut(AOP(result),"a",1);
3271             if(size > 2){
3272                 /* get the sign */
3273                 emitcode("rlc","a");
3274                 emitcode("subb","a,acc");
3275             }
3276         }
3277         size -= 2;   
3278         offset = 2;
3279         if (size > 0)
3280             while (size--)
3281                 aopPut(AOP(result),"a",offset++);
3282     }
3283 }
3284
3285 /*-----------------------------------------------------------------*/
3286 /* genMult - generates code for multiplication                     */
3287 /*-----------------------------------------------------------------*/
3288 static void genMult (iCode *ic)
3289 {
3290     operand *left = IC_LEFT(ic);
3291     operand *right = IC_RIGHT(ic);
3292     operand *result= IC_RESULT(ic);   
3293
3294     D(emitcode(";", "genMult "););
3295
3296     /* assign the amsops */
3297     AOP_OP_3(ic);
3298 #if 0
3299     aopOp (left,ic,FALSE, FALSE);
3300     aopOp (right,ic,FALSE, TRUE);
3301     aopOp (result,ic,TRUE, FALSE);
3302 #endif
3303
3304     /* special cases first */
3305     /* both are bits */
3306     if (AOP_TYPE(left) == AOP_CRY &&
3307         AOP_TYPE(right)== AOP_CRY) {
3308         genMultbits(left,right,result);
3309         goto release ;
3310     }
3311
3312     /* if both are of size == 1 */
3313     if (AOP_SIZE(left) == 1 &&
3314         AOP_SIZE(right) == 1 ) {
3315         genMultOneByte(left,right,result);
3316         goto release ;
3317     }
3318
3319     /* should have been converted to function call */       
3320     assert(1) ;
3321
3322 release :
3323     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3324     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3325     freeAsmop(result,NULL,ic,TRUE); 
3326 }
3327
3328 /*-----------------------------------------------------------------*/
3329 /* genDivbits :- division of bits                                  */
3330 /*-----------------------------------------------------------------*/
3331 static void genDivbits (operand *left, 
3332                         operand *right, 
3333                         operand *result)
3334 {
3335
3336     char *l;
3337
3338     /* the result must be bit */
3339     LOAD_AB_FOR_DIV(left, right, l);
3340     emitcode("div","ab");
3341     emitcode("rrc","a");
3342     aopPut(AOP(result),"c",0);
3343 }
3344
3345 /*-----------------------------------------------------------------*/
3346 /* genDivOneByte : 8 bit division                                  */
3347 /*-----------------------------------------------------------------*/
3348 static void genDivOneByte (operand *left,
3349                            operand *right,
3350                            operand *result)
3351 {
3352     link *opetype = operandType(result);
3353     char *l ;
3354     symbol *lbl ;
3355     int size,offset;
3356
3357     size = AOP_SIZE(result) - 1;
3358     offset = 1;
3359     /* signed or unsigned */
3360     if (SPEC_USIGN(opetype)) {
3361         /* unsigned is easy */
3362         LOAD_AB_FOR_DIV(left, right, l);
3363         emitcode("div","ab");
3364         aopPut(AOP(result),"a",0);
3365         while (size--)
3366             aopPut(AOP(result),zero,offset++);
3367         return ;
3368     }
3369
3370     /* signed is a little bit more difficult */
3371
3372     /* save the signs of the operands */
3373     l = aopGet(AOP(left),0,FALSE,FALSE);    
3374     MOVA(l);    
3375     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3376     emitcode("push","acc"); /* save it on the stack */
3377
3378     /* now sign adjust for both left & right */
3379     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3380     MOVA(l);       
3381     lbl = newiTempLabel(NULL);
3382     emitcode("jnb","acc.7,%05d$",(lbl->key+100));   
3383     emitcode("cpl","a");   
3384     emitcode("inc","a");
3385     emitcode("","%05d$:",(lbl->key+100));
3386     emitcode("mov","b,a");
3387
3388     /* sign adjust left side */
3389     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3390     MOVA(l);
3391
3392     lbl = newiTempLabel(NULL);
3393     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3394     emitcode("cpl","a");
3395     emitcode("inc","a");
3396     emitcode("","%05d$:",(lbl->key+100));
3397
3398     /* now the division */
3399     emitcode("nop", "; workaround for DS80C390 div bug.");
3400     emitcode("div","ab");
3401     /* we are interested in the lower order
3402     only */
3403     emitcode("mov","b,a");
3404     lbl = newiTempLabel(NULL);
3405     emitcode("pop","acc");   
3406     /* if there was an over flow we don't 
3407     adjust the sign of the result */
3408     emitcode("jb","ov,%05d$",(lbl->key+100));
3409     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3410     CLRC;
3411     emitcode("clr","a");
3412     emitcode("subb","a,b");
3413     emitcode("mov","b,a");
3414     emitcode("","%05d$:",(lbl->key+100));
3415
3416     /* now we are done */
3417     aopPut(AOP(result),"b",0);
3418     if(size > 0){
3419         emitcode("mov","c,b.7");
3420         emitcode("subb","a,acc");   
3421     }
3422     while (size--)
3423         aopPut(AOP(result),"a",offset++);
3424
3425 }
3426
3427 /*-----------------------------------------------------------------*/
3428 /* genDiv - generates code for division                            */
3429 /*-----------------------------------------------------------------*/
3430 static void genDiv (iCode *ic)
3431 {
3432     operand *left = IC_LEFT(ic);
3433     operand *right = IC_RIGHT(ic);
3434     operand *result= IC_RESULT(ic);   
3435
3436     D(emitcode(";", "genDiv "););
3437
3438     /* assign the amsops */
3439     AOP_OP_3(ic);
3440 #if 0
3441     aopOp (left,ic,FALSE, FALSE);
3442     aopOp (right,ic,FALSE, TRUE);
3443     aopOp (result,ic,TRUE, FALSE);
3444 #endif
3445
3446     /* special cases first */
3447     /* both are bits */
3448     if (AOP_TYPE(left) == AOP_CRY &&
3449         AOP_TYPE(right)== AOP_CRY) {
3450         genDivbits(left,right,result);
3451         goto release ;
3452     }
3453
3454     /* if both are of size == 1 */
3455     if (AOP_SIZE(left) == 1 &&
3456         AOP_SIZE(right) == 1 ) {
3457         genDivOneByte(left,right,result);
3458         goto release ;
3459     }
3460
3461     /* should have been converted to function call */
3462     assert(1);
3463 release :
3464     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3465     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3466     freeAsmop(result,NULL,ic,TRUE); 
3467 }
3468
3469 /*-----------------------------------------------------------------*/
3470 /* genModbits :- modulus of bits                                   */
3471 /*-----------------------------------------------------------------*/
3472 static void genModbits (operand *left, 
3473                         operand *right, 
3474                         operand *result)
3475 {
3476
3477     char *l;
3478
3479     /* the result must be bit */    
3480     LOAD_AB_FOR_DIV(left, right, l);
3481     emitcode("div","ab");
3482     emitcode("mov","a,b");
3483     emitcode("rrc","a");
3484     aopPut(AOP(result),"c",0);
3485 }
3486
3487 /*-----------------------------------------------------------------*/
3488 /* genModOneByte : 8 bit modulus                                   */
3489 /*-----------------------------------------------------------------*/
3490 static void genModOneByte (operand *left,
3491                            operand *right,
3492                            operand *result)
3493 {
3494     link *opetype = operandType(result);
3495     char *l ;
3496     symbol *lbl ;
3497
3498     /* signed or unsigned */
3499     if (SPEC_USIGN(opetype)) {
3500         /* unsigned is easy */
3501         LOAD_AB_FOR_DIV(left, right, l);
3502         emitcode("div","ab");
3503         aopPut(AOP(result),"b",0);
3504         return ;
3505     }
3506
3507     /* signed is a little bit more difficult */
3508
3509     /* save the signs of the operands */
3510     l = aopGet(AOP(left),0,FALSE,FALSE);    
3511     MOVA(l);
3512
3513     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3514     emitcode("push","acc"); /* save it on the stack */
3515
3516     /* now sign adjust for both left & right */
3517     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3518     MOVA(l);
3519
3520     lbl = newiTempLabel(NULL);
3521     emitcode("jnb","acc.7,%05d$",(lbl->key+100));  
3522     emitcode("cpl","a");   
3523     emitcode("inc","a");
3524     emitcode("","%05d$:",(lbl->key+100));
3525     emitcode("mov","b,a"); 
3526
3527     /* sign adjust left side */
3528     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3529     MOVA(l);
3530
3531     lbl = newiTempLabel(NULL);
3532     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3533     emitcode("cpl","a");   
3534     emitcode("inc","a");
3535     emitcode("","%05d$:",(lbl->key+100));
3536
3537     /* now the multiplication */
3538     emitcode("nop", "; workaround for DS80C390 div bug.");
3539     emitcode("div","ab");
3540     /* we are interested in the lower order
3541     only */
3542     lbl = newiTempLabel(NULL);
3543     emitcode("pop","acc");   
3544     /* if there was an over flow we don't 
3545     adjust the sign of the result */
3546     emitcode("jb","ov,%05d$",(lbl->key+100));
3547     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3548     CLRC ;
3549     emitcode("clr","a");
3550     emitcode("subb","a,b");
3551     emitcode("mov","b,a");
3552     emitcode("","%05d$:",(lbl->key+100));
3553
3554     /* now we are done */
3555     aopPut(AOP(result),"b",0);
3556
3557 }
3558
3559 /*-----------------------------------------------------------------*/
3560 /* genMod - generates code for division                            */
3561 /*-----------------------------------------------------------------*/
3562 static void genMod (iCode *ic)
3563 {
3564     operand *left = IC_LEFT(ic);
3565     operand *right = IC_RIGHT(ic);
3566     operand *result= IC_RESULT(ic);  
3567
3568     D(emitcode(";", "genMod "););
3569
3570     /* assign the amsops */
3571     AOP_OP_3(ic);
3572 #if 0
3573     aopOp (left,ic,FALSE, FALSE);
3574     aopOp (right,ic,FALSE, TRUE);
3575     aopOp (result,ic,TRUE, FALSE);
3576 #endif
3577
3578     /* special cases first */
3579     /* both are bits */
3580     if (AOP_TYPE(left) == AOP_CRY &&
3581         AOP_TYPE(right)== AOP_CRY) {
3582         genModbits(left,right,result);
3583         goto release ;
3584     }
3585
3586     /* if both are of size == 1 */
3587     if (AOP_SIZE(left) == 1 &&
3588         AOP_SIZE(right) == 1 ) {
3589         genModOneByte(left,right,result);
3590         goto release ;
3591     }
3592
3593     /* should have been converted to function call */
3594     assert(1);
3595
3596 release :
3597     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3598     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3599     freeAsmop(result,NULL,ic,TRUE); 
3600 }
3601
3602 /*-----------------------------------------------------------------*/
3603 /* genIfxJump :- will create a jump depending on the ifx           */
3604 /*-----------------------------------------------------------------*/
3605 static void genIfxJump (iCode *ic, char *jval)
3606 {
3607     symbol *jlbl ;
3608     symbol *tlbl = newiTempLabel(NULL);
3609     char *inst;
3610
3611     D(emitcode(";", "genIfxJump "););
3612
3613     /* if true label then we jump if condition
3614     supplied is true */
3615     if ( IC_TRUE(ic) ) {
3616         jlbl = IC_TRUE(ic);
3617         inst = ((strcmp(jval,"a") == 0 ? "jz" :
3618                  (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3619     }
3620     else {
3621         /* false label is present */
3622         jlbl = IC_FALSE(ic) ;
3623         inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3624                  (strcmp(jval,"c") == 0 ? "jc" : "jb" )));              
3625     }
3626     if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0) 
3627         emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3628     else
3629         emitcode(inst,"%05d$",tlbl->key+100);
3630     emitcode("ljmp","%05d$",jlbl->key+100);
3631     emitcode("","%05d$:",tlbl->key+100);                
3632
3633     /* mark the icode as generated */
3634     ic->generated = 1;
3635 }
3636
3637 /*-----------------------------------------------------------------*/
3638 /* genCmp :- greater or less than comparison                       */
3639 /*-----------------------------------------------------------------*/
3640 static void genCmp (operand *left,operand *right,
3641                     operand *result, iCode *ifx, int sign)
3642 {
3643     int size, offset = 0 ;
3644     unsigned long lit = 0L;
3645     bool swappedOps = FALSE;
3646
3647     D(emitcode(";", "genCmp"););
3648
3649 #if 0
3650     /* If left if lit and right isn't, swap 'em. */
3651     if (AOP_TYPE(left) == AOP_LIT &&
3652         AOP_TYPE(right) != AOP_LIT)
3653     {
3654         operand *tmp = left;
3655         left = right;
3656         right = tmp;
3657         D(emitcode(";", "kevin literal hack"););
3658         swappedOps = !swappedOps;
3659     }
3660
3661     if (AOP_NEEDSACC(right))
3662     {
3663         if (AOP_NEEDSACC(left))
3664         {
3665             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3666                    "both CMP operands need ACC!");
3667             exit(-1);
3668         }
3669         else
3670         {
3671             operand *tmp = left;
3672             left = right;
3673             right = tmp;
3674             D(emitcode(";", "kevin ACC hack"););
3675             swappedOps = !swappedOps;
3676         }
3677     }
3678 #endif
3679
3680     /* if left & right are bit variables */
3681     if (AOP_TYPE(left) == AOP_CRY &&
3682         AOP_TYPE(right) == AOP_CRY ) {
3683         emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3684         emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3685     } else {
3686         /* subtract right from left if at the
3687         end the carry flag is set then we know that
3688         left is greater than right */
3689         size = max(AOP_SIZE(left),AOP_SIZE(right));
3690
3691         /* if unsigned char cmp with lit, do cjne left,#right,zz */
3692         if((size == 1) && !sign &&
3693            (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3694             symbol *lbl  = newiTempLabel(NULL);
3695             emitcode("cjne","%s,%s,%05d$",
3696                      aopGet(AOP(left),offset,FALSE,FALSE),
3697                      aopGet(AOP(right),offset,FALSE,FALSE),
3698                      lbl->key+100);
3699             emitcode("","%05d$:",lbl->key+100);
3700         } else {
3701             if(AOP_TYPE(right) == AOP_LIT){
3702                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3703                 /* optimize if(x < 0) or if(x >= 0) */
3704                 if(lit == 0L){
3705                     if(!sign){
3706                         CLRC;
3707                     }
3708                     else{
3709                         MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3710                         if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3711                             genIfxJump (ifx,"acc.7");
3712                             return;
3713                         }
3714                         else    
3715                             emitcode("rlc","a");
3716                     }
3717                     goto release;
3718                 }
3719             }
3720             CLRC;
3721             while (size--)
3722             {
3723                 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3724                 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3725                 emitcode(";", "genCmp #2");
3726                 if (sign && (size == 0))
3727                 {
3728                     emitcode(";", "genCmp #3");
3729                     emitcode("xrl","a,#0x80");
3730                     if (AOP_TYPE(right) == AOP_LIT)
3731                     {
3732                         unsigned long lit = (unsigned long)
3733                             floatFromVal(AOP(right)->aopu.aop_lit);
3734                         emitcode(";", "genCmp #3.1");
3735                         emitcode("subb","a,#0x%02x",
3736                             0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3737                     }
3738                     else
3739                     {
3740                         emitcode(";", "genCmp #3.2");
3741                         if (AOP_NEEDSACC(right))
3742                         {
3743                             emitcode("push", "acc");
3744                         }
3745                         emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3746                                   FALSE,FALSE));
3747                         emitcode("xrl","b,#0x80");
3748                         if (AOP_NEEDSACC(right))
3749                         {
3750                             emitcode("pop", "acc");
3751                         }
3752                         emitcode("subb","a,b");
3753                     }
3754                 }
3755                 else
3756                 {
3757                     const char *s;
3758
3759                     emitcode(";", "genCmp #4");
3760                     if (AOP_NEEDSACC(right))
3761                     {
3762                         /* Yuck!! */
3763                         emitcode(";", "genCmp #4.1");
3764                         emitcode("xch", "a, b");
3765                         MOVA(aopGet(AOP(right),offset++,FALSE,FALSE));
3766                         emitcode("xch", "a, b");
3767                         s = "b";
3768                     }
3769                     else
3770                     {
3771                         emitcode(";", "genCmp #4.2");
3772                         s = aopGet(AOP(right),offset++,FALSE,FALSE);
3773                     }
3774
3775                     emitcode("subb","a,%s",s);
3776                 }
3777             }
3778         }
3779     }
3780
3781 release:
3782     if (swappedOps)
3783     {
3784         D(emitcode(";","kevHack: flip carry."););
3785         emitcode("cpl", "c");
3786     }
3787
3788     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3789         outBitC(result);
3790     } else {
3791         /* if the result is used in the next
3792         ifx conditional branch then generate
3793         code a little differently */
3794         if (ifx )
3795             genIfxJump (ifx,"c");
3796         else
3797             outBitC(result);
3798         /* leave the result in acc */
3799     }
3800 }
3801
3802 /*-----------------------------------------------------------------*/
3803 /* genCmpGt :- greater than comparison                             */
3804 /*-----------------------------------------------------------------*/
3805 static void genCmpGt (iCode *ic, iCode *ifx)
3806 {
3807     operand *left, *right, *result;
3808     link *letype , *retype;
3809     int sign ;
3810
3811     D(emitcode(";", "genCmpGt "););
3812
3813     left = IC_LEFT(ic);
3814     right= IC_RIGHT(ic);
3815     result = IC_RESULT(ic);
3816
3817     letype = getSpec(operandType(left));
3818     retype =getSpec(operandType(right));
3819     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3820     /* assign the amsops */
3821     AOP_OP_3(ic);
3822 #if 0
3823     aopOp (left,ic,FALSE, TRUE);
3824     aopOp (right,ic,FALSE, FALSE);
3825     aopOp (result,ic,TRUE, FALSE);
3826 #endif
3827
3828     genCmp(right, left, result, ifx, sign);
3829
3830     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3831     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3832     freeAsmop(result,NULL,ic,TRUE); 
3833 }
3834
3835 /*-----------------------------------------------------------------*/
3836 /* genCmpLt - less than comparisons                                */
3837 /*-----------------------------------------------------------------*/
3838 static void genCmpLt (iCode *ic, iCode *ifx)
3839 {
3840     operand *left, *right, *result;
3841     link *letype , *retype;
3842     int sign ;
3843
3844     D(emitcode(";", "genCmpLt "););
3845
3846     left = IC_LEFT(ic);
3847     right= IC_RIGHT(ic);
3848     result = IC_RESULT(ic);
3849
3850     letype = getSpec(operandType(left));
3851     retype =getSpec(operandType(right));
3852     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3853
3854     /* assign the amsops */
3855     AOP_OP_3(ic);
3856 #if 0
3857     aopOp (left,ic,FALSE, FALSE);
3858     aopOp (right,ic,FALSE, TRUE);
3859     aopOp (result,ic,TRUE, FALSE);
3860 #endif
3861
3862     genCmp(left, right, result, ifx, sign);
3863
3864     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3865     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3866     freeAsmop(result,NULL,ic,TRUE); 
3867 }
3868
3869 /*-----------------------------------------------------------------*/
3870 /* gencjneshort - compare and jump if not equal                    */
3871 /*-----------------------------------------------------------------*/
3872 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3873 {
3874     int size = max(AOP_SIZE(left),AOP_SIZE(right));
3875     int offset = 0;
3876     unsigned long lit = 0L;
3877
3878     D(emitcode(";", "gencjneshort"););
3879
3880     /* if the left side is a literal or 
3881     if the right is in a pointer register and left 
3882     is not */
3883     if ((AOP_TYPE(left) == AOP_LIT) || 
3884         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3885         operand *t = right;
3886         right = left;
3887         left = t;
3888     }
3889     if(AOP_TYPE(right) == AOP_LIT)
3890         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3891
3892     /* if the right side is a literal then anything goes */
3893     if (AOP_TYPE(right) == AOP_LIT &&
3894         AOP_TYPE(left) != AOP_DIR ) {
3895         while (size--) {
3896             char *l = aopGet(AOP(left), offset, FALSE, FALSE);
3897             MOVA(l);
3898             emitcode("cjne","a,%s,%05d$",
3899                      aopGet(AOP(right),offset,FALSE,FALSE),
3900                      lbl->key+100);
3901             offset++;
3902         }
3903     }
3904
3905     /* if the right side is in a register or in direct space or
3906     if the left is a pointer register & right is not */    
3907     else if (AOP_TYPE(right) == AOP_REG ||
3908              AOP_TYPE(right) == AOP_DIR || 
3909              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3910              (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3911         while (size--) {
3912             MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3913             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3914                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3915                 emitcode("jnz","%05d$",lbl->key+100);
3916             else
3917                 emitcode("cjne","a,%s,%05d$",
3918                          aopGet(AOP(right),offset,FALSE,TRUE),
3919                          lbl->key+100);
3920             offset++;
3921         }
3922     } else {
3923         /* right is a pointer reg need both a & b */
3924         while(size--) {
3925             char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3926             if(strcmp(l,"b"))
3927                 emitcode("mov","b,%s",l);
3928             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3929             emitcode("cjne","a,b,%05d$",lbl->key+100);    
3930             offset++;
3931         }
3932     }
3933 }
3934
3935 /*-----------------------------------------------------------------*/
3936 /* gencjne - compare and jump if not equal                         */
3937 /*-----------------------------------------------------------------*/
3938 static void gencjne(operand *left, operand *right, symbol *lbl)
3939 {
3940     symbol *tlbl  = newiTempLabel(NULL);
3941
3942     D(emitcode(";", "gencjne"););
3943
3944     gencjneshort(left, right, lbl);
3945
3946     emitcode("mov","a,%s",one);
3947     emitcode("sjmp","%05d$",tlbl->key+100);
3948     emitcode("","%05d$:",lbl->key+100);
3949     emitcode("clr","a");
3950     emitcode("","%05d$:",tlbl->key+100);
3951 }
3952
3953 /*-----------------------------------------------------------------*/
3954 /* genCmpEq - generates code for equal to                          */
3955 /*-----------------------------------------------------------------*/
3956 static void genCmpEq (iCode *ic, iCode *ifx)
3957 {
3958     operand *left, *right, *result;
3959
3960     D(emitcode(";", "genCmpEq "););
3961
3962     AOP_OP_3(ic);
3963     AOP_SET_LOCALS(ic);
3964 #if 0
3965     aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
3966     aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3967     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3968 #endif
3969
3970     /* if literal, literal on the right or 
3971     if the right is in a pointer register and left 
3972     is not */
3973     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
3974         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3975         operand *t = IC_RIGHT(ic);
3976         IC_RIGHT(ic) = IC_LEFT(ic);
3977         IC_LEFT(ic) = t;
3978     }
3979
3980     if(ifx && !AOP_SIZE(result)){
3981         symbol *tlbl;
3982         /* if they are both bit variables */
3983         if (AOP_TYPE(left) == AOP_CRY &&
3984             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3985             if(AOP_TYPE(right) == AOP_LIT){
3986                 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3987                 if(lit == 0L){
3988                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3989                     emitcode("cpl","c");
3990                 } else if(lit == 1L) {
3991                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3992                 } else {
3993                     emitcode("clr","c");
3994                 }
3995                 /* AOP_TYPE(right) == AOP_CRY */
3996             } else {
3997                 symbol *lbl = newiTempLabel(NULL);
3998                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3999                 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4000                 emitcode("cpl","c");
4001                 emitcode("","%05d$:",(lbl->key+100));
4002             }
4003             /* if true label then we jump if condition
4004             supplied is true */
4005             tlbl = newiTempLabel(NULL);
4006             if ( IC_TRUE(ifx) ) {
4007                 emitcode("jnc","%05d$",tlbl->key+100);
4008                 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4009             } else {
4010                 emitcode("jc","%05d$",tlbl->key+100);
4011                 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4012             }
4013             emitcode("","%05d$:",tlbl->key+100);                
4014         } else {
4015             tlbl = newiTempLabel(NULL);
4016             gencjneshort(left, right, tlbl);
4017             if ( IC_TRUE(ifx) ) {
4018                 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4019                 emitcode("","%05d$:",tlbl->key+100);                
4020             } else {
4021                 symbol *lbl = newiTempLabel(NULL);
4022                 emitcode("sjmp","%05d$",lbl->key+100);
4023                 emitcode("","%05d$:",tlbl->key+100);                
4024                 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4025                 emitcode("","%05d$:",lbl->key+100);             
4026             }
4027         }
4028         /* mark the icode as generated */
4029         ifx->generated = 1;
4030         goto release ;
4031     }
4032
4033     /* if they are both bit variables */
4034     if (AOP_TYPE(left) == AOP_CRY &&
4035         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4036         if(AOP_TYPE(right) == AOP_LIT){
4037             unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4038             if(lit == 0L){
4039                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4040                 emitcode("cpl","c");
4041             } else if(lit == 1L) {
4042                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4043             } else {
4044                 emitcode("clr","c");
4045             }
4046             /* AOP_TYPE(right) == AOP_CRY */
4047         } else {
4048             symbol *lbl = newiTempLabel(NULL);
4049             emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4050             emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4051             emitcode("cpl","c");
4052             emitcode("","%05d$:",(lbl->key+100));
4053         }
4054         /* c = 1 if egal */
4055         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4056             outBitC(result);
4057             goto release ;
4058         }
4059         if (ifx) {
4060             genIfxJump (ifx,"c");
4061             goto release ;
4062         }
4063         /* if the result is used in an arithmetic operation
4064         then put the result in place */
4065         outBitC(result);
4066     } else {
4067         gencjne(left,right,newiTempLabel(NULL));    
4068         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4069             aopPut(AOP(result),"a",0);
4070             goto release ;
4071         }
4072         if (ifx) {
4073             genIfxJump (ifx,"a");
4074             goto release ;
4075         }
4076         /* if the result is used in an arithmetic operation
4077         then put the result in place */
4078         if (AOP_TYPE(result) != AOP_CRY) 
4079             outAcc(result);
4080         /* leave the result in acc */
4081     }
4082
4083 release:
4084     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4085     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4086     freeAsmop(result,NULL,ic,TRUE);
4087 }
4088
4089 /*-----------------------------------------------------------------*/
4090 /* ifxForOp - returns the icode containing the ifx for operand     */
4091 /*-----------------------------------------------------------------*/
4092 static iCode *ifxForOp ( operand *op, iCode *ic )
4093 {
4094     /* if true symbol then needs to be assigned */
4095     if (IS_TRUE_SYMOP(op))
4096         return NULL ;
4097
4098     /* if this has register type condition and
4099     the next instruction is ifx with the same operand
4100     and live to of the operand is upto the ifx only then */
4101     if (ic->next &&
4102         ic->next->op == IFX &&
4103         IC_COND(ic->next)->key == op->key &&
4104         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4105         return ic->next;
4106
4107     return NULL;
4108 }
4109 /*-----------------------------------------------------------------*/
4110 /* genAndOp - for && operation                                     */
4111 /*-----------------------------------------------------------------*/
4112 static void genAndOp (iCode *ic)
4113 {
4114     operand *left,*right, *result;
4115     symbol *tlbl;
4116
4117     D(emitcode(";", "genAndOp "););
4118
4119     /* note here that && operations that are in an
4120     if statement are taken away by backPatchLabels
4121     only those used in arthmetic operations remain */
4122     AOP_OP_3(ic);
4123     AOP_SET_LOCALS(ic);
4124 #if 0
4125     aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4126     aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4127     aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4128 #endif
4129
4130     /* if both are bit variables */
4131     if (AOP_TYPE(left) == AOP_CRY &&
4132         AOP_TYPE(right) == AOP_CRY ) {
4133         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4134         emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4135         outBitC(result);
4136     } else {
4137         tlbl = newiTempLabel(NULL);
4138         toBoolean(left);    
4139         emitcode("jz","%05d$",tlbl->key+100);
4140         toBoolean(right);
4141         emitcode("","%05d$:",tlbl->key+100);
4142         outBitAcc(result);
4143     }
4144
4145     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4146     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4147     freeAsmop(result,NULL,ic,TRUE);
4148 }
4149
4150
4151 /*-----------------------------------------------------------------*/
4152 /* genOrOp - for || operation                                      */
4153 /*-----------------------------------------------------------------*/
4154 static void genOrOp (iCode *ic)
4155 {
4156     operand *left,*right, *result;
4157     symbol *tlbl;
4158
4159     D(emitcode(";", "genOrOp "););
4160
4161     /* note here that || operations that are in an
4162     if statement are taken away by backPatchLabels
4163     only those used in arthmetic operations remain */
4164     AOP_OP_3(ic);
4165     AOP_SET_LOCALS(ic);
4166 #if 0
4167     aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4168     aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4169     aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4170 #endif
4171
4172     /* if both are bit variables */
4173     if (AOP_TYPE(left) == AOP_CRY &&
4174         AOP_TYPE(right) == AOP_CRY ) {
4175         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4176         emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4177         outBitC(result);
4178     } else {
4179         tlbl = newiTempLabel(NULL);
4180         toBoolean(left);
4181         emitcode("jnz","%05d$",tlbl->key+100);
4182         toBoolean(right);
4183         emitcode("","%05d$:",tlbl->key+100);
4184         outBitAcc(result);
4185     }
4186
4187     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4188     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4189     freeAsmop(result,NULL,ic,TRUE);            
4190 }
4191
4192 /*-----------------------------------------------------------------*/
4193 /* isLiteralBit - test if lit == 2^n                               */
4194 /*-----------------------------------------------------------------*/
4195 static int isLiteralBit(unsigned long lit)
4196 {
4197     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4198     0x100L,0x200L,0x400L,0x800L,
4199     0x1000L,0x2000L,0x4000L,0x8000L,
4200     0x10000L,0x20000L,0x40000L,0x80000L,
4201     0x100000L,0x200000L,0x400000L,0x800000L,
4202     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4203     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4204     int idx;
4205     
4206     for(idx = 0; idx < 32; idx++)
4207         if(lit == pw[idx])
4208             return idx+1;
4209     return 0;
4210 }
4211
4212 /*-----------------------------------------------------------------*/
4213 /* continueIfTrue -                                                */
4214 /*-----------------------------------------------------------------*/
4215 static void continueIfTrue (iCode *ic)
4216 {
4217     if(IC_TRUE(ic))
4218         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4219     ic->generated = 1;
4220 }
4221
4222 /*-----------------------------------------------------------------*/
4223 /* jmpIfTrue -                                                     */
4224 /*-----------------------------------------------------------------*/
4225 static void jumpIfTrue (iCode *ic)
4226 {
4227     if(!IC_TRUE(ic))
4228         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4229     ic->generated = 1;
4230 }
4231
4232 /*-----------------------------------------------------------------*/
4233 /* jmpTrueOrFalse -                                                */
4234 /*-----------------------------------------------------------------*/
4235 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4236 {
4237     // ugly but optimized by peephole
4238     if(IC_TRUE(ic)){
4239         symbol *nlbl = newiTempLabel(NULL);
4240         emitcode("sjmp","%05d$",nlbl->key+100);                 
4241         emitcode("","%05d$:",tlbl->key+100);
4242         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4243         emitcode("","%05d$:",nlbl->key+100);
4244     }
4245     else{
4246         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4247         emitcode("","%05d$:",tlbl->key+100);
4248     }
4249     ic->generated = 1;
4250 }
4251
4252 /*-----------------------------------------------------------------*/
4253 /* genAnd  - code for and                                          */
4254 /*-----------------------------------------------------------------*/
4255 static void genAnd (iCode *ic, iCode *ifx)
4256 {
4257     operand *left, *right, *result;
4258     int size, offset=0;  
4259     unsigned long lit = 0L;
4260     int bytelit = 0;
4261     char buffer[10];
4262
4263     D(emitcode(";", "genAnd "););
4264
4265     AOP_OP_3(ic);
4266     AOP_SET_LOCALS(ic);
4267 #if 0
4268     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4269     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4270     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4271 #endif
4272
4273 #ifdef DEBUG_TYPE
4274     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4275              AOP_TYPE(result),
4276              AOP_TYPE(left), AOP_TYPE(right));
4277     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4278              AOP_SIZE(result),
4279              AOP_SIZE(left), AOP_SIZE(right));
4280 #endif
4281
4282     /* if left is a literal & right is not then exchange them */
4283     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4284         AOP_NEEDSACC(left)) {
4285         operand *tmp = right ;
4286         right = left;
4287         left = tmp;
4288     }
4289
4290     /* if result = right then exchange them */
4291     if(sameRegs(AOP(result),AOP(right))){
4292         operand *tmp = right ;
4293         right = left;
4294         left = tmp;
4295     }
4296
4297     /* if right is bit then exchange them */
4298     if (AOP_TYPE(right) == AOP_CRY &&
4299         AOP_TYPE(left) != AOP_CRY){
4300         operand *tmp = right ;
4301         right = left;
4302         left = tmp;
4303     }
4304     if(AOP_TYPE(right) == AOP_LIT)
4305         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4306
4307     size = AOP_SIZE(result);
4308
4309     // if(bit & yy)
4310     // result = bit & yy;
4311     if (AOP_TYPE(left) == AOP_CRY){
4312         // c = bit & literal;
4313         if(AOP_TYPE(right) == AOP_LIT){
4314             if(lit & 1) {
4315                 if(size && sameRegs(AOP(result),AOP(left)))
4316                     // no change
4317                     goto release;
4318                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4319             } else {
4320                 // bit(result) = 0;
4321                 if(size && (AOP_TYPE(result) == AOP_CRY)){
4322                     emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4323                     goto release;
4324                 }
4325                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4326                     jumpIfTrue(ifx);
4327                     goto release;
4328                 }
4329                 emitcode("clr","c");
4330             }
4331         } else {
4332             if (AOP_TYPE(right) == AOP_CRY){
4333                 // c = bit & bit;
4334                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4335                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4336             } else {
4337                 // c = bit & val;
4338                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4339                 // c = lsb
4340                 emitcode("rrc","a");
4341                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4342             }
4343         }
4344         // bit = c
4345         // val = c
4346         if(size)
4347             outBitC(result);
4348         // if(bit & ...)
4349         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4350             genIfxJump(ifx, "c");           
4351         goto release ;
4352     }
4353
4354     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4355     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4356     if((AOP_TYPE(right) == AOP_LIT) &&
4357        (AOP_TYPE(result) == AOP_CRY) &&
4358        (AOP_TYPE(left) != AOP_CRY)){
4359         int posbit = isLiteralBit(lit);
4360         /* left &  2^n */
4361         if(posbit){
4362             posbit--;
4363             MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4364             // bit = left & 2^n
4365             if(size)
4366                 emitcode("mov","c,acc.%d",posbit&0x07);
4367             // if(left &  2^n)
4368             else{
4369                 if(ifx){
4370                     sprintf(buffer,"acc.%d",posbit&0x07);
4371                     genIfxJump(ifx, buffer);
4372                 }
4373                 goto release;
4374             }
4375         } else {
4376             symbol *tlbl = newiTempLabel(NULL);
4377             int sizel = AOP_SIZE(left);
4378             if(size)
4379                 emitcode("setb","c");
4380             while(sizel--){
4381                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4382                     MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4383                     // byte ==  2^n ?
4384                     if((posbit = isLiteralBit(bytelit)) != 0)
4385                         emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4386                     else{
4387                         if(bytelit != 0x0FFL)
4388                             emitcode("anl","a,%s",
4389                                      aopGet(AOP(right),offset,FALSE,TRUE));
4390                         emitcode("jnz","%05d$",tlbl->key+100);
4391                     }
4392                 }
4393                 offset++;
4394             }
4395             // bit = left & literal
4396             if(size){
4397                 emitcode("clr","c");
4398                 emitcode("","%05d$:",tlbl->key+100);
4399             }
4400             // if(left & literal)
4401             else{
4402                 if(ifx)
4403                     jmpTrueOrFalse(ifx, tlbl);
4404                 goto release ;
4405             }
4406         }
4407         outBitC(result);
4408         goto release ;
4409     }
4410
4411     /* if left is same as result */
4412     if(sameRegs(AOP(result),AOP(left))){
4413         for(;size--; offset++) {
4414             if(AOP_TYPE(right) == AOP_LIT){
4415                 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4416                     continue;
4417                 else 
4418                     if (bytelit == 0)
4419                         aopPut(AOP(result),zero,offset);
4420                     else 
4421                         if (IS_AOP_PREG(result)) {
4422                             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4423                             emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4424                             aopPut(AOP(result),"a",offset);
4425                         } else
4426                             emitcode("anl","%s,%s",
4427                                      aopGet(AOP(left),offset,FALSE,TRUE),
4428                                      aopGet(AOP(right),offset,FALSE,FALSE));
4429             } else {
4430                 if (AOP_TYPE(left) == AOP_ACC)
4431                     emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4432                 else {
4433                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4434                     if (IS_AOP_PREG(result)) {
4435                         emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4436                         aopPut(AOP(result),"a",offset);
4437
4438                     } else
4439                         emitcode("anl","%s,a",
4440                                  aopGet(AOP(left),offset,FALSE,TRUE));
4441                 }
4442             }
4443         }
4444     } else {
4445         // left & result in different registers
4446         if(AOP_TYPE(result) == AOP_CRY){
4447             // result = bit
4448             // if(size), result in bit
4449             // if(!size && ifx), conditional oper: if(left & right)
4450             symbol *tlbl = newiTempLabel(NULL);
4451             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4452             if(size)
4453                 emitcode("setb","c");
4454             while(sizer--){
4455                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4456                 emitcode("anl","a,%s",
4457                          aopGet(AOP(left),offset,FALSE,FALSE));
4458                 emitcode("jnz","%05d$",tlbl->key+100);
4459                 offset++;
4460             }
4461             if(size){
4462                 CLRC;
4463                 emitcode("","%05d$:",tlbl->key+100);
4464                 outBitC(result);
4465             } else if(ifx)
4466                 jmpTrueOrFalse(ifx, tlbl);
4467         } else {
4468             for(;(size--);offset++) {
4469                 // normal case
4470                 // result = left & right
4471                 if(AOP_TYPE(right) == AOP_LIT){
4472                     if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4473                         aopPut(AOP(result),
4474                                aopGet(AOP(left),offset,FALSE,FALSE),
4475                                offset);
4476                         continue;
4477                     } else if(bytelit == 0){
4478                         aopPut(AOP(result),zero,offset);
4479                         continue;
4480                     }
4481                 }
4482                 // faster than result <- left, anl result,right
4483                 // and better if result is SFR
4484                 if (AOP_TYPE(left) == AOP_ACC) 
4485                     emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4486                 else {
4487                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4488                     emitcode("anl","a,%s",
4489                              aopGet(AOP(left),offset,FALSE,FALSE));
4490                 }
4491                 aopPut(AOP(result),"a",offset);
4492             }
4493         }
4494     }
4495
4496 release :
4497     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4498     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4499     freeAsmop(result,NULL,ic,TRUE);     
4500 }
4501
4502 /*-----------------------------------------------------------------*/
4503 /* genOr  - code for or                                            */
4504 /*-----------------------------------------------------------------*/
4505 static void genOr (iCode *ic, iCode *ifx)
4506 {
4507     operand *left, *right, *result;
4508     int size, offset=0;
4509     unsigned long lit = 0L;
4510
4511     D(emitcode(";", "genOr "););
4512
4513     AOP_OP_3(ic);
4514     AOP_SET_LOCALS(ic);
4515     #if 0
4516     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4517     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4518     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4519     #endif
4520
4521 #ifdef DEBUG_TYPE
4522     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4523              AOP_TYPE(result),
4524              AOP_TYPE(left), AOP_TYPE(right));
4525     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4526              AOP_SIZE(result),
4527              AOP_SIZE(left), AOP_SIZE(right));
4528 #endif
4529
4530     /* if left is a literal & right is not then exchange them */
4531     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4532         AOP_NEEDSACC(left)) {
4533         operand *tmp = right ;
4534         right = left;
4535         left = tmp;
4536     }
4537
4538     /* if result = right then exchange them */
4539     if(sameRegs(AOP(result),AOP(right))){
4540         operand *tmp = right ;
4541         right = left;
4542         left = tmp;
4543     }
4544
4545     /* if right is bit then exchange them */
4546     if (AOP_TYPE(right) == AOP_CRY &&
4547         AOP_TYPE(left) != AOP_CRY){
4548         operand *tmp = right ;
4549         right = left;
4550         left = tmp;
4551     }
4552     if(AOP_TYPE(right) == AOP_LIT)
4553         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4554
4555     size = AOP_SIZE(result);
4556
4557     // if(bit | yy)
4558     // xx = bit | yy;
4559     if (AOP_TYPE(left) == AOP_CRY){
4560         if(AOP_TYPE(right) == AOP_LIT){
4561             // c = bit & literal;
4562             if(lit){
4563                 // lit != 0 => result = 1
4564                 if(AOP_TYPE(result) == AOP_CRY){
4565                     if(size)
4566                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4567                     else if(ifx)
4568                         continueIfTrue(ifx);
4569                     goto release;
4570                 }
4571                 emitcode("setb","c");
4572             } else {
4573                 // lit == 0 => result = left
4574                 if(size && sameRegs(AOP(result),AOP(left)))
4575                     goto release;
4576                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4577             }
4578         } else {
4579             if (AOP_TYPE(right) == AOP_CRY){
4580                 // c = bit | bit;
4581                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4582                 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4583             }
4584             else{
4585                 // c = bit | val;
4586                 symbol *tlbl = newiTempLabel(NULL);
4587                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4588                     emitcode("setb","c");
4589                 emitcode("jb","%s,%05d$",
4590                          AOP(left)->aopu.aop_dir,tlbl->key+100);
4591                 toBoolean(right);
4592                 emitcode("jnz","%05d$",tlbl->key+100);
4593                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4594                     jmpTrueOrFalse(ifx, tlbl);
4595                     goto release;
4596                 } else {
4597                     CLRC;
4598                     emitcode("","%05d$:",tlbl->key+100);
4599                 }
4600             }
4601         }
4602         // bit = c
4603         // val = c
4604         if(size)
4605             outBitC(result);
4606         // if(bit | ...)
4607         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4608             genIfxJump(ifx, "c");           
4609         goto release ;
4610     }
4611
4612     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
4613     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
4614     if((AOP_TYPE(right) == AOP_LIT) &&
4615        (AOP_TYPE(result) == AOP_CRY) &&
4616        (AOP_TYPE(left) != AOP_CRY)){
4617         if(lit){
4618             // result = 1
4619             if(size)
4620                 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4621             else 
4622                 continueIfTrue(ifx);
4623             goto release;
4624         } else {
4625             // lit = 0, result = boolean(left)
4626             if(size)
4627                 emitcode("setb","c");
4628             toBoolean(right);
4629             if(size){
4630                 symbol *tlbl = newiTempLabel(NULL);
4631                 emitcode("jnz","%05d$",tlbl->key+100);
4632                 CLRC;
4633                 emitcode("","%05d$:",tlbl->key+100);
4634             } else {
4635                 genIfxJump (ifx,"a");
4636                 goto release;
4637             }
4638         }
4639         outBitC(result);
4640         goto release ;
4641     }
4642
4643     /* if left is same as result */
4644     if(sameRegs(AOP(result),AOP(left))){
4645         for(;size--; offset++) {
4646             if(AOP_TYPE(right) == AOP_LIT){
4647                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4648                     continue;
4649                 else 
4650                     if (IS_AOP_PREG(left)) {
4651                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4652                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4653                         aopPut(AOP(result),"a",offset);
4654                     } else
4655                         emitcode("orl","%s,%s",
4656                                  aopGet(AOP(left),offset,FALSE,TRUE),
4657                                  aopGet(AOP(right),offset,FALSE,FALSE));
4658             } else {
4659                 if (AOP_TYPE(left) == AOP_ACC) 
4660                     emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4661                 else {              
4662                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4663                     if (IS_AOP_PREG(left)) {
4664                         emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4665                         aopPut(AOP(result),"a",offset);
4666                     } else
4667                         emitcode("orl","%s,a",
4668                                  aopGet(AOP(left),offset,FALSE,TRUE));
4669                 }
4670             }
4671         }
4672     } else {
4673         // left & result in different registers
4674         if(AOP_TYPE(result) == AOP_CRY){
4675             // result = bit
4676             // if(size), result in bit
4677             // if(!size && ifx), conditional oper: if(left | right)
4678             symbol *tlbl = newiTempLabel(NULL);
4679             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4680             if(size)
4681                 emitcode("setb","c");
4682             while(sizer--){
4683                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4684                 emitcode("orl","a,%s",
4685                          aopGet(AOP(left),offset,FALSE,FALSE));
4686                 emitcode("jnz","%05d$",tlbl->key+100);
4687                 offset++;
4688             }
4689             if(size){
4690                 CLRC;
4691                 emitcode("","%05d$:",tlbl->key+100);
4692                 outBitC(result);
4693             } else if(ifx)
4694                 jmpTrueOrFalse(ifx, tlbl);
4695         } else for(;(size--);offset++){
4696             // normal case
4697             // result = left & right
4698             if(AOP_TYPE(right) == AOP_LIT){
4699                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4700                     aopPut(AOP(result),
4701                            aopGet(AOP(left),offset,FALSE,FALSE),
4702                            offset);
4703                     continue;
4704                 }
4705             }
4706             // faster than result <- left, anl result,right
4707             // and better if result is SFR
4708             if (AOP_TYPE(left) == AOP_ACC) 
4709                 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4710             else {
4711                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4712                 emitcode("orl","a,%s",
4713                          aopGet(AOP(left),offset,FALSE,FALSE));
4714             }
4715             aopPut(AOP(result),"a",offset);                     
4716         }
4717     }
4718
4719 release :
4720     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4721     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4722     freeAsmop(result,NULL,ic,TRUE);     
4723 }
4724
4725 /*-----------------------------------------------------------------*/
4726 /* genXor - code for xclusive or                                   */
4727 /*-----------------------------------------------------------------*/
4728 static void genXor (iCode *ic, iCode *ifx)
4729 {
4730     operand *left, *right, *result;
4731     int size, offset=0;
4732     unsigned long lit = 0L;
4733
4734     D(emitcode(";", "genXor "););
4735
4736     AOP_OP_3(ic);
4737     AOP_SET_LOCALS(ic);
4738 #if 0
4739     aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4740     aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4741     aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4742 #endif
4743
4744 #ifdef DEBUG_TYPE
4745     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4746              AOP_TYPE(result),
4747              AOP_TYPE(left), AOP_TYPE(right));
4748     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4749              AOP_SIZE(result),
4750              AOP_SIZE(left), AOP_SIZE(right));
4751 #endif
4752
4753     /* if left is a literal & right is not ||
4754        if left needs acc & right does not */
4755     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4756         (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4757         operand *tmp = right ;
4758         right = left;
4759         left = tmp;
4760     }
4761
4762     /* if result = right then exchange them */
4763     if(sameRegs(AOP(result),AOP(right))){
4764         operand *tmp = right ;
4765         right = left;
4766         left = tmp;
4767     }
4768
4769     /* if right is bit then exchange them */
4770     if (AOP_TYPE(right) == AOP_CRY &&
4771         AOP_TYPE(left) != AOP_CRY){
4772         operand *tmp = right ;
4773         right = left;
4774         left = tmp;
4775     }
4776     if(AOP_TYPE(right) == AOP_LIT)
4777         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4778
4779     size = AOP_SIZE(result);
4780
4781     // if(bit ^ yy)
4782     // xx = bit ^ yy;
4783     if (AOP_TYPE(left) == AOP_CRY){
4784         if(AOP_TYPE(right) == AOP_LIT){
4785             // c = bit & literal;
4786             if(lit>>1){
4787                 // lit>>1  != 0 => result = 1
4788                 if(AOP_TYPE(result) == AOP_CRY){
4789                     if(size)
4790                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4791                     else if(ifx)
4792                         continueIfTrue(ifx);
4793                     goto release;
4794                 }
4795                 emitcode("setb","c");
4796             } else{
4797                 // lit == (0 or 1)
4798                 if(lit == 0){
4799                     // lit == 0, result = left
4800                     if(size && sameRegs(AOP(result),AOP(left)))
4801                         goto release;
4802                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4803                 } else{
4804                     // lit == 1, result = not(left)
4805                     if(size && sameRegs(AOP(result),AOP(left))){
4806                         emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4807                         goto release;
4808                     } else {
4809                         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4810                         emitcode("cpl","c");
4811                     }
4812                 }
4813             }
4814
4815         } else {
4816             // right != literal
4817             symbol *tlbl = newiTempLabel(NULL);
4818             if (AOP_TYPE(right) == AOP_CRY){
4819                 // c = bit ^ bit;
4820                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4821             }
4822             else{
4823                 int sizer = AOP_SIZE(right);
4824                 // c = bit ^ val
4825                 // if val>>1 != 0, result = 1
4826                 emitcode("setb","c");
4827                 while(sizer){
4828                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4829                     if(sizer == 1)
4830                         // test the msb of the lsb
4831                         emitcode("anl","a,#0xfe");
4832                     emitcode("jnz","%05d$",tlbl->key+100);
4833                     sizer--;
4834                 }
4835                 // val = (0,1)
4836                 emitcode("rrc","a");
4837             }
4838             emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4839             emitcode("cpl","c");
4840             emitcode("","%05d$:",(tlbl->key+100));
4841         }
4842         // bit = c
4843         // val = c
4844         if(size)
4845             outBitC(result);
4846         // if(bit | ...)
4847         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4848             genIfxJump(ifx, "c");           
4849         goto release ;
4850     }
4851
4852     if(sameRegs(AOP(result),AOP(left))){
4853         /* if left is same as result */
4854         for(;size--; offset++) {
4855             if(AOP_TYPE(right) == AOP_LIT){
4856                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4857                     continue;
4858                 else
4859                     if (IS_AOP_PREG(left)) {
4860                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4861                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4862                         aopPut(AOP(result),"a",offset);
4863                     } else 
4864                         emitcode("xrl","%s,%s",
4865                                  aopGet(AOP(left),offset,FALSE,TRUE),
4866                                  aopGet(AOP(right),offset,FALSE,FALSE));
4867             } else {
4868                 if (AOP_TYPE(left) == AOP_ACC)
4869                     emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4870                 else {
4871                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4872                     if (IS_AOP_PREG(left)) {
4873                         emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4874                         aopPut(AOP(result),"a",offset);
4875                     } else
4876                         emitcode("xrl","%s,a",
4877                                  aopGet(AOP(left),offset,FALSE,TRUE));
4878                 }
4879             }
4880         }
4881     } else {
4882         // left & result in different registers
4883         if(AOP_TYPE(result) == AOP_CRY){
4884             // result = bit
4885             // if(size), result in bit
4886             // if(!size && ifx), conditional oper: if(left ^ right)
4887             symbol *tlbl = newiTempLabel(NULL);
4888             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4889             if(size)
4890                 emitcode("setb","c");
4891             while(sizer--){
4892                 if((AOP_TYPE(right) == AOP_LIT) &&
4893                    (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4894                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4895                 } else {
4896                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4897                     emitcode("xrl","a,%s",
4898                              aopGet(AOP(left),offset,FALSE,FALSE));
4899                 }
4900                 emitcode("jnz","%05d$",tlbl->key+100);
4901                 offset++;
4902             }
4903             if(size){
4904                 CLRC;
4905                 emitcode("","%05d$:",tlbl->key+100);
4906                 outBitC(result);
4907             } else if(ifx)
4908                 jmpTrueOrFalse(ifx, tlbl);
4909         } else for(;(size--);offset++){
4910             // normal case
4911             // result = left & right
4912             if(AOP_TYPE(right) == AOP_LIT){
4913                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4914                     aopPut(AOP(result),
4915                            aopGet(AOP(left),offset,FALSE,FALSE),
4916                            offset);
4917                     continue;
4918                 }
4919             }
4920             // faster than result <- left, anl result,right
4921             // and better if result is SFR
4922             if (AOP_TYPE(left) == AOP_ACC)
4923                 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4924             else {
4925                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4926                 emitcode("xrl","a,%s",
4927                          aopGet(AOP(left),offset,FALSE,TRUE));
4928             }
4929             aopPut(AOP(result),"a",offset);
4930         }
4931     }
4932
4933 release :
4934     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4935     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4936     freeAsmop(result,NULL,ic,TRUE);     
4937 }
4938
4939 /*-----------------------------------------------------------------*/
4940 /* genInline - write the inline code out                           */
4941 /*-----------------------------------------------------------------*/
4942 static void genInline (iCode *ic)
4943 {
4944     char buffer[MAX_INLINEASM];
4945     char *bp = buffer;
4946     char *bp1= buffer;
4947     
4948     D(emitcode(";", "genInline "););
4949
4950     _G.inLine += (!options.asmpeep);
4951     strcpy(buffer,IC_INLINE(ic));
4952
4953     /* emit each line as a code */
4954     while (*bp) {
4955         if (*bp == '\n') {
4956             *bp++ = '\0';
4957             emitcode(bp1,"");
4958             bp1 = bp;
4959         } else {
4960             if (*bp == ':') {
4961                 bp++;
4962                 *bp = '\0';
4963                 bp++;
4964                 emitcode(bp1,"");
4965                 bp1 = bp;
4966             } else
4967                 bp++;
4968         }
4969     }
4970     if (bp1 != bp)
4971         emitcode(bp1,"");
4972     /*     emitcode("",buffer); */
4973     _G.inLine -= (!options.asmpeep);
4974 }
4975
4976 /*-----------------------------------------------------------------*/
4977 /* genRRC - rotate right with carry                                */
4978 /*-----------------------------------------------------------------*/
4979 static void genRRC (iCode *ic)
4980 {
4981     operand *left , *result ;
4982     int size, offset = 0;
4983     char *l;    
4984
4985     D(emitcode(";", "genRRC "););
4986
4987     /* rotate right with carry */
4988     left = IC_LEFT(ic);
4989     result=IC_RESULT(ic);
4990     aopOp (left,ic,FALSE, FALSE);
4991     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
4992
4993     /* move it to the result */
4994     size = AOP_SIZE(result);    
4995     offset = size - 1 ;
4996     CLRC;
4997     while (size--) {
4998         l = aopGet(AOP(left),offset,FALSE,FALSE);
4999         MOVA(l);
5000         emitcode("rrc","a");
5001         if (AOP_SIZE(result) > 1)
5002             aopPut(AOP(result),"a",offset--);
5003     }
5004     /* now we need to put the carry into the
5005     highest order byte of the result */
5006     if (AOP_SIZE(result) > 1) {
5007         l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5008         MOVA(l);
5009     }
5010     emitcode("mov","acc.7,c");
5011     aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5012     freeAsmop(left,NULL,ic,TRUE);
5013     freeAsmop(result,NULL,ic,TRUE);
5014 }
5015
5016 /*-----------------------------------------------------------------*/
5017 /* genRLC - generate code for rotate left with carry               */
5018 /*-----------------------------------------------------------------*/
5019 static void genRLC (iCode *ic)
5020 {    
5021     operand *left , *result ;
5022     int size, offset = 0;
5023     char *l;    
5024
5025     D(emitcode(";", "genRLC "););
5026
5027     /* rotate right with carry */
5028     left = IC_LEFT(ic);
5029     result=IC_RESULT(ic);
5030     aopOp (left,ic,FALSE, FALSE);
5031     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5032
5033     /* move it to the result */
5034     size = AOP_SIZE(result);    
5035     offset = 0 ;
5036     if (size--) {
5037         l = aopGet(AOP(left),offset,FALSE,FALSE);
5038         MOVA(l);
5039         emitcode("add","a,acc");
5040         if (AOP_SIZE(result) > 1)
5041             aopPut(AOP(result),"a",offset++);
5042         while (size--) {
5043             l = aopGet(AOP(left),offset,FALSE,FALSE);
5044             MOVA(l);
5045             emitcode("rlc","a");
5046             if (AOP_SIZE(result) > 1)
5047                 aopPut(AOP(result),"a",offset++);
5048         }
5049     }
5050     /* now we need to put the carry into the
5051     highest order byte of the result */
5052     if (AOP_SIZE(result) > 1) {
5053         l = aopGet(AOP(result),0,FALSE,FALSE);
5054         MOVA(l);
5055     }
5056     emitcode("mov","acc.0,c");
5057     aopPut(AOP(result),"a",0);
5058     freeAsmop(left,NULL,ic,TRUE);
5059     freeAsmop(result,NULL,ic,TRUE);
5060 }
5061
5062 /*-----------------------------------------------------------------*/
5063 /* genGetHbit - generates code get highest order bit               */
5064 /*-----------------------------------------------------------------*/
5065 static void genGetHbit (iCode *ic)
5066 {
5067     operand *left, *result;
5068     left = IC_LEFT(ic);
5069     result=IC_RESULT(ic);
5070     aopOp (left,ic,FALSE, FALSE);
5071     aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5072
5073     D(emitcode(";", "genGetHbit "););
5074
5075     /* get the highest order byte into a */
5076     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5077     if(AOP_TYPE(result) == AOP_CRY){
5078         emitcode("rlc","a");
5079         outBitC(result);
5080     }
5081     else{
5082         emitcode("rl","a");
5083         emitcode("anl","a,#0x01");
5084         outAcc(result);
5085     }
5086
5087
5088     freeAsmop(left,NULL,ic,TRUE);
5089     freeAsmop(result,NULL,ic,TRUE);
5090 }
5091
5092 /*-----------------------------------------------------------------*/
5093 /* AccRol - rotate left accumulator by known count                 */
5094 /*-----------------------------------------------------------------*/
5095 static void AccRol (int shCount)
5096 {
5097     shCount &= 0x0007;              // shCount : 0..7
5098     switch(shCount){
5099         case 0 :
5100             break;
5101         case 1 :
5102             emitcode("rl","a");
5103             break;
5104         case 2 :
5105             emitcode("rl","a");
5106             emitcode("rl","a");
5107             break;
5108         case 3 :
5109             emitcode("swap","a");
5110             emitcode("rr","a");
5111             break;
5112         case 4 :
5113             emitcode("swap","a");
5114             break;
5115         case 5 :
5116             emitcode("swap","a");
5117             emitcode("rl","a");
5118             break;
5119         case 6 :
5120             emitcode("rr","a");
5121             emitcode("rr","a");
5122             break;
5123         case 7 :
5124             emitcode("rr","a");
5125             break;
5126     }
5127 }
5128
5129 /*-----------------------------------------------------------------*/
5130 /* AccLsh - left shift accumulator by known count                  */
5131 /*-----------------------------------------------------------------*/
5132 static void AccLsh (int shCount)
5133 {
5134     if(shCount != 0){
5135         if(shCount == 1)
5136             emitcode("add","a,acc");
5137         else 
5138             if(shCount == 2) {
5139             emitcode("add","a,acc");
5140             emitcode("add","a,acc");
5141         } else {
5142             /* rotate left accumulator */
5143             AccRol(shCount);
5144             /* and kill the lower order bits */
5145             emitcode("anl","a,#0x%02x", SLMask[shCount]);
5146         }
5147     }
5148 }
5149
5150 /*-----------------------------------------------------------------*/
5151 /* AccRsh - right shift accumulator by known count                 */
5152 /*-----------------------------------------------------------------*/
5153 static void AccRsh (int shCount)
5154 {
5155     if(shCount != 0){
5156         if(shCount == 1){
5157             CLRC;
5158             emitcode("rrc","a");
5159         } else {
5160             /* rotate right accumulator */
5161             AccRol(8 - shCount);
5162             /* and kill the higher order bits */
5163             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5164         }
5165     }
5166 }
5167
5168 /*-----------------------------------------------------------------*/
5169 /* AccSRsh - signed right shift accumulator by known count                 */
5170 /*-----------------------------------------------------------------*/
5171 static void AccSRsh (int shCount)
5172 {
5173     symbol *tlbl ;
5174     if(shCount != 0){
5175         if(shCount == 1){
5176             emitcode("mov","c,acc.7");
5177             emitcode("rrc","a");
5178         } else if(shCount == 2){
5179             emitcode("mov","c,acc.7");
5180             emitcode("rrc","a");
5181             emitcode("mov","c,acc.7");
5182             emitcode("rrc","a");
5183         } else {
5184             tlbl = newiTempLabel(NULL);
5185             /* rotate right accumulator */
5186             AccRol(8 - shCount);
5187             /* and kill the higher order bits */
5188             emitcode("anl","a,#0x%02x", SRMask[shCount]);
5189             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5190             emitcode("orl","a,#0x%02x",
5191                      (unsigned char)~SRMask[shCount]);
5192             emitcode("","%05d$:",tlbl->key+100);
5193         }
5194     }
5195 }
5196
5197 /*-----------------------------------------------------------------*/
5198 /* shiftR1Left2Result - shift right one byte from left to result   */
5199 /*-----------------------------------------------------------------*/
5200 static void shiftR1Left2Result (operand *left, int offl,
5201                                 operand *result, int offr,
5202                                 int shCount, int sign)
5203 {
5204     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5205     /* shift right accumulator */
5206     if(sign)
5207         AccSRsh(shCount);
5208     else
5209         AccRsh(shCount);
5210     aopPut(AOP(result),"a",offr);
5211 }
5212
5213 /*-----------------------------------------------------------------*/
5214 /* shiftL1Left2Result - shift left one byte from left to result    */
5215 /*-----------------------------------------------------------------*/
5216 static void shiftL1Left2Result (operand *left, int offl,
5217                                 operand *result, int offr, int shCount)
5218 {
5219     char *l;
5220     l = aopGet(AOP(left),offl,FALSE,FALSE);
5221     MOVA(l);
5222     /* shift left accumulator */
5223     AccLsh(shCount);
5224     aopPut(AOP(result),"a",offr);
5225 }
5226
5227 /*-----------------------------------------------------------------*/
5228 /* movLeft2Result - move byte from left to result                  */
5229 /*-----------------------------------------------------------------*/
5230 static void movLeft2Result (operand *left, int offl,
5231                             operand *result, int offr, int sign)
5232 {
5233     char *l;
5234     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5235         l = aopGet(AOP(left),offl,FALSE,FALSE);
5236
5237         if (*l == '@' && (IS_AOP_PREG(result))) {
5238             emitcode("mov","a,%s",l);
5239             aopPut(AOP(result),"a",offr);
5240         } else {
5241             if(!sign)
5242                 aopPut(AOP(result),l,offr);
5243             else{
5244                 /* MSB sign in acc.7 ! */
5245                 if(getDataSize(left) == offl+1){
5246                     emitcode("mov","a,%s",l);
5247                     aopPut(AOP(result),"a",offr);
5248                 }
5249             }
5250         }
5251     }
5252 }
5253
5254 /*-----------------------------------------------------------------*/
5255 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
5256 /*-----------------------------------------------------------------*/
5257 static void AccAXRrl1 (char *x)
5258 {
5259     emitcode("rrc","a");
5260     emitcode("xch","a,%s", x);
5261     emitcode("rrc","a");
5262     emitcode("xch","a,%s", x);
5263 }
5264
5265 /*-----------------------------------------------------------------*/
5266 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
5267 /*-----------------------------------------------------------------*/
5268 static void AccAXLrl1 (char *x)
5269 {
5270     emitcode("xch","a,%s",x);
5271     emitcode("rlc","a");
5272     emitcode("xch","a,%s",x);
5273     emitcode("rlc","a");
5274 }
5275
5276 /*-----------------------------------------------------------------*/
5277 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
5278 /*-----------------------------------------------------------------*/
5279 static void AccAXLsh1 (char *x)
5280 {
5281     emitcode("xch","a,%s",x);
5282     emitcode("add","a,acc");
5283     emitcode("xch","a,%s",x);
5284     emitcode("rlc","a");
5285 }
5286
5287 /*-----------------------------------------------------------------*/
5288 /* AccAXLsh - left shift a:x by known count (0..7)                 */
5289 /*-----------------------------------------------------------------*/
5290 static void AccAXLsh (char *x, int shCount)
5291 {
5292     switch(shCount){
5293         case 0 :
5294             break;
5295         case 1 :
5296             AccAXLsh1(x);
5297             break;
5298         case 2 :
5299             AccAXLsh1(x);
5300             AccAXLsh1(x);
5301             break;
5302         case 3 :
5303         case 4 :
5304         case 5 :                        // AAAAABBB:CCCCCDDD
5305             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
5306             emitcode("anl","a,#0x%02x",
5307                      SLMask[shCount]);  // BBB00000:CCCCCDDD
5308             emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
5309             AccRol(shCount);            // DDDCCCCC:BBB00000
5310             emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
5311             emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
5312             emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
5313             emitcode("anl","a,#0x%02x",
5314                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
5315             emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
5316             emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
5317             break;
5318         case 6 :                        // AAAAAABB:CCCCCCDD
5319             emitcode("anl","a,#0x%02x",
5320                      SRMask[shCount]);  // 000000BB:CCCCCCDD
5321             emitcode("mov","c,acc.0");  // c = B
5322             emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
5323             AccAXRrl1(x);               // BCCCCCCD:D000000B
5324             AccAXRrl1(x);               // BBCCCCCC:DD000000
5325             break;
5326         case 7 :                        // a:x <<= 7
5327             emitcode("anl","a,#0x%02x",
5328                      SRMask[shCount]);  // 0000000B:CCCCCCCD
5329             emitcode("mov","c,acc.0");  // c = B
5330             emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
5331             AccAXRrl1(x);               // BCCCCCCC:D0000000
5332             break;
5333         default :
5334             break;
5335     }
5336 }
5337
5338 /*-----------------------------------------------------------------*/
5339 /* AccAXRsh - right shift a:x known count (0..7)                   */
5340 /*-----------------------------------------------------------------*/
5341 static void AccAXRsh (char *x, int shCount)
5342 {   
5343     switch(shCount){
5344         case 0 :
5345             break;
5346         case 1 :
5347             CLRC;
5348             AccAXRrl1(x);               // 0->a:x
5349             break;
5350         case 2 :
5351             CLRC;
5352             AccAXRrl1(x);               // 0->a:x
5353             CLRC;
5354             AccAXRrl1(x);               // 0->a:x
5355             break;
5356         case 3 :
5357         case 4 :
5358         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
5359             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
5360             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
5361             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
5362             emitcode("anl","a,#0x%02x",
5363                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
5364             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
5365             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
5366             emitcode("anl","a,#0x%02x",
5367                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
5368             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
5369             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
5370             emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
5371             break;
5372         case 6 :                        // AABBBBBB:CCDDDDDD
5373             emitcode("mov","c,acc.7");
5374             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
5375             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
5376             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
5377             emitcode("anl","a,#0x%02x",
5378                      SRMask[shCount]);  // 000000AA:BBBBBBCC
5379             break;
5380         case 7 :                        // ABBBBBBB:CDDDDDDD
5381             emitcode("mov","c,acc.7");  // c = A
5382             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
5383             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
5384             emitcode("anl","a,#0x%02x",
5385                      SRMask[shCount]);  // 0000000A:BBBBBBBC
5386             break;
5387         default :
5388             break;
5389     }
5390 }
5391
5392 /*-----------------------------------------------------------------*/
5393 /* AccAXRshS - right shift signed a:x known count (0..7)           */
5394 /*-----------------------------------------------------------------*/
5395 static void AccAXRshS (char *x, int shCount)
5396 {   
5397     symbol *tlbl ;
5398     switch(shCount){
5399         case 0 :
5400             break;
5401         case 1 :
5402             emitcode("mov","c,acc.7");
5403             AccAXRrl1(x);               // s->a:x
5404             break;
5405         case 2 :
5406             emitcode("mov","c,acc.7");
5407             AccAXRrl1(x);               // s->a:x
5408             emitcode("mov","c,acc.7");
5409             AccAXRrl1(x);               // s->a:x
5410             break;
5411         case 3 :
5412         case 4 :
5413         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
5414             tlbl = newiTempLabel(NULL);
5415             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
5416             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
5417             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
5418             emitcode("anl","a,#0x%02x",
5419                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
5420             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
5421             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
5422             emitcode("anl","a,#0x%02x",
5423                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
5424             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
5425             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
5426             emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
5427             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5428             emitcode("orl","a,#0x%02x",
5429                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
5430             emitcode("","%05d$:",tlbl->key+100);
5431             break;                      // SSSSAAAA:BBBCCCCC
5432         case 6 :                        // AABBBBBB:CCDDDDDD
5433             tlbl = newiTempLabel(NULL);
5434             emitcode("mov","c,acc.7");
5435             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
5436             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
5437             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
5438             emitcode("anl","a,#0x%02x",
5439                      SRMask[shCount]);  // 000000AA:BBBBBBCC
5440             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5441             emitcode("orl","a,#0x%02x",
5442                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
5443             emitcode("","%05d$:",tlbl->key+100);
5444             break;
5445         case 7 :                        // ABBBBBBB:CDDDDDDD
5446             tlbl = newiTempLabel(NULL);
5447             emitcode("mov","c,acc.7");  // c = A
5448             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
5449             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
5450             emitcode("anl","a,#0x%02x",
5451                      SRMask[shCount]);  // 0000000A:BBBBBBBC
5452             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
5453             emitcode("orl","a,#0x%02x",
5454                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
5455             emitcode("","%05d$:",tlbl->key+100);
5456             break;
5457         default :
5458             break;
5459     }
5460 }
5461
5462 /*-----------------------------------------------------------------*/
5463 /* shiftL2Left2Result - shift left two bytes from left to result   */
5464 /*-----------------------------------------------------------------*/
5465 static void shiftL2Left2Result (operand *left, int offl,
5466                                 operand *result, int offr, int shCount)
5467 {
5468     if(sameRegs(AOP(result), AOP(left)) &&
5469        ((offl + MSB16) == offr)){
5470         /* don't crash result[offr] */
5471         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5472         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5473     } else {
5474         movLeft2Result(left,offl, result, offr, 0);
5475         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5476     }
5477     /* ax << shCount (x = lsb(result))*/
5478     AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5479     aopPut(AOP(result),"a",offr+MSB16);
5480 }
5481
5482
5483 /*-----------------------------------------------------------------*/
5484 /* shiftR2Left2Result - shift right two bytes from left to result  */
5485 /*-----------------------------------------------------------------*/
5486 static void shiftR2Left2Result (operand *left, int offl,
5487                                 operand *result, int offr,
5488                                 int shCount, int sign)
5489 {
5490     if(sameRegs(AOP(result), AOP(left)) &&
5491        ((offl + MSB16) == offr)){
5492         /* don't crash result[offr] */
5493         MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5494         emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5495     } else {
5496         movLeft2Result(left,offl, result, offr, 0);
5497         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5498     }
5499     /* a:x >> shCount (x = lsb(result))*/
5500     if(sign)
5501         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5502     else
5503         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5504     if(getDataSize(result) > 1)
5505         aopPut(AOP(result),"a",offr+MSB16);
5506 }
5507
5508 /*-----------------------------------------------------------------*/
5509 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5510 /*-----------------------------------------------------------------*/
5511 static void shiftLLeftOrResult (operand *left, int offl,
5512                                 operand *result, int offr, int shCount)
5513 {
5514     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5515     /* shift left accumulator */
5516     AccLsh(shCount);
5517     /* or with result */
5518     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5519     /* back to result */
5520     aopPut(AOP(result),"a",offr);
5521 }
5522
5523 /*-----------------------------------------------------------------*/
5524 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5525 /*-----------------------------------------------------------------*/
5526 static void shiftRLeftOrResult (operand *left, int offl,
5527                                 operand *result, int offr, int shCount)
5528 {
5529     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5530     /* shift right accumulator */
5531     AccRsh(shCount);
5532     /* or with result */
5533     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5534     /* back to result */
5535     aopPut(AOP(result),"a",offr);
5536 }
5537
5538 /*-----------------------------------------------------------------*/
5539 /* genlshOne - left shift a one byte quantity by known count       */
5540 /*-----------------------------------------------------------------*/
5541 static void genlshOne (operand *result, operand *left, int shCount)
5542 {       
5543     D(emitcode(";", "genlshOne "););
5544     shiftL1Left2Result(left, LSB, result, LSB, shCount);
5545 }
5546
5547 /*-----------------------------------------------------------------*/
5548 /* genlshTwo - left shift two bytes by known amount != 0           */
5549 /*-----------------------------------------------------------------*/
5550 static void genlshTwo (operand *result,operand *left, int shCount)
5551 {
5552     int size;
5553     
5554     D(emitcode(";", "genlshTwo "););
5555
5556     size = getDataSize(result);
5557
5558     /* if shCount >= 8 */
5559     if (shCount >= 8) {
5560         shCount -= 8 ;
5561
5562         if (size > 1){
5563             if (shCount)
5564                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5565             else 
5566                 movLeft2Result(left, LSB, result, MSB16, 0);
5567         }
5568         aopPut(AOP(result),zero,LSB);   
5569     }
5570
5571     /*  1 <= shCount <= 7 */
5572     else {  
5573         if(size == 1)
5574             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
5575         else 
5576             shiftL2Left2Result(left, LSB, result, LSB, shCount);
5577     }
5578 }
5579
5580 /*-----------------------------------------------------------------*/
5581 /* shiftLLong - shift left one long from left to result            */
5582 /* offl = LSB or MSB16                                             */
5583 /*-----------------------------------------------------------------*/
5584 static void shiftLLong (operand *left, operand *result, int offr )
5585 {
5586     char *l;
5587     int size = AOP_SIZE(result);
5588
5589     if(size >= LSB+offr){
5590         l = aopGet(AOP(left),LSB,FALSE,FALSE);
5591         MOVA(l);
5592         emitcode("add","a,acc");
5593         if (sameRegs(AOP(left),AOP(result)) && 
5594             size >= MSB16+offr && offr != LSB )
5595             emitcode("xch","a,%s",
5596                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5597         else        
5598             aopPut(AOP(result),"a",LSB+offr);
5599     }
5600
5601     if(size >= MSB16+offr){
5602         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5603             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5604             MOVA(l);
5605         }
5606         emitcode("rlc","a");
5607         if (sameRegs(AOP(left),AOP(result)) && 
5608             size >= MSB24+offr && offr != LSB)
5609             emitcode("xch","a,%s",
5610                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5611         else        
5612             aopPut(AOP(result),"a",MSB16+offr);
5613     }
5614
5615     if(size >= MSB24+offr){
5616         if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5617             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5618             MOVA(l);
5619         }
5620         emitcode("rlc","a");
5621         if (sameRegs(AOP(left),AOP(result)) && 
5622             size >= MSB32+offr && offr != LSB )
5623             emitcode("xch","a,%s",
5624                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5625         else        
5626             aopPut(AOP(result),"a",MSB24+offr);
5627     }
5628
5629     if(size > MSB32+offr){
5630         if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5631             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5632             MOVA(l);    
5633         }
5634         emitcode("rlc","a");
5635         aopPut(AOP(result),"a",MSB32+offr);
5636     }
5637     if(offr != LSB)
5638         aopPut(AOP(result),zero,LSB);       
5639 }
5640
5641 /*-----------------------------------------------------------------*/
5642 /* genlshFour - shift four byte by a known amount != 0             */
5643 /*-----------------------------------------------------------------*/
5644 static void genlshFour (operand *result, operand *left, int shCount)
5645 {
5646     int size;
5647
5648     D(emitcode(";", "genlshFour "););
5649
5650     size = AOP_SIZE(result);
5651
5652     /* if shifting more that 3 bytes */
5653     if (shCount >= 24 ) {
5654         shCount -= 24;
5655         if (shCount)
5656             /* lowest order of left goes to the highest
5657             order of the destination */
5658             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5659         else
5660             movLeft2Result(left, LSB, result, MSB32, 0);
5661         aopPut(AOP(result),zero,LSB);
5662         aopPut(AOP(result),zero,MSB16);
5663         aopPut(AOP(result),zero,MSB32);
5664         return;
5665     }
5666
5667     /* more than two bytes */
5668     else if ( shCount >= 16 ) {
5669         /* lower order two bytes goes to higher order two bytes */
5670         shCount -= 16;
5671         /* if some more remaining */
5672         if (shCount)
5673             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5674         else {
5675             movLeft2Result(left, MSB16, result, MSB32, 0);
5676             movLeft2Result(left, LSB, result, MSB24, 0);
5677         }
5678         aopPut(AOP(result),zero,MSB16);
5679         aopPut(AOP(result),zero,LSB);
5680         return;
5681     }    
5682
5683     /* if more than 1 byte */
5684     else if ( shCount >= 8 ) {
5685         /* lower order three bytes goes to higher order  three bytes */
5686         shCount -= 8;
5687         if(size == 2){
5688             if(shCount)
5689                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5690             else
5691                 movLeft2Result(left, LSB, result, MSB16, 0);
5692         }
5693         else{   /* size = 4 */
5694             if(shCount == 0){
5695                 movLeft2Result(left, MSB24, result, MSB32, 0);
5696                 movLeft2Result(left, MSB16, result, MSB24, 0);
5697                 movLeft2Result(left, LSB, result, MSB16, 0);
5698                 aopPut(AOP(result),zero,LSB);
5699             }
5700             else if(shCount == 1)
5701                 shiftLLong(left, result, MSB16);
5702             else{
5703                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5704                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5705                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5706                 aopPut(AOP(result),zero,LSB);
5707             }
5708         }
5709     }
5710
5711     /* 1 <= shCount <= 7 */
5712     else if(shCount <= 2){
5713         shiftLLong(left, result, LSB);
5714         if(shCount == 2)
5715             shiftLLong(result, result, LSB);
5716     }
5717     /* 3 <= shCount <= 7, optimize */
5718     else{
5719         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5720         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5721         shiftL2Left2Result(left, LSB, result, LSB, shCount);
5722     }
5723 }
5724
5725 /*-----------------------------------------------------------------*/
5726 /* genLeftShiftLiteral - left shifting by known count              */
5727 /*-----------------------------------------------------------------*/
5728 static void genLeftShiftLiteral (operand *left,
5729                                  operand *right,
5730                                  operand *result,
5731                                  iCode *ic)
5732 {    
5733     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5734     int size;
5735
5736     D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
5737
5738     freeAsmop(right,NULL,ic,TRUE);
5739
5740     aopOp(left,ic,FALSE, FALSE);
5741     aopOp(result,ic,FALSE, TRUE);
5742
5743     size = getSize(operandType(result));
5744
5745 #if VIEW_SIZE
5746     emitcode("; shift left ","result %d, left %d",size,
5747              AOP_SIZE(left));
5748 #endif
5749
5750     /* I suppose that the left size >= result size */
5751     if(shCount == 0){
5752         while(size--){
5753             movLeft2Result(left, size, result, size, 0);
5754         }
5755     }
5756
5757     else if(shCount >= (size * 8))
5758         while(size--)
5759             aopPut(AOP(result),zero,size);
5760     else{
5761         switch (size) {
5762             case 1:
5763                 genlshOne (result,left,shCount);
5764                 break;
5765
5766             case 2:
5767             case 3: /* bug: this is for generic pointers, I bet. */
5768                 genlshTwo (result,left,shCount);
5769                 break;
5770
5771             case 4:
5772                 genlshFour (result,left,shCount);
5773                 break;
5774         }
5775     }
5776     freeAsmop(left,NULL,ic,TRUE);
5777     freeAsmop(result,NULL,ic,TRUE);
5778 }
5779
5780 /*-----------------------------------------------------------------*/
5781 /* genLeftShift - generates code for left shifting                 */
5782 /*-----------------------------------------------------------------*/
5783 static void genLeftShift (iCode *ic)
5784 {
5785     operand *left,*right, *result;
5786     int size, offset;
5787     char *l;
5788     symbol *tlbl , *tlbl1;
5789
5790     D(emitcode(";", "genLeftShift "););
5791
5792     right = IC_RIGHT(ic);
5793     left  = IC_LEFT(ic);
5794     result = IC_RESULT(ic);
5795
5796     aopOp(right,ic,FALSE, FALSE);
5797
5798     #if 0
5799     /* if the shift count is known then do it 
5800     as efficiently as possible */
5801     if (AOP_TYPE(right) == AOP_LIT) {
5802         genLeftShiftLiteral (left,right,result,ic);
5803         return ;
5804     }
5805     #endif
5806
5807     /* shift count is unknown then we have to form 
5808     a loop get the loop count in B : Note: we take
5809     only the lower order byte since shifting
5810     more that 32 bits make no sense anyway, ( the
5811     largest size of an object can be only 32 bits ) */  
5812
5813     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5814     emitcode("inc","b");
5815     freeAsmop (right,NULL,ic,TRUE);
5816     aopOp(left,ic,FALSE, FALSE);
5817     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5818
5819     /* now move the left to the result if they are not the
5820     same */
5821     if (!sameRegs(AOP(left),AOP(result)) && 
5822         AOP_SIZE(result) > 1) {
5823
5824         size = AOP_SIZE(result);
5825         offset=0;
5826         while (size--) {
5827             l = aopGet(AOP(left),offset,FALSE,TRUE);
5828             if (*l == '@' && (IS_AOP_PREG(result))) {
5829
5830                 emitcode("mov","a,%s",l);
5831                 aopPut(AOP(result),"a",offset);
5832             } else
5833                 aopPut(AOP(result),l,offset);
5834             offset++;
5835         }
5836     }
5837
5838     tlbl = newiTempLabel(NULL);
5839     size = AOP_SIZE(result);
5840     offset = 0 ;   
5841     tlbl1 = newiTempLabel(NULL);
5842
5843     /* if it is only one byte then */
5844     if (size == 1) {
5845         symbol *tlbl1 = newiTempLabel(NULL);
5846
5847         l = aopGet(AOP(left),0,FALSE,FALSE);
5848         MOVA(l);
5849         emitcode("sjmp","%05d$",tlbl1->key+100); 
5850         emitcode("","%05d$:",tlbl->key+100);
5851         emitcode("add","a,acc");
5852         emitcode("","%05d$:",tlbl1->key+100);
5853         emitcode("djnz","b,%05d$",tlbl->key+100);      
5854         aopPut(AOP(result),"a",0);
5855         goto release ;
5856     }
5857     
5858     reAdjustPreg(AOP(result));    
5859     
5860     emitcode("sjmp","%05d$",tlbl1->key+100); 
5861     emitcode("","%05d$:",tlbl->key+100);    
5862     l = aopGet(AOP(result),offset,FALSE,FALSE);
5863     MOVA(l);
5864     emitcode("add","a,acc");         
5865     aopPut(AOP(result),"a",offset++);
5866     while (--size) {
5867         l = aopGet(AOP(result),offset,FALSE,FALSE);
5868         MOVA(l);
5869         emitcode("rlc","a");         
5870         aopPut(AOP(result),"a",offset++);
5871     }
5872     reAdjustPreg(AOP(result));
5873
5874     emitcode("","%05d$:",tlbl1->key+100);
5875     emitcode("djnz","b,%05d$",tlbl->key+100);
5876 release:
5877     freeAsmop(left,NULL,ic,TRUE);
5878     freeAsmop(result,NULL,ic,TRUE);
5879 }
5880
5881 /*-----------------------------------------------------------------*/
5882 /* genrshOne - right shift a one byte quantity by known count      */
5883 /*-----------------------------------------------------------------*/
5884 static void genrshOne (operand *result, operand *left,
5885                        int shCount, int sign)
5886 {
5887     D(emitcode(";", "genrshOne"););
5888     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5889 }
5890
5891 /*-----------------------------------------------------------------*/
5892 /* genrshTwo - right shift two bytes by known amount != 0          */
5893 /*-----------------------------------------------------------------*/
5894 static void genrshTwo (operand *result,operand *left,
5895                        int shCount, int sign)
5896 {
5897     D(emitcode(";", "genrshTwo"););
5898
5899     /* if shCount >= 8 */
5900     if (shCount >= 8) {
5901         shCount -= 8 ;
5902         if (shCount)
5903             shiftR1Left2Result(left, MSB16, result, LSB,
5904                                shCount, sign);
5905         else 
5906             movLeft2Result(left, MSB16, result, LSB, sign);
5907         addSign(result, MSB16, sign);
5908     }
5909
5910     /*  1 <= shCount <= 7 */
5911     else
5912         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
5913 }
5914
5915 /*-----------------------------------------------------------------*/
5916 /* shiftRLong - shift right one long from left to result           */
5917 /* offl = LSB or MSB16                                             */
5918 /*-----------------------------------------------------------------*/
5919 static void shiftRLong (operand *left, int offl,
5920                         operand *result, int sign)
5921 {
5922     if(!sign)
5923         emitcode("clr","c");
5924     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5925     if(sign)
5926         emitcode("mov","c,acc.7");
5927     emitcode("rrc","a");
5928     aopPut(AOP(result),"a",MSB32-offl);
5929     if(offl == MSB16)
5930         /* add sign of "a" */
5931         addSign(result, MSB32, sign);
5932
5933     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5934     emitcode("rrc","a");
5935     aopPut(AOP(result),"a",MSB24-offl);
5936
5937     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5938     emitcode("rrc","a");
5939     aopPut(AOP(result),"a",MSB16-offl);
5940
5941     if(offl == LSB){
5942         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5943         emitcode("rrc","a");
5944         aopPut(AOP(result),"a",LSB);
5945     }
5946 }
5947
5948 /*-----------------------------------------------------------------*/
5949 /* genrshFour - shift four byte by a known amount != 0             */
5950 /*-----------------------------------------------------------------*/
5951 static void genrshFour (operand *result, operand *left,
5952                         int shCount, int sign)
5953 {
5954     D(emitcode(";", "genrshFour"););
5955     
5956     /* if shifting more that 3 bytes */
5957     if(shCount >= 24 ) {
5958         shCount -= 24;
5959         if(shCount)
5960             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5961         else
5962             movLeft2Result(left, MSB32, result, LSB, sign);
5963         addSign(result, MSB16, sign);
5964     }
5965     else if(shCount >= 16){
5966         shCount -= 16;
5967         if(shCount)
5968             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5969         else{
5970             movLeft2Result(left, MSB24, result, LSB, 0);
5971             movLeft2Result(left, MSB32, result, MSB16, sign);
5972         }
5973         addSign(result, MSB24, sign);
5974     }
5975     else if(shCount >= 8){
5976         shCount -= 8;
5977         if(shCount == 1)
5978             shiftRLong(left, MSB16, result, sign);
5979         else if(shCount == 0){
5980             movLeft2Result(left, MSB16, result, LSB, 0);
5981             movLeft2Result(left, MSB24, result, MSB16, 0);
5982             movLeft2Result(left, MSB32, result, MSB24, sign);
5983             addSign(result, MSB32, sign);
5984         }
5985         else{
5986             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5987             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5988             /* the last shift is signed */
5989             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5990             addSign(result, MSB32, sign);
5991         }
5992     }
5993     else{   /* 1 <= shCount <= 7 */
5994         if(shCount <= 2){
5995             shiftRLong(left, LSB, result, sign);
5996             if(shCount == 2)
5997                 shiftRLong(result, LSB, result, sign);
5998         }
5999         else{
6000             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6001             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6002             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6003         }
6004     }
6005 }
6006
6007 /*-----------------------------------------------------------------*/
6008 /* genRightShiftLiteral - right shifting by known count            */
6009 /*-----------------------------------------------------------------*/
6010 static void genRightShiftLiteral (operand *left,
6011                                   operand *right,
6012                                   operand *result,
6013                                   iCode *ic,
6014                                   int sign)
6015 {    
6016     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6017     int size;
6018
6019     D(emitcode(";", "genRightShiftLiteral"););
6020
6021     freeAsmop(right,NULL,ic,TRUE);
6022
6023     aopOp(left,ic,FALSE, FALSE);
6024     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6025
6026 #if VIEW_SIZE
6027     emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6028              AOP_SIZE(left));
6029 #endif
6030
6031     size = getDataSize(left);
6032     /* test the LEFT size !!! */
6033
6034     /* I suppose that the left size >= result size */
6035     if(shCount == 0){
6036         size = getDataSize(result);
6037         while(size--)
6038             movLeft2Result(left, size, result, size, 0);
6039     }
6040
6041     else if(shCount >= (size * 8)){
6042         if(sign)
6043             /* get sign in acc.7 */
6044             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6045         addSign(result, LSB, sign);
6046     } else{
6047         switch (size) {
6048             case 1:
6049                 genrshOne (result,left,shCount,sign);
6050                 break;
6051
6052             case 2:
6053                 genrshTwo (result,left,shCount,sign);
6054                 break;
6055
6056             case 4:
6057                 genrshFour (result,left,shCount,sign);
6058                 break;
6059             default :
6060                 break;
6061         }
6062
6063         freeAsmop(left,NULL,ic,TRUE);
6064         freeAsmop(result,NULL,ic,TRUE);
6065     }
6066 }
6067
6068 /*-----------------------------------------------------------------*/
6069 /* genSignedRightShift - right shift of signed number              */
6070 /*-----------------------------------------------------------------*/
6071 static void genSignedRightShift (iCode *ic)
6072 {
6073     operand *right, *left, *result;
6074     int size, offset;
6075     char *l;
6076     symbol *tlbl, *tlbl1 ;
6077
6078     D(emitcode(";", "genSignedRightShift "););
6079
6080     /* we do it the hard way put the shift count in b
6081     and loop thru preserving the sign */
6082
6083     right = IC_RIGHT(ic);
6084     left  = IC_LEFT(ic);
6085     result = IC_RESULT(ic);
6086
6087     aopOp(right,ic,FALSE, FALSE);
6088
6089     #if 0
6090     if ( AOP_TYPE(right) == AOP_LIT) {
6091         genRightShiftLiteral (left,right,result,ic,1);
6092         return ;
6093     }
6094     #endif
6095         /* shift count is unknown then we have to form 
6096        a loop get the loop count in B : Note: we take
6097        only the lower order byte since shifting
6098        more that 32 bits make no sense anyway, ( the
6099        largest size of an object can be only 32 bits ) */  
6100
6101     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6102     emitcode("inc","b");
6103     freeAsmop (right,NULL,ic,TRUE);
6104     aopOp(left,ic,FALSE, FALSE);
6105     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6106
6107     /* now move the left to the result if they are not the
6108     same */
6109     if (!sameRegs(AOP(left),AOP(result)) && 
6110         AOP_SIZE(result) > 1) {
6111
6112         size = AOP_SIZE(result);
6113         offset=0;
6114         while (size--) {
6115             l = aopGet(AOP(left),offset,FALSE,TRUE);
6116             if (*l == '@' && IS_AOP_PREG(result)) {
6117
6118                 emitcode("mov","a,%s",l);
6119                 aopPut(AOP(result),"a",offset);
6120             } else
6121                 aopPut(AOP(result),l,offset);
6122             offset++;
6123         }
6124     }
6125
6126     /* mov the highest order bit to OVR */    
6127     tlbl = newiTempLabel(NULL);
6128     tlbl1= newiTempLabel(NULL);
6129
6130     size = AOP_SIZE(result);
6131     offset = size - 1;
6132     emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6133     emitcode("rlc","a");
6134     emitcode("mov","ov,c");
6135     /* if it is only one byte then */
6136     if (size == 1) {
6137         l = aopGet(AOP(left),0,FALSE,FALSE);
6138         MOVA(l);
6139         emitcode("sjmp","%05d$",tlbl1->key+100);
6140         emitcode("","%05d$:",tlbl->key+100);
6141         emitcode("mov","c,ov");
6142         emitcode("rrc","a");
6143         emitcode("","%05d$:",tlbl1->key+100);
6144         emitcode("djnz","b,%05d$",tlbl->key+100);
6145         aopPut(AOP(result),"a",0);
6146         goto release ;
6147     }
6148
6149     reAdjustPreg(AOP(result));
6150     emitcode("sjmp","%05d$",tlbl1->key+100);
6151     emitcode("","%05d$:",tlbl->key+100);    
6152     emitcode("mov","c,ov");
6153     while (size--) {
6154         l = aopGet(AOP(result),offset,FALSE,FALSE);
6155         MOVA(l);
6156         emitcode("rrc","a");         
6157         aopPut(AOP(result),"a",offset--);
6158     }
6159     reAdjustPreg(AOP(result));
6160     emitcode("","%05d$:",tlbl1->key+100);
6161     emitcode("djnz","b,%05d$",tlbl->key+100);
6162
6163 release:
6164     freeAsmop(left,NULL,ic,TRUE);
6165     freeAsmop(result,NULL,ic,TRUE);
6166 }
6167
6168 /*-----------------------------------------------------------------*/
6169 /* genRightShift - generate code for right shifting                */
6170 /*-----------------------------------------------------------------*/
6171 static void genRightShift (iCode *ic)
6172 {
6173     operand *right, *left, *result;
6174     link *retype ;
6175     int size, offset;
6176     char *l;
6177     symbol *tlbl, *tlbl1 ;
6178
6179     D(emitcode(";", "genRightShift "););
6180
6181     /* if signed then we do it the hard way preserve the
6182     sign bit moving it inwards */
6183     retype = getSpec(operandType(IC_RESULT(ic)));
6184
6185     if (!SPEC_USIGN(retype)) {
6186         genSignedRightShift (ic);
6187         return ;
6188     }
6189
6190     /* signed & unsigned types are treated the same : i.e. the
6191     signed is NOT propagated inwards : quoting from the
6192     ANSI - standard : "for E1 >> E2, is equivalent to division
6193     by 2**E2 if unsigned or if it has a non-negative value,
6194     otherwise the result is implementation defined ", MY definition
6195     is that the sign does not get propagated */
6196
6197     right = IC_RIGHT(ic);
6198     left  = IC_LEFT(ic);
6199     result = IC_RESULT(ic);
6200
6201     aopOp(right,ic,FALSE, FALSE);
6202
6203     #if 0
6204     /* if the shift count is known then do it 
6205     as efficiently as possible */
6206     if (AOP_TYPE(right) == AOP_LIT) {
6207         genRightShiftLiteral (left,right,result,ic, 0);
6208         return ;
6209     }
6210     #endif
6211
6212     /* shift count is unknown then we have to form 
6213     a loop get the loop count in B : Note: we take
6214     only the lower order byte since shifting
6215     more that 32 bits make no sense anyway, ( the
6216     largest size of an object can be only 32 bits ) */  
6217
6218     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6219     emitcode("inc","b");
6220     freeAsmop (right,NULL,ic,TRUE);
6221     aopOp(left,ic,FALSE, FALSE);
6222     aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6223
6224     /* now move the left to the result if they are not the
6225     same */
6226     if (!sameRegs(AOP(left),AOP(result)) && 
6227         AOP_SIZE(result) > 1) {
6228
6229         size = AOP_SIZE(result);
6230         offset=0;
6231         while (size--) {
6232             l = aopGet(AOP(left),offset,FALSE,TRUE);
6233             if (*l == '@' && IS_AOP_PREG(result)) {
6234
6235                 emitcode("mov","a,%s",l);
6236                 aopPut(AOP(result),"a",offset);
6237             } else
6238                 aopPut(AOP(result),l,offset);
6239             offset++;
6240         }
6241     }
6242
6243     tlbl = newiTempLabel(NULL);
6244     tlbl1= newiTempLabel(NULL);
6245     size = AOP_SIZE(result);
6246     offset = size - 1;
6247
6248     /* if it is only one byte then */
6249     if (size == 1) {
6250         l = aopGet(AOP(left),0,FALSE,FALSE);
6251         MOVA(l);
6252         emitcode("sjmp","%05d$",tlbl1->key+100);
6253         emitcode("","%05d$:",tlbl->key+100);
6254         CLRC;
6255         emitcode("rrc","a");
6256         emitcode("","%05d$:",tlbl1->key+100);
6257         emitcode("djnz","b,%05d$",tlbl->key+100);
6258         aopPut(AOP(result),"a",0);
6259         goto release ;
6260     }
6261
6262     reAdjustPreg(AOP(result));
6263     emitcode("sjmp","%05d$",tlbl1->key+100);
6264     emitcode("","%05d$:",tlbl->key+100);    
6265     CLRC;
6266     while (size--) {
6267         l = aopGet(AOP(result),offset,FALSE,FALSE);
6268         MOVA(l);
6269         emitcode("rrc","a");         
6270         aopPut(AOP(result),"a",offset--);
6271     }
6272     reAdjustPreg(AOP(result));
6273
6274     emitcode("","%05d$:",tlbl1->key+100);
6275     emitcode("djnz","b,%05d$",tlbl->key+100);
6276
6277 release:
6278     freeAsmop(left,NULL,ic,TRUE);
6279     freeAsmop(result,NULL,ic,TRUE);
6280 }
6281
6282 /*-----------------------------------------------------------------*/
6283 /* genUnpackBits - generates code for unpacking bits               */
6284 /*-----------------------------------------------------------------*/
6285 static void genUnpackBits (operand *result, char *rname, int ptype)
6286 {    
6287     int shCnt ;
6288     int rlen = 0 ;
6289     link *etype;
6290     int offset = 0 ;
6291
6292     D(emitcode(";", "genUnpackBits "););
6293
6294     etype = getSpec(operandType(result));
6295
6296     /* read the first byte  */
6297     switch (ptype) {
6298
6299     case POINTER:
6300     case IPOINTER:
6301         emitcode("mov","a,@%s",rname);
6302         break;
6303         
6304     case PPOINTER:
6305         emitcode("movx","a,@%s",rname);
6306         break;
6307         
6308     case FPOINTER:
6309         emitcode("movx","a,@dptr");
6310         break;
6311
6312     case CPOINTER:
6313         emitcode("clr","a");
6314         emitcode("movc","a","@a+dptr");
6315         break;
6316
6317     case GPOINTER:
6318         emitcode("lcall","__gptrget");
6319         break;
6320     }
6321
6322     /* if we have bitdisplacement then it fits   */
6323     /* into this byte completely or if length is */
6324     /* less than a byte                          */
6325     if ((shCnt = SPEC_BSTR(etype)) || 
6326         (SPEC_BLEN(etype) <= 8))  {
6327
6328         /* shift right acc */
6329         AccRsh(shCnt);
6330
6331         emitcode("anl","a,#0x%02x",
6332                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6333         aopPut(AOP(result),"a",offset);
6334         return ;
6335     }
6336
6337     /* bit field did not fit in a byte  */
6338     rlen = SPEC_BLEN(etype) - 8;
6339     aopPut(AOP(result),"a",offset++);
6340
6341     while (1)  {
6342
6343         switch (ptype) {
6344         case POINTER:
6345         case IPOINTER:
6346             emitcode("inc","%s",rname);
6347             emitcode("mov","a,@%s",rname);
6348             break;
6349             
6350         case PPOINTER:
6351             emitcode("inc","%s",rname);
6352             emitcode("movx","a,@%s",rname);
6353             break;
6354
6355         case FPOINTER:
6356             emitcode("inc","dptr");
6357             emitcode("movx","a,@dptr");
6358             break;
6359             
6360         case CPOINTER:
6361             emitcode("clr","a");
6362             emitcode("inc","dptr");
6363             emitcode("movc","a","@a+dptr");
6364             break;
6365             
6366         case GPOINTER:
6367             emitcode("inc","dptr");
6368             emitcode("lcall","__gptrget");
6369             break;
6370         }
6371
6372         rlen -= 8;            
6373         /* if we are done */
6374         if ( rlen <= 0 )
6375             break ;
6376         
6377         aopPut(AOP(result),"a",offset++);
6378                               
6379     }
6380     
6381     if (rlen) {
6382         emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6383         aopPut(AOP(result),"a",offset);        
6384     }
6385     
6386     return ;
6387 }
6388
6389
6390 /*-----------------------------------------------------------------*/
6391 /* genDataPointerGet - generates code when ptr offset is known     */
6392 /*-----------------------------------------------------------------*/
6393 static void genDataPointerGet (operand *left, 
6394                                operand *result, 
6395                                iCode *ic)
6396 {
6397     char *l;
6398     char buffer[256];
6399     int size , offset = 0;
6400     aopOp(result,ic,TRUE, FALSE);
6401
6402     /* get the string representation of the name */
6403     l = aopGet(AOP(left),0,FALSE,TRUE);
6404     size = AOP_SIZE(result);
6405     while (size--) {
6406         if (offset)
6407             sprintf(buffer,"(%s + %d)",l+1,offset);
6408         else
6409             sprintf(buffer,"%s",l+1);
6410         aopPut(AOP(result),buffer,offset++);
6411     }
6412
6413     freeAsmop(left,NULL,ic,TRUE);
6414     freeAsmop(result,NULL,ic,TRUE);
6415 }
6416
6417 /*-----------------------------------------------------------------*/
6418 /* genNearPointerGet - emitcode for near pointer fetch             */
6419 /*-----------------------------------------------------------------*/
6420 static void genNearPointerGet (operand *left, 
6421                                operand *result, 
6422                                iCode *ic)
6423 {
6424     asmop *aop = NULL;
6425     regs *preg = NULL ;
6426     char *rname ;
6427     link *rtype, *retype;
6428     link *ltype = operandType(left);    
6429     char buffer[80];
6430
6431     rtype = operandType(result);
6432     retype= getSpec(rtype);
6433     
6434     aopOp(left,ic,FALSE, FALSE);
6435     
6436     /* if left is rematerialisable and
6437        result is not bit variable type and
6438        the left is pointer to data space i.e
6439        lower 128 bytes of space */
6440     if (AOP_TYPE(left) == AOP_IMMD &&
6441         !IS_BITVAR(retype)         &&
6442         DCL_TYPE(ltype) == POINTER) {
6443         genDataPointerGet (left,result,ic);
6444         return ;
6445     }
6446     
6447         /* if the value is already in a pointer register
6448        then don't need anything more */
6449     if (!AOP_INPREG(AOP(left))) {
6450         /* otherwise get a free pointer register */
6451         aop = newAsmop(0);
6452         preg = getFreePtr(ic,&aop,FALSE);
6453         emitcode("mov","%s,%s",
6454                 preg->name,
6455                 aopGet(AOP(left),0,FALSE,TRUE));
6456         rname = preg->name ;
6457     } else
6458         rname = aopGet(AOP(left),0,FALSE,FALSE);
6459     
6460     freeAsmop(left,NULL,ic,TRUE);
6461     aopOp (result,ic,FALSE, FALSE);
6462     
6463       /* if bitfield then unpack the bits */
6464     if (IS_BITVAR(retype)) 
6465         genUnpackBits (result,rname,POINTER);
6466     else {
6467         /* we have can just get the values */
6468         int size = AOP_SIZE(result);
6469         int offset = 0 ;        
6470         
6471         while (size--) {
6472             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6473
6474                 emitcode("mov","a,@%s",rname);
6475                 aopPut(AOP(result),"a",offset);
6476             } else {
6477                 sprintf(buffer,"@%s",rname);
6478                 aopPut(AOP(result),buffer,offset);
6479             }
6480             offset++ ;
6481             if (size)
6482                 emitcode("inc","%s",rname);
6483         }
6484     }
6485
6486     /* now some housekeeping stuff */
6487     if (aop) {
6488         /* we had to allocate for this iCode */
6489         freeAsmop(NULL,aop,ic,TRUE);
6490     } else { 
6491         /* we did not allocate which means left
6492            already in a pointer register, then
6493            if size > 0 && this could be used again
6494            we have to point it back to where it 
6495            belongs */
6496         if (AOP_SIZE(result) > 1 &&
6497             !OP_SYMBOL(left)->remat &&
6498             ( OP_SYMBOL(left)->liveTo > ic->seq ||
6499               ic->depth )) {
6500             int size = AOP_SIZE(result) - 1;
6501             while (size--)
6502                 emitcode("dec","%s",rname);
6503         }
6504     }
6505
6506     /* done */
6507     freeAsmop(result,NULL,ic,TRUE);
6508      
6509 }
6510
6511 /*-----------------------------------------------------------------*/
6512 /* genPagedPointerGet - emitcode for paged pointer fetch           */
6513 /*-----------------------------------------------------------------*/
6514 static void genPagedPointerGet (operand *left, 
6515                                operand *result, 
6516                                iCode *ic)
6517 {
6518     asmop *aop = NULL;
6519     regs *preg = NULL ;
6520     char *rname ;
6521     link *rtype, *retype;    
6522
6523     rtype = operandType(result);
6524     retype= getSpec(rtype);
6525     
6526     aopOp(left,ic,FALSE, FALSE);
6527
6528   /* if the value is already in a pointer register
6529        then don't need anything more */
6530     if (!AOP_INPREG(AOP(left))) {
6531         /* otherwise get a free pointer register */
6532         aop = newAsmop(0);
6533         preg = getFreePtr(ic,&aop,FALSE);
6534         emitcode("mov","%s,%s",
6535                 preg->name,
6536                 aopGet(AOP(left),0,FALSE,TRUE));
6537         rname = preg->name ;
6538     } else
6539         rname = aopGet(AOP(left),0,FALSE,FALSE);
6540     
6541     freeAsmop(left,NULL,ic,TRUE);
6542     aopOp (result,ic,FALSE, FALSE);
6543
6544     /* if bitfield then unpack the bits */
6545     if (IS_BITVAR(retype)) 
6546         genUnpackBits (result,rname,PPOINTER);
6547     else {
6548         /* we have can just get the values */
6549         int size = AOP_SIZE(result);
6550         int offset = 0 ;        
6551         
6552         while (size--) {
6553             
6554             emitcode("movx","a,@%s",rname);
6555             aopPut(AOP(result),"a",offset);
6556             
6557             offset++ ;
6558             
6559             if (size)
6560                 emitcode("inc","%s",rname);
6561         }
6562     }
6563
6564     /* now some housekeeping stuff */
6565     if (aop) {
6566         /* we had to allocate for this iCode */
6567         freeAsmop(NULL,aop,ic,TRUE);
6568     } else { 
6569         /* we did not allocate which means left
6570            already in a pointer register, then
6571            if size > 0 && this could be used again
6572            we have to point it back to where it 
6573            belongs */
6574         if (AOP_SIZE(result) > 1 &&
6575             !OP_SYMBOL(left)->remat &&
6576             ( OP_SYMBOL(left)->liveTo > ic->seq ||
6577               ic->depth )) {
6578             int size = AOP_SIZE(result) - 1;
6579             while (size--)
6580                 emitcode("dec","%s",rname);
6581         }
6582     }
6583
6584     /* done */
6585     freeAsmop(result,NULL,ic,TRUE);
6586     
6587         
6588 }
6589
6590 /*-----------------------------------------------------------------*/
6591 /* genFarPointerGet - gget value from far space                    */
6592 /*-----------------------------------------------------------------*/
6593 static void genFarPointerGet (operand *left,
6594                               operand *result, iCode *ic)
6595 {
6596     int size, offset ;
6597     link *retype = getSpec(operandType(result));
6598
6599     D(emitcode(";", "genFarPointerGet"););
6600
6601     aopOp(left,ic,FALSE, FALSE);
6602
6603     /* if the operand is already in dptr 
6604     then we do nothing else we move the value to dptr */
6605     if (AOP_TYPE(left) != AOP_STR) {
6606         /* if this is remateriazable */
6607         if (AOP_TYPE(left) == AOP_IMMD)
6608         {
6609             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6610         }
6611         else 
6612         { 
6613             /* we need to get it byte by byte */
6614             if (AOP_TYPE(left) != AOP_DPTR)
6615             {
6616                 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6617                 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6618                 if (options.model == MODEL_FLAT24)
6619                 {
6620                     emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6621                 }
6622             }
6623             else
6624             {
6625                  /* We need to generate a load to DPTR indirect through DPTR. */
6626                  D(emitcode(";", "genFarPointerGet -- indirection special case."););
6627                  emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE));
6628                  emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE));
6629                  emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6630                  emitcode("pop", "dph");
6631                  emitcode("pop", "dpl");
6632             }
6633         }
6634     }
6635     /* so dptr know contains the address */
6636     freeAsmop(left,NULL,ic,TRUE);
6637     aopOp(result,ic,FALSE, TRUE);
6638
6639     /* if bit then unpack */
6640     if (IS_BITVAR(retype)) 
6641         genUnpackBits(result,"dptr",FPOINTER);
6642     else {
6643         size = AOP_SIZE(result);
6644         offset = 0 ;
6645
6646         while (size--) {
6647             emitcode("movx","a,@dptr");
6648             aopPut(AOP(result),"a",offset++);
6649             if (size)
6650                 emitcode("inc","dptr");
6651         }
6652     }
6653
6654     freeAsmop(result,NULL,ic,TRUE);
6655 }
6656
6657 /*-----------------------------------------------------------------*/
6658 /* emitcodePointerGet - gget value from code space                  */
6659 /*-----------------------------------------------------------------*/
6660 static void emitcodePointerGet (operand *left,
6661                                 operand *result, iCode *ic)
6662 {
6663     int size, offset ;
6664     link *retype = getSpec(operandType(result));
6665
6666     aopOp(left,ic,FALSE, FALSE);
6667
6668     /* if the operand is already in dptr 
6669     then we do nothing else we move the value to dptr */
6670     if (AOP_TYPE(left) != AOP_STR) {
6671         /* if this is remateriazable */
6672         if (AOP_TYPE(left) == AOP_IMMD)
6673             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6674         else { /* we need to get it byte by byte */
6675             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6676             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6677             if (options.model == MODEL_FLAT24)
6678             {
6679                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6680             }
6681         }
6682     }
6683     /* so dptr know contains the address */
6684     freeAsmop(left,NULL,ic,TRUE);
6685     aopOp(result,ic,FALSE, FALSE);
6686
6687     /* if bit then unpack */
6688     if (IS_BITVAR(retype)) 
6689         genUnpackBits(result,"dptr",CPOINTER);
6690     else {
6691         size = AOP_SIZE(result);
6692         offset = 0 ;
6693
6694         while (size--) {
6695             emitcode("clr","a");
6696             emitcode("movc","a,@a+dptr");
6697             aopPut(AOP(result),"a",offset++);
6698             if (size)
6699                 emitcode("inc","dptr");
6700         }
6701     }
6702
6703     freeAsmop(result,NULL,ic,TRUE);
6704 }
6705
6706 /*-----------------------------------------------------------------*/
6707 /* genGenPointerGet - gget value from generic pointer space        */
6708 /*-----------------------------------------------------------------*/
6709 static void genGenPointerGet (operand *left,
6710                               operand *result, iCode *ic)
6711 {
6712     int size, offset ;
6713     link *retype = getSpec(operandType(result));
6714
6715     aopOp(left,ic,FALSE, TRUE);
6716
6717     /* if the operand is already in dptr 
6718     then we do nothing else we move the value to dptr */
6719     if (AOP_TYPE(left) != AOP_STR) {
6720         /* if this is remateriazable */
6721         if (AOP_TYPE(left) == AOP_IMMD) {
6722             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6723             emitcode("mov","b,#%d",pointerCode(retype));
6724         }
6725         else { /* we need to get it byte by byte */
6726             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6727             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6728             if (options.model == MODEL_FLAT24)
6729             {
6730                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6731                emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6732             }
6733             else
6734             {
6735                 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6736             }
6737         }
6738     }
6739     /* so dptr know contains the address */
6740     freeAsmop(left,NULL,ic,TRUE);
6741     aopOp(result,ic,FALSE, TRUE);
6742
6743     /* if bit then unpack */
6744     if (IS_BITVAR(retype)) 
6745         genUnpackBits(result,"dptr",GPOINTER);
6746     else {
6747         size = AOP_SIZE(result);
6748         offset = 0 ;
6749
6750         while (size--) {
6751             emitcode("lcall","__gptrget");
6752             aopPut(AOP(result),"a",offset++);
6753             if (size)
6754                 emitcode("inc","dptr");
6755         }
6756     }
6757
6758     freeAsmop(result,NULL,ic,TRUE);
6759 }
6760
6761 /*-----------------------------------------------------------------*/
6762 /* genPointerGet - generate code for pointer get                   */
6763 /*-----------------------------------------------------------------*/
6764 static void genPointerGet (iCode *ic)
6765 {
6766     operand *left, *result ;
6767     link *type, *etype;
6768     int p_type;
6769
6770     D(emitcode(";", "genPointerGet "););
6771
6772     left = IC_LEFT(ic);
6773     result = IC_RESULT(ic) ;
6774
6775     /* depending on the type of pointer we need to
6776     move it to the correct pointer register */
6777     type = operandType(left);
6778     etype = getSpec(type);
6779     /* if left is of type of pointer then it is simple */
6780     if (IS_PTR(type) && !IS_FUNC(type->next)) 
6781         p_type = DCL_TYPE(type);
6782     else {
6783         /* we have to go by the storage class */
6784         p_type = PTR_TYPE(SPEC_OCLS(etype));
6785
6786 /*      if (SPEC_OCLS(etype)->codesp ) { */
6787 /*          p_type = CPOINTER ;  */
6788 /*      } */
6789 /*      else */
6790 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6791 /*              p_type = FPOINTER ; */
6792 /*          else */
6793 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6794 /*                  p_type = PPOINTER; */
6795 /*              else */
6796 /*                  if (SPEC_OCLS(etype) == idata ) */
6797 /*                      p_type = IPOINTER; */
6798 /*                  else */
6799 /*                      p_type = POINTER ; */
6800     }
6801
6802     /* now that we have the pointer type we assign
6803     the pointer values */
6804     switch (p_type) {
6805
6806     case POINTER:       
6807     case IPOINTER:
6808         genNearPointerGet (left,result,ic);
6809         break;
6810
6811     case PPOINTER:
6812         genPagedPointerGet(left,result,ic);
6813         break;
6814
6815     case FPOINTER:
6816         genFarPointerGet (left,result,ic);
6817         break;
6818
6819     case CPOINTER:
6820         emitcodePointerGet (left,result,ic);
6821         break;
6822
6823     case GPOINTER:
6824         genGenPointerGet (left,result,ic);
6825         break;
6826     }
6827
6828 }
6829
6830 /*-----------------------------------------------------------------*/
6831 /* genPackBits - generates code for packed bit storage             */
6832 /*-----------------------------------------------------------------*/
6833 static void genPackBits (link    *etype ,
6834                          operand *right ,
6835                          char *rname, int p_type)
6836 {
6837     int shCount = 0 ;
6838     int offset = 0  ;
6839     int rLen = 0 ;
6840     int blen, bstr ;   
6841     char *l ;
6842
6843     blen = SPEC_BLEN(etype);
6844     bstr = SPEC_BSTR(etype);
6845
6846     l = aopGet(AOP(right),offset++,FALSE,FALSE);
6847     MOVA(l);   
6848
6849     /* if the bit lenth is less than or    */
6850     /* it exactly fits a byte then         */
6851     if (SPEC_BLEN(etype) <= 8 )  {
6852         shCount = SPEC_BSTR(etype) ;
6853
6854         /* shift left acc */
6855         AccLsh(shCount);
6856
6857         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6858
6859
6860             switch (p_type) {
6861                 case POINTER:
6862                     emitcode ("mov","b,a");
6863                     emitcode("mov","a,@%s",rname);
6864                     break;
6865
6866                 case FPOINTER:
6867                     emitcode ("mov","b,a");
6868                     emitcode("movx","a,@dptr");
6869                     break;
6870
6871                 case GPOINTER:
6872                     emitcode ("push","b");
6873                     emitcode ("push","acc");
6874                     emitcode ("lcall","__gptrget");
6875                     emitcode ("pop","b");
6876                     break;
6877             }
6878
6879             emitcode ("anl","a,#0x%02x",(unsigned char)
6880                       ((unsigned char)(0xFF << (blen+bstr)) | 
6881                        (unsigned char)(0xFF >> (8-bstr)) ) );
6882             emitcode ("orl","a,b");
6883             if (p_type == GPOINTER)
6884                 emitcode("pop","b");
6885         }
6886     }
6887
6888     switch (p_type) {
6889         case POINTER:
6890             emitcode("mov","@%s,a",rname);
6891             break;
6892
6893         case FPOINTER:
6894             emitcode("movx","@dptr,a");
6895             break;
6896
6897         case GPOINTER:
6898             emitcode("lcall","__gptrput");
6899             break;
6900     }
6901
6902     /* if we r done */
6903     if ( SPEC_BLEN(etype) <= 8 )
6904         return ;
6905
6906     emitcode("inc","%s",rname);
6907     rLen = SPEC_BLEN(etype) ;     
6908
6909     /* now generate for lengths greater than one byte */
6910     while (1) {
6911
6912         l = aopGet(AOP(right),offset++,FALSE,TRUE);
6913
6914         rLen -= 8 ;
6915         if (rLen <= 0 )
6916             break ;
6917
6918         switch (p_type) {
6919             case POINTER:
6920                 if (*l == '@') {
6921                     MOVA(l);
6922                     emitcode("mov","@%s,a",rname);
6923                 } else
6924                     emitcode("mov","@%s,%s",rname,l);
6925                 break;
6926
6927             case FPOINTER:
6928                 MOVA(l);
6929                 emitcode("movx","@dptr,a");
6930                 break;
6931
6932             case GPOINTER:
6933                 MOVA(l);
6934                 emitcode("lcall","__gptrput");
6935                 break;  
6936         }   
6937         emitcode ("inc","%s",rname);
6938     }
6939
6940     MOVA(l);
6941
6942     /* last last was not complete */
6943     if (rLen)   {
6944         /* save the byte & read byte */
6945         switch (p_type) {
6946             case POINTER:
6947                 emitcode ("mov","b,a");
6948                 emitcode("mov","a,@%s",rname);
6949                 break;
6950
6951             case FPOINTER:
6952                 emitcode ("mov","b,a");
6953                 emitcode("movx","a,@dptr");
6954                 break;
6955
6956             case GPOINTER:
6957                 emitcode ("push","b");
6958                 emitcode ("push","acc");
6959                 emitcode ("lcall","__gptrget");
6960                 emitcode ("pop","b");
6961                 break;
6962         }
6963
6964         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6965         emitcode ("orl","a,b");
6966     }
6967
6968     if (p_type == GPOINTER)
6969         emitcode("pop","b");
6970
6971     switch (p_type) {
6972
6973     case POINTER:
6974         emitcode("mov","@%s,a",rname);
6975         break;
6976         
6977     case FPOINTER:
6978         emitcode("movx","@dptr,a");
6979         break;
6980         
6981     case GPOINTER:
6982         emitcode("lcall","__gptrput");
6983         break;                  
6984     }
6985 }
6986 /*-----------------------------------------------------------------*/
6987 /* genDataPointerSet - remat pointer to data space                 */
6988 /*-----------------------------------------------------------------*/
6989 static void genDataPointerSet(operand *right,
6990                               operand *result,
6991                               iCode *ic)
6992 {
6993     int size, offset = 0 ;
6994     char *l, buffer[256];
6995
6996     aopOp(right,ic,FALSE, FALSE);
6997     
6998     l = aopGet(AOP(result),0,FALSE,TRUE);
6999     size = AOP_SIZE(right);
7000     while (size--) {
7001         if (offset)
7002             sprintf(buffer,"(%s + %d)",l+1,offset);
7003         else
7004             sprintf(buffer,"%s",l+1);
7005         emitcode("mov","%s,%s",buffer,
7006                  aopGet(AOP(right),offset++,FALSE,FALSE));
7007     }
7008
7009     freeAsmop(right,NULL,ic,TRUE);
7010     freeAsmop(result,NULL,ic,TRUE);
7011 }
7012
7013 /*-----------------------------------------------------------------*/
7014 /* genNearPointerSet - emitcode for near pointer put                */
7015 /*-----------------------------------------------------------------*/
7016 static void genNearPointerSet (operand *right,
7017                                operand *result, 
7018                                iCode *ic)
7019 {
7020     asmop *aop = NULL;
7021     regs *preg = NULL ;
7022     char *rname , *l;
7023     link *retype;
7024     link *ptype = operandType(result);
7025     
7026     retype= getSpec(operandType(right));
7027
7028     aopOp(result,ic,FALSE, FALSE);
7029     
7030     /* if the result is rematerializable &
7031        in data space & not a bit variable */
7032     if (AOP_TYPE(result) == AOP_IMMD &&
7033         DCL_TYPE(ptype) == POINTER   &&
7034         !IS_BITVAR(retype)) {
7035         genDataPointerSet (right,result,ic);
7036         return;
7037     }
7038
7039     /* if the value is already in a pointer register
7040     then don't need anything more */
7041     if (!AOP_INPREG(AOP(result))) {
7042         /* otherwise get a free pointer register */
7043         aop = newAsmop(0);
7044         preg = getFreePtr(ic,&aop,FALSE);
7045         emitcode("mov","%s,%s",
7046                  preg->name,
7047                  aopGet(AOP(result),0,FALSE,TRUE));
7048         rname = preg->name ;
7049     } else
7050         rname = aopGet(AOP(result),0,FALSE,FALSE);
7051
7052     freeAsmop(result,NULL,ic,TRUE);
7053     aopOp (right,ic,FALSE, FALSE);
7054
7055     /* if bitfield then unpack the bits */
7056     if (IS_BITVAR(retype)) 
7057         genPackBits (retype,right,rname,POINTER);
7058     else {
7059         /* we have can just get the values */
7060         int size = AOP_SIZE(right);
7061         int offset = 0 ;    
7062
7063         while (size--) {
7064             l = aopGet(AOP(right),offset,FALSE,TRUE);
7065             if (*l == '@' ) {
7066                 MOVA(l);
7067                 emitcode("mov","@%s,a",rname);
7068             } else
7069                 emitcode("mov","@%s,%s",rname,l);
7070             if (size)
7071                 emitcode("inc","%s",rname);
7072             offset++;
7073         }
7074     }
7075
7076     /* now some housekeeping stuff */
7077     if (aop) {
7078         /* we had to allocate for this iCode */
7079         freeAsmop(NULL,aop,ic,TRUE);
7080     } else { 
7081         /* we did not allocate which means left
7082         already in a pointer register, then
7083         if size > 0 && this could be used again
7084         we have to point it back to where it 
7085         belongs */
7086         if (AOP_SIZE(right) > 1 &&
7087             !OP_SYMBOL(result)->remat &&
7088             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7089               ic->depth )) {
7090             int size = AOP_SIZE(right) - 1;
7091             while (size--)
7092                 emitcode("dec","%s",rname);
7093         }
7094     }
7095
7096     /* done */
7097     freeAsmop(right,NULL,ic,TRUE);
7098
7099
7100 }
7101
7102 /*-----------------------------------------------------------------*/
7103 /* genPagedPointerSet - emitcode for Paged pointer put             */
7104 /*-----------------------------------------------------------------*/
7105 static void genPagedPointerSet (operand *right,
7106                                operand *result, 
7107                                iCode *ic)
7108 {
7109     asmop *aop = NULL;
7110     regs *preg = NULL ;
7111     char *rname , *l;
7112     link *retype;
7113        
7114     retype= getSpec(operandType(right));
7115     
7116     aopOp(result,ic,FALSE, FALSE);
7117     
7118     /* if the value is already in a pointer register
7119        then don't need anything more */
7120     if (!AOP_INPREG(AOP(result))) {
7121         /* otherwise get a free pointer register */
7122         aop = newAsmop(0);
7123         preg = getFreePtr(ic,&aop,FALSE);
7124         emitcode("mov","%s,%s",
7125                 preg->name,
7126                 aopGet(AOP(result),0,FALSE,TRUE));
7127         rname = preg->name ;
7128     } else
7129         rname = aopGet(AOP(result),0,FALSE,FALSE);
7130     
7131     freeAsmop(result,NULL,ic,TRUE);
7132     aopOp (right,ic,FALSE, FALSE);
7133
7134     /* if bitfield then unpack the bits */
7135     if (IS_BITVAR(retype)) 
7136         genPackBits (retype,right,rname,PPOINTER);
7137     else {
7138         /* we have can just get the values */
7139         int size = AOP_SIZE(right);
7140         int offset = 0 ;        
7141         
7142         while (size--) {
7143             l = aopGet(AOP(right),offset,FALSE,TRUE);
7144             
7145             MOVA(l);
7146             emitcode("movx","@%s,a",rname);
7147
7148             if (size)
7149                 emitcode("inc","%s",rname);
7150
7151             offset++;
7152         }
7153     }
7154     
7155     /* now some housekeeping stuff */
7156     if (aop) {
7157         /* we had to allocate for this iCode */
7158         freeAsmop(NULL,aop,ic,TRUE);
7159     } else { 
7160         /* we did not allocate which means left
7161            already in a pointer register, then
7162            if size > 0 && this could be used again
7163            we have to point it back to where it 
7164            belongs */
7165         if (AOP_SIZE(right) > 1 &&
7166             !OP_SYMBOL(result)->remat &&
7167             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7168               ic->depth )) {
7169             int size = AOP_SIZE(right) - 1;
7170             while (size--)
7171                 emitcode("dec","%s",rname);
7172         }
7173     }
7174
7175     /* done */
7176     freeAsmop(right,NULL,ic,TRUE);
7177     
7178         
7179 }
7180
7181 /*-----------------------------------------------------------------*/
7182 /* genFarPointerSet - set value from far space                     */
7183 /*-----------------------------------------------------------------*/
7184 static void genFarPointerSet (operand *right,
7185                               operand *result, iCode *ic)
7186 {
7187     int size, offset ;
7188     link *retype = getSpec(operandType(right));
7189
7190     aopOp(result,ic,FALSE, FALSE);
7191
7192     /* if the operand is already in dptr 
7193     then we do nothing else we move the value to dptr */
7194     if (AOP_TYPE(result) != AOP_STR) {
7195         /* if this is remateriazable */
7196         if (AOP_TYPE(result) == AOP_IMMD)
7197             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7198         else 
7199         {
7200             /* we need to get it byte by byte */
7201             if (AOP_TYPE(result) != AOP_DPTR)
7202             {
7203                 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7204                 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7205                 if (options.model == MODEL_FLAT24)
7206                 {
7207                     emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7208                 }
7209             }
7210             else
7211             {
7212                  /* We need to generate a load to DPTR indirect through DPTR. */
7213                  D(emitcode(";", "genFarPointerSet -- indirection special case."););
7214                  emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE));
7215                  emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE));
7216                  emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7217                  emitcode("pop", "dph");
7218                  emitcode("pop", "dpl");
7219             }
7220         }
7221     }
7222     /* so dptr know contains the address */
7223     freeAsmop(result,NULL,ic,TRUE);
7224     aopOp(right,ic,FALSE, TRUE);
7225
7226     /* if bit then unpack */
7227     if (IS_BITVAR(retype)) 
7228         genPackBits(retype,right,"dptr",FPOINTER);
7229     else {
7230         size = AOP_SIZE(right);
7231         offset = 0 ;
7232
7233         while (size--) {
7234             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7235             MOVA(l);
7236             emitcode("movx","@dptr,a");
7237             if (size)
7238                 emitcode("inc","dptr");
7239         }
7240     }
7241
7242     freeAsmop(right,NULL,ic,TRUE);
7243 }
7244
7245 /*-----------------------------------------------------------------*/
7246 /* genGenPointerSet - set value from generic pointer space         */
7247 /*-----------------------------------------------------------------*/
7248 static void genGenPointerSet (operand *right,
7249                               operand *result, iCode *ic)
7250 {
7251     int size, offset ;
7252     link *retype = getSpec(operandType(right));
7253
7254     aopOp(result,ic,FALSE, TRUE);
7255
7256     /* if the operand is already in dptr 
7257     then we do nothing else we move the value to dptr */
7258     if (AOP_TYPE(result) != AOP_STR) {
7259         /* if this is remateriazable */
7260         if (AOP_TYPE(result) == AOP_IMMD) {
7261             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7262             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
7263         }
7264         else { /* we need to get it byte by byte */
7265             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7266             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7267             if (options.model == MODEL_FLAT24)
7268             {
7269                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7270                emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
7271             }
7272             else
7273             {
7274                 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
7275             }
7276         }
7277     }
7278     /* so dptr know contains the address */
7279     freeAsmop(result,NULL,ic,TRUE);
7280     aopOp(right,ic,FALSE, TRUE);
7281
7282     /* if bit then unpack */
7283     if (IS_BITVAR(retype)) 
7284         genPackBits(retype,right,"dptr",GPOINTER);
7285     else {
7286         size = AOP_SIZE(right);
7287         offset = 0 ;
7288
7289         while (size--) {
7290             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7291             MOVA(l);
7292             emitcode("lcall","__gptrput");
7293             if (size)
7294                 emitcode("inc","dptr");
7295         }
7296     }
7297
7298     freeAsmop(right,NULL,ic,TRUE);
7299 }
7300
7301 /*-----------------------------------------------------------------*/
7302 /* genPointerSet - stores the value into a pointer location        */
7303 /*-----------------------------------------------------------------*/
7304 static void genPointerSet (iCode *ic)
7305 {    
7306     operand *right, *result ;
7307     link *type, *etype;
7308     int p_type;
7309
7310     D(emitcode(";", "genPointerSet "););
7311
7312     right = IC_RIGHT(ic);
7313     result = IC_RESULT(ic) ;
7314
7315     /* depending on the type of pointer we need to
7316     move it to the correct pointer register */
7317     type = operandType(result);
7318     etype = getSpec(type);
7319     /* if left is of type of pointer then it is simple */
7320     if (IS_PTR(type) && !IS_FUNC(type->next)) {
7321         p_type = DCL_TYPE(type);
7322     }
7323     else {
7324         /* we have to go by the storage class */
7325         p_type = PTR_TYPE(SPEC_OCLS(etype));
7326
7327 /*      if (SPEC_OCLS(etype)->codesp ) { */
7328 /*          p_type = CPOINTER ;  */
7329 /*      } */
7330 /*      else */
7331 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7332 /*              p_type = FPOINTER ; */
7333 /*          else */
7334 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7335 /*                  p_type = PPOINTER ; */
7336 /*              else */
7337 /*                  if (SPEC_OCLS(etype) == idata ) */
7338 /*                      p_type = IPOINTER ; */
7339 /*                  else */
7340 /*                      p_type = POINTER ; */
7341     }
7342
7343     /* now that we have the pointer type we assign
7344     the pointer values */
7345     switch (p_type) {
7346
7347     case POINTER:
7348     case IPOINTER:
7349         genNearPointerSet (right,result,ic);
7350         break;
7351
7352     case PPOINTER:
7353         genPagedPointerSet (right,result,ic);
7354         break;
7355
7356     case FPOINTER:
7357         genFarPointerSet (right,result,ic);
7358         break;
7359
7360     case GPOINTER:
7361         genGenPointerSet (right,result,ic);
7362         break;
7363     }
7364
7365 }
7366
7367 /*-----------------------------------------------------------------*/
7368 /* genIfx - generate code for Ifx statement                        */
7369 /*-----------------------------------------------------------------*/
7370 static void genIfx (iCode *ic, iCode *popIc)
7371 {
7372     operand *cond = IC_COND(ic);
7373     int isbit =0;
7374
7375     D(emitcode(";", "genIfx "););
7376
7377     aopOp(cond,ic,FALSE, FALSE);
7378
7379     /* get the value into acc */
7380     if (AOP_TYPE(cond) != AOP_CRY)
7381         toBoolean(cond);
7382     else
7383         isbit = 1;
7384     /* the result is now in the accumulator */
7385     freeAsmop(cond,NULL,ic,TRUE);
7386
7387     /* if there was something to be popped then do it */
7388     if (popIc)
7389         genIpop(popIc);
7390
7391     /* if the condition is  a bit variable */
7392     if (isbit && IS_ITEMP(cond) && 
7393         SPIL_LOC(cond))
7394         genIfxJump(ic,SPIL_LOC(cond)->rname);
7395     else
7396         if (isbit && !IS_ITEMP(cond))
7397             genIfxJump(ic,OP_SYMBOL(cond)->rname);
7398         else
7399             genIfxJump(ic,"a");
7400
7401     ic->generated = 1;
7402 }
7403
7404 /*-----------------------------------------------------------------*/
7405 /* genAddrOf - generates code for address of                       */
7406 /*-----------------------------------------------------------------*/
7407 static void genAddrOf (iCode *ic)
7408 {
7409     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7410     int size, offset ;
7411
7412     D(emitcode(";", "genAddrOf "););
7413
7414     aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7415
7416     /* if the operand is on the stack then we 
7417     need to get the stack offset of this
7418     variable */
7419     if (sym->onStack) {
7420         /* if it has an offset then we need to compute
7421         it */
7422         if (sym->stack) {
7423             emitcode("mov","a,_bp");
7424             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7425             aopPut(AOP(IC_RESULT(ic)),"a",0);       
7426         } else {
7427             /* we can just move _bp */
7428             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7429         }
7430         /* fill the result with zero */
7431         size = AOP_SIZE(IC_RESULT(ic)) - 1;
7432         
7433         
7434         if (options.stack10bit && size < (FPTRSIZE - 1))
7435         {
7436             fprintf(stderr, 
7437                     "*** warning: pointer to stack var truncated.\n");
7438         }
7439         
7440         offset = 1;
7441         while (size--)
7442         {
7443             /* Yuck! */
7444             if (options.stack10bit && offset == 2)
7445             {
7446                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7447             }
7448             else
7449             {
7450                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7451             }
7452         }
7453
7454         goto release;
7455     }
7456
7457     /* object not on stack then we need the name */
7458     size = AOP_SIZE(IC_RESULT(ic));
7459     offset = 0;
7460
7461     while (size--) {
7462         char s[SDCC_NAME_MAX];
7463         if (offset) 
7464             sprintf(s,"#(%s >> %d)",
7465                     sym->rname,
7466                     offset*8);
7467         else
7468             sprintf(s,"#%s",sym->rname);
7469         aopPut(AOP(IC_RESULT(ic)),s,offset++);
7470     }
7471
7472 release:
7473     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7474
7475 }
7476
7477 /*-----------------------------------------------------------------*/
7478 /* genFarFarAssign - assignment when both are in far space         */
7479 /*-----------------------------------------------------------------*/
7480 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7481 {
7482     int size = AOP_SIZE(right);
7483     int offset = 0;
7484     char *l ;
7485     /* first push the right side on to the stack */
7486     while (size--) {
7487         l = aopGet(AOP(right),offset++,FALSE,FALSE);
7488         MOVA(l);
7489         emitcode ("push","acc");
7490     }
7491     
7492     D(emitcode(";", "genFarFarAssign "););
7493
7494     freeAsmop(right,NULL,ic,FALSE);
7495     /* now assign DPTR to result */
7496     aopOp(result,ic,FALSE, FALSE);
7497     size = AOP_SIZE(result);
7498     while (size--) {
7499         emitcode ("pop","acc");
7500         aopPut(AOP(result),"a",--offset);
7501     }
7502     freeAsmop(result,NULL,ic,FALSE);
7503         
7504 }
7505
7506 /*-----------------------------------------------------------------*/
7507 /* genAssign - generate code for assignment                        */
7508 /*-----------------------------------------------------------------*/
7509 static void genAssign (iCode *ic)
7510 {
7511     operand *result, *right;
7512     int size, offset ;
7513         unsigned long lit = 0L;
7514
7515     D(emitcode(";", "genAssign "););
7516
7517     result = IC_RESULT(ic);
7518     right  = IC_RIGHT(ic) ;
7519
7520     /* if they are the same */
7521     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7522         return ;
7523
7524     aopOp(right,ic,FALSE, FALSE);
7525     
7526     emitcode(";", "genAssign: resultIsFar = %s",
7527              isOperandInFarSpace(result) ?
7528              "TRUE" : "FALSE");
7529
7530     /* special case both in far space */
7531     if ((AOP_TYPE(right) == AOP_DPTR ||
7532          AOP_TYPE(right) == AOP_DPTR2) &&
7533     /* IS_TRUE_SYMOP(result)       && */
7534     isOperandInFarSpace(result)) {
7535         
7536         genFarFarAssign (result,right,ic);
7537         return ;
7538     }
7539
7540     aopOp(result,ic,TRUE, FALSE);
7541
7542     /* if they are the same registers */
7543     if (sameRegs(AOP(right),AOP(result)))
7544         goto release;
7545
7546     /* if the result is a bit */
7547     if (AOP_TYPE(result) == AOP_CRY) {
7548
7549         /* if the right size is a literal then
7550         we know what the value is */
7551         if (AOP_TYPE(right) == AOP_LIT) {
7552             if (((int) operandLitValue(right))) 
7553                 aopPut(AOP(result),one,0);
7554             else
7555                 aopPut(AOP(result),zero,0);
7556             goto release;
7557         }
7558
7559         /* the right is also a bit variable */
7560         if (AOP_TYPE(right) == AOP_CRY) {
7561             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7562             aopPut(AOP(result),"c",0);
7563             goto release ;
7564         }
7565
7566         /* we need to or */
7567         toBoolean(right);
7568         aopPut(AOP(result),"a",0);
7569         goto release ;
7570     }
7571
7572     /* bit variables done */
7573     /* general case */
7574     size = AOP_SIZE(result);
7575     offset = 0 ;
7576     if(AOP_TYPE(right) == AOP_LIT)
7577         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7578     if((size > 1) &&
7579        (AOP_TYPE(result) != AOP_REG) &&
7580        (AOP_TYPE(right) == AOP_LIT) &&
7581        !IS_FLOAT(operandType(right)) &&
7582        (lit < 256L)){
7583         emitcode("clr","a");
7584         while (size--) {
7585             if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7586                 aopPut(AOP(result),"a",size);
7587             else
7588                 aopPut(AOP(result),
7589                        aopGet(AOP(right),size,FALSE,FALSE),
7590                        size);
7591         }
7592     } else {
7593         while (size--) {
7594             aopPut(AOP(result),
7595                    aopGet(AOP(right),offset,FALSE,FALSE),
7596                    offset);
7597             offset++;
7598         }
7599     }
7600     
7601 release:
7602     freeAsmop (right,NULL,ic,FALSE);
7603     freeAsmop (result,NULL,ic,TRUE);
7604 }   
7605
7606 /*-----------------------------------------------------------------*/
7607 /* genJumpTab - genrates code for jump table                       */
7608 /*-----------------------------------------------------------------*/
7609 static void genJumpTab (iCode *ic)
7610 {
7611     symbol *jtab;
7612     char *l;
7613
7614     D(emitcode(";", "genJumpTab "););
7615
7616     aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7617     /* get the condition into accumulator */
7618     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7619     MOVA(l);
7620     /* multiply by four! */
7621     emitcode("add","a,acc");
7622     emitcode("add","a,acc");
7623     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7624
7625     jtab = newiTempLabel(NULL);
7626     emitcode("mov","dptr,#%05d$",jtab->key+100);
7627     emitcode("jmp","@a+dptr");
7628     emitcode("","%05d$:",jtab->key+100);
7629     /* now generate the jump labels */
7630     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7631          jtab = setNextItem(IC_JTLABELS(ic)))
7632         emitcode("ljmp","%05d$",jtab->key+100);
7633
7634 }
7635
7636 /*-----------------------------------------------------------------*/
7637 /* genCast - gen code for casting                                  */
7638 /*-----------------------------------------------------------------*/
7639 static void genCast (iCode *ic)
7640 {
7641     operand *result = IC_RESULT(ic);
7642     link *ctype = operandType(IC_LEFT(ic));
7643     link *rtype = operandType(IC_RIGHT(ic));
7644     operand *right = IC_RIGHT(ic);
7645     int size, offset ;
7646
7647     D(emitcode(";", "genCast "););
7648
7649     /* if they are equivalent then do nothing */
7650     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7651         return ;
7652
7653     aopOp(right,ic,FALSE, FALSE) ;
7654     aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
7655
7656     /* if the result is a bit */
7657     if (AOP_TYPE(result) == AOP_CRY) {
7658         /* if the right size is a literal then
7659         we know what the value is */
7660         if (AOP_TYPE(right) == AOP_LIT) {
7661             if (((int) operandLitValue(right))) 
7662                 aopPut(AOP(result),one,0);
7663             else
7664                 aopPut(AOP(result),zero,0);
7665
7666             goto release;
7667         }
7668
7669         /* the right is also a bit variable */
7670         if (AOP_TYPE(right) == AOP_CRY) {
7671             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7672             aopPut(AOP(result),"c",0);
7673             goto release ;
7674         }
7675
7676         /* we need to or */
7677         toBoolean(right);
7678         aopPut(AOP(result),"a",0);
7679         goto release ;
7680     }
7681
7682     /* if they are the same size : or less */
7683     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7684
7685         /* if they are in the same place */
7686         if (sameRegs(AOP(right),AOP(result)))
7687             goto release;
7688
7689         /* if they in different places then copy */
7690         size = AOP_SIZE(result);
7691         offset = 0 ;
7692         while (size--) {
7693             aopPut(AOP(result),
7694                    aopGet(AOP(right),offset,FALSE,FALSE),
7695                    offset);
7696             offset++;
7697         }
7698         goto release;
7699     }
7700
7701
7702     /* if the result is of type pointer */
7703     if (IS_PTR(ctype)) {
7704
7705         int p_type;
7706         link *type = operandType(right);
7707         link *etype = getSpec(type);
7708
7709         /* pointer to generic pointer */
7710         if (IS_GENPTR(ctype)) {
7711             char *l = zero;
7712             
7713             if (IS_PTR(type)) 
7714                 p_type = DCL_TYPE(type);
7715             else {
7716                 /* we have to go by the storage class */
7717                 p_type = PTR_TYPE(SPEC_OCLS(etype));
7718             }
7719                 
7720             /* the first two bytes are known */
7721             size = GPTRSIZE - 1; 
7722             offset = 0 ;
7723             while (size--) {
7724                 aopPut(AOP(result),
7725                        aopGet(AOP(right),offset,FALSE,FALSE),
7726                        offset);
7727                 offset++;
7728             }
7729             /* the last byte depending on type */
7730             switch (p_type) {
7731             case IPOINTER:
7732             case POINTER:
7733                 l = zero;
7734                 break;
7735             case FPOINTER:
7736                 l = one;
7737                 break;
7738             case CPOINTER:
7739                 l = "#0x02";
7740                 break;                          
7741             case PPOINTER:
7742                 l = "#0x03";
7743                 break;
7744                 
7745             default:
7746                 /* this should never happen */
7747         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7748                        "got unknown pointer type");
7749                 exit(1);
7750             }
7751             aopPut(AOP(result),l, GPTRSIZE - 1);            
7752             goto release ;
7753         }
7754         
7755         /* just copy the pointers */
7756         size = AOP_SIZE(result);
7757         offset = 0 ;
7758         while (size--) {
7759             aopPut(AOP(result),
7760                    aopGet(AOP(right),offset,FALSE,FALSE),
7761                    offset);
7762             offset++;
7763         }
7764         goto release ;
7765     }
7766     
7767     /* so we now know that the size of destination is greater
7768     than the size of the source */
7769     /* we move to result for the size of source */
7770     size = AOP_SIZE(right);
7771     offset = 0 ;
7772     while (size--) {
7773         aopPut(AOP(result),
7774                aopGet(AOP(right),offset,FALSE,FALSE),
7775                offset);
7776         offset++;
7777     }
7778
7779     /* now depending on the sign of the source && destination */
7780     size = AOP_SIZE(result) - AOP_SIZE(right);
7781     /* if unsigned or not an integral type */
7782     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7783         while (size--)
7784             aopPut(AOP(result),zero,offset++);
7785     } else {
7786         /* we need to extend the sign :{ */
7787         char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7788                          FALSE,FALSE);
7789         MOVA(l);
7790         emitcode("rlc","a");
7791         emitcode("subb","a,acc");
7792         while (size--)
7793             aopPut(AOP(result),"a",offset++);   
7794     }
7795
7796     /* we are done hurray !!!! */
7797
7798 release:
7799     freeAsmop(right,NULL,ic,TRUE);
7800     freeAsmop(result,NULL,ic,TRUE);
7801
7802 }
7803
7804 /*-----------------------------------------------------------------*/
7805 /* genDjnz - generate decrement & jump if not zero instrucion      */
7806 /*-----------------------------------------------------------------*/
7807 static int genDjnz (iCode *ic, iCode *ifx)
7808 {
7809     symbol *lbl, *lbl1;
7810     if (!ifx)
7811         return 0;
7812     
7813     /* if the if condition has a false label
7814        then we cannot save */
7815     if (IC_FALSE(ifx))
7816         return 0;
7817
7818     /* if the minus is not of the form 
7819        a = a - 1 */
7820     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7821         !IS_OP_LITERAL(IC_RIGHT(ic)))
7822         return 0;
7823
7824     if (operandLitValue(IC_RIGHT(ic)) != 1)
7825         return 0;
7826
7827     /* if the size of this greater than one then no
7828        saving */
7829     if (getSize(operandType(IC_RESULT(ic))) > 1)
7830         return 0;
7831
7832     /* otherwise we can save BIG */
7833     lbl = newiTempLabel(NULL);
7834     lbl1= newiTempLabel(NULL);
7835
7836     aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7837     
7838     if (IS_AOP_PREG(IC_RESULT(ic))) {
7839         emitcode("dec","%s",
7840                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7841         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7842         emitcode("jnz","%05d$",lbl->key+100);
7843     } else {    
7844         emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7845                   lbl->key+100);
7846     }
7847     emitcode ("sjmp","%05d$",lbl1->key+100);
7848     emitcode ("","%05d$:",lbl->key+100);
7849     emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7850     emitcode ("","%05d$:",lbl1->key+100);
7851     
7852     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7853     ifx->generated = 1;
7854     return 1;
7855 }
7856
7857 /*-----------------------------------------------------------------*/
7858 /* genReceive - generate code for a receive iCode                  */
7859 /*-----------------------------------------------------------------*/
7860 static void genReceive (iCode *ic)
7861 {    
7862
7863     D(emitcode(";", "genReceive "););
7864
7865     if (isOperandInFarSpace(IC_RESULT(ic)) && 
7866         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7867           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7868         int size = getSize(operandType(IC_RESULT(ic)));
7869         int offset =  fReturnSize_390 - size;
7870         while (size--) {
7871             emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
7872                                     fReturn[fReturnSize_390 - offset - 1] : "acc"));
7873             offset++;
7874         }
7875         aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7876         size = AOP_SIZE(IC_RESULT(ic));
7877         offset = 0;
7878         while (size--) {
7879             emitcode ("pop","acc");
7880             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7881         }
7882         
7883     } else {
7884         _G.accInUse++;
7885         aopOp(IC_RESULT(ic),ic,FALSE, FALSE);  
7886         _G.accInUse--;
7887         assignResultValue(IC_RESULT(ic));       
7888     }
7889
7890     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7891 }
7892
7893 /*-----------------------------------------------------------------*/
7894 /* gen390Code - generate code for 8051 based controllers            */
7895 /*-----------------------------------------------------------------*/
7896 void gen390Code (iCode *lic)
7897 {
7898     iCode *ic;
7899     int cln = 0;
7900
7901     lineHead = lineCurr = NULL;
7902
7903     /* print the allocation information */
7904     if (allocInfo)
7905         printAllocInfo( currFunc, codeOutFile);
7906     /* if debug information required */
7907 /*     if (options.debug && currFunc) { */
7908     if (currFunc) {
7909         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7910         _G.debugLine = 1;
7911         if (IS_STATIC(currFunc->etype))
7912             emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
7913         else
7914             emitcode("","G$%s$0$0 ==.",currFunc->name);
7915         _G.debugLine = 0;
7916     }
7917     /* stack pointer name */
7918     if (options.useXstack)
7919         spname = "_spx";
7920     else
7921         spname = "sp";
7922     
7923  
7924     for (ic = lic ; ic ; ic = ic->next ) {
7925         
7926         if ( cln != ic->lineno ) {
7927             if ( options.debug ) {
7928                 _G.debugLine = 1;
7929                 emitcode("","C$%s$%d$%d$%d ==.",
7930                          ic->filename,ic->lineno,
7931                          ic->level,ic->block);
7932                 _G.debugLine = 0;
7933             }
7934             emitcode(";","%s %d",ic->filename,ic->lineno);
7935             cln = ic->lineno ;
7936         }
7937         /* if the result is marked as
7938            spilt and rematerializable or code for
7939            this has already been generated then
7940            do nothing */
7941         if (resultRemat(ic) || ic->generated ) 
7942             continue ;
7943         
7944         /* depending on the operation */
7945         switch (ic->op) {
7946         case '!' :
7947             genNot(ic);
7948             break;
7949             
7950         case '~' :
7951             genCpl(ic);
7952             break;
7953             
7954         case UNARYMINUS:
7955             genUminus (ic);
7956             break;
7957             
7958         case IPUSH:
7959             genIpush (ic);
7960             break;
7961             
7962         case IPOP:
7963             /* IPOP happens only when trying to restore a 
7964                spilt live range, if there is an ifx statement
7965                following this pop then the if statement might
7966                be using some of the registers being popped which
7967                would destory the contents of the register so
7968                we need to check for this condition and handle it */
7969             if (ic->next            && 
7970                 ic->next->op == IFX &&
7971                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
7972                 genIfx (ic->next,ic);
7973             else
7974                 genIpop (ic);
7975             break; 
7976             
7977         case CALL:
7978             genCall (ic);
7979             break;
7980             
7981         case PCALL:
7982             genPcall (ic);
7983             break;
7984             
7985         case FUNCTION:
7986             genFunction (ic);
7987             break;
7988             
7989         case ENDFUNCTION:
7990             genEndFunction (ic);
7991             break;
7992             
7993         case RETURN:
7994             genRet (ic);
7995             break;
7996             
7997         case LABEL:
7998             genLabel (ic);
7999             break;
8000             
8001         case GOTO:
8002             genGoto (ic);
8003             break;
8004             
8005         case '+' :
8006             genPlus (ic) ;
8007             break;
8008             
8009         case '-' :
8010             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8011                 genMinus (ic);
8012             break;
8013             
8014         case '*' :
8015             genMult (ic);
8016             break;
8017             
8018         case '/' :
8019             genDiv (ic) ;
8020             break;
8021             
8022         case '%' :
8023             genMod (ic);
8024             break;
8025             
8026         case '>' :
8027             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
8028             break;
8029             
8030         case '<' :
8031             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8032             break;
8033             
8034         case LE_OP:
8035         case GE_OP:
8036         case NE_OP:
8037             
8038             /* note these two are xlated by algebraic equivalence
8039                during parsing SDCC.y */
8040             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8041                    "got '>=' or '<=' shouldn't have come here");
8042             break;      
8043             
8044         case EQ_OP:
8045             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8046             break;          
8047             
8048         case AND_OP:
8049             genAndOp (ic);
8050             break;
8051             
8052         case OR_OP:
8053             genOrOp (ic);
8054             break;
8055             
8056         case '^' :
8057             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8058             break;
8059             
8060         case '|' :
8061                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8062             break;
8063             
8064         case BITWISEAND:
8065             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8066             break;
8067             
8068         case INLINEASM:
8069             genInline (ic);
8070             break;
8071             
8072         case RRC:
8073             genRRC (ic);
8074             break;
8075             
8076         case RLC:
8077             genRLC (ic);
8078             break;
8079             
8080         case GETHBIT:
8081             genGetHbit (ic);
8082             break;
8083             
8084         case LEFT_OP:
8085             genLeftShift (ic);
8086             break;
8087             
8088         case RIGHT_OP:
8089             genRightShift (ic);
8090             break;
8091             
8092         case GET_VALUE_AT_ADDRESS:
8093             genPointerGet(ic);
8094             break;
8095             
8096         case '=' :
8097             if (POINTER_SET(ic))
8098                 genPointerSet(ic);
8099             else
8100                 genAssign(ic);
8101             break;
8102             
8103         case IFX:
8104             genIfx (ic,NULL);
8105             break;
8106             
8107         case ADDRESS_OF:
8108             genAddrOf (ic);
8109             break;
8110             
8111         case JUMPTABLE:
8112             genJumpTab (ic);
8113             break;
8114             
8115         case CAST:
8116             genCast (ic);
8117             break;
8118             
8119         case RECEIVE:
8120             genReceive(ic);
8121             break;
8122             
8123         case SEND:
8124             addSet(&_G.sendSet,ic);
8125             break;
8126
8127         default :
8128             ic = ic;
8129             /*      piCode(ic,stdout); */
8130             
8131         }
8132     }
8133     
8134
8135     /* now we are ready to call the 
8136        peep hole optimizer */
8137     if (!options.nopeep)
8138         peepHole (&lineHead);
8139
8140     /* now do the actual printing */
8141     printLine (lineHead,codeOutFile);    
8142     return;
8143 }