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