Break DS80C390 support into seperate port (ds390); first pass at spilling temporaries...
[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!\n");   \
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             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6587         else { /* we need to get it byte by byte */
6588             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6589             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6590             if (options.model == MODEL_FLAT24)
6591             {
6592                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6593             }
6594         }
6595     }
6596     /* so dptr know contains the address */
6597     freeAsmop(left,NULL,ic,TRUE);
6598     aopOp(result,ic,FALSE, TRUE);
6599
6600     /* if bit then unpack */
6601     if (IS_BITVAR(retype)) 
6602         genUnpackBits(result,"dptr",FPOINTER);
6603     else {
6604         size = AOP_SIZE(result);
6605         offset = 0 ;
6606
6607         while (size--) {
6608             emitcode("movx","a,@dptr");
6609             aopPut(AOP(result),"a",offset++);
6610             if (size)
6611                 emitcode("inc","dptr");
6612         }
6613     }
6614
6615     freeAsmop(result,NULL,ic,TRUE);
6616 }
6617
6618 /*-----------------------------------------------------------------*/
6619 /* emitcodePointerGet - gget value from code space                  */
6620 /*-----------------------------------------------------------------*/
6621 static void emitcodePointerGet (operand *left,
6622                                 operand *result, iCode *ic)
6623 {
6624     int size, offset ;
6625     link *retype = getSpec(operandType(result));
6626
6627     aopOp(left,ic,FALSE, FALSE);
6628
6629     /* if the operand is already in dptr 
6630     then we do nothing else we move the value to dptr */
6631     if (AOP_TYPE(left) != AOP_STR) {
6632         /* if this is remateriazable */
6633         if (AOP_TYPE(left) == AOP_IMMD)
6634             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6635         else { /* we need to get it byte by byte */
6636             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6637             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6638             if (options.model == MODEL_FLAT24)
6639             {
6640                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6641             }
6642         }
6643     }
6644     /* so dptr know contains the address */
6645     freeAsmop(left,NULL,ic,TRUE);
6646     aopOp(result,ic,FALSE, FALSE);
6647
6648     /* if bit then unpack */
6649     if (IS_BITVAR(retype)) 
6650         genUnpackBits(result,"dptr",CPOINTER);
6651     else {
6652         size = AOP_SIZE(result);
6653         offset = 0 ;
6654
6655         while (size--) {
6656             emitcode("clr","a");
6657             emitcode("movc","a,@a+dptr");
6658             aopPut(AOP(result),"a",offset++);
6659             if (size)
6660                 emitcode("inc","dptr");
6661         }
6662     }
6663
6664     freeAsmop(result,NULL,ic,TRUE);
6665 }
6666
6667 /*-----------------------------------------------------------------*/
6668 /* genGenPointerGet - gget value from generic pointer space        */
6669 /*-----------------------------------------------------------------*/
6670 static void genGenPointerGet (operand *left,
6671                               operand *result, iCode *ic)
6672 {
6673     int size, offset ;
6674     link *retype = getSpec(operandType(result));
6675
6676     aopOp(left,ic,FALSE, TRUE);
6677
6678     /* if the operand is already in dptr 
6679     then we do nothing else we move the value to dptr */
6680     if (AOP_TYPE(left) != AOP_STR) {
6681         /* if this is remateriazable */
6682         if (AOP_TYPE(left) == AOP_IMMD) {
6683             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6684             emitcode("mov","b,#%d",pointerCode(retype));
6685         }
6686         else { /* we need to get it byte by byte */
6687             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6688             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6689             if (options.model == MODEL_FLAT24)
6690             {
6691                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6692                emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6693             }
6694             else
6695             {
6696                 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6697             }
6698         }
6699     }
6700     /* so dptr know contains the address */
6701     freeAsmop(left,NULL,ic,TRUE);
6702     aopOp(result,ic,FALSE, TRUE);
6703
6704     /* if bit then unpack */
6705     if (IS_BITVAR(retype)) 
6706         genUnpackBits(result,"dptr",GPOINTER);
6707     else {
6708         size = AOP_SIZE(result);
6709         offset = 0 ;
6710
6711         while (size--) {
6712             emitcode("lcall","__gptrget");
6713             aopPut(AOP(result),"a",offset++);
6714             if (size)
6715                 emitcode("inc","dptr");
6716         }
6717     }
6718
6719     freeAsmop(result,NULL,ic,TRUE);
6720 }
6721
6722 /*-----------------------------------------------------------------*/
6723 /* genPointerGet - generate code for pointer get                   */
6724 /*-----------------------------------------------------------------*/
6725 static void genPointerGet (iCode *ic)
6726 {
6727     operand *left, *result ;
6728     link *type, *etype;
6729     int p_type;
6730
6731     D(emitcode(";", "genPointerGet "););
6732
6733     left = IC_LEFT(ic);
6734     result = IC_RESULT(ic) ;
6735
6736     /* depending on the type of pointer we need to
6737     move it to the correct pointer register */
6738     type = operandType(left);
6739     etype = getSpec(type);
6740     /* if left is of type of pointer then it is simple */
6741     if (IS_PTR(type) && !IS_FUNC(type->next)) 
6742         p_type = DCL_TYPE(type);
6743     else {
6744         /* we have to go by the storage class */
6745         p_type = PTR_TYPE(SPEC_OCLS(etype));
6746
6747 /*      if (SPEC_OCLS(etype)->codesp ) { */
6748 /*          p_type = CPOINTER ;  */
6749 /*      } */
6750 /*      else */
6751 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6752 /*              p_type = FPOINTER ; */
6753 /*          else */
6754 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6755 /*                  p_type = PPOINTER; */
6756 /*              else */
6757 /*                  if (SPEC_OCLS(etype) == idata ) */
6758 /*                      p_type = IPOINTER; */
6759 /*                  else */
6760 /*                      p_type = POINTER ; */
6761     }
6762
6763     /* now that we have the pointer type we assign
6764     the pointer values */
6765     switch (p_type) {
6766
6767     case POINTER:       
6768     case IPOINTER:
6769         genNearPointerGet (left,result,ic);
6770         break;
6771
6772     case PPOINTER:
6773         genPagedPointerGet(left,result,ic);
6774         break;
6775
6776     case FPOINTER:
6777         genFarPointerGet (left,result,ic);
6778         break;
6779
6780     case CPOINTER:
6781         emitcodePointerGet (left,result,ic);
6782         break;
6783
6784     case GPOINTER:
6785         genGenPointerGet (left,result,ic);
6786         break;
6787     }
6788
6789 }
6790
6791 /*-----------------------------------------------------------------*/
6792 /* genPackBits - generates code for packed bit storage             */
6793 /*-----------------------------------------------------------------*/
6794 static void genPackBits (link    *etype ,
6795                          operand *right ,
6796                          char *rname, int p_type)
6797 {
6798     int shCount = 0 ;
6799     int offset = 0  ;
6800     int rLen = 0 ;
6801     int blen, bstr ;   
6802     char *l ;
6803
6804     blen = SPEC_BLEN(etype);
6805     bstr = SPEC_BSTR(etype);
6806
6807     l = aopGet(AOP(right),offset++,FALSE,FALSE);
6808     MOVA(l);   
6809
6810     /* if the bit lenth is less than or    */
6811     /* it exactly fits a byte then         */
6812     if (SPEC_BLEN(etype) <= 8 )  {
6813         shCount = SPEC_BSTR(etype) ;
6814
6815         /* shift left acc */
6816         AccLsh(shCount);
6817
6818         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6819
6820
6821             switch (p_type) {
6822                 case POINTER:
6823                     emitcode ("mov","b,a");
6824                     emitcode("mov","a,@%s",rname);
6825                     break;
6826
6827                 case FPOINTER:
6828                     emitcode ("mov","b,a");
6829                     emitcode("movx","a,@dptr");
6830                     break;
6831
6832                 case GPOINTER:
6833                     emitcode ("push","b");
6834                     emitcode ("push","acc");
6835                     emitcode ("lcall","__gptrget");
6836                     emitcode ("pop","b");
6837                     break;
6838             }
6839
6840             emitcode ("anl","a,#0x%02x",(unsigned char)
6841                       ((unsigned char)(0xFF << (blen+bstr)) | 
6842                        (unsigned char)(0xFF >> (8-bstr)) ) );
6843             emitcode ("orl","a,b");
6844             if (p_type == GPOINTER)
6845                 emitcode("pop","b");
6846         }
6847     }
6848
6849     switch (p_type) {
6850         case POINTER:
6851             emitcode("mov","@%s,a",rname);
6852             break;
6853
6854         case FPOINTER:
6855             emitcode("movx","@dptr,a");
6856             break;
6857
6858         case GPOINTER:
6859             emitcode("lcall","__gptrput");
6860             break;
6861     }
6862
6863     /* if we r done */
6864     if ( SPEC_BLEN(etype) <= 8 )
6865         return ;
6866
6867     emitcode("inc","%s",rname);
6868     rLen = SPEC_BLEN(etype) ;     
6869
6870     /* now generate for lengths greater than one byte */
6871     while (1) {
6872
6873         l = aopGet(AOP(right),offset++,FALSE,TRUE);
6874
6875         rLen -= 8 ;
6876         if (rLen <= 0 )
6877             break ;
6878
6879         switch (p_type) {
6880             case POINTER:
6881                 if (*l == '@') {
6882                     MOVA(l);
6883                     emitcode("mov","@%s,a",rname);
6884                 } else
6885                     emitcode("mov","@%s,%s",rname,l);
6886                 break;
6887
6888             case FPOINTER:
6889                 MOVA(l);
6890                 emitcode("movx","@dptr,a");
6891                 break;
6892
6893             case GPOINTER:
6894                 MOVA(l);
6895                 emitcode("lcall","__gptrput");
6896                 break;  
6897         }   
6898         emitcode ("inc","%s",rname);
6899     }
6900
6901     MOVA(l);
6902
6903     /* last last was not complete */
6904     if (rLen)   {
6905         /* save the byte & read byte */
6906         switch (p_type) {
6907             case POINTER:
6908                 emitcode ("mov","b,a");
6909                 emitcode("mov","a,@%s",rname);
6910                 break;
6911
6912             case FPOINTER:
6913                 emitcode ("mov","b,a");
6914                 emitcode("movx","a,@dptr");
6915                 break;
6916
6917             case GPOINTER:
6918                 emitcode ("push","b");
6919                 emitcode ("push","acc");
6920                 emitcode ("lcall","__gptrget");
6921                 emitcode ("pop","b");
6922                 break;
6923         }
6924
6925         emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6926         emitcode ("orl","a,b");
6927     }
6928
6929     if (p_type == GPOINTER)
6930         emitcode("pop","b");
6931
6932     switch (p_type) {
6933
6934     case POINTER:
6935         emitcode("mov","@%s,a",rname);
6936         break;
6937         
6938     case FPOINTER:
6939         emitcode("movx","@dptr,a");
6940         break;
6941         
6942     case GPOINTER:
6943         emitcode("lcall","__gptrput");
6944         break;                  
6945     }
6946 }
6947 /*-----------------------------------------------------------------*/
6948 /* genDataPointerSet - remat pointer to data space                 */
6949 /*-----------------------------------------------------------------*/
6950 static void genDataPointerSet(operand *right,
6951                               operand *result,
6952                               iCode *ic)
6953 {
6954     int size, offset = 0 ;
6955     char *l, buffer[256];
6956
6957     aopOp(right,ic,FALSE, FALSE);
6958     
6959     l = aopGet(AOP(result),0,FALSE,TRUE);
6960     size = AOP_SIZE(right);
6961     while (size--) {
6962         if (offset)
6963             sprintf(buffer,"(%s + %d)",l+1,offset);
6964         else
6965             sprintf(buffer,"%s",l+1);
6966         emitcode("mov","%s,%s",buffer,
6967                  aopGet(AOP(right),offset++,FALSE,FALSE));
6968     }
6969
6970     freeAsmop(right,NULL,ic,TRUE);
6971     freeAsmop(result,NULL,ic,TRUE);
6972 }
6973
6974 /*-----------------------------------------------------------------*/
6975 /* genNearPointerSet - emitcode for near pointer put                */
6976 /*-----------------------------------------------------------------*/
6977 static void genNearPointerSet (operand *right,
6978                                operand *result, 
6979                                iCode *ic)
6980 {
6981     asmop *aop = NULL;
6982     regs *preg = NULL ;
6983     char *rname , *l;
6984     link *retype;
6985     link *ptype = operandType(result);
6986     
6987     retype= getSpec(operandType(right));
6988
6989     aopOp(result,ic,FALSE, FALSE);
6990     
6991     /* if the result is rematerializable &
6992        in data space & not a bit variable */
6993     if (AOP_TYPE(result) == AOP_IMMD &&
6994         DCL_TYPE(ptype) == POINTER   &&
6995         !IS_BITVAR(retype)) {
6996         genDataPointerSet (right,result,ic);
6997         return;
6998     }
6999
7000     /* if the value is already in a pointer register
7001     then don't need anything more */
7002     if (!AOP_INPREG(AOP(result))) {
7003         /* otherwise get a free pointer register */
7004         aop = newAsmop(0);
7005         preg = getFreePtr(ic,&aop,FALSE);
7006         emitcode("mov","%s,%s",
7007                  preg->name,
7008                  aopGet(AOP(result),0,FALSE,TRUE));
7009         rname = preg->name ;
7010     } else
7011         rname = aopGet(AOP(result),0,FALSE,FALSE);
7012
7013     freeAsmop(result,NULL,ic,TRUE);
7014     aopOp (right,ic,FALSE, FALSE);
7015
7016     /* if bitfield then unpack the bits */
7017     if (IS_BITVAR(retype)) 
7018         genPackBits (retype,right,rname,POINTER);
7019     else {
7020         /* we have can just get the values */
7021         int size = AOP_SIZE(right);
7022         int offset = 0 ;    
7023
7024         while (size--) {
7025             l = aopGet(AOP(right),offset,FALSE,TRUE);
7026             if (*l == '@' ) {
7027                 MOVA(l);
7028                 emitcode("mov","@%s,a",rname);
7029             } else
7030                 emitcode("mov","@%s,%s",rname,l);
7031             if (size)
7032                 emitcode("inc","%s",rname);
7033             offset++;
7034         }
7035     }
7036
7037     /* now some housekeeping stuff */
7038     if (aop) {
7039         /* we had to allocate for this iCode */
7040         freeAsmop(NULL,aop,ic,TRUE);
7041     } else { 
7042         /* we did not allocate which means left
7043         already in a pointer register, then
7044         if size > 0 && this could be used again
7045         we have to point it back to where it 
7046         belongs */
7047         if (AOP_SIZE(right) > 1 &&
7048             !OP_SYMBOL(result)->remat &&
7049             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7050               ic->depth )) {
7051             int size = AOP_SIZE(right) - 1;
7052             while (size--)
7053                 emitcode("dec","%s",rname);
7054         }
7055     }
7056
7057     /* done */
7058     freeAsmop(right,NULL,ic,TRUE);
7059
7060
7061 }
7062
7063 /*-----------------------------------------------------------------*/
7064 /* genPagedPointerSet - emitcode for Paged pointer put             */
7065 /*-----------------------------------------------------------------*/
7066 static void genPagedPointerSet (operand *right,
7067                                operand *result, 
7068                                iCode *ic)
7069 {
7070     asmop *aop = NULL;
7071     regs *preg = NULL ;
7072     char *rname , *l;
7073     link *retype;
7074        
7075     retype= getSpec(operandType(right));
7076     
7077     aopOp(result,ic,FALSE, FALSE);
7078     
7079     /* if the value is already in a pointer register
7080        then don't need anything more */
7081     if (!AOP_INPREG(AOP(result))) {
7082         /* otherwise get a free pointer register */
7083         aop = newAsmop(0);
7084         preg = getFreePtr(ic,&aop,FALSE);
7085         emitcode("mov","%s,%s",
7086                 preg->name,
7087                 aopGet(AOP(result),0,FALSE,TRUE));
7088         rname = preg->name ;
7089     } else
7090         rname = aopGet(AOP(result),0,FALSE,FALSE);
7091     
7092     freeAsmop(result,NULL,ic,TRUE);
7093     aopOp (right,ic,FALSE, FALSE);
7094
7095     /* if bitfield then unpack the bits */
7096     if (IS_BITVAR(retype)) 
7097         genPackBits (retype,right,rname,PPOINTER);
7098     else {
7099         /* we have can just get the values */
7100         int size = AOP_SIZE(right);
7101         int offset = 0 ;        
7102         
7103         while (size--) {
7104             l = aopGet(AOP(right),offset,FALSE,TRUE);
7105             
7106             MOVA(l);
7107             emitcode("movx","@%s,a",rname);
7108
7109             if (size)
7110                 emitcode("inc","%s",rname);
7111
7112             offset++;
7113         }
7114     }
7115     
7116     /* now some housekeeping stuff */
7117     if (aop) {
7118         /* we had to allocate for this iCode */
7119         freeAsmop(NULL,aop,ic,TRUE);
7120     } else { 
7121         /* we did not allocate which means left
7122            already in a pointer register, then
7123            if size > 0 && this could be used again
7124            we have to point it back to where it 
7125            belongs */
7126         if (AOP_SIZE(right) > 1 &&
7127             !OP_SYMBOL(result)->remat &&
7128             ( OP_SYMBOL(result)->liveTo > ic->seq ||
7129               ic->depth )) {
7130             int size = AOP_SIZE(right) - 1;
7131             while (size--)
7132                 emitcode("dec","%s",rname);
7133         }
7134     }
7135
7136     /* done */
7137     freeAsmop(right,NULL,ic,TRUE);
7138     
7139         
7140 }
7141
7142 /*-----------------------------------------------------------------*/
7143 /* genFarPointerSet - set value from far space                     */
7144 /*-----------------------------------------------------------------*/
7145 static void genFarPointerSet (operand *right,
7146                               operand *result, iCode *ic)
7147 {
7148     int size, offset ;
7149     link *retype = getSpec(operandType(right));
7150
7151     aopOp(result,ic,FALSE, FALSE);
7152
7153     /* if the operand is already in dptr 
7154     then we do nothing else we move the value to dptr */
7155     if (AOP_TYPE(result) != AOP_STR) {
7156         /* if this is remateriazable */
7157         if (AOP_TYPE(result) == AOP_IMMD)
7158             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7159         else { /* we need to get it byte by byte */
7160             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7161             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7162             if (options.model == MODEL_FLAT24)
7163             {
7164                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7165             }
7166         }
7167     }
7168     /* so dptr know contains the address */
7169     freeAsmop(result,NULL,ic,TRUE);
7170     aopOp(right,ic,FALSE, FALSE);
7171
7172     /* if bit then unpack */
7173     if (IS_BITVAR(retype)) 
7174         genPackBits(retype,right,"dptr",FPOINTER);
7175     else {
7176         size = AOP_SIZE(right);
7177         offset = 0 ;
7178
7179         while (size--) {
7180             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7181             MOVA(l);
7182             emitcode("movx","@dptr,a");
7183             if (size)
7184                 emitcode("inc","dptr");
7185         }
7186     }
7187
7188     freeAsmop(right,NULL,ic,TRUE);
7189 }
7190
7191 /*-----------------------------------------------------------------*/
7192 /* genGenPointerSet - set value from generic pointer space         */
7193 /*-----------------------------------------------------------------*/
7194 static void genGenPointerSet (operand *right,
7195                               operand *result, iCode *ic)
7196 {
7197     int size, offset ;
7198     link *retype = getSpec(operandType(right));
7199
7200     aopOp(result,ic,FALSE, TRUE);
7201
7202     /* if the operand is already in dptr 
7203     then we do nothing else we move the value to dptr */
7204     if (AOP_TYPE(result) != AOP_STR) {
7205         /* if this is remateriazable */
7206         if (AOP_TYPE(result) == AOP_IMMD) {
7207             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7208             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
7209         }
7210         else { /* we need to get it byte by byte */
7211             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7212             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7213             if (options.model == MODEL_FLAT24)
7214             {
7215                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7216                emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
7217             }
7218             else
7219             {
7220                 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
7221             }
7222         }
7223     }
7224     /* so dptr know contains the address */
7225     freeAsmop(result,NULL,ic,TRUE);
7226     aopOp(right,ic,FALSE, TRUE);
7227
7228     /* if bit then unpack */
7229     if (IS_BITVAR(retype)) 
7230         genPackBits(retype,right,"dptr",GPOINTER);
7231     else {
7232         size = AOP_SIZE(right);
7233         offset = 0 ;
7234
7235         while (size--) {
7236             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7237             MOVA(l);
7238             emitcode("lcall","__gptrput");
7239             if (size)
7240                 emitcode("inc","dptr");
7241         }
7242     }
7243
7244     freeAsmop(right,NULL,ic,TRUE);
7245 }
7246
7247 /*-----------------------------------------------------------------*/
7248 /* genPointerSet - stores the value into a pointer location        */
7249 /*-----------------------------------------------------------------*/
7250 static void genPointerSet (iCode *ic)
7251 {    
7252     operand *right, *result ;
7253     link *type, *etype;
7254     int p_type;
7255
7256     D(emitcode(";", "genPointerSet "););
7257
7258     right = IC_RIGHT(ic);
7259     result = IC_RESULT(ic) ;
7260
7261     /* depending on the type of pointer we need to
7262     move it to the correct pointer register */
7263     type = operandType(result);
7264     etype = getSpec(type);
7265     /* if left is of type of pointer then it is simple */
7266     if (IS_PTR(type) && !IS_FUNC(type->next)) {
7267         p_type = DCL_TYPE(type);
7268     }
7269     else {
7270         /* we have to go by the storage class */
7271         p_type = PTR_TYPE(SPEC_OCLS(etype));
7272
7273 /*      if (SPEC_OCLS(etype)->codesp ) { */
7274 /*          p_type = CPOINTER ;  */
7275 /*      } */
7276 /*      else */
7277 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7278 /*              p_type = FPOINTER ; */
7279 /*          else */
7280 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7281 /*                  p_type = PPOINTER ; */
7282 /*              else */
7283 /*                  if (SPEC_OCLS(etype) == idata ) */
7284 /*                      p_type = IPOINTER ; */
7285 /*                  else */
7286 /*                      p_type = POINTER ; */
7287     }
7288
7289     /* now that we have the pointer type we assign
7290     the pointer values */
7291     switch (p_type) {
7292
7293     case POINTER:
7294     case IPOINTER:
7295         genNearPointerSet (right,result,ic);
7296         break;
7297
7298     case PPOINTER:
7299         genPagedPointerSet (right,result,ic);
7300         break;
7301
7302     case FPOINTER:
7303         genFarPointerSet (right,result,ic);
7304         break;
7305
7306     case GPOINTER:
7307         genGenPointerSet (right,result,ic);
7308         break;
7309     }
7310
7311 }
7312
7313 /*-----------------------------------------------------------------*/
7314 /* genIfx - generate code for Ifx statement                        */
7315 /*-----------------------------------------------------------------*/
7316 static void genIfx (iCode *ic, iCode *popIc)
7317 {
7318     operand *cond = IC_COND(ic);
7319     int isbit =0;
7320
7321     D(emitcode(";", "genIfx "););
7322
7323     aopOp(cond,ic,FALSE, FALSE);
7324
7325     /* get the value into acc */
7326     if (AOP_TYPE(cond) != AOP_CRY)
7327         toBoolean(cond);
7328     else
7329         isbit = 1;
7330     /* the result is now in the accumulator */
7331     freeAsmop(cond,NULL,ic,TRUE);
7332
7333     /* if there was something to be popped then do it */
7334     if (popIc)
7335         genIpop(popIc);
7336
7337     /* if the condition is  a bit variable */
7338     if (isbit && IS_ITEMP(cond) && 
7339         SPIL_LOC(cond))
7340         genIfxJump(ic,SPIL_LOC(cond)->rname);
7341     else
7342         if (isbit && !IS_ITEMP(cond))
7343             genIfxJump(ic,OP_SYMBOL(cond)->rname);
7344         else
7345             genIfxJump(ic,"a");
7346
7347     ic->generated = 1;
7348 }
7349
7350 /*-----------------------------------------------------------------*/
7351 /* genAddrOf - generates code for address of                       */
7352 /*-----------------------------------------------------------------*/
7353 static void genAddrOf (iCode *ic)
7354 {
7355     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7356     int size, offset ;
7357
7358     D(emitcode(";", "genAddrOf "););
7359
7360     aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7361
7362     /* if the operand is on the stack then we 
7363     need to get the stack offset of this
7364     variable */
7365     if (sym->onStack) {
7366         /* if it has an offset then we need to compute
7367         it */
7368         if (sym->stack) {
7369             emitcode("mov","a,_bp");
7370             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7371             aopPut(AOP(IC_RESULT(ic)),"a",0);       
7372         } else {
7373             /* we can just move _bp */
7374             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7375         }
7376         /* fill the result with zero */
7377         size = AOP_SIZE(IC_RESULT(ic)) - 1;
7378         
7379         
7380         if (options.stack10bit && size < (FPTRSIZE - 1))
7381         {
7382             fprintf(stderr, 
7383                     "*** warning: pointer to stack var truncated.\n");
7384         }
7385         
7386         offset = 1;
7387         while (size--)
7388         {
7389             /* Yuck! */
7390             if (options.stack10bit && offset == 2)
7391             {
7392                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7393             }
7394             else
7395             {
7396                 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7397             }
7398         }
7399
7400         goto release;
7401     }
7402
7403     /* object not on stack then we need the name */
7404     size = AOP_SIZE(IC_RESULT(ic));
7405     offset = 0;
7406
7407     while (size--) {
7408         char s[SDCC_NAME_MAX];
7409         if (offset) 
7410             sprintf(s,"#(%s >> %d)",
7411                     sym->rname,
7412                     offset*8);
7413         else
7414             sprintf(s,"#%s",sym->rname);
7415         aopPut(AOP(IC_RESULT(ic)),s,offset++);
7416     }
7417
7418 release:
7419     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7420
7421 }
7422
7423 /*-----------------------------------------------------------------*/
7424 /* genFarFarAssign - assignment when both are in far space         */
7425 /*-----------------------------------------------------------------*/
7426 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7427 {
7428     int size = AOP_SIZE(right);
7429     int offset = 0;
7430     char *l ;
7431     /* first push the right side on to the stack */
7432     while (size--) {
7433         l = aopGet(AOP(right),offset++,FALSE,FALSE);
7434         MOVA(l);
7435         emitcode ("push","acc");
7436     }
7437     
7438     D(emitcode(";", "genFarFarAssign "););
7439
7440     freeAsmop(right,NULL,ic,FALSE);
7441     /* now assign DPTR to result */
7442     aopOp(result,ic,FALSE, FALSE);
7443     size = AOP_SIZE(result);
7444     while (size--) {
7445         emitcode ("pop","acc");
7446         aopPut(AOP(result),"a",--offset);
7447     }
7448     freeAsmop(result,NULL,ic,FALSE);
7449         
7450 }
7451
7452 /*-----------------------------------------------------------------*/
7453 /* genAssign - generate code for assignment                        */
7454 /*-----------------------------------------------------------------*/
7455 static void genAssign (iCode *ic)
7456 {
7457     operand *result, *right;
7458     int size, offset ;
7459         unsigned long lit = 0L;
7460
7461     D(emitcode(";", "genAssign "););
7462
7463     result = IC_RESULT(ic);
7464     right  = IC_RIGHT(ic) ;
7465
7466     /* if they are the same */
7467     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7468         return ;
7469
7470     aopOp(right,ic,FALSE, FALSE);
7471     
7472     emitcode(";", "genAssign: resultIsFar = %s",
7473              isOperandInFarSpace(result) ?
7474              "TRUE" : "FALSE");
7475
7476     /* special case both in far space */
7477     if ((AOP_TYPE(right) == AOP_DPTR ||
7478          AOP_TYPE(right) == AOP_DPTR2) &&
7479     /* IS_TRUE_SYMOP(result)       && */
7480     isOperandInFarSpace(result)) {
7481         
7482         genFarFarAssign (result,right,ic);
7483         return ;
7484     }
7485
7486     aopOp(result,ic,TRUE, FALSE);
7487
7488     /* if they are the same registers */
7489     if (sameRegs(AOP(right),AOP(result)))
7490         goto release;
7491
7492     /* if the result is a bit */
7493     if (AOP_TYPE(result) == AOP_CRY) {
7494
7495         /* if the right size is a literal then
7496         we know what the value is */
7497         if (AOP_TYPE(right) == AOP_LIT) {
7498             if (((int) operandLitValue(right))) 
7499                 aopPut(AOP(result),one,0);
7500             else
7501                 aopPut(AOP(result),zero,0);
7502             goto release;
7503         }
7504
7505         /* the right is also a bit variable */
7506         if (AOP_TYPE(right) == AOP_CRY) {
7507             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7508             aopPut(AOP(result),"c",0);
7509             goto release ;
7510         }
7511
7512         /* we need to or */
7513         toBoolean(right);
7514         aopPut(AOP(result),"a",0);
7515         goto release ;
7516     }
7517
7518     /* bit variables done */
7519     /* general case */
7520     size = AOP_SIZE(result);
7521     offset = 0 ;
7522     if(AOP_TYPE(right) == AOP_LIT)
7523         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7524     if((size > 1) &&
7525        (AOP_TYPE(result) != AOP_REG) &&
7526        (AOP_TYPE(right) == AOP_LIT) &&
7527        !IS_FLOAT(operandType(right)) &&
7528        (lit < 256L)){
7529         emitcode("clr","a");
7530         while (size--) {
7531             if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7532                 aopPut(AOP(result),"a",size);
7533             else
7534                 aopPut(AOP(result),
7535                        aopGet(AOP(right),size,FALSE,FALSE),
7536                        size);
7537         }
7538     } else {
7539         while (size--) {
7540             aopPut(AOP(result),
7541                    aopGet(AOP(right),offset,FALSE,FALSE),
7542                    offset);
7543             offset++;
7544         }
7545     }
7546     
7547 release:
7548     freeAsmop (right,NULL,ic,FALSE);
7549     freeAsmop (result,NULL,ic,TRUE);
7550 }   
7551
7552 /*-----------------------------------------------------------------*/
7553 /* genJumpTab - genrates code for jump table                       */
7554 /*-----------------------------------------------------------------*/
7555 static void genJumpTab (iCode *ic)
7556 {
7557     symbol *jtab;
7558     char *l;
7559
7560     D(emitcode(";", "genJumpTab "););
7561
7562     aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7563     /* get the condition into accumulator */
7564     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7565     MOVA(l);
7566     /* multiply by three */
7567     emitcode("add","a,acc");
7568     emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7569     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7570
7571     jtab = newiTempLabel(NULL);
7572     emitcode("mov","dptr,#%05d$",jtab->key+100);
7573     emitcode("jmp","@a+dptr");
7574     emitcode("","%05d$:",jtab->key+100);
7575     /* now generate the jump labels */
7576     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7577          jtab = setNextItem(IC_JTLABELS(ic)))
7578         emitcode("ljmp","%05d$",jtab->key+100);
7579
7580 }
7581
7582 /*-----------------------------------------------------------------*/
7583 /* genCast - gen code for casting                                  */
7584 /*-----------------------------------------------------------------*/
7585 static void genCast (iCode *ic)
7586 {
7587     operand *result = IC_RESULT(ic);
7588     link *ctype = operandType(IC_LEFT(ic));
7589     link *rtype = operandType(IC_RIGHT(ic));
7590     operand *right = IC_RIGHT(ic);
7591     int size, offset ;
7592
7593     D(emitcode(";", "genCast "););
7594
7595     /* if they are equivalent then do nothing */
7596     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7597         return ;
7598
7599     aopOp(right,ic,FALSE, FALSE) ;
7600     aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
7601
7602     /* if the result is a bit */
7603     if (AOP_TYPE(result) == AOP_CRY) {
7604         /* if the right size is a literal then
7605         we know what the value is */
7606         if (AOP_TYPE(right) == AOP_LIT) {
7607             if (((int) operandLitValue(right))) 
7608                 aopPut(AOP(result),one,0);
7609             else
7610                 aopPut(AOP(result),zero,0);
7611
7612             goto release;
7613         }
7614
7615         /* the right is also a bit variable */
7616         if (AOP_TYPE(right) == AOP_CRY) {
7617             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7618             aopPut(AOP(result),"c",0);
7619             goto release ;
7620         }
7621
7622         /* we need to or */
7623         toBoolean(right);
7624         aopPut(AOP(result),"a",0);
7625         goto release ;
7626     }
7627
7628     /* if they are the same size : or less */
7629     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7630
7631         /* if they are in the same place */
7632         if (sameRegs(AOP(right),AOP(result)))
7633             goto release;
7634
7635         /* if they in different places then copy */
7636         size = AOP_SIZE(result);
7637         offset = 0 ;
7638         while (size--) {
7639             aopPut(AOP(result),
7640                    aopGet(AOP(right),offset,FALSE,FALSE),
7641                    offset);
7642             offset++;
7643         }
7644         goto release;
7645     }
7646
7647
7648     /* if the result is of type pointer */
7649     if (IS_PTR(ctype)) {
7650
7651         int p_type;
7652         link *type = operandType(right);
7653         link *etype = getSpec(type);
7654
7655         /* pointer to generic pointer */
7656         if (IS_GENPTR(ctype)) {
7657             char *l = zero;
7658             
7659             if (IS_PTR(type)) 
7660                 p_type = DCL_TYPE(type);
7661             else {
7662                 /* we have to go by the storage class */
7663                 p_type = PTR_TYPE(SPEC_OCLS(etype));
7664             }
7665                 
7666             /* the first two bytes are known */
7667             size = GPTRSIZE - 1; 
7668             offset = 0 ;
7669             while (size--) {
7670                 aopPut(AOP(result),
7671                        aopGet(AOP(right),offset,FALSE,FALSE),
7672                        offset);
7673                 offset++;
7674             }
7675             /* the last byte depending on type */
7676             switch (p_type) {
7677             case IPOINTER:
7678             case POINTER:
7679                 l = zero;
7680                 break;
7681             case FPOINTER:
7682                 l = one;
7683                 break;
7684             case CPOINTER:
7685                 l = "#0x02";
7686                 break;                          
7687             case PPOINTER:
7688                 l = "#0x03";
7689                 break;
7690                 
7691             default:
7692                 /* this should never happen */
7693         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7694                        "got unknown pointer type");
7695                 exit(1);
7696             }
7697             aopPut(AOP(result),l, GPTRSIZE - 1);            
7698             goto release ;
7699         }
7700         
7701         /* just copy the pointers */
7702         size = AOP_SIZE(result);
7703         offset = 0 ;
7704         while (size--) {
7705             aopPut(AOP(result),
7706                    aopGet(AOP(right),offset,FALSE,FALSE),
7707                    offset);
7708             offset++;
7709         }
7710         goto release ;
7711     }
7712     
7713     /* so we now know that the size of destination is greater
7714     than the size of the source */
7715     /* we move to result for the size of source */
7716     size = AOP_SIZE(right);
7717     offset = 0 ;
7718     while (size--) {
7719         aopPut(AOP(result),
7720                aopGet(AOP(right),offset,FALSE,FALSE),
7721                offset);
7722         offset++;
7723     }
7724
7725     /* now depending on the sign of the source && destination */
7726     size = AOP_SIZE(result) - AOP_SIZE(right);
7727     /* if unsigned or not an integral type */
7728     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7729         while (size--)
7730             aopPut(AOP(result),zero,offset++);
7731     } else {
7732         /* we need to extend the sign :{ */
7733         char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7734                          FALSE,FALSE);
7735         MOVA(l);
7736         emitcode("rlc","a");
7737         emitcode("subb","a,acc");
7738         while (size--)
7739             aopPut(AOP(result),"a",offset++);   
7740     }
7741
7742     /* we are done hurray !!!! */
7743
7744 release:
7745     freeAsmop(right,NULL,ic,TRUE);
7746     freeAsmop(result,NULL,ic,TRUE);
7747
7748 }
7749
7750 /*-----------------------------------------------------------------*/
7751 /* genDjnz - generate decrement & jump if not zero instrucion      */
7752 /*-----------------------------------------------------------------*/
7753 static int genDjnz (iCode *ic, iCode *ifx)
7754 {
7755     symbol *lbl, *lbl1;
7756     if (!ifx)
7757         return 0;
7758     
7759     /* if the if condition has a false label
7760        then we cannot save */
7761     if (IC_FALSE(ifx))
7762         return 0;
7763
7764     /* if the minus is not of the form 
7765        a = a - 1 */
7766     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7767         !IS_OP_LITERAL(IC_RIGHT(ic)))
7768         return 0;
7769
7770     if (operandLitValue(IC_RIGHT(ic)) != 1)
7771         return 0;
7772
7773     /* if the size of this greater than one then no
7774        saving */
7775     if (getSize(operandType(IC_RESULT(ic))) > 1)
7776         return 0;
7777
7778     /* otherwise we can save BIG */
7779     lbl = newiTempLabel(NULL);
7780     lbl1= newiTempLabel(NULL);
7781
7782     aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7783     
7784     if (IS_AOP_PREG(IC_RESULT(ic))) {
7785         emitcode("dec","%s",
7786                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7787         emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7788         emitcode("jnz","%05d$",lbl->key+100);
7789     } else {    
7790         emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7791                   lbl->key+100);
7792     }
7793     emitcode ("sjmp","%05d$",lbl1->key+100);
7794     emitcode ("","%05d$:",lbl->key+100);
7795     emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7796     emitcode ("","%05d$:",lbl1->key+100);
7797     
7798     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7799     ifx->generated = 1;
7800     return 1;
7801 }
7802
7803 /*-----------------------------------------------------------------*/
7804 /* genReceive - generate code for a receive iCode                  */
7805 /*-----------------------------------------------------------------*/
7806 static void genReceive (iCode *ic)
7807 {    
7808
7809     D(emitcode(";", "genReceive "););
7810
7811     if (isOperandInFarSpace(IC_RESULT(ic)) && 
7812         ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7813           IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7814         int size = getSize(operandType(IC_RESULT(ic)));
7815         int offset =  fReturnSize_390 - size;
7816         while (size--) {
7817             emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
7818                                     fReturn[fReturnSize_390 - offset - 1] : "acc"));
7819             offset++;
7820         }
7821         aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7822         size = AOP_SIZE(IC_RESULT(ic));
7823         offset = 0;
7824         while (size--) {
7825             emitcode ("pop","acc");
7826             aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7827         }
7828         
7829     } else {
7830         _G.accInUse++;
7831         aopOp(IC_RESULT(ic),ic,FALSE, FALSE);  
7832         _G.accInUse--;
7833         assignResultValue(IC_RESULT(ic));       
7834     }
7835
7836     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7837 }
7838
7839 /*-----------------------------------------------------------------*/
7840 /* gen390Code - generate code for 8051 based controllers            */
7841 /*-----------------------------------------------------------------*/
7842 void gen390Code (iCode *lic)
7843 {
7844     iCode *ic;
7845     int cln = 0;
7846
7847     lineHead = lineCurr = NULL;
7848
7849     /* print the allocation information */
7850     if (allocInfo)
7851         printAllocInfo( currFunc, codeOutFile);
7852     /* if debug information required */
7853 /*     if (options.debug && currFunc) { */
7854     if (currFunc) {
7855         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7856         _G.debugLine = 1;
7857         if (IS_STATIC(currFunc->etype))
7858             emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
7859         else
7860             emitcode("","G$%s$0$0 ==.",currFunc->name);
7861         _G.debugLine = 0;
7862     }
7863     /* stack pointer name */
7864     if (options.useXstack)
7865         spname = "_spx";
7866     else
7867         spname = "sp";
7868     
7869  
7870     for (ic = lic ; ic ; ic = ic->next ) {
7871         
7872         if ( cln != ic->lineno ) {
7873             if ( options.debug ) {
7874                 _G.debugLine = 1;
7875                 emitcode("","C$%s$%d$%d$%d ==.",
7876                          ic->filename,ic->lineno,
7877                          ic->level,ic->block);
7878                 _G.debugLine = 0;
7879             }
7880             emitcode(";","%s %d",ic->filename,ic->lineno);
7881             cln = ic->lineno ;
7882         }
7883         /* if the result is marked as
7884            spilt and rematerializable or code for
7885            this has already been generated then
7886            do nothing */
7887         if (resultRemat(ic) || ic->generated ) 
7888             continue ;
7889         
7890         /* depending on the operation */
7891         switch (ic->op) {
7892         case '!' :
7893             genNot(ic);
7894             break;
7895             
7896         case '~' :
7897             genCpl(ic);
7898             break;
7899             
7900         case UNARYMINUS:
7901             genUminus (ic);
7902             break;
7903             
7904         case IPUSH:
7905             genIpush (ic);
7906             break;
7907             
7908         case IPOP:
7909             /* IPOP happens only when trying to restore a 
7910                spilt live range, if there is an ifx statement
7911                following this pop then the if statement might
7912                be using some of the registers being popped which
7913                would destory the contents of the register so
7914                we need to check for this condition and handle it */
7915             if (ic->next            && 
7916                 ic->next->op == IFX &&
7917                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
7918                 genIfx (ic->next,ic);
7919             else
7920                 genIpop (ic);
7921             break; 
7922             
7923         case CALL:
7924             genCall (ic);
7925             break;
7926             
7927         case PCALL:
7928             genPcall (ic);
7929             break;
7930             
7931         case FUNCTION:
7932             genFunction (ic);
7933             break;
7934             
7935         case ENDFUNCTION:
7936             genEndFunction (ic);
7937             break;
7938             
7939         case RETURN:
7940             genRet (ic);
7941             break;
7942             
7943         case LABEL:
7944             genLabel (ic);
7945             break;
7946             
7947         case GOTO:
7948             genGoto (ic);
7949             break;
7950             
7951         case '+' :
7952             genPlus (ic) ;
7953             break;
7954             
7955         case '-' :
7956             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7957                 genMinus (ic);
7958             break;
7959             
7960         case '*' :
7961             genMult (ic);
7962             break;
7963             
7964         case '/' :
7965             genDiv (ic) ;
7966             break;
7967             
7968         case '%' :
7969             genMod (ic);
7970             break;
7971             
7972         case '>' :
7973             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
7974             break;
7975             
7976         case '<' :
7977             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7978             break;
7979             
7980         case LE_OP:
7981         case GE_OP:
7982         case NE_OP:
7983             
7984             /* note these two are xlated by algebraic equivalence
7985                during parsing SDCC.y */
7986             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7987                    "got '>=' or '<=' shouldn't have come here");
7988             break;      
7989             
7990         case EQ_OP:
7991             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7992             break;          
7993             
7994         case AND_OP:
7995             genAndOp (ic);
7996             break;
7997             
7998         case OR_OP:
7999             genOrOp (ic);
8000             break;
8001             
8002         case '^' :
8003             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8004             break;
8005             
8006         case '|' :
8007                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8008             break;
8009             
8010         case BITWISEAND:
8011             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8012             break;
8013             
8014         case INLINEASM:
8015             genInline (ic);
8016             break;
8017             
8018         case RRC:
8019             genRRC (ic);
8020             break;
8021             
8022         case RLC:
8023             genRLC (ic);
8024             break;
8025             
8026         case GETHBIT:
8027             genGetHbit (ic);
8028             break;
8029             
8030         case LEFT_OP:
8031             genLeftShift (ic);
8032             break;
8033             
8034         case RIGHT_OP:
8035             genRightShift (ic);
8036             break;
8037             
8038         case GET_VALUE_AT_ADDRESS:
8039             genPointerGet(ic);
8040             break;
8041             
8042         case '=' :
8043             if (POINTER_SET(ic))
8044                 genPointerSet(ic);
8045             else
8046                 genAssign(ic);
8047             break;
8048             
8049         case IFX:
8050             genIfx (ic,NULL);
8051             break;
8052             
8053         case ADDRESS_OF:
8054             genAddrOf (ic);
8055             break;
8056             
8057         case JUMPTABLE:
8058             genJumpTab (ic);
8059             break;
8060             
8061         case CAST:
8062             genCast (ic);
8063             break;
8064             
8065         case RECEIVE:
8066             genReceive(ic);
8067             break;
8068             
8069         case SEND:
8070             addSet(&_G.sendSet,ic);
8071             break;
8072
8073         default :
8074             ic = ic;
8075             /*      piCode(ic,stdout); */
8076             
8077         }
8078     }
8079     
8080
8081     /* now we are ready to call the 
8082        peep hole optimizer */
8083     if (!options.nopeep)
8084         peepHole (&lineHead);
8085
8086     /* now do the actual printing */
8087     printLine (lineHead,codeOutFile);    
8088     return;
8089 }