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