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