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