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