Initial import
[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   D(emitcode (";     genMinus",""));
3330
3331   aopOp (IC_LEFT (ic), ic, FALSE);
3332   aopOp (IC_RIGHT (ic), ic, FALSE);
3333   aopOp (IC_RESULT (ic), ic, TRUE);
3334
3335   /* special cases :- */
3336   /* if I can do an decrement instead
3337      of subtract then GOOD for ME */
3338   if (genMinusDec (ic) == TRUE)
3339     goto release;
3340
3341   size = getDataSize (IC_RESULT (ic));
3342
3343   asmop *leftOp, *rightOp;
3344
3345   leftOp = AOP(IC_LEFT(ic));
3346   rightOp = AOP(IC_RIGHT(ic));
3347
3348   sub = "sub";
3349   offset = 0;
3350   while (size--)
3351     {
3352       loadRegFromAop ( hc08_reg_a, leftOp, offset);
3353       accopWithAop(sub, rightOp, offset);
3354       storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3355       sub = "sbc";
3356     }
3357   
3358   
3359 //  adjustArithmeticResult (ic);
3360
3361 release:
3362   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3363   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3364   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3365 }
3366
3367
3368
3369 /*-----------------------------------------------------------------*/
3370 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3371 /*-----------------------------------------------------------------*/
3372 static void
3373 genMultOneByte (operand * left,
3374                 operand * right,
3375                 operand * result)
3376 {
3377   sym_link *opetype = operandType (result);
3378   symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3379   int size=AOP_SIZE(result);
3380   bool negLiteral = FALSE;
3381
3382   D(emitcode (";     genMultOneByte",""));
3383
3384   if (size<1 || size>2) {
3385     // this should never happen
3386       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3387                AOP_SIZE(result), __FILE__, lineno);
3388       exit (1);
3389   }
3390
3391   /* (if two literals: the value is computed before) */
3392   /* if one literal, literal on the right */
3393   if (AOP_TYPE (left) == AOP_LIT)
3394     {
3395       operand *t = right;
3396       right = left;
3397       left = t;
3398       //emitcode (";", "swapped left and right");
3399     }
3400
3401   if (SPEC_USIGN(opetype))
3402     {
3403       // just an unsigned 8*8=8/16 multiply
3404       //emitcode (";","unsigned");
3405
3406       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3407       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3408       emitcode ("mul", "");
3409       hc08_dirtyReg (hc08_reg_xa, FALSE);
3410       storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3411       hc08_freeReg (hc08_reg_xa);
3412       
3413       return;
3414     }
3415
3416   // we have to do a signed multiply
3417
3418
3419   //emitcode (";", "signed");
3420   adjustStack (-1);
3421   emitcode ("clr", "1,s");
3422
3423   tlbl1 = newiTempLabel (NULL);
3424   loadRegFromAop (hc08_reg_a, AOP (left), 0);
3425   emitcode ("tsta","");
3426   emitBranch ("bpl", tlbl1);
3427   emitcode ("inc", "1,s");
3428   rmwWithReg ("neg", hc08_reg_a);
3429   emitLabel (tlbl1);
3430
3431   if (AOP_TYPE(right)==AOP_LIT)
3432     {
3433       signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3434       /* AND literal negative */
3435       if (val < 0) {
3436         emitcode ("ldx", "#0x%02x", -val);
3437         negLiteral = TRUE;
3438       } else {
3439         emitcode ("ldx", "#0x%02x", val);
3440       }
3441       hc08_useReg (hc08_reg_x);
3442     }
3443   else
3444     {
3445       tlbl2 = newiTempLabel (NULL);
3446       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3447       emitcode ("tstx", "");
3448       emitBranch ("bpl", tlbl2);
3449       emitcode ("inc", "1,s");
3450       rmwWithReg ("neg", hc08_reg_x);
3451       emitLabel (tlbl2);
3452     }
3453
3454   emitcode ("mul", "");
3455   hc08_dirtyReg (hc08_reg_xa, FALSE);
3456
3457   tlbl3 = newiTempLabel (NULL);
3458   emitcode ("dec", "1,s");
3459   if (negLiteral)
3460     emitBranch ("bne", tlbl3);
3461   else
3462     emitBranch ("beq", tlbl3);
3463
3464   rmwWithReg ("neg", hc08_reg_a);
3465   if (size>1)
3466     {
3467       tlbl4 = newiTempLabel (NULL);
3468       emitBranch ("bcc", tlbl4);
3469       rmwWithReg ("inc", hc08_reg_x);
3470       emitLabel (tlbl4);
3471       rmwWithReg ("neg", hc08_reg_x);
3472     }
3473
3474   emitLabel (tlbl3);
3475   adjustStack (1);
3476   storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3477   hc08_freeReg (hc08_reg_xa);
3478
3479 }
3480
3481 /*-----------------------------------------------------------------*/
3482 /* genMult - generates code for multiplication                     */
3483 /*-----------------------------------------------------------------*/
3484 static void
3485 genMult (iCode * ic)
3486 {
3487   operand *left = IC_LEFT (ic);
3488   operand *right = IC_RIGHT (ic);
3489   operand *result = IC_RESULT (ic);
3490
3491   D(emitcode (";     genMult",""));
3492
3493   /* assign the amsops */
3494   aopOp (left, ic, FALSE);
3495   aopOp (right, ic, FALSE);
3496   aopOp (result, ic, TRUE);
3497
3498   /* special cases first */
3499   /* if both are of size == 1 */
3500 //  if (getSize(operandType(left)) == 1 && 
3501 //      getSize(operandType(right)) == 1)
3502   if (AOP_SIZE (left) == 1 && 
3503       AOP_SIZE (right) == 1)
3504     {
3505       genMultOneByte (left, right, result);
3506       goto release;
3507     }
3508
3509   /* should have been converted to function call */
3510     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3511              getSize(OP_SYMBOL(right)->type));
3512     fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3513              AOP_SIZE (right));
3514   assert (0);
3515
3516 release:
3517   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3518   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3519   freeAsmop (result, NULL, ic, TRUE);
3520 }
3521
3522 /*-----------------------------------------------------------------*/
3523 /* genDivOneByte : 8 bit division                                  */
3524 /*-----------------------------------------------------------------*/
3525 static void
3526 genDivOneByte (operand * left,
3527                operand * right,
3528                operand * result)
3529 {
3530   sym_link *opetype = operandType (result);
3531 //  char *l;
3532   symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3533   int size;
3534   bool negLiteral = FALSE;
3535
3536   D(emitcode (";     genDivOneByte",""));
3537
3538   size = AOP_SIZE (result);
3539   /* signed or unsigned */
3540   if (SPEC_USIGN (opetype))
3541     {
3542       /* unsigned is easy */
3543       loadRegFromAop (hc08_reg_h, AOP (left), 1);
3544       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3545       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3546       emitcode ("div", "");
3547       hc08_dirtyReg (hc08_reg_a, FALSE);
3548       hc08_dirtyReg (hc08_reg_h, FALSE);
3549       storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3550       hc08_freeReg (hc08_reg_a);
3551       hc08_freeReg (hc08_reg_x);
3552       hc08_freeReg (hc08_reg_h);
3553       return;
3554     }
3555
3556   /* signed is a little bit more difficult */
3557
3558   adjustStack (-1);
3559   emitcode ("clr", "1,s");
3560
3561   tlbl1 = newiTempLabel (NULL);
3562   tlbl2 = newiTempLabel (NULL);
3563   loadRegFromAop (hc08_reg_a, AOP (left), 0);
3564   loadRegFromAop (hc08_reg_x, AOP (left), 1);
3565   emitBranch ("bpl", tlbl1);
3566   emitcode ("inc", "1,s");
3567   rmwWithReg ("neg", hc08_reg_a);
3568   emitBranch ("bcc", tlbl2);
3569   rmwWithReg ("inc", hc08_reg_x);
3570   emitLabel (tlbl2);
3571   rmwWithReg ("neg", hc08_reg_x);
3572   transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3573   emitLabel (tlbl1);
3574
3575   if (AOP_TYPE(right)==AOP_LIT)
3576     {
3577       signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3578       /* AND literal negative */
3579       if (val < 0) {
3580         emitcode ("ldx", "#0x%02x", -val);
3581         negLiteral = TRUE;
3582       } else {
3583         emitcode ("ldx", "#0x%02x", val);
3584       }
3585       hc08_useReg (hc08_reg_x);
3586     }
3587   else
3588     {
3589       tlbl3 = newiTempLabel (NULL);
3590       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3591       emitBranch ("bpl", tlbl3);
3592       emitcode ("inc", "1,s");
3593       rmwWithReg ("neg", hc08_reg_x);
3594       emitLabel (tlbl3);
3595     }
3596
3597   emitcode ("div", "");
3598   hc08_dirtyReg (hc08_reg_x, FALSE);
3599   hc08_dirtyReg (hc08_reg_a, FALSE);
3600   hc08_dirtyReg (hc08_reg_h, FALSE);
3601
3602   tlbl4 = newiTempLabel (NULL);
3603   emitcode ("dec", "1,s");
3604   if (negLiteral)
3605     emitBranch ("bne", tlbl4);
3606   else
3607     emitBranch ("beq", tlbl4);
3608   rmwWithReg ("neg", hc08_reg_a);
3609
3610   emitLabel (tlbl4);
3611   adjustStack (1);
3612   storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3613   hc08_freeReg (hc08_reg_a);
3614   hc08_freeReg (hc08_reg_x);
3615   hc08_freeReg (hc08_reg_h);
3616
3617
3618 }
3619
3620 /*-----------------------------------------------------------------*/
3621 /* genDiv - generates code for division                            */
3622 /*-----------------------------------------------------------------*/
3623 static void
3624 genDiv (iCode * ic)
3625 {
3626   operand *left = IC_LEFT (ic);
3627   operand *right = IC_RIGHT (ic);
3628   operand *result = IC_RESULT (ic);
3629
3630   D(emitcode (";     genDiv",""));
3631
3632   /* assign the amsops */
3633   aopOp (left, ic, FALSE);
3634   aopOp (right, ic, FALSE);
3635   aopOp (result, ic, TRUE);
3636
3637   /* special cases first */
3638   /* if both are of size == 1 */
3639   if (AOP_SIZE (left) <= 2 &&
3640       AOP_SIZE (right) == 1)
3641     {
3642       genDivOneByte (left, right, result);
3643       goto release;
3644     }
3645
3646   /* should have been converted to function call */
3647   assert (0);
3648 release:
3649   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3650   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3651   freeAsmop (result, NULL, ic, TRUE);
3652 }
3653
3654 /*-----------------------------------------------------------------*/
3655 /* genModOneByte : 8 bit modulus                                   */
3656 /*-----------------------------------------------------------------*/
3657 static void
3658 genModOneByte (operand * left,
3659                operand * right,
3660                operand * result)
3661 {
3662   sym_link *opetype = operandType (result);
3663 //  symbol *lbl;
3664   symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3665   int size;
3666   bool negLiteral = FALSE;
3667
3668   D(emitcode (";     genModOneByte",""));
3669
3670   size = AOP_SIZE (result);
3671   /* signed or unsigned */
3672   if (SPEC_USIGN (opetype))
3673     {
3674       /* unsigned is easy */
3675       loadRegFromAop (hc08_reg_h, AOP (left), 1);
3676       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3677       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3678       emitcode ("div", "");
3679       hc08_dirtyReg (hc08_reg_a, FALSE);
3680       hc08_dirtyReg (hc08_reg_h, FALSE);
3681       storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3682       hc08_freeReg (hc08_reg_a);
3683       hc08_freeReg (hc08_reg_x);
3684       hc08_freeReg (hc08_reg_h);
3685       return;
3686     }
3687
3688   /* signed is a little bit more difficult */
3689
3690   adjustStack (-1);
3691   emitcode ("clr", "1,s");
3692
3693   tlbl1 = newiTempLabel (NULL);
3694   tlbl2 = newiTempLabel (NULL);
3695   loadRegFromAop (hc08_reg_a, AOP (left), 0);
3696   loadRegFromAop (hc08_reg_x, AOP (left), 1);
3697   emitBranch ("bpl", tlbl1);
3698   emitcode ("inc", "1,s");
3699   rmwWithReg ("neg", hc08_reg_a);
3700   emitBranch ("bcc", tlbl2);
3701   rmwWithReg ("inc", hc08_reg_x);
3702   emitLabel (tlbl2);
3703   rmwWithReg ("neg", hc08_reg_x);
3704   transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3705   emitLabel (tlbl1);
3706
3707   if (AOP_TYPE(right)==AOP_LIT)
3708     {
3709       signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3710       /* AND literal negative */
3711       if (val < 0) {
3712         emitcode ("ldx", "#0x%02x", -val);
3713         negLiteral = TRUE;
3714       } else {
3715         emitcode ("ldx", "#0x%02x", val);
3716       }
3717       hc08_useReg (hc08_reg_x);
3718     }
3719   else
3720     {
3721       tlbl3 = newiTempLabel (NULL);
3722       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3723       emitBranch ("bpl", tlbl3);
3724       emitcode ("inc", "1,s");
3725       rmwWithReg ("neg", hc08_reg_x);
3726       emitLabel (tlbl3);
3727     }
3728
3729   emitcode ("div", "");
3730   hc08_dirtyReg (hc08_reg_x, FALSE);
3731   hc08_dirtyReg (hc08_reg_a, FALSE);
3732   hc08_dirtyReg (hc08_reg_h, FALSE);
3733
3734   tlbl4 = newiTempLabel (NULL);
3735   transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
3736   emitcode ("dec", "1,s");
3737   if (negLiteral)
3738     emitBranch ("bne", tlbl4);
3739   else
3740     emitBranch ("beq", tlbl4);
3741   rmwWithReg ("neg", hc08_reg_a);
3742
3743   emitLabel (tlbl4);
3744   adjustStack (1);
3745   storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3746   hc08_freeReg (hc08_reg_a);
3747   hc08_freeReg (hc08_reg_x);
3748   hc08_freeReg (hc08_reg_h);
3749
3750 }
3751
3752 /*-----------------------------------------------------------------*/
3753 /* genMod - generates code for division                            */
3754 /*-----------------------------------------------------------------*/
3755 static void
3756 genMod (iCode * ic)
3757 {
3758   operand *left = IC_LEFT (ic);
3759   operand *right = IC_RIGHT (ic);
3760   operand *result = IC_RESULT (ic);
3761
3762   D(emitcode (";     genMod",""));
3763
3764   /* assign the amsops */
3765   aopOp (left, ic, FALSE);
3766   aopOp (right, ic, FALSE);
3767   aopOp (result, ic, TRUE);
3768
3769   /* special cases first */
3770   /* if both are of size == 1 */
3771   if (AOP_SIZE (left) <= 2 &&
3772       AOP_SIZE (right) == 1)
3773     {
3774       genModOneByte (left, right, result);
3775       goto release;
3776     }
3777
3778   /* should have been converted to function call */
3779   assert (0);
3780
3781 release:
3782   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3783   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3784   freeAsmop (result, NULL, ic, TRUE);
3785 }
3786
3787 /*-----------------------------------------------------------------*/
3788 /* genIfxJump :- will create a jump depending on the ifx           */
3789 /*-----------------------------------------------------------------*/
3790 static void
3791 genIfxJump (iCode * ic, char *jval)
3792 {
3793   symbol *jlbl;
3794   symbol *tlbl = newiTempLabel (NULL);
3795   char *inst;
3796
3797   D(emitcode (";     genIfxJump",""));
3798
3799   /* if true label then we jump if condition
3800      supplied is true */
3801   if (IC_TRUE (ic))
3802     {
3803       jlbl = IC_TRUE (ic);
3804       if (!strcmp (jval, "a"))
3805         inst = "beq";
3806       else if (!strcmp (jval, "c"))
3807         inst = "bcc";
3808       else
3809         inst = "bge";
3810     }
3811   else
3812     {
3813       /* false label is present */
3814       jlbl = IC_FALSE (ic);
3815       if (!strcmp (jval, "a"))
3816         inst = "bne";
3817       else if (!strcmp (jval, "c"))
3818         inst = "bcs";
3819       else
3820         inst = "blt";
3821     }
3822   emitBranch (inst, tlbl);
3823   emitBranch ("jmp", jlbl);
3824   emitLabel (tlbl);
3825
3826   /* mark the icode as generated */
3827   ic->generated = 1;
3828 }
3829
3830 /*-----------------------------------------------------------------*/
3831 /* genCmp :- greater or less than comparison                       */
3832 /*-----------------------------------------------------------------*/
3833 static void
3834 genCmp (operand * left, operand * right,
3835         operand * result, iCode * ifx, int sign, iCode *ic)
3836 {
3837   int size, offset = 0;
3838   unsigned long lit = 0L;
3839   char *sub;
3840   bool needpula = FALSE;
3841
3842   D(emitcode (";     genCmp",""));
3843
3844   /* subtract right from left if at the
3845      end the carry flag is set then we know that
3846      left is greater than right */
3847   size = max (AOP_SIZE (left), AOP_SIZE (right));
3848
3849   if (AOP_TYPE (right) == AOP_LIT)
3850     {
3851       lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3852       /* optimize if(x < 0) or if(x >= 0) */
3853       if (lit == 0L)
3854         {
3855           if (!sign)
3856             {
3857               CLRC;
3858             }
3859           else
3860             {
3861               needpula = pushRegIfUsed (hc08_reg_a);
3862               loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
3863               emitcode ("rola", "");
3864               hc08_useReg (hc08_reg_a);
3865             }
3866           sign = 0;
3867           goto release;
3868         }
3869     }
3870
3871   if ((size==2)
3872       && ((AOP_TYPE (right) == AOP_LIT) || 
3873           ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
3874       && hc08_reg_hx->isFree)
3875     {
3876       loadRegFromAop (hc08_reg_hx, AOP (left), 0);
3877       emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
3878       hc08_freeReg (hc08_reg_hx);
3879       goto release;
3880     }
3881
3882   offset = 0;
3883   if (size==1)
3884     sub="cmp";
3885   else
3886     sub="sub";
3887   while (size--)
3888     {
3889       loadRegFromAop (hc08_reg_a, AOP (left), offset);
3890       accopWithAop (sub, AOP (right), offset);
3891       hc08_freeReg (hc08_reg_a);
3892       offset++;
3893       sub="sbc";
3894     }
3895
3896 release:
3897   freeAsmop (right, NULL, ic, TRUE);
3898   freeAsmop (left, NULL, ic, TRUE);
3899   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3900     {
3901       outBitC (result);
3902     }
3903   else
3904     {
3905       /* if the result is used in the next
3906          ifx conditional branch then generate
3907          code a little differently */
3908       if (ifx)
3909         {
3910           pullOrFreeReg(hc08_reg_a,needpula);
3911           genIfxJump (ifx, sign ? "s" : "c");
3912         }
3913       else
3914         if (!sign)
3915           outBitC (result);
3916         else
3917           outBitNV (result);
3918         pullOrFreeReg(hc08_reg_a,needpula);
3919     }
3920 }
3921
3922 /*-----------------------------------------------------------------*/
3923 /* genCmpGt :- greater than comparison                             */
3924 /*-----------------------------------------------------------------*/
3925 static void
3926 genCmpGt (iCode * ic, iCode * ifx)
3927 {
3928   operand *left, *right, *result;
3929   sym_link *letype, *retype;
3930   int sign;
3931
3932   D(emitcode (";     genCmpGt",""));
3933
3934   result = IC_RESULT (ic);
3935   left = IC_LEFT (ic);
3936   right = IC_RIGHT (ic);
3937
3938   letype = getSpec (operandType (left));
3939   retype = getSpec (operandType (right));
3940   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3941   /* assign the amsops */
3942   aopOp (left, ic, FALSE);
3943   aopOp (right, ic, FALSE);
3944   aopOp (result, ic, TRUE);
3945
3946   genCmp (right, left, result, ifx, sign,ic);
3947
3948   freeAsmop (result, NULL, ic, TRUE);
3949 }
3950
3951 /*-----------------------------------------------------------------*/
3952 /* genCmpLt - less than comparisons                                */
3953 /*-----------------------------------------------------------------*/
3954 static void
3955 genCmpLt (iCode * ic, iCode * ifx)
3956 {
3957   operand *left, *right, *result;
3958   sym_link *letype, *retype;
3959   int sign;
3960
3961   D(emitcode (";     genCmpLt",""));
3962
3963   result = IC_RESULT (ic);
3964   left = IC_LEFT (ic);
3965   right = IC_RIGHT (ic);
3966
3967   letype = getSpec (operandType (left));
3968   retype = getSpec (operandType (right));
3969   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3970
3971   /* assign the amsops */
3972   aopOp (left, ic, FALSE);
3973   aopOp (right, ic, FALSE);
3974   aopOp (result, ic, TRUE);
3975
3976   genCmp (left, right, result, ifx, sign,ic);
3977
3978   freeAsmop (result, NULL, ic, TRUE);
3979 }
3980
3981 /*-----------------------------------------------------------------*/
3982 /*  - compare and branch if not equal                    */
3983 /*-----------------------------------------------------------------*/
3984 static void
3985 gencbneshort (operand * left, operand * right, symbol * lbl)
3986 {
3987   int size = max (AOP_SIZE (left), AOP_SIZE (right));
3988   int offset = 0;
3989   unsigned long lit = 0L;
3990
3991   /* if the left side is a literal or
3992      if the right is in a pointer register and left
3993      is not */
3994   if (AOP_TYPE (left) == AOP_LIT)
3995     {
3996       operand *t = right;
3997       right = left;
3998       left = t;
3999     }
4000   if (AOP_TYPE (right) == AOP_LIT)
4001     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4002
4003   while (size--)
4004     {
4005       loadRegFromAop (hc08_reg_a, AOP (left), offset);
4006       accopWithAop ("cmp", AOP (right), offset);
4007       hc08_useReg (hc08_reg_a);
4008       hc08_freeReg (hc08_reg_a);
4009       emitBranch ("bne", lbl);
4010       offset++;
4011     }
4012
4013 }
4014
4015 /*-----------------------------------------------------------------*/
4016 /* gencjne - compare and jump if not equal                         */
4017 /*-----------------------------------------------------------------*/
4018 static void
4019 gencjne (operand * left, operand * right, symbol * lbl)
4020 {
4021   symbol *tlbl = newiTempLabel (NULL);
4022
4023   gencbneshort (left, right, lbl);
4024
4025   loadRegFromConst (hc08_reg_a, one);
4026   emitBranch ("bra", tlbl);
4027   emitLabel (lbl);
4028   loadRegFromConst (hc08_reg_a, zero);
4029   emitLabel (tlbl);
4030
4031   hc08_useReg(hc08_reg_a);
4032   hc08_freeReg(hc08_reg_a);
4033 }
4034
4035 /*-----------------------------------------------------------------*/
4036 /* genCmpEq - generates code for equal to                          */
4037 /*-----------------------------------------------------------------*/
4038 static void
4039 genCmpEq (iCode * ic, iCode * ifx)
4040 {
4041   operand *left, *right, *result;
4042
4043   D(emitcode (";     genCmpEq",""));
4044
4045   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4046   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4047   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4048
4049   /* if literal, literal on the right or
4050      if the right is in a pointer register and left
4051      is not */
4052   if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4053     {
4054       operand *t = IC_RIGHT (ic);
4055       IC_RIGHT (ic) = IC_LEFT (ic);
4056       IC_LEFT (ic) = t;
4057     }
4058
4059   if (ifx && !AOP_SIZE (result))
4060     {
4061       symbol *tlbl;
4062       tlbl = newiTempLabel (NULL);
4063       gencbneshort (left, right, tlbl);
4064       if (IC_TRUE (ifx))
4065         {
4066           emitBranch ("jmp", IC_TRUE (ifx));
4067           emitLabel (tlbl);
4068         }
4069       else
4070         {
4071           symbol *lbl = newiTempLabel (NULL);
4072           emitBranch ("bra", lbl);
4073           emitLabel (tlbl);
4074           emitBranch ("jmp", IC_FALSE (ifx));
4075           emitLabel (lbl);
4076         }
4077       
4078       /* mark the icode as generated */
4079       ifx->generated = 1;
4080       goto release;
4081     }
4082
4083   gencjne (left, right, newiTempLabel (NULL));
4084   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4085     {
4086       storeRegToAop (hc08_reg_a, AOP (result), 0);
4087       goto release;
4088     }
4089   if (ifx)
4090     {
4091       genIfxJump (ifx, "a");
4092       goto release;
4093     }
4094   /* if the result is used in an arithmetic operation
4095      then put the result in place */
4096   if (AOP_TYPE (result) != AOP_CRY)
4097     outAcc (result);
4098
4099 release:
4100   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4101   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4102   freeAsmop (result, NULL, ic, TRUE);
4103 }
4104
4105 /*-----------------------------------------------------------------*/
4106 /* ifxForOp - returns the icode containing the ifx for operand     */
4107 /*-----------------------------------------------------------------*/
4108 static iCode *
4109 ifxForOp (operand * op, iCode * ic)
4110 {
4111   /* if true symbol then needs to be assigned */
4112   if (IS_TRUE_SYMOP (op))
4113     return NULL;
4114
4115   /* if this has register type condition and
4116      the next instruction is ifx with the same operand
4117      and live to of the operand is upto the ifx only then */
4118   if (ic->next &&
4119       ic->next->op == IFX &&
4120       IC_COND (ic->next)->key == op->key &&
4121       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4122     return ic->next;
4123
4124   return NULL;
4125 }
4126
4127 static bool
4128 genPointerGetSetOfs (iCode *ic)
4129 {
4130   iCode *lic = ic->next;
4131   bool pset, pget;
4132   int offset, size;
4133   symbol *sym;
4134   asmop *derefaop;
4135
4136   /* Make sure we have a next iCode */
4137   emitcode("","; checking lic");
4138   if (!lic)
4139     return FALSE;
4140
4141   /* Make sure the result of the addition is an iCode */
4142   emitcode("","; checking IS_ITEMP");
4143   if (!IS_ITEMP (IC_RESULT (ic)))
4144     return FALSE;
4145
4146   /* Make sure the next iCode is a pointer set or get */
4147   pset = POINTER_SET(lic);
4148   pget = POINTER_GET(lic);
4149   emitcode("","; pset=%d, pget=%d",pset,pget);
4150   if (!pset && !pget)
4151     return FALSE;
4152
4153   emitcode("", "; checking pset operandsEqu");
4154   if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4155     return FALSE;
4156
4157   emitcode("", "; checking pget operandsEqu");
4158   if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4159     return FALSE;
4160
4161   emitcode("", "; checking IS_SYMOP");
4162   if (!IS_SYMOP (IC_LEFT (ic)))
4163     return FALSE;
4164
4165   emitcode("", "; checking !IS_TRUE_SYMOP");
4166   if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4167     return FALSE;
4168
4169   sym = OP_SYMBOL (IC_LEFT (ic));
4170   
4171   emitcode("", "; checking remat");
4172   if (!sym->remat)
4173     return FALSE;
4174     
4175   if (pget)
4176     {
4177       D(emitcode (";     genPointerGetOfs",""));
4178       aopOp (IC_LEFT(ic), ic, FALSE);
4179       derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4180       freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4181       
4182       aopOp (IC_RIGHT(ic), ic, FALSE);
4183       aopOp (IC_RESULT(lic), lic, FALSE);
4184       
4185
4186       loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4187       size = AOP_SIZE (IC_RESULT(lic));
4188       derefaop->size = size;
4189       offset=0;
4190       
4191       while (size--)
4192         {
4193           emitcode ("lda", "%s,x",
4194                     aopAdrStr (derefaop, offset, TRUE));
4195           hc08_useReg (hc08_reg_a);
4196           storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
4197           hc08_freeReg (hc08_reg_a);
4198         }
4199
4200       lic->generated = 1;
4201       hc08_freeReg (hc08_reg_hx);
4202
4203       freeAsmop (NULL, derefaop, ic, TRUE);
4204       freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4205       freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4206       
4207       return TRUE;
4208     }
4209
4210   if (pset)
4211     {
4212       D(emitcode (";     genPointerSetOfs",""));
4213       aopOp (IC_LEFT(ic), ic, FALSE);
4214       derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4215       freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4216
4217       aopOp (IC_RIGHT(ic), ic, FALSE);
4218       aopOp (IC_RIGHT(lic), lic, FALSE);
4219       
4220
4221       loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4222       size = AOP_SIZE (IC_RIGHT(lic));
4223       derefaop->size = size;
4224       offset=0;
4225       
4226       while (size--)
4227         {
4228           loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
4229           emitcode ("sta", "%s,x",
4230                     aopAdrStr (derefaop, offset, TRUE));
4231           hc08_freeReg (hc08_reg_a);
4232           offset++;
4233         }
4234
4235       lic->generated = 1;
4236       hc08_freeReg (hc08_reg_hx);
4237
4238       freeAsmop (NULL, derefaop, ic, TRUE);
4239       freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4240       freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4241       
4242       return TRUE;
4243     }
4244     
4245   return FALSE;
4246 }
4247
4248
4249 /*-----------------------------------------------------------------*/
4250 /* hasInc - operand is incremented before any other use            */
4251 /*-----------------------------------------------------------------*/
4252 static iCode *
4253 hasInc (operand *op, iCode *ic,int osize)
4254 {
4255   sym_link *type = operandType(op);
4256   sym_link *retype = getSpec (type);
4257   iCode *lic = ic->next;
4258   int isize ;
4259   
4260   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4261   if (!IS_SYMOP(op)) return NULL;
4262
4263   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4264   if (IS_AGGREGATE(type->next)) return NULL;
4265   if (osize != (isize = getSize(type->next))) return NULL;
4266
4267   while (lic) {
4268     /* if operand of the form op = op + <sizeof *op> */
4269     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4270         isOperandEqual(IC_RESULT(lic),op) && 
4271         isOperandLiteral(IC_RIGHT(lic)) &&
4272         operandLitValue(IC_RIGHT(lic)) == isize) {
4273       return lic;
4274     }
4275     /* if the operand used or deffed */
4276     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4277       return NULL;
4278     }
4279     /* if GOTO or IFX */
4280     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4281     lic = lic->next;
4282   }
4283   return NULL;
4284 }
4285
4286 /*-----------------------------------------------------------------*/
4287 /* genAndOp - for && operation                                     */
4288 /*-----------------------------------------------------------------*/
4289 static void
4290 genAndOp (iCode * ic)
4291 {
4292   operand *left, *right, *result;
4293   symbol *tlbl, *tlbl0;
4294
4295   D(emitcode (";     genAndOp",""));
4296
4297   /* note here that && operations that are in an
4298      if statement are taken away by backPatchLabels
4299      only those used in arthmetic operations remain */
4300   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4301   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4302   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4303
4304   tlbl = newiTempLabel (NULL);
4305   tlbl0 = newiTempLabel (NULL);
4306   
4307   asmopToBool (AOP (left), FALSE);
4308   emitBranch ("beq", tlbl0);
4309   asmopToBool (AOP (right), FALSE);
4310   emitBranch ("beq", tlbl0);
4311   loadRegFromConst (hc08_reg_a,one);
4312   emitBranch ("bra", tlbl);
4313   emitLabel (tlbl0);
4314   loadRegFromConst (hc08_reg_a,zero);
4315   emitLabel (tlbl);
4316
4317   hc08_useReg (hc08_reg_a);
4318   hc08_freeReg (hc08_reg_a);
4319   
4320   storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4321
4322   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4323   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4324   freeAsmop (result, NULL, ic, TRUE);
4325 }
4326
4327
4328 /*-----------------------------------------------------------------*/
4329 /* genOrOp - for || operation                                      */
4330 /*-----------------------------------------------------------------*/
4331 static void
4332 genOrOp (iCode * ic)
4333 {
4334   operand *left, *right, *result;
4335   symbol *tlbl, *tlbl0;
4336
4337   D(emitcode (";     genOrOp",""));
4338
4339   /* note here that || operations that are in an
4340      if statement are taken away by backPatchLabels
4341      only those used in arthmetic operations remain */
4342   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4343   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4344   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4345
4346   tlbl = newiTempLabel (NULL);
4347   tlbl0 = newiTempLabel (NULL);
4348   
4349   asmopToBool (AOP (left), FALSE);
4350   emitBranch ("bne", tlbl0);
4351   asmopToBool (AOP (right), FALSE);
4352   emitBranch ("bne", tlbl0);
4353   loadRegFromConst (hc08_reg_a,zero);
4354   emitBranch ("bra", tlbl);
4355   emitLabel (tlbl0);
4356   loadRegFromConst (hc08_reg_a,one);
4357   emitLabel (tlbl);
4358
4359   hc08_useReg (hc08_reg_a);
4360   hc08_freeReg (hc08_reg_a);
4361   
4362   storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4363
4364
4365   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4366   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4367   freeAsmop (result, NULL, ic, TRUE);
4368 }
4369
4370 /*-----------------------------------------------------------------*/
4371 /* isLiteralBit - test if lit == 2^n                               */
4372 /*-----------------------------------------------------------------*/
4373 static int
4374 isLiteralBit (unsigned long lit)
4375 {
4376   unsigned long pw[32] =
4377   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4378    0x100L, 0x200L, 0x400L, 0x800L,
4379    0x1000L, 0x2000L, 0x4000L, 0x8000L,
4380    0x10000L, 0x20000L, 0x40000L, 0x80000L,
4381    0x100000L, 0x200000L, 0x400000L, 0x800000L,
4382    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4383    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4384   int idx;
4385
4386   for (idx = 0; idx < 32; idx++)
4387     if (lit == pw[idx])
4388       return idx + 1;
4389   return 0;
4390 }
4391
4392 #if 0
4393 /*-----------------------------------------------------------------*/
4394 /* continueIfTrue -                                                */
4395 /*-----------------------------------------------------------------*/
4396 static void
4397 continueIfTrue (iCode * ic)
4398 {
4399   if (IC_TRUE (ic))
4400     emitBranch ("jmp", IC_TRUE (ic));
4401   ic->generated = 1;
4402 }
4403
4404 /*-----------------------------------------------------------------*/
4405 /* jmpIfTrue -                                                     */
4406 /*-----------------------------------------------------------------*/
4407 static void
4408 jumpIfTrue (iCode * ic)
4409 {
4410   if (!IC_TRUE (ic))
4411     emitBranch ("jmp", IC_FALSE (ic));
4412   ic->generated = 1;
4413 }
4414
4415 /*-----------------------------------------------------------------*/
4416 /* jmpTrueOrFalse -                                                */
4417 /*-----------------------------------------------------------------*/
4418 static void
4419 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4420 {
4421   // ugly but optimized by peephole
4422   if (IC_TRUE (ic))
4423     {
4424       symbol *nlbl = newiTempLabel (NULL);
4425       emitBranch ("bra", nlbl);
4426       emitLabel (tlbl);
4427       emitBranch ("jmp", IC_TRUE (ic));
4428       emitLabel (nlbl);
4429     }
4430   else
4431     {
4432       emitBranch ("jmp", IC_FALSE (ic));
4433       emitLabel (tlbl);
4434     }
4435   ic->generated = 1;
4436 }
4437 #endif
4438
4439 /*-----------------------------------------------------------------*/
4440 /* genAnd  - code for and                                          */
4441 /*-----------------------------------------------------------------*/
4442 static void
4443 genAnd (iCode * ic, iCode * ifx)
4444 {
4445   operand *left, *right, *result;
4446   int size, offset = 0;
4447   unsigned long lit = 0L;
4448   unsigned long litinv;
4449
4450   
4451 //  int bytelit = 0;
4452 //  char buffer[10];
4453
4454   D(emitcode (";     genAnd",""));
4455
4456   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4457   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4458   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4459
4460 #ifdef DEBUG_TYPE
4461   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4462             AOP_TYPE (result),
4463             AOP_TYPE (left), AOP_TYPE (right));
4464   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4465             AOP_SIZE (result),
4466             AOP_SIZE (left), AOP_SIZE (right));
4467 #endif
4468
4469   /* if left is a literal & right is not then exchange them */
4470   if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4471     {
4472       operand *tmp = right;
4473       right = left;
4474       left = tmp;
4475     }
4476
4477   /* if left is accumulator & right is not then exchange them */
4478   if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4479     {
4480       operand *tmp = right;
4481       right = left;
4482       left = tmp;
4483     }
4484
4485   size = AOP_SIZE (result);
4486
4487   if (AOP_TYPE (right) == AOP_LIT)
4488     {
4489       lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4490       litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4491
4492       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4493           (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4494         {
4495           int bitpos = isLiteralBit(litinv)-1;
4496           emitcode ("bclr","#%d,%s",bitpos & 7,
4497                     aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4498           goto release;
4499         }
4500     }
4501
4502   offset = 0;
4503   while (size--)
4504     {
4505       loadRegFromAop (hc08_reg_a, AOP (left), offset);
4506       if ((AOP_TYPE (right) != AOP_LIT)
4507           || (((lit >> (offset*8)) & 0xff) != 0xff))
4508         accopWithAop ("and", AOP (right), offset);
4509       storeRegToAop (hc08_reg_a, AOP (result), offset++);
4510       hc08_freeReg( hc08_reg_a);      
4511     }
4512
4513 release:
4514   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4515   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4516   freeAsmop (result, NULL, ic, TRUE);
4517 }
4518
4519 /*-----------------------------------------------------------------*/
4520 /* genOr  - code for or                                            */
4521 /*-----------------------------------------------------------------*/
4522 static void
4523 genOr (iCode * ic, iCode * ifx)
4524 {
4525   operand *left, *right, *result;
4526   int size, offset = 0;
4527   unsigned long lit = 0L;
4528
4529   D(emitcode (";     genOr",""));
4530
4531   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4532   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4533   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4534
4535 #ifdef DEBUG_TYPE
4536   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4537             AOP_TYPE (result),
4538             AOP_TYPE (left), AOP_TYPE (right));
4539   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4540             AOP_SIZE (result),
4541             AOP_SIZE (left), AOP_SIZE (right));
4542 #endif
4543
4544   /* if left is a literal & right is not then exchange them */
4545   if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4546     {
4547       operand *tmp = right;
4548       right = left;
4549       left = tmp;
4550     }
4551
4552   /* if left is accumulator & right is not then exchange them */
4553   if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4554     {
4555       operand *tmp = right;
4556       right = left;
4557       left = tmp;
4558     }
4559
4560   /* if right is bit then exchange them */
4561   if (AOP_TYPE (right) == AOP_CRY &&
4562       AOP_TYPE (left) != AOP_CRY)
4563     {
4564       operand *tmp = right;
4565       right = left;
4566       left = tmp;
4567     }
4568   if (AOP_TYPE (right) == AOP_LIT)
4569     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4570
4571   size = AOP_SIZE (result);
4572
4573   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4574       (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
4575       (AOP_TYPE (left) == AOP_DIR))
4576     {
4577       int bitpos = isLiteralBit(lit)-1;
4578       emitcode ("bset","#%d,%s",bitpos & 7,
4579                 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4580       goto release;
4581     }
4582     
4583
4584
4585   offset = 0;
4586   while (size--)
4587     {
4588       loadRegFromAop (hc08_reg_a, AOP (left), offset);
4589       accopWithAop ("ora", AOP (right), offset);
4590       storeRegToAop (hc08_reg_a, AOP (result), offset++);
4591       hc08_freeReg( hc08_reg_a);      
4592     }
4593
4594
4595 release:
4596   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4597   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4598   freeAsmop (result, NULL, ic, TRUE);
4599 }
4600
4601 /*-----------------------------------------------------------------*/
4602 /* genXor - code for xclusive or                                   */
4603 /*-----------------------------------------------------------------*/
4604 static void
4605 genXor (iCode * ic, iCode * ifx)
4606 {
4607   operand *left, *right, *result;
4608   int size, offset = 0;
4609   unsigned long lit = 0L;
4610
4611   D(emitcode (";     genXor",""));
4612
4613   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4614   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4615   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4616
4617 #ifdef DEBUG_TYPE
4618   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4619             AOP_TYPE (result),
4620             AOP_TYPE (left), AOP_TYPE (right));
4621   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4622             AOP_SIZE (result),
4623             AOP_SIZE (left), AOP_SIZE (right));
4624 #endif
4625
4626   /* if left is a literal & right is not ||
4627      if left needs acc & right does not */
4628   if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4629     {
4630       operand *tmp = right;
4631       right = left;
4632       left = tmp;
4633     }
4634
4635   /* if left is accumulator & right is not then exchange them */
4636   if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4637     {
4638       operand *tmp = right;
4639       right = left;
4640       left = tmp;
4641     }
4642
4643   /* if right is bit then exchange them */
4644   if (AOP_TYPE (right) == AOP_CRY &&
4645       AOP_TYPE (left) != AOP_CRY)
4646     {
4647       operand *tmp = right;
4648       right = left;
4649       left = tmp;
4650     }
4651   if (AOP_TYPE (right) == AOP_LIT)
4652     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4653
4654   size = AOP_SIZE (result);
4655   offset = 0;
4656   while (size--)
4657     {
4658       loadRegFromAop (hc08_reg_a, AOP (left), offset);
4659       accopWithAop ("eor", AOP (right), offset);
4660       storeRegToAop (hc08_reg_a, AOP (result), offset++);
4661       hc08_freeReg( hc08_reg_a);      
4662     }
4663
4664
4665 //release:
4666   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4667   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4668   freeAsmop (result, NULL, ic, TRUE);
4669 }
4670
4671 static void
4672 emitinline (iCode * ic, char *inlin)
4673 {
4674   char buffer[512];
4675   char *symname;
4676   char c;
4677   char *bp=buffer;
4678   symbol *sym, *tempsym;
4679   asmop *aop;
4680   char *l;
4681   
4682   while (*inlin)
4683     {
4684       if (*inlin == '_')
4685         {
4686           symname = ++inlin;
4687           while (isalnum(*inlin) || (*inlin == '_'))
4688             inlin++;
4689           c = *inlin;
4690           *inlin = '\0';
4691           //printf("Found possible symbol '%s'\n",symname);
4692           tempsym = newSymbol (symname, ic->level);
4693           tempsym->block = ic->block;
4694           sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
4695           *inlin = c;
4696           if (!sym)
4697             {
4698               *bp++ = '_';
4699               inlin = symname;
4700             }
4701           else
4702             {
4703               aop = aopForSym (ic, sym, FALSE);
4704               l = aopAdrStr (aop, aop->size - 1, TRUE);
4705               if (*l=='#')
4706                 l++;
4707               sym->isref = 1;
4708               if (!sym->allocreq && !sym->ismyparm)
4709                 {
4710                   werror (E_ID_UNDEF, sym->name);
4711                   werror (W_CONTINUE,
4712                           "  Add 'volatile' to the variable declaration so that it\n"
4713                           "  can be referenced within inline assembly");
4714                 }
4715               //printf("Replacing with '%s'\n",l);
4716               while (*l)
4717                 {
4718                   *bp++ = *l++;
4719                   if ((2+bp-buffer)>sizeof(buffer))
4720                     goto endofline;
4721                 }
4722             }
4723         }
4724       else
4725         {
4726           *bp++ = *inlin++;
4727         }
4728       if ((2+bp-buffer)>sizeof(buffer))
4729         goto endofline;
4730     }
4731
4732 endofline:
4733   *bp = '\0';
4734
4735   if ((2+bp-buffer)>sizeof(buffer))
4736     fprintf(stderr, "Inline assembly buffer overflow\n");
4737   
4738   //printf("%s\n",buffer);
4739   emitcode (buffer,"");
4740 }
4741
4742
4743 /*-----------------------------------------------------------------*/
4744 /* genInline - write the inline code out                           */
4745 /*-----------------------------------------------------------------*/
4746 static void
4747 genInline (iCode * ic)
4748 {
4749   char *buffer, *bp, *bp1;
4750
4751   D(emitcode (";     genInline",""));
4752
4753   _G.inLine += (!options.asmpeep);
4754
4755   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4756   strcpy (buffer, IC_INLINE (ic));
4757
4758   /* emit each line as a code */
4759   while (*bp)
4760     {
4761       if (*bp == '\n')
4762         {
4763           *bp++ = '\0';
4764           /* emitcode (bp1, ""); */
4765           emitinline (ic, bp1);
4766           bp1 = bp;
4767         }
4768       else
4769         {
4770           if (*bp == ':')
4771             {
4772               bp++;
4773               *bp = '\0';
4774               bp++;
4775               emitcode (bp1, "");
4776               bp1 = bp;
4777             }
4778           else
4779             bp++;
4780         }
4781     }
4782   if (bp1 != bp)
4783     {
4784       /* emitcode (bp1, ""); */
4785       emitinline (ic, bp1);
4786     }
4787   /*     emitcode("",buffer); */
4788   _G.inLine -= (!options.asmpeep);
4789 }
4790
4791 /*-----------------------------------------------------------------*/
4792 /* genRRC - rotate right with carry                                */
4793 /*-----------------------------------------------------------------*/
4794 static void
4795 genRRC (iCode * ic)
4796 {
4797   operand *left, *result;
4798   int size, offset = 0;
4799   bool needpula = FALSE;
4800   bool resultInA = FALSE;
4801   char *shift;
4802
4803   D(emitcode (";     genRRC",""));
4804
4805   /* rotate right with carry */
4806   left = IC_LEFT (ic);
4807   result = IC_RESULT (ic);
4808   aopOp (left, ic, FALSE);
4809   aopOp (result, ic, FALSE);
4810
4811   if ((AOP_TYPE (result) == AOP_REG)
4812       && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4813    resultInA = TRUE;
4814
4815   size = AOP_SIZE (result);
4816   offset = size-1;
4817
4818   shift="lsr";
4819   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4820     {
4821       while (size--)
4822         {
4823           rmwWithAop (shift, AOP (result), offset--);
4824           shift="ror";
4825         }
4826     }
4827   else
4828     {
4829       while (size--)
4830         {
4831           loadRegFromAop (hc08_reg_a, AOP (left), offset);
4832           rmwWithReg (shift, hc08_reg_a);
4833           storeRegToAop (hc08_reg_a, AOP (result), offset--);
4834           hc08_freeReg (hc08_reg_a);
4835           shift="ror";
4836         }
4837     }
4838
4839   if ((!hc08_reg_a->isFree) || resultInA)
4840     {
4841       pushReg (hc08_reg_a, TRUE);
4842       needpula = TRUE;
4843     }
4844
4845   /* now we need to put the carry into the
4846      highest order byte of the result */
4847   offset = AOP_SIZE (result) - 1;
4848   emitcode ("clra","");
4849   emitcode ("rora","");
4850   hc08_dirtyReg (hc08_reg_a, FALSE);
4851   if (resultInA)
4852     {
4853       emitcode ("ora", "1,s");
4854       emitcode ("ais", "#1");
4855       hc08_dirtyReg (hc08_reg_a, FALSE);
4856       needpula = FALSE;
4857     }
4858   else
4859     accopWithAop ("ora", AOP (result), offset);
4860   storeRegToAop (hc08_reg_a, AOP (result), offset);
4861
4862   pullOrFreeReg (hc08_reg_a, needpula);
4863
4864   freeAsmop (left, NULL, ic, TRUE);
4865   freeAsmop (result, NULL, ic, TRUE);
4866 }
4867
4868 /*-----------------------------------------------------------------*/
4869 /* genRLC - generate code for rotate left with carry               */
4870 /*-----------------------------------------------------------------*/
4871 static void
4872 genRLC (iCode * ic)
4873 {
4874   operand *left, *result;
4875   int size, offset = 0;
4876   char *shift;
4877   bool resultInA = FALSE;
4878   bool needpula = FALSE;
4879
4880   D(emitcode (";     genRLC",""));
4881
4882   /* rotate right with carry */
4883   left = IC_LEFT (ic);
4884   result = IC_RESULT (ic);
4885   aopOp (left, ic, FALSE);
4886   aopOp (result, ic, FALSE);
4887
4888   if ((AOP_TYPE (result) == AOP_REG)
4889       && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4890    resultInA = TRUE;
4891
4892   size = AOP_SIZE (result);
4893   offset = 0;
4894
4895   shift="lsl";
4896   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4897     {
4898       while (size--)
4899         {
4900           rmwWithAop (shift, AOP (result), offset--);
4901           shift="rol";
4902         }
4903     }
4904   else
4905     {
4906       while (size--)
4907         {
4908           loadRegFromAop (hc08_reg_a, AOP (left), offset);
4909           rmwWithReg (shift, hc08_reg_a);
4910           storeRegToAop (hc08_reg_a, AOP (result), offset++);
4911           hc08_freeReg (hc08_reg_a);
4912           shift="rol";
4913         }
4914     }
4915
4916   if ((!hc08_reg_a->isFree) || resultInA)
4917     {
4918       pushReg (hc08_reg_a, TRUE);
4919       needpula = TRUE;
4920     }
4921
4922   /* now we need to put the carry into the
4923      lowest order byte of the result */
4924   offset = 0;
4925   emitcode ("clra","");
4926   emitcode ("rola","");
4927   hc08_dirtyReg (hc08_reg_a, FALSE);
4928   if (resultInA)
4929     {
4930       emitcode ("ora", "1,s");
4931       emitcode ("ais", "#1");
4932       hc08_dirtyReg (hc08_reg_a, FALSE);
4933       needpula = FALSE;
4934     }
4935   else
4936     accopWithAop ("ora", AOP (result), offset);
4937   storeRegToAop (hc08_reg_a, AOP (result), offset);
4938
4939   pullOrFreeReg (hc08_reg_a, needpula);
4940
4941   freeAsmop (left, NULL, ic, TRUE);
4942   freeAsmop (result, NULL, ic, TRUE);
4943 }
4944
4945 /*-----------------------------------------------------------------*/
4946 /* genGetHbit - generates code get highest order bit               */
4947 /*-----------------------------------------------------------------*/
4948 static void
4949 genGetHbit (iCode * ic)
4950 {
4951   operand *left, *result;
4952
4953   D(emitcode (";     genGetHbit",""));
4954
4955   left = IC_LEFT (ic);
4956   result = IC_RESULT (ic);
4957   aopOp (left, ic, FALSE);
4958   aopOp (result, ic, FALSE);
4959
4960   /* get the highest order byte into a */
4961   loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
4962   emitcode ("rola", "");
4963   emitcode ("clra", "");
4964   emitcode ("rola", "");
4965   hc08_dirtyReg (hc08_reg_a, FALSE);
4966   storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4967   
4968   freeAsmop (left, NULL, ic, TRUE);
4969   freeAsmop (result, NULL, ic, TRUE);
4970 }
4971
4972 #if 0
4973 /*-----------------------------------------------------------------*/
4974 /* AccRol - rotate left accumulator by known count                 */
4975 /*-----------------------------------------------------------------*/
4976 static void
4977 AccRol (int shCount)
4978 {
4979   shCount &= 0x0007;            // shCount : 0..7
4980
4981   switch (shCount)
4982     {
4983     case 0:
4984       break;
4985     case 1:
4986       emitcode ("rola", "");    /* 1 cycle */
4987       break;
4988     case 2:
4989       emitcode ("rola", "");    /* 1 cycle */
4990       emitcode ("rola", "");    /* 1 cycle */
4991       break;
4992     case 3:
4993       emitcode ("nsa", "");
4994       emitcode ("rora", "");
4995       break;
4996     case 4:
4997       emitcode ("nsa", "");     /* 3 cycles */
4998       break;
4999     case 5:
5000       emitcode ("nsa", "");     /* 3 cycles */
5001       emitcode ("rola", "");    /* 1 cycle */
5002       break;
5003     case 6:
5004       emitcode ("nsa", "");     /* 3 cycles */
5005       emitcode ("rola", "");    /* 1 cycle */
5006       emitcode ("rola", "");    /* 1 cycle */
5007       break;
5008     case 7:
5009       emitcode ("nsa", "");     /* 3 cycles */
5010       emitcode ("rola", "");    /* 1 cycle */
5011       emitcode ("rola", "");    /* 1 cycle */
5012       emitcode ("rola", "");    /* 1 cycle */
5013       break;
5014     }
5015 }
5016 #endif
5017
5018
5019 /*-----------------------------------------------------------------*/
5020 /* AccLsh - left shift accumulator by known count                  */
5021 /*-----------------------------------------------------------------*/
5022 static void
5023 AccLsh (int shCount)
5024 {
5025   int i;
5026   
5027   shCount &= 0x0007;            // shCount : 0..7
5028
5029   /* Shift counts of 4 and 5 are currently optimized for code size.        */
5030   /* Falling through to the unrolled loop would be optimal for code speed. */
5031   /* For shift counts of 6 and 7, the unrolled loop is never optimal.      */
5032   switch (shCount)
5033     {
5034     case 4:
5035       accopWithMisc ("nsa", "");
5036       accopWithMisc ("and", "#0xf0");
5037       /* total: 5 cycles, 3 bytes */
5038       return;
5039     case 5:
5040       accopWithMisc ("nsa", "");
5041       accopWithMisc ("and", "#0xf0");
5042       accopWithMisc ("lsla", "");
5043       /* total: 6 cycles, 4 bytes */
5044       return;
5045     case 6:
5046       accopWithMisc ("rora", "");
5047       accopWithMisc ("rora", "");
5048       accopWithMisc ("rora", "");
5049       accopWithMisc ("and", "#0xc0");
5050       /* total: 5 cycles, 5 bytes */
5051       return;
5052     case 7:
5053       accopWithMisc ("rora", "");
5054       accopWithMisc ("clra", "");
5055       accopWithMisc ("rora", "");
5056       /* total: 3 cycles, 3 bytes */
5057       return;
5058     }
5059
5060     /* lsla is only 1 cycle and byte, so an unrolled loop is often  */
5061     /* the fastest (shCount<6) and shortest (shCount<4).            */
5062     for (i=0;i<shCount;i++)
5063       accopWithMisc ("lsla", "");
5064 }
5065
5066
5067 /*-----------------------------------------------------------------*/
5068 /* AccSRsh - signed right shift accumulator by known count         */
5069 /*-----------------------------------------------------------------*/
5070 static void
5071 AccSRsh (int shCount)
5072 {
5073   int i;
5074   
5075   shCount &= 0x0007;            // shCount : 0..7
5076
5077   if (shCount == 7)
5078     {
5079       accopWithMisc ("rola", "");
5080       accopWithMisc ("clra", "");
5081       accopWithMisc ("sbc", zero);
5082       /* total: 4 cycles, 4 bytes */
5083       return;
5084     }
5085
5086     for (i=0;i<shCount;i++)
5087       accopWithMisc ("asra", "");
5088 }
5089
5090 /*-----------------------------------------------------------------*/
5091 /* AccRsh - right shift accumulator by known count                 */
5092 /*-----------------------------------------------------------------*/
5093 static void
5094 AccRsh (int shCount, bool sign)
5095 {
5096   int i;
5097   
5098   if (sign)
5099     {
5100       AccSRsh (shCount);
5101       return;
5102     }
5103   
5104   shCount &= 0x0007;            // shCount : 0..7
5105
5106   /* Shift counts of 4 and 5 are currently optimized for code size.        */
5107   /* Falling through to the unrolled loop would be optimal for code speed. */
5108   /* For shift counts of 6 and 7, the unrolled loop is never optimal.      */
5109   switch (shCount)
5110     {
5111     case 4:
5112       accopWithMisc ("nsa", "");
5113       accopWithMisc ("and", "#0x0f");
5114       /* total: 5 cycles, 3 bytes */
5115       return;
5116     case 5:
5117       accopWithMisc ("nsa", "");
5118       accopWithMisc ("and", "#0x0f");
5119       accopWithMisc ("lsra", "");
5120       /* total: 6 cycles, 4 bytes */
5121       return;
5122     case 6:
5123       accopWithMisc ("rola", "");
5124       accopWithMisc ("rola", "");
5125       accopWithMisc ("rola", "");
5126       accopWithMisc ("and", "#0x03");
5127       /* total: 5 cycles, 5 bytes */
5128       return;
5129     case 7:
5130       accopWithMisc ("rola", "");
5131       accopWithMisc ("clra", "");
5132       accopWithMisc ("rola", "");
5133       /* total: 3 cycles, 3 bytes */
5134       return;
5135     }
5136
5137     /* lsra is only 1 cycle and byte, so an unrolled loop is often  */
5138     /* the fastest (shCount<6) and shortest (shCount<4).            */
5139     for (i=0;i<shCount;i++)
5140       accopWithMisc ("lsra", "");
5141 }
5142
5143
5144 /*-----------------------------------------------------------------*/
5145 /* XAccLsh - left shift register pair XA by known count            */
5146 /*-----------------------------------------------------------------*/
5147 static void
5148 XAccLsh (int shCount)
5149 {
5150   int i;
5151   
5152   shCount &= 0x000f;            // shCount : 0..15
5153
5154   if (shCount>=8)
5155     {
5156       AccLsh (shCount-8);
5157       transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5158       loadRegFromConst (hc08_reg_a, zero);
5159       return;
5160     }
5161
5162   /* if we can beat 2n cycles or bytes for some special case, do it here */
5163   switch (shCount)
5164     {
5165     case 7:
5166       /*          bytes  cycles     reg x      reg a   carry
5167       **                          abcd efgh  ijkl mnop   ?
5168       **   lsrx       1  1        0abc defg  ijkl mnop   h
5169       **   rora       1  1        0abc defg  hijk lmno   p
5170       **   tax        1  1        hijk lmno  hijk lmno   p
5171       **   clra       1  1        hijk lmno  0000 0000   p
5172       **   rora       1  1        hijk lmno  p000 0000   0
5173       ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5174       */
5175       rmwWithReg ("lsr", hc08_reg_x);
5176       rmwWithReg ("ror", hc08_reg_a);
5177       transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5178       loadRegFromConst (hc08_reg_a, zero);
5179       rmwWithReg ("ror", hc08_reg_a);
5180       return;
5181
5182     default:
5183       ;
5184     }
5185
5186   /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often  */
5187   /* the fastest and shortest.                                           */
5188   for (i=0;i<shCount;i++)
5189     {
5190       rmwWithReg ("lsl", hc08_reg_a);
5191       rmwWithReg ("rol", hc08_reg_x);
5192     }
5193 }
5194
5195 /*-----------------------------------------------------------------*/
5196 /* XAccSRsh - signed right shift register pair XA by known count   */
5197 /*-----------------------------------------------------------------*/
5198 static void
5199 XAccSRsh (int shCount)
5200 {
5201   int i;
5202   
5203   shCount &= 0x000f;            // shCount : 0..7
5204
5205   /* if we can beat 2n cycles or bytes for some special case, do it here */
5206   switch (shCount)
5207     {
5208     case 15:
5209       /*          bytes  cycles     reg x      reg a   carry
5210       **                          abcd efgh  ijkl mnop   ?
5211       **   lslx       1  1        bcde fgh0  ijkl mnop   a
5212       **   clra       1  1        bcde fgh0  0000 0000   a
5213       **   rola       1  1        bcde fgh0  0000 000a   0
5214       **   nega       1  1        bcde fgh0  aaaa aaaa   a
5215       **   tax        1  1        aaaa aaaa  aaaa aaaa   a
5216       ** total: 5 cycles, 5 bytes
5217       */
5218       rmwWithReg ("lsl", hc08_reg_x);
5219       loadRegFromConst (hc08_reg_a, zero);
5220       rmwWithReg ("rol", hc08_reg_a);
5221       rmwWithReg ("neg", hc08_reg_a);
5222       transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5223       return;
5224
5225     case 14:
5226     case 13:
5227     case 12:
5228     case 11:
5229     case 10:
5230     case 9:
5231     case 8:
5232       /*          bytes  cycles     reg x      reg a   carry
5233       **                          abcd efgh  ijkl mnop   ?
5234       **   txa        1  1        abcd efgh  abcd efgh   ?
5235       **   (AccSRsh) <8 <8        abcd efgh  LSBresult   ?
5236       **   lsla       1  1        abcd efgh  ???? ????   a
5237       **   clrx       1  1        0000 0000  ???? ????   a
5238       **   rolx       1  1        0000 000a  ???? ????   0
5239       **   negx       1  1        aaaa aaaa  ???? ????   a
5240       **   rora       1  1        aaaa aaaa  LSBresult   0
5241       ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5242       */
5243       transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5244       AccSRsh (shCount-8);
5245       rmwWithReg ("lsl", hc08_reg_a);
5246       loadRegFromConst (hc08_reg_x, zero);
5247       rmwWithReg ("rol", hc08_reg_x);
5248       rmwWithReg ("neg", hc08_reg_x);
5249       rmwWithReg ("ror", hc08_reg_a);
5250       return;
5251
5252     default:
5253       ;
5254     }
5255
5256   /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often  */
5257   /* the fastest and shortest.                                           */
5258   for (i=0;i<shCount;i++)
5259     {
5260       rmwWithReg ("asr", hc08_reg_x);
5261       rmwWithReg ("ror", hc08_reg_a);
5262     }
5263 }
5264
5265 /*-----------------------------------------------------------------*/
5266 /* XAccRsh - right shift register pair XA by known count           */
5267 /*-----------------------------------------------------------------*/
5268 static void
5269 XAccRsh (int shCount, bool sign)
5270 {
5271   int i;
5272   
5273   if (sign)
5274     {
5275       XAccSRsh (shCount);
5276       return;
5277     }
5278   
5279   shCount &= 0x000f;            // shCount : 0..7
5280
5281   /* if we can beat 2n cycles or bytes for some special case, do it here */
5282   switch (shCount)
5283     {
5284     case 15:
5285       /*          bytes  cycles     reg x      reg a   carry
5286       **                          abcd efgh  ijkl mnop   ?
5287       **   clra       1  1        abcd efgh  0000 0000   a
5288       **   lslx       1  1        bcde fgh0  0000 0000   a
5289       **   rola       1  1        bcde fgh0  0000 000a   0
5290       **   clrx       1  1        0000 0000  0000 000a   0
5291       ** total: 4 cycles, 4 bytes
5292       */
5293       loadRegFromConst (hc08_reg_x, zero);
5294       rmwWithReg ("lsl", hc08_reg_x);
5295       rmwWithReg ("rol", hc08_reg_a);
5296       loadRegFromConst (hc08_reg_a, zero);
5297       return;
5298
5299     case 14:
5300       /*          bytes  cycles     reg x      reg a   carry
5301       **                          abcd efgh  ijkl mnop   ?
5302       **   clra       1  1        abcd efgh  0000 0000   a
5303       **   lslx       1  1        bcde fgh0  0000 0000   a
5304       **   rola       1  1        bcde fgh0  0000 000a   0
5305       **   lslx       1  1        cdef gh00  0000 000a   b
5306       **   rola       1  1        cdef gh00  0000 00ab   0
5307       **   clrx       1  1        0000 0000  0000 000a   0
5308       ** total: 6 cycles, 6 bytes
5309       */
5310       loadRegFromConst (hc08_reg_x, zero);
5311       rmwWithReg ("lsl", hc08_reg_x);
5312       rmwWithReg ("rol", hc08_reg_a);
5313       rmwWithReg ("lsl", hc08_reg_x);
5314       rmwWithReg ("rol", hc08_reg_a);
5315       loadRegFromConst (hc08_reg_a, zero);
5316       return;
5317
5318     case 13:
5319     case 12:
5320     case 11:
5321     case 10:
5322     case 9:
5323     case 8:
5324       transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5325       AccRsh (shCount-8, FALSE);
5326       loadRegFromConst (hc08_reg_x, zero);
5327       return;
5328
5329     case 7:
5330       /*          bytes  cycles     reg x      reg a   carry
5331       **                          abcd efgh  ijkl mnop   ?
5332       **   lsla       1  1        abcd efgh  jklm nop0   i
5333       **   txa        1  1        abcd efgh  abcd efgh   i
5334       **   rola       1  1        abcd efgh  bcde fghi   a
5335       **   clrx       1  1        0000 0000  bcde fghi   a
5336       **   rolx       1  1        0000 000a  bcde fghi   0
5337       ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5338       */
5339       rmwWithReg ("lsl", hc08_reg_a);
5340       transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5341       rmwWithReg ("rol", hc08_reg_a);
5342       loadRegFromConst (hc08_reg_x, zero);
5343       rmwWithReg ("rol", hc08_reg_x);
5344       return;
5345     case 6:
5346       /*          bytes  cycles     reg x      reg a   carry
5347       **                          abcd efgh  ijkl mnop   ?
5348       **   lsla       1  1        abcd efgh  jklm nop0   i
5349       **   rolx       1  1        bcde fghi  jklm nop0   a
5350       **   rola       1  1        bcde fghi  klmn op0a   j
5351       **   rolx       1  1        cdef ghij  klmn op0a   b
5352       **   rola       1  1        cdef ghij  lmno p0ab   k
5353       **   and #3     2  2        cdef ghij  0000 00ab   k
5354       **   psha       1  2        cdef ghij  0000 00ab   k
5355       **   txa        1  1        cdef ghij  cdef ghij   k
5356       **   pula       1  2        0000 00ab  cdef ghij   k
5357       ** total: 12 cycles, 10 bytes (beats 12 bytes)
5358       */
5359     default:
5360       ;
5361     }
5362
5363   /* lslx/rola is only 2 cycles and bytes, so an unrolled loop is often  */
5364   /* the fastest and shortest.                                           */
5365   for (i=0;i<shCount;i++)
5366     {
5367       rmwWithReg ("lsl", hc08_reg_x);
5368       rmwWithReg ("rol", hc08_reg_a);
5369     }
5370
5371 }
5372
5373
5374 #if 0
5375 /*-----------------------------------------------------------------*/
5376 /* shiftR1Left2Result - shift right one byte from left to result   */
5377 /*-----------------------------------------------------------------*/
5378 static void
5379 shiftR1Left2Result (operand * left, int offl,
5380                     operand * result, int offr,
5381                     int shCount, int sign)
5382 {
5383   loadRegFromAop (hc08_reg_a, AOP (left), offl);
5384   /* shift right accumulator */
5385   AccRsh (shCount, sign);
5386   storeRegToAop (hc08_reg_a, AOP (result), offr);
5387 }
5388 #endif
5389
5390 /*-----------------------------------------------------------------*/
5391 /* shiftL1Left2Result - shift left one byte from left to result    */
5392 /*-----------------------------------------------------------------*/
5393 static void
5394 shiftL1Left2Result (operand * left, int offl,
5395                     operand * result, int offr, int shCount)
5396 {
5397   loadRegFromAop (hc08_reg_a, AOP (left), offl);
5398   /* shift left accumulator */
5399   AccLsh (shCount);
5400   storeRegToAop (hc08_reg_a, AOP (result), offr);
5401 }
5402
5403 /*-----------------------------------------------------------------*/
5404 /* movLeft2Result - move byte from left to result                  */
5405 /*-----------------------------------------------------------------*/
5406 static void
5407 movLeft2Result (operand * left, int offl,
5408                 operand * result, int offr, int sign)
5409 {
5410   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5411     {
5412       transferAopAop (AOP (left), offl, AOP (result), offr);
5413     }
5414 }
5415
5416
5417 /*-----------------------------------------------------------------*/
5418 /* AccAXRsh1 - right shift 0->a:x->c by 1                         */
5419 /*-----------------------------------------------------------------*/
5420 static void
5421 AccAXRsh1 (char *x)
5422 {
5423   emitcode ("lsra", "");
5424   emitcode ("ror", "%s", x);
5425 }
5426
5427
5428 /*-----------------------------------------------------------------*/
5429 /* AccAXRshS1 - signed right shift s->a:x->c by 1                         */
5430 /*-----------------------------------------------------------------*/
5431 static void
5432 AccAXRshS1 (char *x)
5433 {
5434   emitcode ("asra", "");
5435   emitcode ("ror", "%s", x);
5436 }
5437
5438 /*-----------------------------------------------------------------*/
5439 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
5440 /*-----------------------------------------------------------------*/
5441 static void
5442 AccAXLrl1 (char *x)
5443 {
5444   emitcode ("rol", "%s", x);
5445   emitcode ("rola", "");
5446 }
5447
5448 /*-----------------------------------------------------------------*/
5449 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
5450 /*-----------------------------------------------------------------*/
5451 static void
5452 AccAXLsh1 (char *x)
5453 {
5454   emitcode ("lsl", "%s", x);
5455   emitcode ("rola", "");
5456 }
5457
5458 /*-----------------------------------------------------------------*/
5459 /* AccAXLsh - left shift a:x by known count (0..7)                 */
5460 /*-----------------------------------------------------------------*/
5461 static void
5462 AccAXLsh (char *x, int shCount)
5463 {
5464   int i;
5465
5466   for (i=0;i<shCount;i++) {
5467     AccAXLsh1 (x);
5468   }
5469 }
5470
5471 /*-----------------------------------------------------------------*/
5472 /* AccAXRsh - right shift a:x known count (0..7)                   */
5473 /*-----------------------------------------------------------------*/
5474 static void
5475 AccAXRsh (char *x, int shCount)
5476 {
5477   int i;
5478
5479   for (i=0;i<shCount;i++) {
5480     AccAXRsh1 (x);
5481   }
5482   
5483 }
5484
5485 /*-----------------------------------------------------------------*/
5486 /* AccAXRshS - right shift signed a:x known count (0..7)           */
5487 /*-----------------------------------------------------------------*/
5488 static void
5489 AccAXRshS (char *x, int shCount)
5490 {
5491   int i;
5492
5493   for (i=0;i<shCount;i++) {
5494     AccAXRshS1 (x);
5495   }
5496 }
5497
5498 /*-----------------------------------------------------------------*/
5499 /* shiftL2Left2Result - shift left two bytes from left to result   */
5500 /*-----------------------------------------------------------------*/
5501 static void
5502 shiftL2Left2Result (operand * left, int offl,
5503                     operand * result, int offr, int shCount)
5504 {
5505   int i;
5506   bool needpula = FALSE;
5507   bool needpulx = FALSE;
5508
5509   needpula = pushRegIfUsed (hc08_reg_a);
5510   needpulx = pushRegIfUsed (hc08_reg_x);
5511
5512   loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5513
5514   switch (shCount)
5515     {
5516       case 7:
5517         rmwWithReg ("lsr", hc08_reg_x);
5518         rmwWithReg ("ror", hc08_reg_a);
5519         transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5520         rmwWithReg ("clr", hc08_reg_a);
5521         rmwWithReg ("ror", hc08_reg_a);
5522         break;
5523       default:
5524         for (i=0; i<shCount; i++)
5525           {
5526             rmwWithReg ("lsl", hc08_reg_a);
5527             rmwWithReg ("rol", hc08_reg_x);
5528           }
5529     }
5530   storeRegToAop (hc08_reg_xa, AOP (result), offl);
5531
5532   pullOrFreeReg (hc08_reg_x, needpulx);
5533   pullOrFreeReg (hc08_reg_a, needpula);
5534
5535 }
5536
5537
5538 #if 0
5539 /*-----------------------------------------------------------------*/
5540 /* shiftR2Left2Result - shift right two bytes from left to result  */
5541 /*-----------------------------------------------------------------*/
5542 static void
5543 shiftR2Left2Result (operand * left, int offl,
5544                     operand * result, int offr,
5545                     int shCount, int sign)
5546 {
5547   int i;
5548   bool needpula = FALSE;
5549   bool needpulx = FALSE;
5550   
5551   needpula = pushRegIfUsed (hc08_reg_a);
5552   needpulx = pushRegIfUsed (hc08_reg_x);
5553
5554   loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5555   for (i=0; i<shCount; i++)
5556     {
5557       if (sign)
5558         rmwWithReg ("asr", hc08_reg_x);
5559       else
5560         rmwWithReg ("lsr", hc08_reg_x);
5561       rmwWithReg ("ror", hc08_reg_a);
5562     }
5563   storeRegToAop (hc08_reg_xa, AOP (result), offl);
5564
5565   pullOrFreeReg (hc08_reg_x, needpulx);
5566   pullOrFreeReg (hc08_reg_a, needpula);
5567 }
5568 #endif
5569
5570 #if 0
5571 /*-----------------------------------------------------------------*/
5572 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5573 /*-----------------------------------------------------------------*/
5574 static void
5575 shiftLLeftOrResult (operand * left, int offl,
5576                     operand * result, int offr, int shCount)
5577 {
5578   loadRegFromAop (hc08_reg_a, AOP (left), offl);
5579   /* shift left accumulator */
5580   AccLsh (shCount);
5581   /* or with result */
5582   accopWithAop ("ora", AOP (result), offr);
5583   /* back to result */
5584   storeRegToAop (hc08_reg_a, AOP (result), offr);
5585   hc08_freeReg (hc08_reg_a);
5586 }
5587 #endif
5588
5589 /*-----------------------------------------------------------------*/
5590 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5591 /*-----------------------------------------------------------------*/
5592 static void
5593 shiftRLeftOrResult (operand * left, int offl,
5594                     operand * result, int offr, int shCount)
5595 {
5596   loadRegFromAop (hc08_reg_a, AOP (left), offl);
5597   /* shift left accumulator */
5598   AccRsh (shCount, FALSE);
5599   /* or with result */
5600   accopWithAop ("ora", AOP (result), offr);
5601   /* back to result */
5602   storeRegToAop (hc08_reg_a, AOP (result), offr);
5603   hc08_freeReg (hc08_reg_a);
5604 }
5605
5606 /*-----------------------------------------------------------------*/
5607 /* genlshOne - left shift a one byte quantity by known count       */
5608 /*-----------------------------------------------------------------*/
5609 static void
5610 genlshOne (operand * result, operand * left, int shCount)
5611 {
5612   D(emitcode (";     genlshOne",""));
5613
5614   shiftL1Left2Result (left, LSB, result, LSB, shCount);
5615 }
5616
5617 /*-----------------------------------------------------------------*/
5618 /* genlshTwo - left shift two bytes by known amount != 0           */
5619 /*-----------------------------------------------------------------*/
5620 static void
5621 genlshTwo (operand * result, operand * left, int shCount)
5622 {
5623   int size;
5624
5625   D(emitcode (";     genlshTwo",""));
5626
5627   size = getDataSize (result);
5628
5629   /* if shCount >= 8 */
5630   if (shCount >= 8)
5631     {
5632       shCount -= 8;
5633
5634       if (size > 1)
5635         {
5636           if (shCount)
5637             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5638           else
5639             movLeft2Result (left, LSB, result, MSB16, 0);
5640         }
5641       storeConstToAop(zero, AOP (result), LSB);
5642     }
5643
5644   /*  1 <= shCount <= 7 */
5645   else
5646     {
5647       if (size == 1)
5648         shiftL1Left2Result (left, LSB, result, LSB, shCount);
5649       else
5650         shiftL2Left2Result (left, LSB, result, LSB, shCount);
5651     }
5652 }
5653
5654 /*-----------------------------------------------------------------*/
5655 /* shiftLLong - shift left one long from left to result            */
5656 /* offl = LSB or MSB16                                             */
5657 /*-----------------------------------------------------------------*/
5658 static void
5659 shiftLLong (operand * left, operand * result, int offr)
5660 {
5661 //  char *l;
5662 //  int size = AOP_SIZE (result);
5663
5664   bool needpula = FALSE;
5665   bool needpulx = FALSE;
5666
5667   needpula = pushRegIfUsed (hc08_reg_a);
5668   needpulx = pushRegIfUsed (hc08_reg_x);
5669
5670   loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
5671   rmwWithReg ("lsl", hc08_reg_a);
5672   rmwWithReg ("rol", hc08_reg_x);
5673   storeRegToAop (hc08_reg_xa, AOP (result), offr);
5674
5675   if (offr==LSB)
5676     {
5677       loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5678       rmwWithReg ("rol", hc08_reg_a);
5679       rmwWithReg ("rol", hc08_reg_x);
5680       storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
5681     }
5682   else if (offr==MSB16)
5683     {
5684       loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
5685       rmwWithReg ("rol", hc08_reg_a);
5686       storeRegToAop (hc08_reg_a, AOP (result), offr+2);
5687     }
5688
5689   pullOrFreeReg (hc08_reg_x, needpulx);
5690   pullOrFreeReg (hc08_reg_a, needpula);
5691 }
5692
5693 /*-----------------------------------------------------------------*/
5694 /* genlshFour - shift four byte by a known amount != 0             */
5695 /*-----------------------------------------------------------------*/
5696 static void
5697 genlshFour (operand * result, operand * left, int shCount)
5698 {
5699   int size;
5700
5701   D(emitcode (";     genlshFour",""));
5702
5703   size = AOP_SIZE (result);
5704
5705   /* TODO: deal with the &result == &left case */
5706
5707   /* if shifting more that 3 bytes */
5708   if (shCount >= 24)
5709     {
5710       shCount -= 24;
5711       if (shCount)
5712         /* lowest order of left goes to the highest
5713            order of the destination */
5714         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5715       else
5716         movLeft2Result (left, LSB, result, MSB32, 0);
5717       storeConstToAop (zero, AOP (result), LSB);
5718       storeConstToAop (zero, AOP (result), MSB16);
5719       storeConstToAop (zero, AOP (result), MSB24);
5720       return;
5721     }
5722
5723   /* more than two bytes */
5724   else if (shCount >= 16)
5725     {
5726       /* lower order two bytes goes to higher order two bytes */
5727       shCount -= 16;
5728       /* if some more remaining */
5729       if (shCount)
5730         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5731       else
5732         {
5733           movLeft2Result (left, MSB16, result, MSB32, 0);
5734           movLeft2Result (left, LSB, result, MSB24, 0);
5735         }
5736       storeConstToAop (zero, AOP (result), LSB);
5737       storeConstToAop (zero, AOP (result), MSB16);
5738       return;
5739     }
5740
5741   /* if more than 1 byte */
5742   else if (shCount >= 8)
5743     {
5744       /* lower order three bytes goes to higher order  three bytes */
5745       shCount -= 8;
5746       if (size == 2)
5747         {
5748           if (shCount)
5749             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5750           else
5751             movLeft2Result (left, LSB, result, MSB16, 0);
5752         }
5753       else
5754         {                       /* size = 4 */
5755           if (shCount == 0)
5756             {
5757               movLeft2Result (left, MSB24, result, MSB32, 0);
5758               movLeft2Result (left, MSB16, result, MSB24, 0);
5759               movLeft2Result (left, LSB, result, MSB16, 0);
5760               storeConstToAop (zero, AOP (result), LSB);
5761             }
5762           else if (shCount == 1)
5763             shiftLLong (left, result, MSB16);
5764           else
5765             {
5766               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5767               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5768               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5769               storeConstToAop (zero, AOP (result), LSB);
5770             }
5771         }
5772     }
5773
5774   /* 1 <= shCount <= 7 */
5775   else if (shCount <= 2)
5776     {
5777       shiftLLong (left, result, LSB);
5778       if (shCount == 2)
5779         shiftLLong (result, result, LSB);
5780     }
5781   /* 3 <= shCount <= 7, optimize */
5782   else
5783     {
5784       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5785       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5786       shiftL2Left2Result (left, LSB, result, LSB, shCount);
5787     }
5788 }
5789
5790 /*-----------------------------------------------------------------*/
5791 /* genLeftShiftLiteral - left shifting by known count              */
5792 /*-----------------------------------------------------------------*/
5793 static void
5794 genLeftShiftLiteral (operand * left,
5795                      operand * right,
5796                      operand * result,
5797                      iCode * ic)
5798 {
5799   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5800   int size;
5801
5802   D(emitcode (";     genLeftShiftLiteral",""));
5803
5804   freeAsmop (right, NULL, ic, TRUE);
5805
5806   aopOp (left, ic, FALSE);
5807   aopOp (result, ic, FALSE);
5808
5809 //  size = getSize (operandType (result));
5810   size = AOP_SIZE (result);
5811
5812 #if VIEW_SIZE
5813   emitcode ("; shift left ", "result %d, left %d", size,
5814             AOP_SIZE (left));
5815 #endif
5816
5817   if (shCount == 0)
5818     {
5819       while (size--)
5820         transferAopAop( AOP(left), size, AOP(result), size);
5821     }
5822   else if (shCount >= (size * 8))
5823     {
5824       while (size--)
5825         storeConstToAop (zero, AOP (result), size);
5826     }
5827   else
5828     {
5829       switch (size)
5830         {
5831         case 1:
5832           genlshOne (result, left, shCount);
5833           break;
5834
5835         case 2:
5836           genlshTwo (result, left, shCount);
5837           break;
5838
5839         case 4:
5840           genlshFour (result, left, shCount);
5841           break;
5842         default:
5843           werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
5844                   "*** ack! mystery literal shift!\n");
5845           break;
5846         }
5847     }
5848   freeAsmop (left, NULL, ic, TRUE);
5849   freeAsmop (result, NULL, ic, TRUE);
5850 }
5851
5852 /*-----------------------------------------------------------------*/
5853 /* genLeftShift - generates code for left shifting                 */
5854 /*-----------------------------------------------------------------*/
5855 static void
5856 genLeftShift (iCode * ic)
5857 {
5858   operand *left, *right, *result;
5859   int size, offset;
5860   symbol *tlbl, *tlbl1;
5861 //  int i;
5862   char *shift;
5863   regs *reg;
5864
5865   D(emitcode (";     genLeftShift",""));
5866
5867   right = IC_RIGHT (ic);
5868   left = IC_LEFT (ic);
5869   result = IC_RESULT (ic);
5870
5871   aopOp (right, ic, FALSE);
5872
5873   /* if the shift count is known then do it
5874      as efficiently as possible */
5875   if (AOP_TYPE (right) == AOP_LIT)
5876     {
5877       genLeftShiftLiteral (left, right, result, ic);
5878       return;
5879     }
5880
5881   /* shift count is unknown then we have to form
5882      a loop get the loop count in A : Note: we take
5883      only the lower order byte since shifting
5884      more that 32 bits make no sense anyway, ( the
5885      largest size of an object can be only 32 bits ) */
5886
5887   aopOp (left, ic, FALSE);
5888   aopOp (result, ic, FALSE);
5889
5890   /* now move the left to the result if they are not the
5891      same */
5892   if (!sameRegs (AOP (left), AOP (result)))
5893     {
5894
5895       size = AOP_SIZE (result);
5896       offset = 0;
5897       while (size--)
5898         {
5899           transferAopAop (AOP (left), offset, AOP (result), offset);
5900           offset++;
5901         }
5902     }
5903   freeAsmop (left, NULL, ic, TRUE);
5904   
5905   tlbl = newiTempLabel (NULL);
5906   size = AOP_SIZE (result);
5907   offset = 0;
5908   tlbl1 = newiTempLabel (NULL);
5909
5910   reg = hc08_reg_a;
5911
5912   loadRegFromAop (reg, AOP (right), 0);
5913   freeAsmop (right, NULL, ic, TRUE);
5914   emitBranch ("beq", tlbl1);
5915   emitLabel (tlbl);
5916   
5917   shift="lsl";
5918   for (offset=0;offset<size;offset++)
5919     {
5920       rmwWithAop (shift, AOP (result), offset);  
5921       shift="rol";
5922     }
5923   rmwWithReg ("dec", reg);
5924   emitBranch ("bne", tlbl);
5925   emitLabel (tlbl1);
5926   hc08_freeReg (reg);
5927   
5928   freeAsmop (result, NULL, ic, TRUE);
5929 }
5930
5931 /*-----------------------------------------------------------------*/
5932 /* genrshOne - right shift a one byte quantity by known count      */
5933 /*-----------------------------------------------------------------*/
5934 static void
5935 genrshOne (operand * result, operand * left,
5936            int shCount, int sign)
5937 {
5938   D(emitcode (";     genrshOne",""));
5939
5940   loadRegFromAop (hc08_reg_a, AOP (left), 0);
5941   AccRsh (shCount, sign);
5942   storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5943 }
5944
5945 /*-----------------------------------------------------------------*/
5946 /* genrshTwo - right shift two bytes by known amount != 0          */
5947 /*-----------------------------------------------------------------*/
5948 static void
5949 genrshTwo (operand * result, operand * left,
5950            int shCount, int sign)
5951 {
5952   D(emitcode (";     genrshTwo",""));
5953
5954   /* if shCount >= 8 */
5955   if (shCount >= 8)
5956     {
5957       if (shCount || sign)
5958         {
5959           loadRegFromAop (hc08_reg_a, AOP (left), 1);
5960           AccRsh (shCount-8, sign);
5961           storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5962         }
5963       else
5964         {
5965           transferAopAop (AOP (left), 1, AOP (result), 0);
5966           storeConstToAop (zero, AOP (result), 1);
5967         }
5968     }
5969
5970   /*  1 <= shCount <= 7 */
5971   else
5972     {
5973       loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5974       XAccRsh (shCount, sign);
5975       storeRegToAop (hc08_reg_xa, AOP (result), 0);
5976     }
5977 }
5978
5979 /*-----------------------------------------------------------------*/
5980 /* shiftRLong - shift right one long from left to result           */
5981 /* offl = LSB or MSB16                                             */
5982 /*-----------------------------------------------------------------*/
5983 static void
5984 shiftRLong (operand * left, int offl,
5985             operand * result, int sign)
5986 {
5987 //  char *l;
5988  // int size = AOP_SIZE (result);
5989
5990   bool needpula = FALSE;
5991   bool needpulx = FALSE;
5992
5993   needpula = pushRegIfUsed (hc08_reg_a);
5994   needpulx = pushRegIfUsed (hc08_reg_x);
5995
5996   if (offl==LSB)
5997     {
5998       loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5999       if (sign)
6000         rmwWithReg ("asr", hc08_reg_x);
6001       else
6002         rmwWithReg ("lsr", hc08_reg_x);
6003       rmwWithReg ("rol", hc08_reg_a);
6004       storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6005     }
6006   else if (offl==MSB16)
6007     {
6008       loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6009       if (sign)
6010         rmwWithReg ("asr", hc08_reg_a);
6011       else
6012         rmwWithReg ("lsr", hc08_reg_a);
6013       storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6014     }
6015
6016   loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6017   rmwWithReg ("ror", hc08_reg_x);
6018   rmwWithReg ("ror", hc08_reg_a);
6019   storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6020
6021
6022   pullOrFreeReg (hc08_reg_x, needpulx);
6023   pullOrFreeReg (hc08_reg_a, needpula);
6024 }
6025
6026 /*-----------------------------------------------------------------*/
6027 /* genrshFour - shift four byte by a known amount != 0             */
6028 /*-----------------------------------------------------------------*/
6029 static void
6030 genrshFour (operand * result, operand * left,
6031             int shCount, int sign)
6032 {
6033   /* TODO: handle cases where left == result */
6034   
6035   D(emitcode (";     genrshFour",""));
6036
6037   /* if shifting more that 3 bytes */
6038   if (shCount >= 24)
6039     {
6040       loadRegFromAop (hc08_reg_a, AOP (left), 3);
6041       AccRsh (shCount-24, sign);
6042       storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6043       return;
6044     }
6045   else if (shCount >= 16)
6046     {
6047       loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6048       XAccRsh (shCount-16, sign);
6049       storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6050       return;
6051     }
6052   else if (shCount >= 8)
6053     {
6054       if (shCount == 1)
6055         shiftRLong (left, MSB16, result, sign);
6056       else if (shCount == 8)
6057         {
6058           transferAopAop (AOP (left), 1, AOP (result), 0);
6059           transferAopAop (AOP (left), 2, AOP (result), 1);
6060           loadRegFromAop (hc08_reg_a, AOP (left), 3);
6061           storeRegToAop (hc08_reg_a, AOP (result), 2);
6062           storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6063         }
6064       else if (shCount == 9)
6065         {
6066           shiftRLong (left, MSB16, result, sign);
6067         }
6068       else
6069         {
6070           loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6071           XAccRsh (shCount-8, FALSE);
6072           storeRegToAop (hc08_reg_xa, AOP (result), 0);
6073           loadRegFromAop (hc08_reg_x, AOP (left), 3);
6074           loadRegFromConst (hc08_reg_a, zero);
6075           XAccRsh (shCount-8, sign);
6076           accopWithAop ("ora", AOP (result), 1);
6077           storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6078         }
6079     }
6080   else
6081     {                           /* 1 <= shCount <= 7 */
6082       if (shCount == 1)
6083         {
6084           shiftRLong (left, LSB, result, sign);
6085         }
6086       else
6087         {
6088           loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6089           XAccRsh (shCount, FALSE);
6090           storeRegToAop (hc08_reg_xa, AOP (result), 0);
6091           loadRegFromAop (hc08_reg_a, AOP (left), 2);
6092           AccLsh (8-shCount);
6093           accopWithAop ("ora", AOP (result), 1);
6094           storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6095           loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6096           XAccRsh (shCount, sign);
6097           storeRegToAop (hc08_reg_xa, AOP (result), 2);
6098         }
6099     }
6100 }
6101
6102 /*-----------------------------------------------------------------*/
6103 /* genRightShiftLiteral - right shifting by known count            */
6104 /*-----------------------------------------------------------------*/
6105 static void
6106 genRightShiftLiteral (operand * left,
6107                       operand * right,
6108                       operand * result,
6109                       iCode * ic,
6110                       int sign)
6111 {
6112   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6113   int size;
6114
6115   D(emitcode (";     genRightShiftLiteral",""));
6116
6117   freeAsmop (right, NULL, ic, TRUE);
6118
6119   aopOp (left, ic, FALSE);
6120   aopOp (result, ic, FALSE);
6121
6122 #if VIEW_SIZE
6123   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6124             AOP_SIZE (left));
6125 #endif
6126
6127   size = getDataSize (left);
6128   /* test the LEFT size !!! */
6129
6130   /* I suppose that the left size >= result size */
6131   if (shCount == 0)
6132     {
6133       size = getDataSize (result);
6134       while (size--)
6135         transferAopAop (AOP (left), size, AOP(result), size);
6136     }
6137   else if (shCount >= (size * 8))
6138     {
6139       if (sign) {
6140         /* get sign in acc.7 */
6141         loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6142       }
6143       addSign (result, LSB, sign);
6144     }
6145   else
6146     {
6147       switch (size)
6148         {
6149         case 1:
6150           genrshOne (result, left, shCount, sign);
6151           break;
6152
6153         case 2:
6154           genrshTwo (result, left, shCount, sign);
6155           break;
6156
6157         case 4:
6158           genrshFour (result, left, shCount, sign);
6159           break;
6160         default:
6161           break;
6162         }
6163     }
6164   freeAsmop (left, NULL, ic, TRUE);
6165   freeAsmop (result, NULL, ic, TRUE);
6166 }
6167
6168
6169 /*-----------------------------------------------------------------*/
6170 /* genRightShift - generate code for right shifting                */
6171 /*-----------------------------------------------------------------*/
6172 static void
6173 genRightShift (iCode * ic)
6174 {
6175   operand *right, *left, *result;
6176   sym_link *retype;
6177   int size, offset;
6178 //  char *l;
6179   symbol *tlbl, *tlbl1;
6180   char *shift;
6181   bool sign;
6182   
6183   D(emitcode (";     genRightShift",""));
6184
6185   /* if signed then we do it the hard way preserve the
6186      sign bit moving it inwards */
6187   retype = getSpec (operandType (IC_RESULT (ic)));
6188   sign = !SPEC_USIGN (retype);
6189
6190   /* signed & unsigned types are treated the same : i.e. the
6191      signed is NOT propagated inwards : quoting from the
6192      ANSI - standard : "for E1 >> E2, is equivalent to division
6193      by 2**E2 if unsigned or if it has a non-negative value,
6194      otherwise the result is implementation defined ", MY definition
6195      is that the sign does not get propagated */
6196
6197   right = IC_RIGHT (ic);
6198   left = IC_LEFT (ic);
6199   result = IC_RESULT (ic);
6200
6201   aopOp (right, ic, FALSE);
6202
6203   /* if the shift count is known then do it
6204      as efficiently as possible */
6205   if (AOP_TYPE (right) == AOP_LIT)
6206     {
6207       genRightShiftLiteral (left, right, result, ic, sign);
6208       return;
6209     }
6210
6211   /* shift count is unknown then we have to form
6212      a loop get the loop count in X : Note: we take
6213      only the lower order byte since shifting
6214      more that 32 bits make no sense anyway, ( the
6215      largest size of an object can be only 32 bits ) */
6216
6217   aopOp (left, ic, FALSE);
6218   aopOp (result, ic, FALSE);
6219
6220   if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6221     AOP (result) = forceStackedAop (AOP (result));
6222   
6223   size = AOP_SIZE (result); 
6224   offset = size-1;
6225   while (size--)
6226     {
6227       transferAopAop (AOP (left), offset, AOP (result), offset);
6228       offset--;
6229     }
6230   
6231   tlbl = newiTempLabel (NULL);
6232   size = AOP_SIZE (result);
6233   offset = 0;
6234   tlbl1 = newiTempLabel (NULL);
6235
6236   loadRegFromAop (hc08_reg_x, AOP (right), 0);
6237   emitcode ("tstx", "");
6238   emitcode ("beq", "%05d$", tlbl1->key + 100);
6239   emitcode ("", "%05d$:", tlbl->key + 100);
6240   shift= sign ? "asr" : "lsr";
6241   for (offset=size-1;offset>=0;offset--)
6242     {
6243       rmwWithAop (shift, AOP (result), offset);
6244       shift="ror";
6245     }
6246   rmwWithReg ("dec", hc08_reg_x);
6247   emitcode ("bne","%05d$", tlbl->key + 100);
6248   emitcode ("", "%05d$:", tlbl1->key + 100);
6249   
6250   freeAsmop (result, NULL, ic, TRUE);
6251   freeAsmop (left, NULL, ic, TRUE);
6252   freeAsmop (right, NULL, ic, TRUE);
6253 }
6254
6255 /*-----------------------------------------------------------------*/
6256 /* genUnpackBits - generates code for unpacking bits               */
6257 /*-----------------------------------------------------------------*/
6258 static void
6259 genUnpackBits (operand * result)
6260 {
6261   int offset = 0;       /* result byte offset */
6262   int rsize;            /* result size */
6263   int rlen = 0;         /* remaining bitfield length */
6264   sym_link *etype;      /* bitfield type information */
6265   int blen;             /* bitfield length */
6266   int bstr;             /* bitfield starting bit within byte */
6267
6268   D(emitcode (";     genUnpackBits",""));
6269
6270   etype = getSpec (operandType (result));
6271   rsize = getSize (operandType (result));
6272   blen = SPEC_BLEN (etype);
6273   bstr = SPEC_BSTR (etype);
6274
6275   /* If the bitfield length is less than a byte */
6276   if (blen < 8)
6277     {
6278       emitcode ("lda", ",x");
6279       hc08_dirtyReg (hc08_reg_a, FALSE);
6280       AccRsh (bstr, FALSE);
6281       emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6282       storeRegToAop (hc08_reg_a, AOP (result), offset++);
6283       goto finish;
6284     }
6285
6286   /* Bit field did not fit in a byte. Copy all
6287      but the partial byte at the end.  */
6288   for (rlen=blen;rlen>=8;rlen-=8)
6289     {
6290       emitcode ("lda", ",x");
6291       hc08_dirtyReg (hc08_reg_a, FALSE);
6292       storeRegToAop (hc08_reg_a, AOP (result), offset++);
6293       if (rlen>8)
6294         emitcode ("aix", "#1");
6295     }
6296
6297   /* Handle the partial byte at the end */
6298   if (rlen)
6299     {
6300       emitcode ("lda", ",x");
6301       emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6302       storeRegToAop (hc08_reg_a, AOP (result), offset++);
6303     }
6304
6305 finish:
6306   if (offset < rsize)
6307     {
6308       rsize -= offset;
6309       while (rsize--)
6310         storeConstToAop (zero, AOP (result), offset++);
6311     }
6312 }
6313
6314
6315 /*-----------------------------------------------------------------*/
6316 /* genDataPointerGet - generates code when ptr offset is known     */
6317 /*-----------------------------------------------------------------*/
6318 static void
6319 genDataPointerGet (operand * left,
6320                    operand * result,
6321                    iCode * ic)
6322 {
6323   int size, offset = 0;
6324   asmop *derefaop;
6325   
6326   D(emitcode (";     genDataPointerGet",""));
6327
6328   aopOp (result, ic, TRUE);
6329   size = AOP_SIZE (result);
6330
6331   derefaop = aopDerefAop (AOP (left));
6332   freeAsmop (left, NULL, ic, TRUE);
6333   derefaop->size = size;
6334   
6335   while (size--)
6336     {
6337       transferAopAop(derefaop, offset, AOP (result), offset);
6338       offset++;
6339     }
6340
6341   freeAsmop (NULL, derefaop, ic, TRUE);
6342   freeAsmop (result, NULL, ic, TRUE);
6343 }
6344
6345 /*-----------------------------------------------------------------*/
6346 /* genNearPointerGet - emitcode for near pointer fetch             */
6347 /*-----------------------------------------------------------------*/
6348 static void
6349 genNearPointerGet (operand * left,
6350                    operand * result,
6351                    iCode * ic,
6352                    iCode * pi)
6353 {
6354   int size, offset;
6355   sym_link *retype = getSpec (operandType (result));
6356
6357   D(emitcode (";     genNearPointerGet",""));
6358
6359   aopOp (left, ic, FALSE);
6360
6361   /* if left is rematerialisable and
6362      result is not bit variable type and
6363      the left is pointer to data space i.e
6364      lower 128 bytes of space */
6365   if ((AOP_TYPE (left) == AOP_IMMD)
6366       || (AOP_TYPE (left) == AOP_LIT) 
6367       /* !IS_BITVAR (retype) */
6368       /* && DCL_TYPE (ltype) == POINTER */ )
6369     {
6370       genDataPointerGet (left, result, ic);
6371       return;
6372     }
6373
6374   /* if the operand is already in hx
6375      then we do nothing else we move the value to hx */
6376   if (AOP_TYPE (left) != AOP_STR)
6377     {
6378       /* if this is remateriazable */
6379       loadRegFromAop (hc08_reg_x, AOP (left), 0);
6380       loadRegFromConst (hc08_reg_h, zero);
6381     }
6382
6383   /* so hx now contains the address */
6384   aopOp (result, ic, FALSE);
6385
6386   /* if bit then unpack */
6387   if (IS_BITVAR (retype))
6388     genUnpackBits (result);
6389   else
6390     {
6391       size = AOP_SIZE (result);
6392       offset = size-1;
6393
6394       while (size--)
6395         {
6396           accopWithMisc ("lda", ",x");
6397           if (size || pi)
6398             {
6399               rmwWithReg ("inc", hc08_reg_x);
6400             }
6401           storeRegToAop (hc08_reg_a, AOP (result), offset--);
6402           hc08_freeReg (hc08_reg_a);
6403         }
6404     }
6405
6406   freeAsmop (left, NULL, ic, TRUE);
6407   freeAsmop (result, NULL, ic, TRUE);
6408   
6409   if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6410     aopOp (IC_RESULT (pi), pi, FALSE);
6411     storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6412     freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6413     pi->generated = 1;
6414   }
6415
6416   hc08_freeReg (hc08_reg_hx);
6417   
6418 }
6419
6420
6421 /*-----------------------------------------------------------------*/
6422 /* genFarPointerGet - get value from far space                     */
6423 /*-----------------------------------------------------------------*/
6424 static void
6425 genFarPointerGet (operand * left,
6426                   operand * result, iCode * ic, iCode * pi)
6427 {
6428   int size, offset;
6429   sym_link *retype = getSpec (operandType (result));
6430
6431   D(emitcode (";     genFarPointerGet",""));
6432
6433   aopOp (left, ic, FALSE);
6434
6435   /* if left is rematerialisable and
6436      result is not bit variable type and
6437      the left is pointer to data space i.e
6438      lower 128 bytes of space */
6439   if (AOP_TYPE (left) == AOP_IMMD &&
6440       !IS_BITVAR (retype)
6441       /* && DCL_TYPE (ltype) == POINTER */ )
6442     {
6443       genDataPointerGet (left, result, ic);
6444       return;
6445     }
6446
6447   /* if the operand is already in hx
6448      then we do nothing else we move the value to hx */
6449   if (AOP_TYPE (left) != AOP_STR)
6450     {
6451       /* if this is remateriazable */
6452       loadRegFromAop (hc08_reg_hx, AOP (left), 0);
6453     }
6454
6455   /* so hx now contains the address */
6456   aopOp (result, ic, FALSE);
6457
6458   /* if bit then unpack */
6459   if (IS_BITVAR (retype))
6460     genUnpackBits (result);
6461   else
6462     {
6463       size = AOP_SIZE (result);
6464       offset = size-1;
6465
6466       while (size--)
6467         {
6468           accopWithMisc ("lda", ",x");
6469           if (size || pi)
6470             {
6471               emitcode ("aix", "#1");
6472               hc08_dirtyReg (hc08_reg_hx, FALSE);
6473             }
6474           storeRegToAop (hc08_reg_a, AOP (result), offset--);
6475           hc08_freeReg (hc08_reg_a);
6476         }
6477     }
6478
6479   freeAsmop (left, NULL, ic, TRUE);
6480   freeAsmop (result, NULL, ic, TRUE);
6481   
6482   if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6483     aopOp (IC_RESULT (pi), pi, FALSE);
6484     storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6485     freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6486     pi->generated = 1;
6487   }
6488
6489   hc08_freeReg (hc08_reg_hx);
6490   
6491 }
6492
6493
6494
6495 /*-----------------------------------------------------------------*/
6496 /* genPointerGet - generate code for pointer get                   */
6497 /*-----------------------------------------------------------------*/
6498 static void
6499 genPointerGet (iCode * ic, iCode *pi)
6500 {
6501   operand *left, *result;
6502   sym_link *type, *etype;
6503   int p_type;
6504
6505   D(emitcode (";     genPointerGet",""));
6506
6507   left = IC_LEFT (ic);
6508   result = IC_RESULT (ic);
6509
6510   /* depending on the type of pointer we need to
6511      move it to the correct pointer register */
6512   type = operandType (left);
6513   etype = getSpec (type);
6514   /* if left is of type of pointer then it is simple */
6515   if (IS_PTR (type) && !IS_FUNC (type->next))
6516     p_type = DCL_TYPE (type);
6517   else
6518     {
6519       /* we have to go by the storage class */
6520       p_type = PTR_TYPE (SPEC_OCLS (etype));
6521     }
6522
6523   /* special case when cast remat */
6524   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
6525       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
6526           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
6527           type = operandType (left);
6528           p_type = DCL_TYPE (type);
6529   }
6530   /* now that we have the pointer type we assign
6531      the pointer values */
6532   switch (p_type)
6533     {
6534
6535     case POINTER:
6536     case IPOINTER:
6537 #if 0
6538       genNearPointerGet (left, result, ic, pi);
6539       break;
6540 #endif
6541     case GPOINTER:
6542     case CPOINTER:
6543     case FPOINTER:
6544       genFarPointerGet (left, result, ic, pi);
6545       break;
6546
6547     }
6548
6549 }
6550
6551 /*-----------------------------------------------------------------*/
6552 /* genPackBits - generates code for packed bit storage             */
6553 /*-----------------------------------------------------------------*/
6554 static void
6555 genPackBits (sym_link * etype,
6556              operand * right)
6557 {
6558   int offset = 0;       /* source byte offset */
6559   int rlen = 0;         /* remaining bitfield length */
6560   int blen;             /* bitfield length */
6561   int bstr;             /* bitfield starting bit within byte */
6562   int litval;           /* source literal value (if AOP_LIT) */
6563   unsigned char mask;   /* bitmask within current byte */
6564
6565   D(emitcode (";     genPackBits",""));
6566
6567   blen = SPEC_BLEN (etype);
6568   bstr = SPEC_BSTR (etype);
6569   
6570   /* If the bitfield length is less than a byte */
6571   if (blen < 8)
6572     {
6573       mask = ((unsigned char) (0xFF << (blen + bstr)) |
6574               (unsigned char) (0xFF >> (8 - bstr)));
6575
6576       if (AOP_TYPE (right) == AOP_LIT)
6577         {
6578           /* Case with a bitfield length <8 and literal source
6579           */
6580           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6581           litval <<= bstr;
6582           litval &= (~mask) & 0xff;
6583
6584           emitcode ("lda", ",x");
6585           if ((mask|litval)!=0xff)
6586             emitcode ("and","#0x%02x", mask);
6587           if (litval)
6588             emitcode ("ora","#0x%02x", litval);
6589           hc08_dirtyReg (hc08_reg_a, FALSE);
6590           emitcode ("sta", ",x");
6591           
6592           hc08_freeReg (hc08_reg_a);
6593           return;
6594         }
6595           
6596       /* Case with a bitfield length < 8 and arbitrary source
6597       */
6598       loadRegFromAop (hc08_reg_a, AOP (right), 0);
6599       /* shift and mask source value */
6600       AccLsh (bstr);
6601       emitcode ("and", "#0x%02x", (~mask) & 0xff);
6602       hc08_dirtyReg (hc08_reg_a, FALSE);
6603       pushReg (hc08_reg_a, TRUE);
6604
6605       emitcode ("lda", ",x");
6606       emitcode ("and", "#0x%02x", mask);
6607       emitcode ("ora", "1,s");
6608       emitcode ("sta", ",x");
6609       pullReg (hc08_reg_a);
6610      
6611       hc08_freeReg (hc08_reg_a);
6612       return;
6613     }
6614
6615   /* Bit length is greater than 7 bits. In this case, copy  */
6616   /* all except the partial byte at the end                 */
6617   for (rlen=blen;rlen>=8;rlen-=8)
6618     {
6619       if (AOP (right)->type == AOP_DIR)
6620         {
6621           emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
6622         }
6623       else
6624         {
6625           loadRegFromAop (hc08_reg_a, AOP (right), offset);
6626           emitcode ("sta", "%d,x", offset);
6627         }
6628       offset++;
6629     }
6630
6631   /* If there was a partial byte at the end */
6632   if (rlen)
6633     {
6634       mask = (((unsigned char) -1 << rlen) & 0xff);
6635       
6636       if (AOP_TYPE (right) == AOP_LIT)
6637         {
6638           /* Case with partial byte and literal source
6639           */
6640           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6641           litval >>= (blen-rlen);
6642           litval &= (~mask) & 0xff;
6643           emitcode ("lda", "%d,x", offset);
6644           hc08_dirtyReg (hc08_reg_a, FALSE);
6645           if ((mask|litval)!=0xff)
6646             emitcode ("and","#0x%02x", mask);
6647           if (litval)
6648             emitcode ("ora","#0x%02x", litval);
6649           emitcode ("sta", "%d,x", offset);
6650           hc08_dirtyReg (hc08_reg_a, FALSE);
6651           hc08_freeReg (hc08_reg_a);
6652           return;
6653         }
6654       
6655       /* Case with partial byte and arbitrary source
6656       */
6657       loadRegFromAop (hc08_reg_a, AOP (right), offset++);
6658       emitcode ("and", "#0x%02x", (~mask) & 0xff);
6659       hc08_dirtyReg (hc08_reg_a, FALSE);
6660       pushReg (hc08_reg_a, TRUE);
6661
6662       emitcode ("lda", ",x");
6663       emitcode ("and", "#0x%02x", mask);
6664       emitcode ("ora", "1,s");
6665       emitcode ("sta", ",x");
6666     }
6667
6668   hc08_freeReg (hc08_reg_a);
6669 }
6670
6671 /*-----------------------------------------------------------------*/
6672 /* genDataPointerSet - remat pointer to data space                 */
6673 /*-----------------------------------------------------------------*/
6674 static void
6675 genDataPointerSet (operand * right,
6676                    operand * result,
6677                    iCode * ic)
6678 {
6679   int size, offset = 0;
6680   asmop *derefaop;
6681
6682   D(emitcode (";     genDataPointerSet",""));
6683
6684   aopOp (right, ic, FALSE);
6685   size = AOP_SIZE (right);
6686
6687   derefaop = aopDerefAop (AOP (result));
6688   freeAsmop (result, NULL, ic, TRUE);
6689   derefaop->size = size;
6690   
6691   while (size--)
6692     {
6693       transferAopAop (AOP (right), offset, derefaop, offset);
6694       offset++;
6695     }
6696
6697   freeAsmop (right, NULL, ic, TRUE);
6698   freeAsmop (NULL, derefaop, ic, TRUE);
6699 }
6700
6701 /*-----------------------------------------------------------------*/
6702 /* genNearPointerSet - emitcode for near pointer put                */
6703 /*-----------------------------------------------------------------*/
6704 static void
6705 genNearPointerSet (operand * right,
6706                    operand * result,
6707                    iCode * ic,
6708                    iCode * pi)
6709 {
6710   int size, offset;
6711   sym_link *retype = getSpec (operandType (right));
6712   sym_link *letype = getSpec (operandType (result));
6713
6714   D(emitcode (";     genNearPointerSet",""));
6715
6716   aopOp (result, ic, FALSE);
6717
6718   /* if the result is rematerializable &
6719      in data space & not a bit variable */
6720   if (AOP_TYPE (result) == AOP_IMMD &&
6721       /* DCL_TYPE (ptype) == POINTER && */
6722       !IS_BITVAR (retype) &&
6723       !IS_BITVAR (letype))
6724     {
6725       genDataPointerSet (right, result, ic);
6726       return;
6727     }
6728
6729   /* if the operand is already in hx
6730      then we do nothing else we move the value to hx */
6731   if (AOP_TYPE (result) != AOP_STR)
6732     {
6733       loadRegFromAop (hc08_reg_x, AOP (result), 0);
6734       loadRegFromConst (hc08_reg_h, zero);
6735     }
6736   /* so hx now contains the address */
6737   aopOp (right, ic, FALSE);
6738
6739   /* if bit then unpack */
6740   if (IS_BITVAR (retype) || IS_BITVAR (letype))
6741     genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6742   else
6743     {
6744       size = AOP_SIZE (right);
6745       offset = size-1;
6746
6747       while (size--)
6748         {
6749           loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6750           accopWithMisc ("sta", ",x");
6751           if (size || pi)
6752             {
6753               rmwWithReg ("inc", hc08_reg_x);
6754             }
6755           hc08_freeReg (hc08_reg_a);
6756         }
6757     }
6758
6759   freeAsmop (result, NULL, ic, TRUE);
6760   freeAsmop (right, NULL, ic, TRUE);
6761
6762   if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6763     aopOp (IC_RESULT (pi), pi, FALSE);
6764     storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6765     freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6766     pi->generated=1;
6767   }
6768
6769   hc08_freeReg (hc08_reg_hx);
6770   
6771 }
6772
6773
6774 /*-----------------------------------------------------------------*/
6775 /* genFarPointerSet - set value from far space                     */
6776 /*-----------------------------------------------------------------*/
6777 static void
6778 genFarPointerSet (operand * right,
6779                   operand * result, iCode * ic, iCode * pi)
6780 {
6781   int size, offset;
6782   sym_link *retype = getSpec (operandType (right));
6783   sym_link *letype = getSpec (operandType (result));
6784
6785   D(emitcode (";     genFarPointerSet",""));
6786
6787   aopOp (result, ic, FALSE);
6788
6789   /* if the result is rematerializable &
6790      in data space & not a bit variable */
6791   if (AOP_TYPE (result) == AOP_IMMD &&
6792       /* DCL_TYPE (ptype) == POINTER && */
6793       !IS_BITVAR (retype) &&
6794       !IS_BITVAR (letype))
6795     {
6796       genDataPointerSet (right, result, ic);
6797       return;
6798     }
6799
6800   /* if the operand is already in hx
6801      then we do nothing else we move the value to hx */
6802   if (AOP_TYPE (result) != AOP_STR)
6803     {
6804       loadRegFromAop (hc08_reg_hx, AOP (result), 0);
6805     }
6806   /* so hx now contains the address */
6807   aopOp (right, ic, FALSE);
6808
6809   /* if bit then unpack */
6810   if (IS_BITVAR (retype) || IS_BITVAR (letype))
6811     genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6812   else
6813     {
6814       size = AOP_SIZE (right);
6815       offset = size-1;
6816
6817       while (size--)
6818         {
6819           loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6820           accopWithMisc ("sta", ",x");
6821           if (size || pi)
6822             {
6823               emitcode ("aix", "#1");
6824             }
6825           hc08_freeReg (hc08_reg_a);
6826         }
6827     }
6828
6829   freeAsmop (result, NULL, ic, TRUE);
6830   freeAsmop (right, NULL, ic, TRUE);
6831
6832   if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD  */) {
6833     aopOp (IC_RESULT (pi), pi, FALSE);
6834     storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6835     freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6836     pi->generated=1;
6837   }
6838
6839   hc08_freeReg (hc08_reg_hx);
6840   
6841
6842 }
6843
6844
6845 /*-----------------------------------------------------------------*/
6846 /* genPointerSet - stores the value into a pointer location        */
6847 /*-----------------------------------------------------------------*/
6848 static void
6849 genPointerSet (iCode * ic, iCode *pi)
6850 {
6851   operand *right, *result;
6852   sym_link *type, *etype;
6853   int p_type;
6854
6855   D(emitcode (";     genPointerSet",""));
6856
6857   right = IC_RIGHT (ic);
6858   result = IC_RESULT (ic);
6859
6860   /* depending on the type of pointer we need to
6861      move it to the correct pointer register */
6862   type = operandType (result);
6863   etype = getSpec (type);
6864   /* if left is of type of pointer then it is simple */
6865   if (IS_PTR (type) && !IS_FUNC (type->next))
6866     {
6867       p_type = DCL_TYPE (type);
6868     }
6869   else
6870     {
6871       /* we have to go by the storage class */
6872       p_type = PTR_TYPE (SPEC_OCLS (etype));
6873     }
6874
6875   /* special case when cast remat */
6876   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
6877       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
6878           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
6879           type = operandType (result);
6880           p_type = DCL_TYPE (type);
6881   }
6882   /* now that we have the pointer type we assign
6883      the pointer values */
6884   switch (p_type)
6885     {
6886
6887     case POINTER:
6888     case IPOINTER:
6889 #if 0
6890       genNearPointerSet (right, result, ic, pi);
6891       break;
6892 #endif
6893
6894     case GPOINTER:
6895     case FPOINTER:
6896       genFarPointerSet (right, result, ic, pi);
6897       break;
6898
6899     default:
6900       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
6901               "genPointerSet: illegal pointer type");
6902     }
6903
6904 }
6905
6906 /*-----------------------------------------------------------------*/
6907 /* genIfx - generate code for Ifx statement                        */
6908 /*-----------------------------------------------------------------*/
6909 static void
6910 genIfx (iCode * ic, iCode * popIc)
6911 {
6912   operand *cond = IC_COND (ic);
6913   int isbit = 0;
6914
6915   D(emitcode (";     genIfx",""));
6916
6917   aopOp (cond, ic, FALSE);
6918
6919   /* get the value into acc */
6920   if (AOP_TYPE (cond) != AOP_CRY)
6921     asmopToBool (AOP (cond), FALSE);
6922   else
6923     isbit = 1;
6924   /* the result is now in the accumulator */
6925   freeAsmop (cond, NULL, ic, TRUE);
6926
6927   /* if there was something to be popped then do it */
6928   if (popIc)
6929     genIpop (popIc);
6930
6931   /* if the condition is  a bit variable */
6932   if (isbit && IS_ITEMP (cond) &&
6933       SPIL_LOC (cond))
6934     genIfxJump (ic, SPIL_LOC (cond)->rname);
6935   else if (isbit && !IS_ITEMP (cond))
6936     genIfxJump (ic, OP_SYMBOL (cond)->rname);
6937   else
6938     genIfxJump (ic, "a");
6939
6940   ic->generated = 1;
6941 }
6942
6943 /*-----------------------------------------------------------------*/
6944 /* genAddrOf - generates code for address of                       */
6945 /*-----------------------------------------------------------------*/
6946 static void
6947 genAddrOf (iCode * ic)
6948 {
6949   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
6950   int size, offset;
6951
6952   D(emitcode (";     genAddrOf",""));
6953
6954   aopOp (IC_RESULT (ic), ic, FALSE);
6955
6956   /* if the operand is on the stack then we
6957      need to get the stack offset of this
6958      variable */
6959   if (sym->onStack)
6960     {
6961       /* if it has an offset then we need to compute
6962          it */
6963       hc08_useReg (hc08_reg_hx);
6964       emitcode ("tsx", "");
6965       emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
6966       storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
6967       hc08_freeReg (hc08_reg_hx);
6968
6969       goto release;
6970     }
6971
6972   /* object not on stack then we need the name */
6973   size = AOP_SIZE (IC_RESULT (ic));
6974   offset = 0;
6975
6976   while (size--)
6977     {
6978       char s[SDCC_NAME_MAX+10];
6979       switch (offset) {
6980         case 0:
6981           sprintf (s, "#%s", sym->rname);
6982           break;
6983         case 1:
6984           sprintf (s, "#>%s", sym->rname);
6985           break;
6986         default:
6987           sprintf (s, "#(%s >> %d)",
6988                    sym->rname,
6989                    offset * 8);
6990       }
6991       storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
6992     }
6993
6994 release:
6995   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
6996
6997 }
6998
6999 /*-----------------------------------------------------------------*/
7000 /* genAssign - generate code for assignment                        */
7001 /*-----------------------------------------------------------------*/
7002 static void
7003 genAssign (iCode * ic)
7004 {
7005   operand *result, *right;
7006   int size, offset;
7007 //  unsigned long lit = 0L;
7008
7009   D(emitcode(";     genAssign",""));
7010
7011   result = IC_RESULT (ic);
7012   right = IC_RIGHT (ic);
7013
7014   /* if they are the same */
7015   if (operandsEqu (result, right)) {
7016     return;
7017   }
7018
7019   aopOp (right, ic, FALSE);
7020   aopOp (result, ic, TRUE);
7021
7022   /* if they are the same registers */
7023   if (sameRegs (AOP (right), AOP (result)))
7024     goto release;
7025
7026   if ((AOP_TYPE (right) == AOP_LIT)
7027       && (IS_AOP_HX(AOP(result))))
7028     {
7029       loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7030       goto release;
7031     }
7032     
7033   /* general case */
7034   size = AOP_SIZE (result);
7035   offset = 0;
7036
7037   while (size--)
7038     {
7039       transferAopAop (AOP (right), offset, AOP (result), offset);
7040       offset++;
7041     }
7042
7043 release:
7044   freeAsmop (right, NULL, ic, TRUE);
7045   freeAsmop (result, NULL, ic, TRUE);
7046 }
7047
7048 /*-----------------------------------------------------------------*/
7049 /* genJumpTab - genrates code for jump table                       */
7050 /*-----------------------------------------------------------------*/
7051 static void
7052 genJumpTab (iCode * ic)
7053 {
7054   symbol *jtab;
7055 //  char *l;
7056
7057   D(emitcode (";     genJumpTab",""));
7058
7059   aopOp (IC_JTCOND (ic), ic, FALSE);
7060   /* get the condition into accumulator */
7061   loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7062   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7063   /* multiply by three */
7064   pushReg (hc08_reg_a, FALSE);
7065   emitcode ("lsla", "");
7066   emitcode ("add","1,s");
7067   transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7068   loadRegFromConst (hc08_reg_h, zero);
7069
7070   jtab = newiTempLabel (NULL);
7071   emitcode ("jmp", "%05d$,x", jtab->key + 100);
7072   emitcode ("", "%05d$:", jtab->key + 100);
7073   /* now generate the jump labels */
7074   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7075        jtab = setNextItem (IC_JTLABELS (ic)))
7076     emitcode ("jmp", "%05d$", jtab->key + 100);
7077
7078   hc08_dirtyReg (hc08_reg_a, TRUE);
7079   hc08_dirtyReg (hc08_reg_hx, TRUE);
7080 }
7081
7082 /*-----------------------------------------------------------------*/
7083 /* genCast - gen code for casting                                  */
7084 /*-----------------------------------------------------------------*/
7085 static void
7086 genCast (iCode * ic)
7087 {
7088   operand *result = IC_RESULT (ic);
7089   sym_link *ctype = operandType (IC_LEFT (ic));
7090   sym_link *rtype = operandType (IC_RIGHT (ic));
7091   operand *right = IC_RIGHT (ic);
7092   int size, offset;
7093
7094   D(emitcode(";     genCast",""));
7095
7096   /* if they are equivalent then do nothing */
7097   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7098     return;
7099
7100   aopOp (right, ic, FALSE);
7101   aopOp (result, ic, FALSE);
7102
7103
7104   /* if they are the same size : or less */
7105   if (AOP_SIZE (result) <= AOP_SIZE (right))
7106     {
7107
7108       /* if they are in the same place */
7109       #if 0
7110       if (sameRegs (AOP (right), AOP (result)))
7111         goto release;
7112       #endif
7113
7114       /* if they in different places then copy */
7115       size = AOP_SIZE (result);
7116       offset = 0;
7117       while (size--)
7118         {
7119           transferAopAop(AOP (right), offset, AOP (result), offset);
7120           offset++;
7121         }
7122       goto release;
7123     }
7124
7125
7126   /* if the result is of type pointer */
7127   if (IS_PTR (ctype))
7128     {
7129
7130       int p_type;
7131       sym_link *type = operandType (right);
7132       sym_link *etype = getSpec (type);
7133
7134       /* pointer to generic pointer */
7135       if (IS_GENPTR (ctype))
7136         {
7137           if (IS_PTR (type))
7138             p_type = DCL_TYPE (type);
7139           else
7140             {
7141               if (SPEC_SCLS(etype)==S_REGISTER) {
7142                 // let's assume it is a generic pointer
7143                 p_type=GPOINTER;
7144               } else {
7145                 /* we have to go by the storage class */
7146                 p_type = PTR_TYPE (SPEC_OCLS (etype));
7147               }
7148             }
7149
7150           /* the first two bytes are known */
7151           size = GPTRSIZE - 1;
7152           offset = 0;
7153           while (size--)
7154             {
7155               transferAopAop(AOP (right), offset, AOP (result), offset);
7156               offset++;
7157             }
7158           /* the last byte depending on type */
7159 #if 0
7160             {
7161                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7162                 char gpValStr[10];
7163             
7164                 if (gpVal == -1)
7165                 {
7166                     // pointerTypeToGPByte will have bitched.
7167                     exit(1);
7168                 }
7169             
7170                 sprintf(gpValStr, "#0x%d", gpVal);
7171                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7172             }       
7173 #endif
7174           goto release;
7175         }
7176
7177       /* just copy the pointers */
7178       size = AOP_SIZE (result);
7179       offset = 0;
7180       while (size--)
7181         {
7182           transferAopAop(AOP (right), offset, AOP (result), offset);
7183           offset++;
7184         }
7185       goto release;
7186     }
7187
7188   /* so we now know that the size of destination is greater
7189      than the size of the source */
7190   /* we move to result for the size of source */
7191   size = AOP_SIZE (right);
7192   offset = 0;
7193   while (size--)
7194     {
7195       transferAopAop(AOP (right), offset, AOP (result), offset);
7196       offset++;
7197     }
7198
7199   /* now depending on the sign of the source && destination */
7200   size = AOP_SIZE (result) - AOP_SIZE (right);
7201   /* if unsigned or not an integral type */
7202   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7203     {
7204       while (size--)
7205         storeConstToAop (zero, AOP (result), offset++); 
7206     }
7207   else
7208     {
7209       /* we need to extend the sign :{ */
7210       loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7211       accopWithMisc ("rola", "");
7212       accopWithMisc ("clra", "");
7213       accopWithMisc ("sbc", zero);
7214       while (size--)
7215         storeRegToAop (hc08_reg_a, AOP (result), offset++);
7216     }
7217
7218   /* we are done hurray !!!! */
7219
7220 release:
7221   freeAsmop (right, NULL, ic, TRUE);
7222   freeAsmop (result, NULL, ic, TRUE);
7223
7224 }
7225
7226 /*-----------------------------------------------------------------*/
7227 /* genDjnz - generate decrement & jump if not zero instrucion      */
7228 /*-----------------------------------------------------------------*/
7229 static int
7230 genDjnz (iCode * ic, iCode * ifx)
7231 {
7232   symbol *lbl, *lbl1;
7233   if (!ifx)
7234     return 0;
7235
7236   D(emitcode (";     genDjnz",""));
7237
7238   /* if the if condition has a false label
7239      then we cannot save */
7240   if (IC_FALSE (ifx))
7241     return 0;
7242
7243   /* if the minus is not of the form
7244      a = a - 1 */
7245   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7246       !IS_OP_LITERAL (IC_RIGHT (ic)))
7247     return 0;
7248
7249   if (operandLitValue (IC_RIGHT (ic)) != 1)
7250     return 0;
7251
7252   /* if the size of this greater than one then no
7253      saving */
7254 //  if (getSize (operandType (IC_RESULT (ic))) > 1)
7255 //    return 0;
7256   aopOp (IC_RESULT (ic), ic, FALSE);
7257   if (AOP_SIZE (IC_RESULT (ic))>1)
7258     {
7259       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7260       return 0;
7261     }
7262
7263   /* otherwise we can save BIG */
7264   lbl = newiTempLabel (NULL);
7265   lbl1 = newiTempLabel (NULL);
7266
7267
7268   emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7269                 lbl->key + 100);
7270  
7271   emitBranch ("bra", lbl1);
7272   emitLabel (lbl);
7273   emitBranch ("jmp", IC_TRUE (ifx));
7274   emitLabel (lbl1);
7275
7276   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7277   ifx->generated = 1;
7278   return 1;
7279 }
7280
7281 /*-----------------------------------------------------------------*/
7282 /* genReceive - generate code for a receive iCode                  */
7283 /*-----------------------------------------------------------------*/
7284 static void
7285 genReceive (iCode * ic)
7286 {
7287   int size;
7288   int offset;
7289   D(emitcode (";     genReceive",""));
7290
7291   aopOp (IC_RESULT (ic), ic, FALSE);
7292   size = AOP_SIZE (IC_RESULT (ic));
7293   offset = 0;
7294   
7295   if (ic->argreg) {
7296       while (size--) {
7297           transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7298                           AOP (IC_RESULT (ic)), offset);
7299           if (hc08_aop_pass[offset]->type == AOP_REG)
7300             hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7301           offset++;
7302       }
7303   }       
7304
7305   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7306 }
7307
7308 /*-----------------------------------------------------------------*/
7309 /* genhc08Code - generate code for HC08 based controllers          */
7310 /*-----------------------------------------------------------------*/
7311 void
7312 genhc08Code (iCode * lic)
7313 {
7314   iCode *ic;
7315   int cln = 0;
7316
7317   lineHead = lineCurr = NULL;
7318
7319   /* print the allocation information */
7320   if (allocInfo && currFunc)
7321     printAllocInfo (currFunc, codeOutFile);
7322   /* if debug information required */
7323   if (options.debug && currFunc)
7324     {
7325       debugFile->writeFunction(currFunc);
7326       _G.debugLine = 1;
7327       if (IS_STATIC (currFunc->etype))
7328         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7329       else
7330         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7331       _G.debugLine = 0;
7332     }
7333   /* stack pointer name */
7334   if (options.useXstack)
7335     spname = "_spx";
7336   else
7337     spname = "sp";
7338
7339   hc08_aop_pass[0] = newAsmop (AOP_REG);
7340   hc08_aop_pass[0]->size=1;
7341   hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7342   hc08_aop_pass[1] = newAsmop (AOP_REG);
7343   hc08_aop_pass[1]->size=1;
7344   hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
7345   hc08_aop_pass[2] = newAsmop (AOP_DIR);
7346   hc08_aop_pass[2]->size=1;
7347   hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
7348   hc08_aop_pass[3] = newAsmop (AOP_DIR);
7349   hc08_aop_pass[3]->size=1;
7350   hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
7351
7352   for (ic = lic; ic; ic = ic->next)
7353     {
7354
7355       if (ic->lineno && cln != ic->lineno)
7356         {
7357           if (options.debug)
7358             {
7359               _G.debugLine = 1;
7360               emitcode ("", "C$%s$%d$%d$%d ==.",
7361                         FileBaseName (ic->filename), ic->lineno,
7362                         ic->level, ic->block);
7363               _G.debugLine = 0;
7364             }
7365           if (!options.noCcodeInAsm) {
7366             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno, 
7367                       printCLine(ic->filename, ic->lineno));
7368           }
7369           cln = ic->lineno;
7370         }
7371       if (options.iCodeInAsm) {
7372         char regsInUse[80];
7373         int i;
7374
7375         for (i=0; i<6; i++) {
7376           sprintf (&regsInUse[i],
7377                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); 
7378         }
7379         regsInUse[i]=0;
7380         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
7381       }
7382       /* if the result is marked as
7383          spilt and rematerializable or code for
7384          this has already been generated then
7385          do nothing */
7386       if (resultRemat (ic) || ic->generated)
7387         continue;
7388
7389       {
7390         int i;
7391         regs *reg;
7392         symbol *sym;
7393         
7394         for (i=A_IDX;i<=XA_IDX;i++)
7395           {
7396             reg = hc08_regWithIdx(i);
7397             if (reg->aop)
7398               emitcode("","; %s = %s offset %d", reg->name,
7399                        aopName(reg->aop), reg->aopofs);
7400             reg->isFree = TRUE;
7401           }
7402         if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
7403           {
7404             sym = OP_SYMBOL (IC_LEFT (ic));
7405             if (sym->accuse == ACCUSE_HX)
7406               {
7407                 hc08_reg_h->isFree = FALSE;
7408                 hc08_reg_x->isFree = FALSE;
7409               }
7410             else if (sym->accuse == ACCUSE_XA)
7411               {
7412                 hc08_reg_a->isFree = FALSE;
7413                 if (sym->nRegs>1)
7414                   hc08_reg_x->isFree = FALSE;
7415               }
7416           }
7417         if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
7418           {
7419             sym = OP_SYMBOL (IC_RIGHT (ic));
7420             if (sym->accuse == ACCUSE_HX)
7421               {
7422                 hc08_reg_h->isFree = FALSE;
7423                 hc08_reg_x->isFree = FALSE;
7424               }
7425             else if (sym->accuse == ACCUSE_XA)
7426               {
7427                 hc08_reg_a->isFree = FALSE;
7428                 if (sym->nRegs>1)
7429                   hc08_reg_x->isFree = FALSE;
7430               }
7431           }
7432       }
7433       
7434       /* depending on the operation */
7435       switch (ic->op)
7436         {
7437         case '!':
7438           genNot (ic);
7439           break;
7440
7441         case '~':
7442           genCpl (ic);
7443           break;
7444
7445         case UNARYMINUS:
7446           genUminus (ic);
7447           break;
7448
7449         case IPUSH:
7450           genIpush (ic);
7451           break;
7452
7453         case IPOP:
7454           /* IPOP happens only when trying to restore a
7455              spilt live range, if there is an ifx statement
7456              following this pop then the if statement might
7457              be using some of the registers being popped which
7458              would destory the contents of the register so
7459              we need to check for this condition and handle it */
7460           if (ic->next &&
7461               ic->next->op == IFX &&
7462               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7463             genIfx (ic->next, ic);
7464           else
7465             genIpop (ic);
7466           break;
7467
7468         case CALL:
7469           genCall (ic);
7470           break;
7471
7472         case PCALL:
7473           genPcall (ic);
7474           break;
7475
7476         case FUNCTION:
7477           genFunction (ic);
7478           break;
7479
7480         case ENDFUNCTION:
7481           genEndFunction (ic);
7482           break;
7483
7484         case RETURN:
7485           genRet (ic);
7486           break;
7487
7488         case LABEL:
7489           genLabel (ic);
7490           break;
7491
7492         case GOTO:
7493           genGoto (ic);
7494           break;
7495
7496         case '+':
7497           if (!genPointerGetSetOfs (ic))
7498             genPlus (ic);
7499           break;
7500
7501         case '-':
7502           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7503             genMinus (ic);
7504           break;
7505
7506         case '*':
7507           genMult (ic);
7508           break;
7509
7510         case '/':
7511           genDiv (ic);
7512           break;
7513
7514         case '%':
7515           genMod (ic);
7516           break;
7517
7518         case '>':
7519           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7520           break;
7521
7522         case '<':
7523           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7524           break;
7525
7526         case LE_OP:
7527         case GE_OP:
7528         case NE_OP:
7529
7530           /* note these two are xlated by algebraic equivalence
7531              during parsing SDCC.y */
7532           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7533                   "got '>=' or '<=' shouldn't have come here");
7534           break;
7535
7536         case EQ_OP:
7537           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7538           break;
7539
7540         case AND_OP:
7541           genAndOp (ic);
7542           break;
7543
7544         case OR_OP:
7545           genOrOp (ic);
7546           break;
7547
7548         case '^':
7549           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7550           break;
7551
7552         case '|':
7553           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7554           break;
7555
7556         case BITWISEAND:
7557           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7558           break;
7559
7560         case INLINEASM:
7561           genInline (ic);
7562           break;
7563
7564         case RRC:
7565           genRRC (ic);
7566           break;
7567
7568         case RLC:
7569           genRLC (ic);
7570           break;
7571
7572         case GETHBIT:
7573           genGetHbit (ic);
7574           break;
7575
7576         case LEFT_OP:
7577           genLeftShift (ic);
7578           break;
7579
7580         case RIGHT_OP:
7581           genRightShift (ic);
7582           break;
7583
7584         case GET_VALUE_AT_ADDRESS:
7585           genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
7586           break;
7587
7588         case '=':
7589           if (POINTER_SET (ic))
7590             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
7591           else
7592             genAssign (ic);
7593           break;
7594
7595         case IFX:
7596           genIfx (ic, NULL);
7597           break;
7598
7599         case ADDRESS_OF:
7600           genAddrOf (ic);
7601           break;
7602
7603         case JUMPTABLE:
7604           genJumpTab (ic);
7605           break;
7606
7607         case CAST:
7608           genCast (ic);
7609           break;
7610
7611         case RECEIVE:
7612           genReceive (ic);
7613           break;
7614
7615         case SEND:
7616           addSet (&_G.sendSet, ic);
7617           break;
7618
7619         default:
7620           ic = ic;
7621         }
7622
7623       if (!hc08_reg_a->isFree)
7624         emitcode("","; forgot to free a");
7625       if (!hc08_reg_x->isFree)
7626         emitcode("","; forgot to free x");
7627       if (!hc08_reg_h->isFree)
7628         emitcode("","; forgot to free h");
7629       if (!hc08_reg_hx->isFree)
7630         emitcode("","; forgot to free hx");
7631       if (!hc08_reg_xa->isFree)
7632         emitcode("","; forgot to free xa");
7633     }
7634
7635
7636   /* now we are ready to call the
7637      peep hole optimizer */
7638   if (!options.nopeep)
7639     peepHole (&lineHead);
7640
7641   /* now do the actual printing */
7642   printLine (lineHead, codeOutFile);
7643   return;
7644 }