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