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