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