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