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