* src/hc08/gen.c: fixed MSVC warning C4146: unary minus operator applied to
[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) do if (options.verboseAsm) {x;} while(0)
32 /* Use the DD macro for detailed debugging messages */
33 #define DD(x)
34 //#define DD(x) x
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include "SDCCglobl.h"
41 #include "newalloc.h"
42
43 #include "common.h"
44 #include "SDCCpeeph.h"
45 #include "ralloc.h"
46 #include "gen.h"
47
48 char *aopLiteral (value * val, int offset);
49 char *aopLiteralLong (value * val, int offset, int size);
50 extern int allocInfo;
51 static int pushReg (regs *reg, bool freereg);
52 static void pullReg (regs *reg);
53 static void transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs);
54
55 static char *zero = "#0x00";
56 static char *one = "#0x01";
57 static char *spname;
58
59 char *fReturnhc08[] =
60 {"a", "x", "_ret2", "_ret3"};
61 unsigned fReturnSizeHC08 = 4;   /* shared with ralloc.c */
62 char **fReturn2 = fReturnhc08;
63
64
65 static struct
66   {
67     short hxPushed;
68     short iyPushed;
69     short accInUse;
70     short inLine;
71     short debugLine;
72     short nRegsSaved;
73     int stackOfs;
74     int stackPushes;
75     short regsinuse;
76     set *sendSet;
77     iCode *current_iCode;
78   }
79 _G;
80
81 static asmop *hc08_aop_pass[4];
82
83 extern int hc08_ptrRegReq;
84 extern int hc08_nRegs;
85 extern struct dbuf_s *codeOutBuf;
86 //static void saveRBank (int, iCode *, bool);
87 static bool operandsEqu (operand * op1, operand * op2);
88 static void loadRegFromConst (regs *reg, char *c);
89 static char *aopName (asmop *aop);
90 static asmop * newAsmop (short type);
91 static char * aopAdrStr (asmop * aop, int loffset, bool bit16);
92 #define RESULTONSTACK(x) \
93                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
94                          IC_RESULT(x)->aop->type == AOP_STK )
95
96 #define IS_AOP_HX(x) \
97         (((x)->type == AOP_REG) \
98          && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
99          && ((x)->aopu.aop_reg[1] == hc08_reg_h) )
100
101 #define IS_AOP_XA(x) \
102         (((x)->type == AOP_REG) \
103          && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
104          && ((x)->aopu.aop_reg[1] == hc08_reg_x) )
105
106 #define IS_AOP_A(x) \
107         (((x)->type == AOP_REG) \
108          && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
109          && ((x)->size == 1) )
110
111 #define IS_AOP_X(x) \
112         (((x)->type == AOP_REG) \
113          && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
114          && ((x)->size == 1) )
115
116 #define IS_AOP_H(x) \
117         (((x)->type == AOP_REG) \
118          && ((x)->aopu.aop_reg[0] == hc08_reg_h) \
119          && ((x)->size == 1) )
120          
121 #define CLRC    emitcode("clc","")
122
123 static lineNode *lineHead = NULL;
124 static lineNode *lineCurr = NULL;
125
126 #if 0
127 static unsigned char SLMask[] =
128 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
129  0xE0, 0xC0, 0x80, 0x00};
130 static unsigned char SRMask[] =
131 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
132  0x07, 0x03, 0x01, 0x00};
133 #endif
134
135 #define LSB     0
136 #define MSB16   1
137 #define MSB24   2
138 #define MSB32   3
139
140 #define AOP(op) op->aop
141 #define AOP_TYPE(op) AOP(op)->type
142 #define AOP_SIZE(op) AOP(op)->size
143 #define AOP_OP(aop) aop->op
144
145
146 /*-----------------------------------------------------------------*/
147 /* emitcode - writes the code into a file : for now it is simple    */
148 /*-----------------------------------------------------------------*/
149 static void
150 emitcode (char *inst, char *fmt,...)
151 {
152   va_list ap;
153   char lb[INITIAL_INLINEASM];
154   char *lbp = lb;
155
156   va_start (ap, fmt);
157
158   if (inst && *inst)
159     {
160       if (fmt && *fmt)
161         sprintf (lb, "%s\t", inst);
162       else
163         sprintf (lb, "%s", inst);
164       vsprintf (lb + (strlen (lb)), fmt, ap);
165     }
166   else
167     vsprintf (lb, fmt, ap);
168
169   while (isspace ((unsigned char)*lbp))
170     lbp++;
171
172   if (lbp && *lbp)
173     lineCurr = (lineCurr ?
174                 connectLine (lineCurr, newLineNode (lb)) :
175                 (lineHead = newLineNode (lb)));
176   lineCurr->isInline = _G.inLine;
177   lineCurr->isDebug = _G.debugLine;
178   lineCurr->ic = _G.current_iCode;
179   lineCurr->isComment = (*lbp==';');
180
181   //printf("%s\n", lb);
182   va_end (ap);
183 }
184
185 static void
186 emitBranch (char *branchop, symbol *tlbl)
187 {
188   emitcode (branchop, "%05d$", (tlbl->key + 100));
189 }
190
191 static void
192 emitLabel (symbol *tlbl)
193 {
194   emitcode ("", "%05d$:", (tlbl->key +100));
195   lineCurr->isLabel = 1;
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 = ulFromVal (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 they have the same rname */
1624   if (sym1->rname[0] && sym2->rname[0]
1625       && strcmp (sym1->rname, sym2->rname) == 0)
1626     return TRUE;
1627
1628   /* if left is a tmp & right is not */
1629   if (IS_ITEMP (op1) &&
1630       !IS_ITEMP (op2) &&
1631       sym1->isspilt &&
1632       (sym1->usl.spillLoc == sym2))
1633     return TRUE;
1634
1635   if (IS_ITEMP (op2) &&
1636       !IS_ITEMP (op1) &&
1637       sym2->isspilt &&
1638       sym1->level > 0 &&
1639       (sym2->usl.spillLoc == sym1))
1640     return TRUE;
1641
1642   return FALSE;
1643 }
1644
1645 /*-----------------------------------------------------------------*/
1646 /* sameRegs - two asmops have the same registers                   */
1647 /*-----------------------------------------------------------------*/
1648 static bool
1649 sameRegs (asmop * aop1, asmop * aop2)
1650 {
1651   int i;
1652
1653   if (aop1 == aop2)
1654     return TRUE;
1655
1656 //  if (aop1->size != aop2->size)
1657 //    return FALSE;
1658
1659   if (aop1->type == aop2->type)
1660     {
1661       switch (aop1->type)
1662         {
1663           case AOP_REG:
1664             for (i = 0; i < aop1->size; i++)
1665               if (aop1->aopu.aop_reg[i] !=
1666                   aop2->aopu.aop_reg[i])
1667                 return FALSE;
1668             return TRUE;
1669           case AOP_SOF:
1670             return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1671           case AOP_DIR:
1672           case AOP_EXT:
1673             return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1674         }
1675     }
1676
1677   return FALSE;
1678 }
1679
1680 /*-----------------------------------------------------------------*/
1681 /* aopOp - allocates an asmop for an operand  :                    */
1682 /*-----------------------------------------------------------------*/
1683 static void
1684 aopOp (operand * op, iCode * ic, bool result)
1685 {
1686   asmop *aop = NULL;
1687   symbol *sym;
1688   int i;
1689
1690   if (!op)
1691     return;
1692
1693   // Is this a pointer set result?
1694   //
1695   if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1696     {
1697     }
1698
1699 //  printf("checking literal\n");
1700   /* if this a literal */
1701   if (IS_OP_LITERAL (op))
1702     {
1703       op->aop = aop = newAsmop (AOP_LIT);
1704       aop->aopu.aop_lit = op->operand.valOperand;
1705       aop->size = getSize (operandType (op));
1706       aop->op = op;
1707       aop->isaddr = op->isaddr;
1708       return;
1709     }
1710
1711 //  printf("checking pre-existing\n");
1712   /* if already has a asmop then continue */
1713   if (op->aop )
1714     {
1715       op->aop->op = op;
1716       op->aop->isaddr = op->isaddr;
1717       return;
1718     }
1719
1720 //  printf("checking underlying sym\n");
1721   /* if the underlying symbol has a aop */
1722   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1723     {
1724       op->aop = aop = Safe_calloc(1, sizeof(*aop));
1725       memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1726       //op->aop = aop = OP_SYMBOL (op)->aop;
1727       aop->size = getSize( operandType (op));
1728       //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1729       //printf (" with size = %d\n", aop->size);
1730       
1731       aop->op = op;
1732       aop->isaddr = op->isaddr;
1733       /* if (aop->isaddr & IS_ITEMP (op))
1734         {
1735           aop->psize=aop->size;
1736           aop->size = getSize( operandType (op)->next);
1737         } */
1738       return;
1739     }
1740
1741 //  printf("checking true sym\n");
1742   /* if this is a true symbol */
1743   if (IS_TRUE_SYMOP (op))
1744     {
1745       op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1746       aop->op = op;
1747       aop->isaddr = op->isaddr;
1748       //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1749       //printf (" with size = %d\n", aop->size);
1750       return;
1751     }
1752
1753   /* this is a temporary : this has
1754      only four choices :
1755      a) register
1756      b) spillocation
1757      c) rematerialize
1758      d) conditional
1759      e) can be a return use only */
1760
1761   sym = OP_SYMBOL (op);
1762
1763 //  printf("checking conditional\n");
1764   /* if the type is a conditional */
1765   if (sym->regType == REG_CND)
1766     {
1767       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1768       aop->size = 0;
1769       aop->op = op;
1770       aop->isaddr = op->isaddr;
1771       return;
1772     }
1773
1774 //  printf("checking spilt\n");
1775   /* if it is spilt then two situations
1776      a) is rematerialize
1777      b) has a spill location */
1778   if (sym->isspilt || sym->nRegs == 0)
1779     {
1780
1781 //      printf("checking remat\n");
1782       /* rematerialize it NOW */
1783       if (sym->remat)
1784         {
1785           sym->aop = op->aop = aop =
1786             aopForRemat (sym);
1787           aop->size = getSize (sym->type);
1788           aop->op = op;
1789           aop->isaddr = op->isaddr;
1790           /* if (aop->isaddr & IS_ITEMP (op))
1791             {
1792               aop->psize=aop->size;
1793               aop->size = getSize( operandType (op)->next);
1794             } */
1795           return;
1796         }
1797
1798 //      printf("checking accuse\n");
1799       if (sym->accuse)
1800         {
1801           aop = op->aop = sym->aop = newAsmop (AOP_REG);
1802           aop->size = getSize (sym->type);
1803           switch (sym->accuse)
1804             {
1805             case ACCUSE_XA:
1806               aop->aopu.aop_reg[0] = hc08_reg_a;
1807               aop->aopu.aop_reg[1] = hc08_reg_x;
1808               break;
1809             case ACCUSE_HX:
1810               aop->aopu.aop_reg[0] = hc08_reg_x;
1811               aop->aopu.aop_reg[1] = hc08_reg_h;
1812               break;
1813             }
1814           aop->op = op;
1815           aop->isaddr = op->isaddr;
1816           return;
1817         }
1818
1819 //      printf("checking ruonly\n");
1820 #if 1
1821       if (sym->ruonly)
1822         {
1823           unsigned i;
1824
1825           aop = op->aop = sym->aop = newAsmop (AOP_STR);
1826           aop->size = getSize (sym->type);
1827           for (i = 0; i < fReturnSizeHC08; i++)
1828             aop->aopu.aop_str[i] = fReturn2[i];
1829           aop->op = op;
1830           aop->isaddr = op->isaddr;
1831           return;
1832         }
1833 #endif
1834       /* else spill location  */
1835       if (sym->usl.spillLoc)
1836         {
1837           asmop *oldAsmOp = NULL;
1838
1839           if (sym->usl.spillLoc->aop
1840               && sym->usl.spillLoc->aop->size != getSize (sym->type))
1841             {
1842               /* force a new aop if sizes differ */
1843               oldAsmOp = sym->usl.spillLoc->aop;
1844               sym->usl.spillLoc->aop = NULL;
1845               //printf ("forcing new aop\n");
1846             }
1847           sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1848           if (sym->usl.spillLoc->aop->size != getSize (sym->type))
1849             {
1850               /* Don't reuse the new aop, go with the last one */
1851               sym->usl.spillLoc->aop = oldAsmOp;
1852             }
1853           aop->size = getSize (sym->type);
1854           aop->op = op;
1855           aop->isaddr = op->isaddr;
1856           //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1857           //printf (" with size = %d\n", aop->size);
1858           return;
1859         }
1860       
1861       /* else must be a dummy iTemp */
1862       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1863       aop->size = getSize (sym->type);
1864       return;
1865     }
1866
1867 //  printf("assuming register\n");
1868   /* must be in a register */
1869   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1870   aop->size = sym->nRegs;
1871   for (i = 0; i < sym->nRegs; i++)
1872     aop->aopu.aop_reg[i] = sym->regs[i];
1873   aop->op = op;
1874   aop->isaddr = op->isaddr;
1875
1876 }
1877
1878 /*-----------------------------------------------------------------*/
1879 /* freeAsmop - free up the asmop given to an operand               */
1880 /*----------------------------------------------------------------*/
1881 static void
1882 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1883 {
1884   asmop *aop;
1885
1886   if (!op)
1887     aop = aaop;
1888   else
1889     aop = op->aop;
1890
1891   if (!aop)
1892     return;
1893
1894   if (aop->freed)
1895     goto dealloc;
1896
1897   aop->freed = 1;
1898
1899   if (aop->stacked)
1900     {
1901       int stackAdjust;
1902       int loffset;
1903
1904       DD(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1905       aop->stacked = 0;
1906       stackAdjust = 0;
1907       for (loffset=0; loffset<aop->size; loffset++)
1908         if (aop->stk_aop[loffset])
1909           {
1910             transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1911             stackAdjust++;
1912           }
1913       pullNull (stackAdjust);
1914     }
1915     
1916 dealloc:
1917   /* all other cases just dealloc */
1918   if (op)
1919     {
1920       op->aop = NULL;
1921       if (IS_SYMOP (op))
1922         {
1923           OP_SYMBOL (op)->aop = NULL;
1924           /* if the symbol has a spill */
1925           if (SPIL_LOC (op))
1926             SPIL_LOC (op)->aop = NULL;
1927         }
1928     }
1929 }
1930
1931
1932 /*-----------------------------------------------------------------*/
1933 /* aopDerefAop - treating the aop parameter as a pointer, return   */
1934 /*               an asmop for the object it references             */
1935 /*-----------------------------------------------------------------*/
1936 asmop *
1937 aopDerefAop (asmop *aop)
1938 {
1939   int adr;
1940   char *s = buffer;
1941   char *rs;
1942   asmop *newaop = NULL;
1943   sym_link *type, *etype;
1944   int p_type;
1945   
1946   DD(emitcode ("", ";     aopDerefAop(%s)", aopName(aop)));
1947   if (aop->op)
1948     {
1949     
1950       type = operandType (aop->op);
1951       etype = getSpec (type);
1952       /* if op is of type of pointer then it is simple */
1953       if (IS_PTR (type) && !IS_FUNC (type->next))
1954         p_type = DCL_TYPE (type);
1955       else
1956         {
1957           /* we have to go by the storage class */
1958           p_type = PTR_TYPE (SPEC_OCLS (etype));
1959         }
1960     }
1961   else
1962     p_type = UPOINTER;
1963   
1964   switch (aop->type)
1965     {
1966     case AOP_IMMD:
1967       if (p_type == POINTER)
1968         newaop = newAsmop (AOP_DIR);
1969       else
1970         newaop = newAsmop (AOP_EXT);
1971       newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1972       break;
1973     case AOP_LIT:
1974       adr = (int) ulFromVal (aop->aopu.aop_lit);
1975       if (p_type == POINTER)
1976         adr &= 0xff;
1977
1978       if (adr<0x100)
1979         {
1980           newaop = newAsmop (AOP_DIR);
1981           sprintf (s, "0x%02x",adr);
1982         }
1983       else
1984         {
1985           newaop = newAsmop (AOP_EXT);
1986           sprintf (s, "0x%04x",adr);
1987         }
1988       rs = Safe_calloc (1, strlen (s) + 1);
1989       strcpy (rs, s);
1990       newaop->aopu.aop_dir = rs;
1991       break;
1992     default:
1993       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1994               "unsupported asmop");
1995       return NULL;
1996     }
1997
1998      
1999   return newaop;
2000 }
2001
2002
2003
2004 /*-----------------------------------------------------------------*/
2005 /* aopAdrStr - for referencing the address of the aop              */
2006 /*-----------------------------------------------------------------*/
2007 static char *
2008 aopAdrStr (asmop * aop, int loffset, bool bit16)
2009 {
2010   char *s = buffer;
2011   char *rs;
2012   int offset = aop->size - 1 - loffset;
2013  
2014
2015   /* offset is greater than
2016      size then zero */
2017   if (loffset > (aop->size - 1) &&
2018       aop->type != AOP_LIT)
2019     return zero;
2020
2021   /* depending on type */
2022   switch (aop->type)
2023     {
2024
2025     case AOP_DUMMY:
2026       return zero;
2027       
2028     case AOP_IMMD:
2029       if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
2030               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
2031       } else if (bit16)
2032         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
2033       else if (loffset)
2034         {
2035           if (loffset!=1)
2036             sprintf (s, "#(%s >> %d)",
2037                      aop->aopu.aop_immd.aop_immd1,
2038                      loffset * 8);
2039           else
2040             sprintf (s, "#>%s",
2041                      aop->aopu.aop_immd.aop_immd1);
2042         }
2043       else
2044         sprintf (s, "#%s",
2045                  aop->aopu.aop_immd.aop_immd1);
2046       rs = Safe_calloc (1, strlen (s) + 1);
2047       strcpy (rs, s);
2048       return rs;
2049
2050     case AOP_DIR:
2051       if (offset)
2052         sprintf (s, "*(%s + %d)",
2053                  aop->aopu.aop_dir,
2054                  offset);
2055       else
2056         sprintf (s, "*%s", aop->aopu.aop_dir);
2057       rs = Safe_calloc (1, strlen (s) + 1);
2058       strcpy (rs, s);
2059       return rs;
2060
2061     case AOP_EXT:
2062       if (offset)
2063         sprintf (s, "(%s + %d)",
2064                  aop->aopu.aop_dir,
2065                  offset);
2066       else
2067         sprintf (s, "%s", aop->aopu.aop_dir);
2068       rs = Safe_calloc (1, strlen (s) + 1);
2069       strcpy (rs, s);
2070       return rs;
2071
2072     case AOP_REG:
2073       return aop->aopu.aop_reg[loffset]->name;
2074
2075     case AOP_LIT:
2076       if (bit16)
2077         return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
2078       else
2079         return aopLiteral (aop->aopu.aop_lit, loffset);
2080
2081     case AOP_STR:
2082       aop->coff = offset;
2083       return aop->aopu.aop_str[loffset];
2084
2085     case AOP_SOF:
2086         sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2087                             + offset + 1);
2088       rs = Safe_calloc (1, strlen (s) + 1);
2089       strcpy (rs, s);
2090       return rs;
2091
2092     }
2093
2094   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2095           "aopAdrStr got unsupported aop->type");
2096   exit (1);
2097 }
2098
2099
2100
2101
2102
2103 #if 0
2104 /*-----------------------------------------------------------------*/
2105 /* opIsGptr: returns non-zero if the passed operand is       */
2106 /* a generic pointer type.             */
2107 /*-----------------------------------------------------------------*/
2108 static int
2109 opIsGptr (operand * op)
2110 {
2111   sym_link *type = operandType (op);
2112
2113   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2114     {
2115       return 1;
2116     }
2117   return 0;
2118 }
2119 #endif
2120
2121 /*-----------------------------------------------------------------*/
2122 /* getDataSize - get the operand data size                         */
2123 /*-----------------------------------------------------------------*/
2124 static int
2125 getDataSize (operand * op)
2126 {
2127   int size;
2128   size = AOP_SIZE (op);
2129   return size;
2130 }
2131
2132
2133 /*-----------------------------------------------------------------*/
2134 /* asmopToBool - Emit code to convert an asmop to a boolean.       */
2135 /*               Result left in A (0=FALSE, 1=TRUE) if ResultInA,  */
2136 /*               otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2137 /*-----------------------------------------------------------------*/
2138 static void
2139 asmopToBool (asmop *aop, bool resultInA)
2140 {
2141   symbol *tlbl, *tlbl1;
2142   int size = aop->size;
2143   bool needpula = FALSE;
2144   bool flagsonly = TRUE;
2145   int offset = 0;
2146
2147
2148   if (resultInA)
2149     hc08_freeReg(hc08_reg_a);
2150       
2151   switch (aop->type)
2152     {
2153       case AOP_REG:
2154         if (IS_AOP_A(aop))
2155           {
2156             emitcode ("tsta", "");
2157             flagsonly = FALSE;
2158           }
2159         else if (IS_AOP_X(aop))
2160             emitcode ("tstx", "");
2161         else if (IS_AOP_H(aop))
2162           {
2163             if (hc08_reg_a->isFree)
2164               {
2165                 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2166                 emitcode ("tsta", "");
2167                 flagsonly = FALSE;
2168                 hc08_freeReg(hc08_reg_a);
2169               }
2170             else if (hc08_reg_x->isFree)
2171               {
2172                 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2173                 emitcode ("tstx", "");
2174                 hc08_freeReg(hc08_reg_x);
2175               }
2176             else
2177               {
2178                 emitcode ("pshh", "");
2179                 emitcode ("tst", "1,s");
2180                 emitcode ("ais", "#1");
2181               }
2182           }
2183         else if (IS_AOP_HX(aop))
2184           emitcode ("cphx", zero);
2185         else if (IS_AOP_XA(aop))
2186           {
2187             symbol *tlbl = newiTempLabel (NULL);
2188             emitcode ("tsta", "");
2189             emitcode ("bne", "%05d$", (tlbl->key + 100));
2190             emitcode ("tstx", "");
2191             emitLabel (tlbl);
2192           }
2193         else
2194           {
2195             werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2196                     "Bad rIdx in asmToBool");
2197             return;
2198           }
2199         break;
2200       case AOP_EXT:
2201         if (resultInA)
2202           needpula = FALSE;
2203         else
2204           needpula = pushRegIfUsed (hc08_reg_a);
2205         loadRegFromAop (hc08_reg_a, aop, 0);
2206         for (offset=1; offset<size; offset++)
2207           accopWithAop ("ora", aop, offset);
2208         if (needpula)
2209           pullReg (hc08_reg_a);
2210         else
2211           {
2212             hc08_freeReg (hc08_reg_a);
2213             flagsonly = FALSE;
2214           }
2215         break;
2216       case AOP_LIT:
2217         /* Higher levels should optimize this case away but let's be safe */
2218         if (ulFromVal (aop->aopu.aop_lit))
2219           loadRegFromConst (hc08_reg_a, one);
2220         else
2221           loadRegFromConst (hc08_reg_a, zero);
2222         hc08_freeReg(hc08_reg_a);
2223         break;
2224       default:
2225         if (size==1)
2226           {
2227             if (resultInA)
2228               {
2229                 loadRegFromAop (hc08_reg_a, aop, 0);
2230                 hc08_freeReg (hc08_reg_a);
2231                 flagsonly = FALSE;
2232               }
2233             else
2234               emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2235             break;
2236           }
2237         else if (size==2)
2238           {
2239             if (hc08_reg_a->isFree)
2240               {
2241                 loadRegFromAop (hc08_reg_a, aop, 0);
2242                 accopWithAop ("ora", aop, 1);
2243                 hc08_freeReg (hc08_reg_a);
2244                 flagsonly = FALSE;
2245               }
2246             else
2247               {
2248                 tlbl = newiTempLabel (NULL);
2249                 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2250                 emitcode ("bne", "%05d$", (tlbl->key + 100));
2251                 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2252                 emitLabel (tlbl);
2253                 break;
2254               }
2255           }
2256         else
2257           {
2258             needpula = pushRegIfUsed (hc08_reg_a);
2259             loadRegFromAop (hc08_reg_a, aop, 0);
2260             for (offset=1; offset<size; offset++)
2261               accopWithAop ("ora", aop, offset);
2262             if (needpula)
2263               pullReg (hc08_reg_a);
2264             else
2265               {
2266                 hc08_freeReg (hc08_reg_a);
2267                 flagsonly = FALSE;
2268               }
2269           }
2270     }
2271
2272   if (resultInA)
2273     {
2274       tlbl = newiTempLabel (NULL);
2275
2276       if (flagsonly)
2277         {
2278           tlbl1 = newiTempLabel (NULL);
2279           emitBranch ("bne", tlbl1);
2280           loadRegFromConst (hc08_reg_a, zero);
2281           emitBranch ("bra", tlbl);
2282           emitLabel (tlbl1);
2283           loadRegFromConst (hc08_reg_a, one);
2284         }
2285       else
2286         {
2287           emitBranch ("beq", tlbl);
2288           loadRegFromConst (hc08_reg_a, one);
2289         }
2290       emitLabel (tlbl);
2291       hc08_useReg (hc08_reg_a);
2292     }
2293 }
2294
2295
2296
2297 /*-----------------------------------------------------------------*/
2298 /* genNot - generate code for ! operation                          */
2299 /*-----------------------------------------------------------------*/
2300 static void
2301 genNot (iCode * ic)
2302 {
2303   D(emitcode (";     genNot",""));
2304
2305   /* assign asmOps to operand & result */
2306   aopOp (IC_LEFT (ic), ic, FALSE);
2307   aopOp (IC_RESULT (ic), ic, TRUE);
2308
2309   asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2310   emitcode ("eor", one);
2311   storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2312   
2313   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2314   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2315 }
2316
2317
2318 /*-----------------------------------------------------------------*/
2319 /* genCpl - generate code for complement                           */
2320 /*-----------------------------------------------------------------*/
2321 static void
2322 genCpl (iCode * ic)
2323 {
2324   int offset = 0;
2325   int size;
2326   regs* reg = hc08_reg_a;
2327   
2328   D(emitcode (";     genCpl",""));
2329
2330   /* assign asmOps to operand & result */
2331   aopOp (IC_LEFT (ic), ic, FALSE);
2332   aopOp (IC_RESULT (ic), ic, TRUE);
2333
2334   size = AOP_SIZE (IC_RESULT (ic));
2335   while (size--)
2336     {
2337       loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2338       rmwWithReg ("com", reg);
2339       hc08_useReg (reg);
2340       storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2341       hc08_freeReg (reg);
2342       offset++;
2343     }
2344
2345   /* release the aops */
2346   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2347   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2348 }
2349
2350 /*-----------------------------------------------------------------*/
2351 /* genUminusFloat - unary minus for floating points                */
2352 /*-----------------------------------------------------------------*/
2353 static void
2354 genUminusFloat (operand * op, operand * result)
2355 {
2356   int size, offset = 0;
2357   bool needpula;
2358
2359   D(emitcode (";     genUminusFloat",""));
2360
2361   /* for this we just copy and then flip the bit */
2362
2363   size = AOP_SIZE (op) - 1;
2364
2365   while (size--)
2366     {
2367       transferAopAop (AOP (op), offset, AOP (result), offset);
2368       offset++;
2369     }
2370
2371   needpula = pushRegIfUsed (hc08_reg_a);
2372   loadRegFromAop (hc08_reg_a, AOP (op), offset);
2373   emitcode ("eor", "#0x80");
2374   hc08_useReg (hc08_reg_a);
2375   storeRegToAop (hc08_reg_a, AOP (result), offset);
2376   pullOrFreeReg (hc08_reg_a, needpula);
2377 }
2378
2379 /*-----------------------------------------------------------------*/
2380 /* genUminus - unary minus code generation                         */
2381 /*-----------------------------------------------------------------*/
2382 static void
2383 genUminus (iCode * ic)
2384 {
2385   int offset, size;
2386   sym_link *optype, *rtype;
2387   char *sub;
2388   bool needpula;
2389   asmop *result;
2390
2391   D(emitcode (";     genUminus",""));
2392
2393   /* assign asmops */
2394   aopOp (IC_LEFT (ic), ic, FALSE);
2395   aopOp (IC_RESULT (ic), ic, TRUE);
2396
2397   optype = operandType (IC_LEFT (ic));
2398   rtype = operandType (IC_RESULT (ic));
2399
2400   /* if float then do float stuff */
2401   if (IS_FLOAT (optype))
2402     {
2403       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2404       goto release;
2405     }
2406
2407   /* otherwise subtract from zero */
2408   size = AOP_SIZE (IC_LEFT (ic));
2409   offset = 0;
2410
2411   if (size == 1)
2412     {
2413       if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2414         needpula = pushRegIfUsed (hc08_reg_a);
2415       else
2416         needpula = FALSE;
2417       loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2418       emitcode ("nega", "");
2419       hc08_freeReg (hc08_reg_a);
2420       storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)), 
2421                          SPEC_USIGN (operandType (IC_LEFT (ic))));
2422       pullOrFreeReg (hc08_reg_a, needpula);
2423     }
2424   else
2425     {
2426       if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2427         result = forceStackedAop (AOP (IC_RESULT (ic)), FALSE);
2428       else
2429         result = AOP (IC_RESULT (ic));
2430         
2431       needpula = pushRegIfUsed (hc08_reg_a);
2432       sub="sub";
2433       while (size--)
2434         {
2435           loadRegFromConst (hc08_reg_a, zero);
2436           accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2437           storeRegToAop (hc08_reg_a, result, offset++);
2438           sub = "sbc";
2439         }
2440         storeRegSignToUpperAop (hc08_reg_a, result, offset, 
2441                                 SPEC_USIGN (operandType (IC_LEFT (ic))));
2442       pullOrFreeReg (hc08_reg_a, needpula);
2443       
2444       if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2445         freeAsmop (NULL, result, ic, TRUE);
2446     }
2447
2448
2449
2450 release:
2451   /* release the aops */
2452   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2453   freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2454 }
2455
2456 /*-----------------------------------------------------------------*/
2457 /* saveRegisters - will look for a call and save the registers     */
2458 /*-----------------------------------------------------------------*/
2459 static void
2460 saveRegisters (iCode * lic)
2461 {
2462   int i;
2463   iCode *ic;
2464   bitVect *rsave;
2465
2466   /* look for call */
2467   for (ic = lic; ic; ic = ic->next)
2468     if (ic->op == CALL || ic->op == PCALL)
2469       break;
2470
2471   if (!ic)
2472     {
2473       fprintf (stderr, "found parameter push with no function call\n");
2474       return;
2475     }
2476
2477   /* if the registers have been saved already or don't need to be then
2478      do nothing */
2479   if (ic->regsSaved)
2480     return;
2481   if (IS_SYMOP(IC_LEFT(ic)) &&
2482       (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2483        IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2484     return;
2485   
2486   /* safe the registers in use at this time but skip the
2487      ones for the result */
2488   rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2489                          hc08_rUmaskForOp (IC_RESULT(ic)));
2490
2491   ic->regsSaved = 1;
2492   for (i = 0; i < hc08_nRegs; i++)
2493     {
2494       if (bitVectBitValue (rsave, i))
2495         pushReg ( hc08_regWithIdx (i), FALSE);
2496     }
2497 }
2498
2499 /*-----------------------------------------------------------------*/
2500 /* unsaveRegisters - pop the pushed registers                      */
2501 /*-----------------------------------------------------------------*/
2502 static void
2503 unsaveRegisters (iCode * ic)
2504 {
2505   int i;
2506   bitVect *rsave;
2507
2508   /* restore the registers in use at this time but skip the
2509      ones for the result */
2510   rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2511                          hc08_rUmaskForOp (IC_RESULT(ic)));
2512
2513   for (i = hc08_nRegs; i >= 0; i--)
2514     {
2515       if (bitVectBitValue (rsave, i))
2516         pullReg ( hc08_regWithIdx (i));
2517     }
2518
2519 }
2520
2521
2522 /*-----------------------------------------------------------------*/
2523 /* pushSide -                */
2524 /*-----------------------------------------------------------------*/
2525 static void
2526 pushSide (operand * oper, int size)
2527 {
2528   int offset = 0;
2529   while (size--)
2530     {
2531       loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2532       pushReg ( hc08_reg_a, TRUE);
2533     }
2534 }
2535
2536 /*-----------------------------------------------------------------*/
2537 /* assignResultValue -               */
2538 /*-----------------------------------------------------------------*/
2539 static void
2540 assignResultValue (operand * oper)
2541 {
2542   int size = AOP_SIZE (oper);
2543   int offset = 0;
2544   while (size--)
2545     {
2546       transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2547       if (hc08_aop_pass[offset]->type == AOP_REG)
2548         hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2549       offset++;
2550     }
2551 }
2552
2553
2554
2555 /*-----------------------------------------------------------------*/
2556 /* genIpush - genrate code for pushing this gets a little complex  */
2557 /*-----------------------------------------------------------------*/
2558 static void
2559 genIpush (iCode * ic)
2560 {
2561   int size, offset = 0;
2562
2563   D(emitcode (";     genIpush",""));
2564
2565   /* if this is not a parm push : ie. it is spill push
2566      and spill push is always done on the local stack */
2567   if (!ic->parmPush)
2568     {
2569
2570       /* and the item is spilt then do nothing */
2571       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2572         return;
2573
2574       aopOp (IC_LEFT (ic), ic, FALSE);
2575       size = AOP_SIZE (IC_LEFT (ic));
2576       offset = 0;
2577       /* push it on the stack */
2578       while (size--)
2579         {
2580           loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2581           pushReg ( hc08_reg_a, TRUE);
2582         }
2583
2584       return;
2585     }
2586
2587   /* this is a paramter push: in this case we call
2588      the routine to find the call and save those
2589      registers that need to be saved */
2590   saveRegisters (ic);
2591
2592   /* then do the push */
2593   aopOp (IC_LEFT (ic), ic, FALSE);
2594
2595
2596   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2597   size = AOP_SIZE (IC_LEFT (ic));
2598   offset = 0;
2599
2600 //  l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2601   if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2602     {
2603       if ((size==2) && hc08_reg_hx->isFree)
2604         {
2605           loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2606           pushReg (hc08_reg_hx, TRUE);
2607           goto release;
2608         }
2609     }
2610
2611   while (size--)
2612     {
2613 //      printf("loading %d\n", offset);
2614       loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2615 //      printf("pushing \n");
2616       pushReg (hc08_reg_a, TRUE);
2617     }
2618
2619 release:
2620   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2621 }
2622
2623 /*-----------------------------------------------------------------*/
2624 /* genIpop - recover the registers: can happen only for spilling   */
2625 /*-----------------------------------------------------------------*/
2626 static void
2627 genIpop (iCode * ic)
2628 {
2629   int size, offset;
2630
2631   D(emitcode (";     genIpop",""));
2632
2633   /* if the temp was not pushed then */
2634   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2635     return;
2636
2637   aopOp (IC_LEFT (ic), ic, FALSE);
2638   size = AOP_SIZE (IC_LEFT (ic));
2639   offset = size - 1;
2640   while (size--)
2641     {
2642       pullReg (hc08_reg_a);
2643       storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2644     }
2645   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2646 }
2647
2648
2649 /*-----------------------------------------------------------------*/
2650 /* genSend - gen code for SEND                                     */
2651 /*-----------------------------------------------------------------*/
2652 static void genSend(set *sendSet)
2653 {
2654     iCode *sic;
2655
2656     for (sic = setFirstItem (sendSet); sic;
2657          sic = setNextItem (sendSet)) {
2658           int size, offset = 0;
2659           aopOp (IC_LEFT (sic), sic, FALSE);
2660           size = AOP_SIZE (IC_LEFT (sic));
2661
2662           if (sic->argreg) {
2663               offset = size-1;
2664               while (size--) {
2665                   transferAopAop( AOP (IC_LEFT (sic)), offset,
2666                                   hc08_aop_pass[offset+(sic->argreg-1)], 0);
2667                   offset--;
2668               }
2669           }       
2670           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2671     }
2672 }
2673
2674 /*-----------------------------------------------------------------*/
2675 /* genCall - generates a call statement                            */
2676 /*-----------------------------------------------------------------*/
2677 static void
2678 genCall (iCode * ic)
2679 {
2680   sym_link *dtype;
2681 //  bool restoreBank = FALSE;
2682 //  bool swapBanks = FALSE;
2683
2684   D(emitcode(";     genCall",""));
2685
2686   dtype = operandType (IC_LEFT (ic));
2687   /* if send set is not empty then assign */
2688   if (_G.sendSet)
2689     {
2690         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2691             genSend(reverseSet(_G.sendSet));
2692         } else {
2693             genSend(_G.sendSet);
2694         }
2695
2696       _G.sendSet = NULL;
2697     }
2698
2699   /* if caller saves & we have not saved then */
2700   if (!ic->regsSaved)
2701       saveRegisters (ic);
2702
2703
2704   /* make the call */
2705   emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2706                           OP_SYMBOL (IC_LEFT (ic))->rname :
2707                           OP_SYMBOL (IC_LEFT (ic))->name));
2708
2709
2710   /* if we need assign a result value */
2711   if ((IS_ITEMP (IC_RESULT (ic)) &&
2712        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2713         OP_SYMBOL (IC_RESULT (ic))->accuse || 
2714         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2715       IS_TRUE_SYMOP (IC_RESULT (ic)))
2716     {
2717
2718       _G.accInUse++;
2719       aopOp (IC_RESULT (ic), ic, FALSE);
2720       _G.accInUse--;
2721
2722       assignResultValue (IC_RESULT (ic));
2723
2724       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2725     }
2726
2727   /* adjust the stack for parameters if
2728      required */
2729   if (ic->parmBytes)
2730     {
2731       pullNull (ic->parmBytes);
2732     }
2733
2734   /* if we had saved some registers then unsave them */
2735   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2736     unsaveRegisters (ic);
2737
2738 }
2739
2740 /*-----------------------------------------------------------------*/
2741 /* -10l - generates a call by pointer statement                */
2742 /*-----------------------------------------------------------------*/
2743 static void
2744 genPcall (iCode * ic)
2745 {
2746   sym_link *dtype;
2747   symbol *rlbl = newiTempLabel (NULL);
2748   symbol *tlbl = newiTempLabel (NULL);
2749 //  bool restoreBank=FALSE;
2750 //  bool swapBanks = FALSE;
2751
2752   D(emitcode(";     genPCall",""));
2753
2754   /* if caller saves & we have not saved then */
2755   if (!ic->regsSaved)
2756     saveRegisters (ic);
2757
2758   /* if we are calling a not _naked function that is not using
2759      the same register bank then we need to save the
2760      destination registers on the stack */
2761   dtype = operandType (IC_LEFT (ic))->next;
2762
2763   /* now push the calling address */
2764   emitBranch ("bsr", tlbl);
2765   emitBranch ("bra", rlbl);
2766   emitLabel (tlbl);
2767   _G.stackPushes += 2; /* account for the bsr return address now on stack */
2768   updateCFA();
2769
2770   /* Push the function's address */
2771   aopOp (IC_LEFT (ic), ic, FALSE);
2772   pushSide (IC_LEFT (ic), FPTRSIZE);
2773   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2774
2775   /* if send set is not empty the assign */
2776   if (_G.sendSet)
2777     {
2778         genSend(reverseSet(_G.sendSet));
2779         _G.sendSet = NULL;
2780     }
2781
2782
2783   /* make the call */
2784   emitcode ("rts", "");
2785
2786   emitLabel (rlbl);
2787   _G.stackPushes -= 4; /* account for rts here & in called function */
2788   updateCFA();
2789
2790
2791   /* if we need assign a result value */
2792   if ((IS_ITEMP (IC_RESULT (ic)) &&
2793        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2794         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2795       IS_TRUE_SYMOP (IC_RESULT (ic)))
2796     {
2797
2798       _G.accInUse++;
2799       aopOp (IC_RESULT (ic), ic, FALSE);
2800       _G.accInUse--;
2801
2802       assignResultValue (IC_RESULT (ic));
2803
2804       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2805     }
2806
2807   /* adjust the stack for parameters if
2808      required */
2809   if (ic->parmBytes)
2810     {
2811       pullNull (ic->parmBytes);
2812     }
2813
2814   /* if we hade saved some registers then
2815      unsave them */
2816   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2817     unsaveRegisters (ic);
2818 }
2819
2820 /*-----------------------------------------------------------------*/
2821 /* resultRemat - result  is rematerializable                       */
2822 /*-----------------------------------------------------------------*/
2823 static int
2824 resultRemat (iCode * ic)
2825 {
2826   if (SKIP_IC (ic) || ic->op == IFX)
2827     return 0;
2828
2829   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2830     {
2831       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2832       if (sym->remat && !POINTER_SET (ic))
2833         return 1;
2834     }
2835
2836   return 0;
2837 }
2838
2839 /*-----------------------------------------------------------------*/
2840 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2841 /*-----------------------------------------------------------------*/
2842 static int
2843 regsCmp(void *p1, void *p2)
2844 {
2845   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2846 }
2847
2848 static bool
2849 inExcludeList (char *s)
2850 {
2851   const char *p = setFirstItem(options.excludeRegsSet);
2852
2853   if (p == NULL || STRCASECMP(p, "none") == 0)
2854     return FALSE;
2855
2856
2857   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2858 }
2859
2860 /*-----------------------------------------------------------------*/
2861 /* genFunction - generated code for function entry                 */
2862 /*-----------------------------------------------------------------*/
2863 static void
2864 genFunction (iCode * ic)
2865 {
2866   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2867   sym_link *ftype;
2868   iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2869   int stackAdjust = sym->stack;
2870   int accIsFree = sym->recvSize == 0;
2871
2872   _G.nRegsSaved = 0;
2873   _G.stackPushes = 0;
2874   /* create the function header */
2875   emitcode (";", "-----------------------------------------");
2876   emitcode (";", " function %s", sym->name);
2877   emitcode (";", "-----------------------------------------");
2878
2879   emitcode ("", "%s:", sym->rname);
2880   lineCurr->isLabel = 1;
2881   ftype = operandType (IC_LEFT (ic));
2882   
2883   _G.stackOfs = 0;
2884   _G.stackPushes = 0;
2885   debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2886
2887   if (IFFUNC_ISNAKED(ftype))
2888   {
2889       emitcode(";", "naked function: no prologue.");
2890       return;
2891   }
2892
2893   /* if this is an interrupt service routine then
2894      save h  */
2895   if (IFFUNC_ISISR (sym->type))
2896     {
2897
2898       if (!inExcludeList ("h"))
2899         pushReg (hc08_reg_h, FALSE);
2900     }
2901
2902   /* For some cases it is worthwhile to perform a RECEIVE iCode */
2903   /* before setting up the stack frame completely. */
2904   while (ric && ric->next && ric->next->op == RECEIVE)
2905     ric = ric->next;
2906   while (ric && IC_RESULT (ric))
2907     {
2908       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2909       int rsymSize = rsym ? getSize(rsym->type) : 0;
2910
2911       if (rsym->isitmp)
2912         {
2913           if (rsym && rsym->regType == REG_CND)
2914             rsym = NULL;
2915           if (rsym && (rsym->accuse || rsym->ruonly))
2916             rsym = NULL;
2917           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2918             rsym = rsym->usl.spillLoc;
2919         }
2920
2921       /* If the RECEIVE operand immediately spills to the first entry on the  */
2922       /* stack, we can push it directly rather than use an sp relative store. */
2923       if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize)
2924         {
2925           int ofs;
2926
2927           _G.current_iCode = ric;
2928           D(emitcode (";     genReceive",""));
2929           for (ofs=0; ofs < rsymSize; ofs++)
2930             {
2931               regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
2932               pushReg (reg, TRUE);
2933               if (reg->rIdx == A_IDX)
2934                 accIsFree = 1;
2935               stackAdjust--;
2936             }
2937           _G.current_iCode = ic;
2938           ric->generated = 1;
2939         }
2940       ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
2941     }
2942
2943   /* adjust the stack for the function */
2944   if (stackAdjust)
2945     {
2946       adjustStack (-stackAdjust);
2947     }
2948   _G.stackOfs = sym->stack;
2949   _G.stackPushes = 0;
2950   
2951   /* if critical function then turn interrupts off */
2952   if (IFFUNC_ISCRITICAL (ftype))
2953     {
2954       if (!accIsFree)
2955         {
2956           /* Function was passed parameters, so make sure A is preserved */
2957           pushReg (hc08_reg_a, FALSE);
2958           pushReg (hc08_reg_a, FALSE);
2959           emitcode ("tpa", "");
2960           emitcode ("sta", "2,s");
2961           emitcode ("sei", "");
2962           pullReg (hc08_reg_a);
2963         }
2964       else
2965         {
2966           /* No passed parameters, so A can be freely modified */
2967           emitcode ("tpa", "");
2968           pushReg (hc08_reg_a, TRUE);
2969           emitcode ("sei", "");
2970         }
2971     }
2972
2973 }
2974
2975 /*-----------------------------------------------------------------*/
2976 /* genEndFunction - generates epilogue for functions               */
2977 /*-----------------------------------------------------------------*/
2978 static void
2979 genEndFunction (iCode * ic)
2980 {
2981   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2982
2983   if (IFFUNC_ISNAKED(sym->type))
2984   {
2985       emitcode(";", "naked function: no epilogue.");
2986       if (options.debug && currFunc)
2987         debugFile->writeEndFunction (currFunc, ic, 0);
2988       return;
2989   }
2990
2991   if (IFFUNC_ISCRITICAL (sym->type))
2992     {
2993       if (!IS_VOID(sym->type->next))
2994         {
2995           /* Function has return value, so make sure A is preserved */
2996           pushReg (hc08_reg_a, FALSE);
2997           emitcode ("lda", "2,s");
2998           emitcode ("tap", "");
2999           pullReg (hc08_reg_a);
3000           pullNull (1);
3001         }
3002       else
3003         {
3004           /* Function returns void, so A can be freely modified */
3005           pullReg (hc08_reg_a);
3006           emitcode ("tap", "");
3007         }
3008     }
3009
3010   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
3011     {
3012     }
3013
3014   if (sym->stack)
3015     {
3016       _G.stackPushes += sym->stack;
3017       adjustStack (sym->stack);
3018     }
3019
3020
3021   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3022     {
3023     }
3024
3025   if (IFFUNC_ISISR (sym->type))
3026     {
3027
3028       if (!inExcludeList ("h"))
3029         pullReg (hc08_reg_h);
3030
3031
3032       /* if debug then send end of function */
3033       if (options.debug && currFunc)
3034         {
3035           debugFile->writeEndFunction (currFunc, ic, 1);
3036         }
3037
3038       emitcode ("rti", "");
3039     }
3040   else
3041     {
3042       if (IFFUNC_CALLEESAVES(sym->type))
3043         {
3044           int i;
3045
3046           /* if any registers used */
3047           if (sym->regsUsed)
3048             {
3049               /* save the registers used */
3050               for (i = sym->regsUsed->size; i >= 0; i--)
3051                 {
3052                   if (bitVectBitValue (sym->regsUsed, i) ||
3053                       (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3054                     emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3055                 }
3056             }
3057
3058         }
3059
3060       /* if debug then send end of function */
3061       if (options.debug && currFunc)
3062         {
3063           debugFile->writeEndFunction (currFunc, ic, 1);
3064         }
3065
3066       emitcode ("rts", "");
3067     }
3068
3069 }
3070
3071 /*-----------------------------------------------------------------*/
3072 /* genRet - generate code for return statement                     */
3073 /*-----------------------------------------------------------------*/
3074 static void
3075 genRet (iCode * ic)
3076 {
3077   int size, offset = 0;
3078 //  int pushed = 0;
3079
3080   D(emitcode (";     genRet",""));
3081
3082   /* if we have no return value then
3083      just generate the "ret" */
3084   if (!IC_LEFT (ic))
3085     goto jumpret;
3086
3087   /* we have something to return then
3088      move the return value into place */
3089   aopOp (IC_LEFT (ic), ic, FALSE);
3090   size = AOP_SIZE (IC_LEFT (ic));
3091
3092 #if 1
3093    offset = size - 1;
3094    while (size--)
3095      {
3096        transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3097        offset--;
3098      }
3099 #else
3100   switch (size)
3101     {
3102       case 4:
3103         /* 4 byte return: store value in the global return variable */
3104         offset = size-1;
3105         while (size--)
3106           {
3107             loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3108             STA (fReturn2[offset--], FALSE);
3109             hc08_freeReg (hc08_reg_a);
3110           }
3111         break;
3112       case 2:
3113         /* 2 byte return: store value in x:a */
3114         loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3115         hc08_freeReg (hc08_reg_xa);
3116         break;
3117       case 1:
3118         /* 1 byte return: store value in a */
3119         loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3120         hc08_freeReg (hc08_reg_a);
3121         break;
3122     }
3123 #endif
3124
3125   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3126
3127 jumpret:
3128   /* generate a jump to the return label
3129      if the next is not the return statement */
3130   if (!(ic->next && ic->next->op == LABEL &&
3131         IC_LABEL (ic->next) == returnLabel))
3132
3133     emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3134
3135 }
3136
3137 /*-----------------------------------------------------------------*/
3138 /* genLabel - generates a label                                    */
3139 /*-----------------------------------------------------------------*/
3140 static void
3141 genLabel (iCode * ic)
3142 {
3143   int i;
3144   regs *reg;
3145   
3146   /* For the high level labels we cannot depend on any */
3147   /* register's contents. Amnesia time.                */
3148   for (i=A_IDX;i<=XA_IDX;i++)
3149     {
3150       reg = hc08_regWithIdx(i);
3151       if (reg)
3152         reg->aop = NULL;
3153     }
3154
3155   /* special case never generate */
3156   if (IC_LABEL (ic) == entryLabel)
3157     return;
3158           
3159   debugFile->writeLabel(IC_LABEL (ic), ic);
3160
3161   emitLabel (IC_LABEL (ic));
3162
3163 }
3164
3165 /*-----------------------------------------------------------------*/
3166 /* genGoto - generates a jmp                                      */
3167 /*-----------------------------------------------------------------*/
3168 static void
3169 genGoto (iCode * ic)
3170 {
3171   emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3172 }
3173
3174 #if 0
3175 /*-----------------------------------------------------------------*/
3176 /* findLabelBackwards: walks back through the iCode chain looking  */
3177 /* for the given label. Returns number of iCode instructions     */
3178 /* between that label and given ic.          */
3179 /* Returns zero if label not found.          */
3180 /*-----------------------------------------------------------------*/
3181 static int
3182 findLabelBackwards (iCode * ic, int key)
3183 {
3184   int count = 0;
3185
3186   while (ic->prev)
3187     {
3188       ic = ic->prev;
3189       count++;
3190
3191       /* If we have any pushes or pops, we cannot predict the distance.
3192          I don't like this at all, this should be dealt with in the 
3193          back-end */
3194       if (ic->op == IPUSH || ic->op == IPOP) {
3195         return 0;
3196       }
3197
3198       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3199         {
3200           return count;
3201         }
3202     }
3203
3204   return 0;
3205 }
3206 #endif
3207
3208 /*-----------------------------------------------------------------*/
3209 /* genPlusIncr :- does addition with increment if possible         */
3210 /*-----------------------------------------------------------------*/
3211 static bool
3212 genPlusIncr (iCode * ic)
3213 {
3214   int icount;
3215   operand *left;
3216   operand *result;
3217   bool needpulx;
3218   bool needpulh;
3219   bool needpula;
3220   unsigned int size = getDataSize (IC_RESULT (ic));
3221   unsigned int offset;
3222   symbol *tlbl = NULL;
3223   
3224   left = IC_LEFT (ic);
3225   result = IC_RESULT (ic);
3226
3227   /* will try to generate an increment */
3228   /* if the right side is not a literal
3229      we cannot */
3230   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3231     return FALSE;
3232
3233   icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3234
3235   DD(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3236   
3237   if ((IS_AOP_HX (AOP (left)) ||
3238        ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3239       )
3240       && (icount>=-128) && (icount<=127) && (size==2))
3241     {
3242       if (!IS_AOP_HX (AOP (left)))
3243         {
3244           needpulx = pushRegIfUsed (hc08_reg_x);
3245           needpulh = pushRegIfUsed (hc08_reg_h);
3246         }
3247       else
3248         {
3249           needpulx = FALSE;
3250           needpulh = FALSE;
3251         }
3252       loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3253       emitcode ("aix","#%d", icount);
3254       hc08_dirtyReg (hc08_reg_hx, FALSE);
3255       storeRegToAop (hc08_reg_hx, AOP(result), 0);
3256       pullOrFreeReg (hc08_reg_h, needpulh);
3257       pullOrFreeReg (hc08_reg_x, needpulx);
3258       return TRUE;
3259     }
3260
3261   DD(emitcode ("", "; icount = %d, sameRegs=%d", icount, 
3262             sameRegs (AOP (left), AOP (result))));
3263   
3264   if ((icount > 255) || (icount<0))
3265     return FALSE;
3266
3267   if (!sameRegs (AOP (left), AOP (result)))
3268     return FALSE;
3269
3270   D(emitcode (";     genPlusIncr",""));
3271
3272   if (size>1)
3273     tlbl = newiTempLabel (NULL);
3274
3275   if (icount==1)
3276     {
3277       needpula = FALSE;
3278       rmwWithAop ("inc", AOP (result), 0);
3279       if (1<size)
3280         emitBranch ("bne", tlbl);
3281     }
3282   else
3283     {
3284       if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3285         needpula = pushRegIfUsed (hc08_reg_a);
3286       else
3287         needpula = FALSE;
3288       loadRegFromAop (hc08_reg_a, AOP (result), 0);
3289       accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3290       hc08_useReg (hc08_reg_a);
3291       storeRegToAop (hc08_reg_a, AOP (result), 0);
3292       hc08_freeReg (hc08_reg_a);
3293       if (1<size)
3294         emitBranch ("bcc", tlbl);
3295     }
3296   for (offset=1; offset<size; offset++)
3297     {
3298       rmwWithAop ("inc", AOP (result), offset);
3299       if ((offset+1)<size)
3300         emitBranch ("bne", tlbl);
3301     }
3302
3303   if (size>1)
3304     emitLabel (tlbl);
3305   
3306   pullOrFreeReg (hc08_reg_a, needpula);
3307       
3308   return TRUE;
3309 }
3310
3311
3312
3313 /*-----------------------------------------------------------------*/
3314 /* genPlus - generates code for addition                           */
3315 /*-----------------------------------------------------------------*/
3316 static void
3317 genPlus (iCode * ic)
3318 {
3319   int size, offset = 0;
3320   char *add;
3321   asmop *leftOp, *rightOp;
3322
3323   /* special cases :- */
3324
3325   D(emitcode (";     genPlus",""));
3326
3327   aopOp (IC_LEFT (ic), ic, FALSE);
3328   aopOp (IC_RIGHT (ic), ic, FALSE);
3329   aopOp (IC_RESULT (ic), ic, TRUE);
3330
3331   /* we want registers on the left and literals on the right */
3332   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3333       (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3334     {
3335       operand *t = IC_RIGHT (ic);
3336       IC_RIGHT (ic) = IC_LEFT (ic);
3337       IC_LEFT (ic) = t;
3338     }
3339
3340
3341   /* if I can do an increment instead
3342      of add then GOOD for ME */
3343   if (genPlusIncr (ic) == TRUE)
3344     goto release;
3345
3346   DD(emitcode("",";  left size = %d", getDataSize (IC_LEFT(ic))));
3347   DD(emitcode("",";  right size = %d", getDataSize (IC_RIGHT(ic))));
3348   DD(emitcode("",";  result size = %d", getDataSize (IC_RESULT(ic))));
3349   
3350   size = getDataSize (IC_RESULT (ic));
3351
3352   leftOp = AOP(IC_LEFT(ic));
3353   rightOp = AOP(IC_RIGHT(ic));
3354   add = "add";
3355
3356   offset = 0;
3357   while (size--)
3358     {
3359       loadRegFromAop (hc08_reg_a, leftOp, offset);
3360       accopWithAop(add, rightOp, offset);
3361       storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3362       hc08_freeReg (hc08_reg_a);
3363       add = "adc";  /* further adds must propagate carry */
3364     }
3365
3366
3367 //  adjustArithmeticResult (ic);
3368
3369 release:
3370   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3371   freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3372   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3373 }
3374
3375 /*-----------------------------------------------------------------*/
3376 /* genMinusDec :- does subtraction with decrement if possible      */
3377 /*-----------------------------------------------------------------*/
3378 static bool
3379 genMinusDec (iCode * ic)
3380 {
3381   unsigned int icount;
3382   operand *left;
3383   operand *result;
3384   bool needpulx;
3385   bool needpulh;
3386   unsigned int size = getDataSize (IC_RESULT (ic));
3387 //  int offset;
3388 //  symbol *tlbl;
3389   
3390   left = IC_LEFT (ic);
3391   result = IC_RESULT (ic);
3392
3393   /* will try to generate an increment */
3394   /* if the right side is not a literal
3395      we cannot */
3396   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3397     return FALSE;
3398
3399   icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3400
3401   if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3402       && (icount>=-127) && (icount<=128) && (size==2))
3403     {
3404       if (!IS_AOP_HX (AOP (left)))
3405         {
3406           needpulx = pushRegIfUsed (hc08_reg_x);
3407           needpulh = pushRegIfUsed (hc08_reg_h);
3408         }
3409       else
3410         {
3411           needpulx = FALSE;
3412           needpulh = FALSE;
3413         }
3414       loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3415       emitcode ("aix","#%d", -(int) icount);
3416       hc08_dirtyReg (hc08_reg_hx, FALSE);
3417       storeRegToAop (hc08_reg_hx, AOP(result), 0);
3418       pullOrFreeReg (hc08_reg_h, needpulh);
3419       pullOrFreeReg (hc08_reg_x, needpulx);
3420       return TRUE;
3421     }
3422   
3423   if ((icount > 1) || (icount<0))
3424     return FALSE;
3425
3426   if (!sameRegs (AOP (left), AOP (result)))
3427     return FALSE;
3428
3429   if (size!=1)
3430     return FALSE;
3431
3432   D(emitcode (";     genMinusDec",""));
3433
3434   rmwWithAop ("dec", AOP (result), 0);
3435   
3436   return TRUE;
3437 }
3438
3439 /*-----------------------------------------------------------------*/
3440 /* addSign - complete with sign                                    */
3441 /*-----------------------------------------------------------------*/
3442 static void
3443 addSign (operand * result, int offset, int sign)
3444 {
3445   int size = (getDataSize (result) - offset);
3446   if (size > 0)
3447     {
3448       if (sign)
3449         {
3450           emitcode ("rola", "");
3451           emitcode ("clra", "");
3452           emitcode ("sbc", zero);
3453           while (size--)
3454             storeRegToAop (hc08_reg_a, AOP (result), offset++);
3455         }
3456       else
3457         while (size--)
3458           storeConstToAop (zero, AOP (result), offset++);
3459     }
3460 }
3461
3462
3463 /*-----------------------------------------------------------------*/
3464 /* genMinus - generates code for subtraction                       */
3465 /*-----------------------------------------------------------------*/
3466 static void
3467 genMinus (iCode * ic)
3468 {
3469   char *sub;
3470   int size, offset = 0;
3471   
3472   asmop *leftOp, *rightOp;
3473
3474   D(emitcode (";     genMinus",""));
3475
3476   aopOp (IC_LEFT (ic), ic, FALSE);
3477   aopOp (IC_RIGHT (ic), ic, FALSE);
3478   aopOp (IC_RESULT (ic), ic, TRUE);
3479
3480   /* special cases :- */
3481   /* if I can do an decrement instead
3482      of subtract then GOOD for ME */
3483   if (genMinusDec (ic) == TRUE)
3484     goto release;
3485
3486   size = getDataSize (IC_RESULT (ic));
3487
3488
3489   leftOp = AOP(IC_LEFT(ic));
3490   rightOp = AOP(IC_RIGHT(ic));
3491   sub = "sub";
3492   offset = 0;
3493
3494   if (IS_AOP_A (rightOp))
3495     {
3496       loadRegFromAop ( hc08_reg_a, rightOp, offset);
3497       accopWithAop (sub, leftOp, offset);
3498       accopWithMisc ("nega", "");
3499       storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3500       goto release;
3501     }
3502
3503   while (size--)
3504     {
3505       loadRegFromAop ( hc08_reg_a, leftOp, offset);
3506       accopWithAop (sub, rightOp, offset);
3507       storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3508       sub = "sbc";
3509     }
3510   
3511   
3512 //  adjustArithmeticResult (ic);
3513
3514 release:
3515   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3516   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3517   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3518 }
3519
3520
3521
3522 /*-----------------------------------------------------------------*/
3523 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3524 /*-----------------------------------------------------------------*/
3525 static void
3526 genMultOneByte (operand * left,
3527                 operand * right,
3528                 operand * result)
3529 {
3530   /* sym_link *opetype = operandType (result); */
3531   symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3532   int size=AOP_SIZE(result);
3533   bool negLiteral = FALSE;
3534   bool lUnsigned, rUnsigned;
3535
3536   D(emitcode (";     genMultOneByte",""));
3537
3538   if (size<1 || size>2) {
3539     // this should never happen
3540       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3541                AOP_SIZE(result), __FILE__, lineno);
3542       exit (1);
3543   }
3544
3545   /* (if two literals: the value is computed before) */
3546   /* if one literal, literal on the right */
3547   if (AOP_TYPE (left) == AOP_LIT)
3548     {
3549       operand *t = right;
3550       right = left;
3551       left = t;
3552     }
3553   /* if an operand is in A, make sure it is on the left */
3554   if (IS_AOP_A (AOP (right)))
3555     {
3556       operand *t = right;
3557       right = left;
3558       left = t;
3559     }
3560
3561   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3562   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3563   
3564   /* lUnsigned  rUnsigned  negLiteral  negate     case */
3565   /* false      false      false       odd        3    */
3566   /* false      false      true        even       3    */
3567   /* false      true       false       odd        3    */
3568   /* false      true       true        impossible      */
3569   /* true       false      false       odd        3    */
3570   /* true       false      true        always     2    */
3571   /* true       true       false       never      1    */
3572   /* true       true       true        impossible      */
3573
3574   /* case 1 */
3575   if (size == 1
3576       || (lUnsigned && rUnsigned))
3577     {
3578       // just an unsigned 8*8=8/16 multiply
3579       //DD(emitcode (";","unsigned"));
3580
3581       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3582       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3583       emitcode ("mul", "");
3584       hc08_dirtyReg (hc08_reg_xa, FALSE);
3585       storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3586       hc08_freeReg (hc08_reg_xa);
3587       
3588       return;
3589     }
3590
3591   // we have to do a signed multiply
3592
3593   /* case 2 */
3594   /* left unsigned, right signed literal -- literal determines sign handling */
3595   if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3596     {
3597       signed char val=(signed char) ulFromVal (AOP (right)->aopu.aop_lit);
3598       
3599       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3600       if (val < 0)
3601         emitcode ("ldx", "#0x%02x", -val);
3602       else
3603         emitcode ("ldx", "#0x%02x", val);
3604           
3605       emitcode ("mul", "");
3606           
3607       if (val < 0)
3608         {
3609           rmwWithReg ("neg", hc08_reg_a);
3610           tlbl4 = newiTempLabel (NULL);
3611           emitBranch ("bcc", tlbl4);
3612           rmwWithReg ("inc", hc08_reg_x);
3613           emitLabel (tlbl4);
3614           rmwWithReg ("neg", hc08_reg_x);
3615         }
3616       
3617       hc08_dirtyReg (hc08_reg_xa, FALSE);
3618       storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3619       hc08_freeReg (hc08_reg_xa);
3620       return;
3621     }
3622   
3623
3624   /* case 3 */
3625   adjustStack (-1);
3626   emitcode ("clr", "1,s");
3627
3628   loadRegFromAop (hc08_reg_a, AOP (left), 0);
3629   if (!lUnsigned)
3630     {
3631       tlbl1 = newiTempLabel (NULL);
3632       emitcode ("tsta","");
3633       emitBranch ("bpl", tlbl1);
3634       emitcode ("inc", "1,s");
3635       rmwWithReg ("neg", hc08_reg_a);
3636       emitLabel (tlbl1);
3637     }
3638
3639   if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3640     {
3641       signed char val=(signed char) ulFromVal (AOP (right)->aopu.aop_lit);
3642       /* AND literal negative */
3643       if (val < 0) {
3644         emitcode ("ldx", "#0x%02x", -val);
3645         negLiteral = TRUE;
3646       } else {
3647         emitcode ("ldx", "#0x%02x", val);
3648       }
3649       hc08_useReg (hc08_reg_x);
3650     }
3651   else
3652     {
3653       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3654       if (!rUnsigned)
3655         {
3656           tlbl2 = newiTempLabel (NULL);
3657           emitcode ("tstx", "");
3658           emitBranch ("bpl", tlbl2);
3659           emitcode ("inc", "1,s");
3660           rmwWithReg ("neg", hc08_reg_x);
3661           emitLabel (tlbl2);
3662         }
3663     }
3664
3665   emitcode ("mul", "");
3666   hc08_dirtyReg (hc08_reg_xa, FALSE);
3667
3668   tlbl3 = newiTempLabel (NULL);
3669   emitcode ("dec", "1,s");
3670   if (!lUnsigned && !rUnsigned && negLiteral)
3671     emitBranch ("beq", tlbl3);
3672   else
3673     emitBranch ("bne", tlbl3);
3674
3675   rmwWithReg ("neg", hc08_reg_a);
3676   tlbl4 = newiTempLabel (NULL);
3677   emitBranch ("bcc", tlbl4);
3678   rmwWithReg ("inc", hc08_reg_x);
3679   emitLabel (tlbl4);
3680   rmwWithReg ("neg", hc08_reg_x);
3681
3682   emitLabel (tlbl3);
3683   adjustStack (1);
3684   storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3685   hc08_freeReg (hc08_reg_xa);
3686
3687 }
3688
3689 /*-----------------------------------------------------------------*/
3690 /* genMult - generates code for multiplication                     */
3691 /*-----------------------------------------------------------------*/
3692 static void
3693 genMult (iCode * ic)
3694 {
3695   operand *left = IC_LEFT (ic);
3696   operand *right = IC_RIGHT (ic);
3697   operand *result = IC_RESULT (ic);
3698
3699   D(emitcode (";     genMult",""));
3700
3701   /* assign the amsops */
3702   aopOp (left, ic, FALSE);
3703   aopOp (right, ic, FALSE);
3704   aopOp (result, ic, TRUE);
3705
3706   /* special cases first */
3707   /* if both are of size == 1 */
3708 //  if (getSize(operandType(left)) == 1 && 
3709 //      getSize(operandType(right)) == 1)
3710   if (AOP_SIZE (left) == 1 && 
3711       AOP_SIZE (right) == 1)
3712     {
3713       genMultOneByte (left, right, result);
3714       goto release;
3715     }
3716
3717   /* should have been converted to function call */
3718     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3719              getSize(OP_SYMBOL(right)->type));
3720     fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3721              AOP_SIZE (right));
3722   assert (0);
3723
3724 release:
3725   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3726   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3727   freeAsmop (result, NULL, ic, TRUE);
3728 }
3729
3730 /*-----------------------------------------------------------------*/
3731 /* genDivOneByte : 8 bit division                                  */
3732 /*-----------------------------------------------------------------*/
3733 static void
3734 genDivOneByte (operand * left,
3735                operand * right,
3736                operand * result)
3737 {
3738   symbol *tlbl1, *tlbl2, *tlbl3;
3739   int size;
3740   int offset = 0;
3741   bool lUnsigned, rUnsigned;
3742   bool runtimeSign, compiletimeSign;
3743   
3744   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3745   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3746
3747   D(emitcode (";     genDivOneByte",""));
3748
3749   size = AOP_SIZE (result);
3750   /* signed or unsigned */
3751   if (lUnsigned && rUnsigned)
3752     {
3753       /* unsigned is easy */
3754       loadRegFromAop (hc08_reg_h, AOP (left), 1);
3755       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3756       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3757       emitcode ("div", "");
3758       hc08_dirtyReg (hc08_reg_a, FALSE);
3759       hc08_dirtyReg (hc08_reg_h, FALSE);
3760       storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3761       hc08_freeReg (hc08_reg_a);
3762       hc08_freeReg (hc08_reg_x);
3763       hc08_freeReg (hc08_reg_h);
3764       return;
3765     }
3766
3767   /* signed is a little bit more difficult */
3768
3769   /* now sign adjust for both left & right */
3770
3771   /* let's see what's needed: */
3772   /* apply negative sign during runtime */
3773   runtimeSign = FALSE;
3774   /* negative sign from literals */
3775   compiletimeSign = FALSE;
3776
3777   if (!lUnsigned)
3778     {
3779       if (AOP_TYPE(left) == AOP_LIT)
3780         {
3781           /* signed literal */
3782           signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
3783           if (val < 0)
3784             compiletimeSign = TRUE;
3785         }
3786       else
3787         /* signed but not literal */
3788         runtimeSign = TRUE;
3789     }
3790
3791   if (!rUnsigned)
3792     {
3793       if (AOP_TYPE(right) == AOP_LIT)
3794         {
3795           /* signed literal */
3796           signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
3797           if (val < 0)
3798             compiletimeSign ^= TRUE;
3799         }
3800       else
3801         /* signed but not literal */
3802         runtimeSign = TRUE;
3803     }
3804
3805   /* initialize the runtime sign */
3806   if (runtimeSign)
3807     {
3808       if (compiletimeSign)
3809         loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3810       else
3811         loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3812       pushReg (hc08_reg_x, TRUE);
3813     }
3814
3815   /* save the signs of the operands */
3816   if (AOP_TYPE(right) == AOP_LIT)
3817     {
3818       signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
3819
3820       if (!rUnsigned && val < 0)
3821         emitcode ("ldx", "#0x%02x", -val);
3822       else
3823         emitcode ("ldx", "#0x%02x", (unsigned char) val);
3824     }
3825   else /* ! literal */
3826     {
3827       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3828       if (!rUnsigned)
3829         {
3830           tlbl1 = newiTempLabel (NULL);
3831           emitcode ("tstx", "");
3832           emitBranch ("bpl", tlbl1);
3833           emitcode ("inc", "1,s");
3834           rmwWithReg ("neg", hc08_reg_x);
3835           emitLabel (tlbl1);
3836         }
3837     }
3838
3839   if (AOP_TYPE(left) == AOP_LIT)
3840     {
3841       signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
3842
3843       if (!lUnsigned && val < 0)
3844         emitcode ("lda", "#0x%02x", -val);
3845       else
3846         emitcode ("lda", "#0x%02x", (unsigned char) val);
3847     }
3848   else /* ! literal */
3849     {
3850       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3851       if (!lUnsigned)
3852         {
3853           tlbl2 = newiTempLabel (NULL);
3854           emitcode ("tsta", "");
3855           emitBranch ("bpl", tlbl2);
3856           emitcode ("inc", "1,s");
3857           rmwWithReg ("neg", hc08_reg_a);
3858           emitLabel (tlbl2);
3859         }
3860     }
3861     
3862   loadRegFromConst (hc08_reg_h, zero);
3863   emitcode ("div", "");
3864   hc08_dirtyReg (hc08_reg_x, FALSE);
3865   hc08_dirtyReg (hc08_reg_a, FALSE);
3866   hc08_dirtyReg (hc08_reg_h, FALSE);
3867   
3868   if (runtimeSign || compiletimeSign)
3869     {
3870       tlbl3 = newiTempLabel (NULL);
3871       if (runtimeSign)
3872         {
3873           pullReg (hc08_reg_x);
3874           rmwWithReg ("lsr", hc08_reg_x);
3875           rmwWithReg ("ror", hc08_reg_x);
3876           emitBranch ("bpl", tlbl3);
3877         }
3878      
3879       rmwWithReg ("neg", hc08_reg_a);
3880       if (runtimeSign)
3881         emitLabel (tlbl3);
3882       
3883       storeRegToAop (hc08_reg_a, AOP (result), 0);
3884       
3885       if (size > 1)
3886         {
3887           /* msb is 0x00 or 0xff depending on the sign */
3888           if (runtimeSign)
3889             {
3890               rmwWithReg ("lsl", hc08_reg_x);
3891               emitcode ("clra", "");
3892               emitcode ("sbc", "#0");
3893               while (--size)
3894                 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3895             }
3896           else /* compiletimeSign */
3897             while (--size)
3898               storeConstToAop ("#0xff", AOP (result), ++offset);
3899         }
3900     }
3901   else
3902     {
3903       storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3904     }
3905
3906   hc08_freeReg (hc08_reg_a);
3907   hc08_freeReg (hc08_reg_x);
3908   hc08_freeReg (hc08_reg_h);
3909 }
3910
3911 /*-----------------------------------------------------------------*/
3912 /* genDiv - generates code for division                            */
3913 /*-----------------------------------------------------------------*/
3914 static void
3915 genDiv (iCode * ic)
3916 {
3917   operand *left = IC_LEFT (ic);
3918   operand *right = IC_RIGHT (ic);
3919   operand *result = IC_RESULT (ic);
3920
3921   D(emitcode (";     genDiv",""));
3922
3923   /* assign the amsops */
3924   aopOp (left, ic, FALSE);
3925   aopOp (right, ic, FALSE);
3926   aopOp (result, ic, TRUE);
3927
3928   /* special cases first */
3929   /* if both are of size == 1 */
3930   if (AOP_SIZE (left) <= 2 &&
3931       AOP_SIZE (right) == 1)
3932     {
3933       genDivOneByte (left, right, result);
3934       goto release;
3935     }
3936
3937   /* should have been converted to function call */
3938   assert (0);
3939 release:
3940   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3941   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3942   freeAsmop (result, NULL, ic, TRUE);
3943 }
3944
3945 /*-----------------------------------------------------------------*/
3946 /* genModOneByte : 8 bit modulus                                   */
3947 /*-----------------------------------------------------------------*/
3948 static void
3949 genModOneByte (operand * left,
3950                operand * right,
3951                operand * result)
3952 {
3953   symbol *tlbl1, *tlbl2, *tlbl3;
3954   int size;
3955   int offset = 0;
3956   bool lUnsigned, rUnsigned;
3957   bool runtimeSign, compiletimeSign;
3958   
3959   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3960   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3961
3962   D(emitcode (";     genModOneByte",""));
3963
3964   size = AOP_SIZE (result);
3965   
3966   if (lUnsigned && rUnsigned)
3967     {
3968       /* unsigned is easy */
3969       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3970       loadRegFromAop (hc08_reg_h, AOP (left), 1);
3971       loadRegFromAop (hc08_reg_a, AOP (left), 0);
3972       emitcode ("div", "");
3973       hc08_freeReg (hc08_reg_a);
3974       hc08_freeReg (hc08_reg_x);
3975       hc08_dirtyReg (hc08_reg_h, FALSE);
3976       storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3977       hc08_freeReg (hc08_reg_h);
3978       return;
3979     }
3980
3981   /* signed is a little bit more difficult */
3982   
3983   if (AOP_TYPE(right) == AOP_LIT)
3984     {
3985       signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
3986
3987       if (!rUnsigned && val < 0)
3988         emitcode ("ldx", "#0x%02x", -val);
3989       else
3990         emitcode ("ldx", "#0x%02x", (unsigned char) val);
3991     }
3992   else /* ! literal */
3993     {
3994       loadRegFromAop (hc08_reg_x, AOP (right), 0);
3995       if (!rUnsigned)
3996         {
3997           tlbl1 = newiTempLabel (NULL);
3998           emitcode ("tstx", "");
3999           emitBranch ("bpl", tlbl1);
4000           rmwWithReg ("neg", hc08_reg_x);
4001           emitLabel (tlbl1);
4002         }
4003     }
4004   
4005   /* let's see what's needed: */
4006   /* apply negative sign during runtime */
4007   runtimeSign = FALSE;
4008   /* negative sign from literals */
4009   compiletimeSign = FALSE;
4010
4011   /* sign adjust left side */
4012   if (AOP_TYPE(left) == AOP_LIT)
4013     {
4014       signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
4015
4016       if (!lUnsigned && val < 0)
4017         {
4018           compiletimeSign = TRUE; /* set sign flag */
4019           emitcode ("lda", "#0x%02x", -val);
4020         }
4021       else
4022         emitcode ("lda", "#0x%02x", (unsigned char) val);
4023     }
4024   else /* ! literal */
4025     {
4026       if (lUnsigned)
4027         loadRegFromAop (hc08_reg_a, AOP (left), 0);
4028       else
4029         {
4030           runtimeSign = TRUE;
4031           adjustStack (-1);
4032           emitcode ("clr", "1,s");
4033           
4034           loadRegFromAop (hc08_reg_a, AOP (left), 0);
4035           tlbl2 = newiTempLabel (NULL);
4036           emitcode ("tsta", "");
4037           emitBranch ("bpl", tlbl2);
4038           emitcode ("inc", "1,s");
4039           rmwWithReg ("neg", hc08_reg_a);
4040           emitLabel (tlbl2);
4041         }
4042     }
4043   
4044   loadRegFromConst (hc08_reg_h, zero);
4045   emitcode ("div", "");
4046   hc08_freeReg (hc08_reg_a);
4047   hc08_freeReg (hc08_reg_x);
4048   hc08_dirtyReg (hc08_reg_h, FALSE);
4049
4050   if (runtimeSign || compiletimeSign)
4051     {
4052       transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4053       tlbl3 = newiTempLabel (NULL);
4054       if (runtimeSign)
4055         {
4056           pullReg (hc08_reg_x);
4057           rmwWithReg ("lsr", hc08_reg_x);
4058           rmwWithReg ("ror", hc08_reg_x);
4059           emitBranch ("bpl", tlbl3);
4060         }
4061      
4062       rmwWithReg ("neg", hc08_reg_a);
4063       if (runtimeSign)
4064         emitLabel (tlbl3);
4065       
4066       storeRegToAop (hc08_reg_a, AOP (result), 0);
4067       
4068       if (size > 1)
4069         {
4070           /* msb is 0x00 or 0xff depending on the sign */
4071           if (runtimeSign)
4072             {
4073               rmwWithReg ("lsl", hc08_reg_x);
4074               emitcode ("clra", "");
4075               emitcode ("sbc", "#0");
4076               while (--size)
4077                 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4078             }
4079           else /* compiletimeSign */
4080             while (--size)
4081               storeConstToAop ("#0xff", AOP (result), ++offset);
4082         }
4083     }
4084   else
4085     {
4086       storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4087     }
4088   
4089   hc08_freeReg (hc08_reg_a);
4090   hc08_freeReg (hc08_reg_x);
4091   hc08_freeReg (hc08_reg_h);
4092 }
4093
4094 /*-----------------------------------------------------------------*/
4095 /* genMod - generates code for division                            */
4096 /*-----------------------------------------------------------------*/
4097 static void
4098 genMod (iCode * ic)
4099 {
4100   operand *left = IC_LEFT (ic);
4101   operand *right = IC_RIGHT (ic);
4102   operand *result = IC_RESULT (ic);
4103
4104   D(emitcode (";     genMod",""));
4105
4106   /* assign the amsops */
4107   aopOp (left, ic, FALSE);
4108   aopOp (right, ic, FALSE);
4109   aopOp (result, ic, TRUE);
4110
4111   /* special cases first */
4112   /* if both are of size == 1 */
4113   if (AOP_SIZE (left) <= 2 &&
4114       AOP_SIZE (right) == 1)
4115     {
4116       genModOneByte (left, right, result);
4117       goto release;
4118     }
4119
4120   /* should have been converted to function call */
4121   assert (0);
4122
4123 release:
4124   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4125   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4126   freeAsmop (result, NULL, ic, TRUE);
4127 }
4128
4129 /*-----------------------------------------------------------------*/
4130 /* genIfxJump :- will create a jump depending on the ifx           */
4131 /*-----------------------------------------------------------------*/
4132 static void
4133 genIfxJump (iCode * ic, char *jval)
4134 {
4135   symbol *jlbl;
4136   symbol *tlbl = newiTempLabel (NULL);
4137   char *inst;
4138
4139   D(emitcode (";     genIfxJump",""));
4140
4141   /* if true label then we jump if condition
4142      supplied is true */
4143   if (IC_TRUE (ic))
4144     {
4145       jlbl = IC_TRUE (ic);
4146       if (!strcmp (jval, "a"))
4147         inst = "beq";
4148       else if (!strcmp (jval, "c"))
4149         inst = "bcc";
4150       else
4151         inst = "bge";
4152     }
4153   else
4154     {
4155       /* false label is present */
4156       jlbl = IC_FALSE (ic);
4157       if (!strcmp (jval, "a"))
4158         inst = "bne";
4159       else if (!strcmp (jval, "c"))
4160         inst = "bcs";
4161       else
4162         inst = "blt";
4163     }
4164   emitBranch (inst, tlbl);
4165   emitBranch ("jmp", jlbl);
4166   emitLabel (tlbl);
4167
4168   /* mark the icode as generated */
4169   ic->generated = 1;
4170 }
4171
4172
4173 /*-----------------------------------------------------------------*/
4174 /* exchangedCmp : returns the opcode need if the two operands are  */
4175 /*                exchanged in a comparison                        */
4176 /*-----------------------------------------------------------------*/
4177 static int
4178 exchangedCmp (int opcode)
4179 {
4180   switch (opcode)
4181     {
4182     case '<':
4183       return '>';
4184     case '>':
4185       return '<';
4186     case LE_OP:
4187       return GE_OP;
4188     case GE_OP:
4189       return LE_OP;
4190     case NE_OP:
4191       return NE_OP;
4192     case EQ_OP:
4193       return EQ_OP;
4194     default:
4195       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4196                   "opcode not a comparison");
4197     }
4198   return EQ_OP; /* shouldn't happen, but need to return something */
4199 }
4200
4201 /*------------------------------------------------------------------*/
4202 /* negatedCmp : returns the equivalent opcode for when a comparison */
4203 /*              if not true                                         */
4204 /*------------------------------------------------------------------*/
4205 static int
4206 negatedCmp (int opcode)
4207 {
4208   switch (opcode)
4209     {
4210     case '<':
4211       return GE_OP;
4212     case '>':
4213       return LE_OP;
4214     case LE_OP:
4215       return '>';
4216     case GE_OP:
4217       return '<';
4218     case NE_OP:
4219       return EQ_OP;
4220     case EQ_OP:
4221       return NE_OP;
4222     default:
4223       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4224                   "opcode not a comparison");
4225     }
4226   return EQ_OP; /* shouldn't happen, but need to return something */
4227 }
4228
4229 /*------------------------------------------------------------------*/
4230 /* nameCmp : helper function for human readable debug output        */
4231 /*------------------------------------------------------------------*/
4232 static char *
4233 nameCmp (int opcode)
4234 {
4235   switch (opcode)
4236     {
4237     case '<':
4238       return "<";
4239     case '>':
4240       return ">";
4241     case LE_OP:
4242       return "<=";
4243     case GE_OP:
4244       return ">=";
4245     case NE_OP:
4246       return "!=";
4247     case EQ_OP:
4248       return "==";
4249     default:
4250       return "invalid";
4251     }
4252 }
4253
4254 /*------------------------------------------------------------------*/
4255 /* branchInstCmp : returns the conditional branch instruction that  */
4256 /*                 will branch if the comparison is true            */
4257 /*------------------------------------------------------------------*/
4258 static char *
4259 branchInstCmp (int opcode, int sign)
4260 {
4261   switch (opcode)
4262     {
4263     case '<':
4264       if (sign)
4265         return "blt";
4266       else
4267         return "bcs";   /* same as blo */
4268     case '>':
4269       if (sign)
4270         return "bgt";
4271       else
4272         return "bhi";
4273     case LE_OP:
4274       if (sign)
4275         return "ble";
4276       else
4277         return "bls";
4278     case GE_OP:
4279       if (sign)
4280         return "bge";
4281       else
4282         return "bcc";   /* same as bhs */
4283     case NE_OP:
4284       return "bne";
4285     case EQ_OP:
4286       return "beq";
4287     default:
4288       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4289                   "opcode not a comparison");
4290     }
4291   return "brn";
4292 }
4293
4294
4295 /*------------------------------------------------------------------*/
4296 /* genCmp :- greater or less than (and maybe with equal) comparison */
4297 /*------------------------------------------------------------------*/
4298 static void
4299 genCmp (iCode * ic, iCode * ifx)
4300 {  
4301   operand *left, *right, *result;
4302   sym_link *letype, *retype;
4303   int sign, opcode;
4304   int size, offset = 0;
4305   unsigned long lit = 0L;
4306   char *sub;
4307   symbol *jlbl = NULL;
4308
4309   opcode = ic->op;
4310
4311   D(emitcode (";     genCmp", "(%s)",nameCmp (opcode)));
4312
4313   result = IC_RESULT (ic);
4314   left = IC_LEFT (ic);
4315   right = IC_RIGHT (ic);
4316
4317   letype = getSpec (operandType (left));
4318   retype = getSpec (operandType (right));
4319   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4320   /* assign the amsops */
4321   aopOp (left, ic, FALSE);
4322   aopOp (right, ic, FALSE);
4323   aopOp (result, ic, TRUE);
4324
4325   /* need register operand on left, prefer literal operand on right */
4326   if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4327     {
4328       operand *temp = left;
4329       left = right;
4330       right = temp;
4331       opcode = exchangedCmp (opcode);
4332     }
4333
4334   if (ifx)
4335     {
4336       if (IC_TRUE (ifx))
4337         {
4338           jlbl = IC_TRUE (ifx);
4339           opcode = negatedCmp (opcode);
4340         }
4341       else
4342         {
4343           /* false label is present */
4344           jlbl = IC_FALSE (ifx);
4345         }
4346     }
4347       
4348   size = max (AOP_SIZE (left), AOP_SIZE (right));
4349   
4350   if ((size == 2)
4351       && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4352       && ((AOP_TYPE (right) == AOP_LIT) || 
4353           ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4354       && hc08_reg_hx->isFree)
4355     {
4356       loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4357       emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4358       hc08_freeReg (hc08_reg_hx);
4359     }
4360   else
4361     {
4362       offset = 0;
4363       if (size == 1)
4364         sub = "cmp";
4365       else
4366         {
4367           sub = "sub";
4368         
4369           /* These conditions depend on the Z flag bit, but Z is */
4370           /* only valid for the last byte of the comparison, not */
4371           /* the whole value. So exchange the operands to get a  */
4372           /* comparison that doesn't depend on Z. (This is safe  */
4373           /* to do here since ralloc won't assign multi-byte     */
4374           /* operands to registers for comparisons)              */
4375           if ((opcode == '>') || (opcode == LE_OP))
4376             {
4377               operand *temp = left;
4378               left = right;
4379               right = temp;
4380               opcode = exchangedCmp (opcode);
4381             }
4382           
4383           if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
4384             {
4385               lit = ulFromVal (AOP (right)->aopu.aop_lit);
4386               while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
4387                 {
4388                   offset++;
4389                   size--;
4390                 }
4391             }
4392         }
4393       while (size--)
4394         {
4395           loadRegFromAop (hc08_reg_a, AOP (left), offset);
4396           accopWithAop (sub, AOP (right), offset);
4397           hc08_freeReg (hc08_reg_a);
4398           offset++;
4399           sub = "sbc";
4400         }
4401     }
4402   freeAsmop (right, NULL, ic, FALSE);
4403   freeAsmop (left, NULL, ic, FALSE);
4404
4405   if (ifx)
4406     {
4407       symbol *tlbl = newiTempLabel (NULL);
4408       char *inst;
4409
4410       freeAsmop (result, NULL, ic, TRUE);      
4411       
4412       inst = branchInstCmp (opcode, sign);
4413       emitBranch (inst, tlbl);
4414       emitBranch ("jmp", jlbl);
4415       emitLabel (tlbl);
4416
4417       /* mark the icode as generated */
4418       ifx->generated = 1;
4419     }
4420   else
4421     {
4422       symbol *tlbl1 = newiTempLabel (NULL);
4423       symbol *tlbl2 = newiTempLabel (NULL);
4424       
4425       emitBranch (branchInstCmp (opcode, sign), tlbl1);
4426       loadRegFromConst (hc08_reg_a, zero);
4427       emitBranch ("bra", tlbl2);
4428       emitLabel (tlbl1);
4429       loadRegFromConst (hc08_reg_a, one);
4430       emitLabel (tlbl2);
4431       storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4432       freeAsmop (result, NULL, ic, TRUE);      
4433     }
4434         
4435 }
4436
4437 /*-----------------------------------------------------------------*/
4438 /* genCmpEQorNE - equal or not equal comparison                    */
4439 /*-----------------------------------------------------------------*/
4440 static void
4441 genCmpEQorNE (iCode * ic, iCode * ifx)
4442 {  
4443   operand *left, *right, *result;
4444   sym_link *letype, *retype;
4445   int sign, opcode;
4446   int size, offset = 0;
4447   char *sub;
4448   symbol *jlbl = NULL;
4449   symbol *tlbl_NE = NULL;
4450   symbol *tlbl_EQ = NULL;
4451  
4452   opcode = ic->op;
4453
4454   D(emitcode (";     genCmpEQorNE", "(%s)",nameCmp (opcode)));
4455
4456   result = IC_RESULT (ic);
4457   left = IC_LEFT (ic);
4458   right = IC_RIGHT (ic);
4459
4460   letype = getSpec (operandType (left));
4461   retype = getSpec (operandType (right));
4462   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4463   /* assign the amsops */
4464   aopOp (left, ic, FALSE);
4465   aopOp (right, ic, FALSE);
4466   aopOp (result, ic, TRUE);
4467   
4468   /* need register operand on left, prefer literal operand on right */
4469   if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4470     {
4471       operand *temp = left;
4472       left = right;
4473       right = temp;
4474       opcode = exchangedCmp (opcode);
4475     }
4476
4477   if (ifx)
4478     {
4479       if (IC_TRUE (ifx))
4480         {
4481           jlbl = IC_TRUE (ifx);
4482           opcode = negatedCmp (opcode);
4483         }
4484       else
4485         {
4486           /* false label is present */
4487           jlbl = IC_FALSE (ifx);
4488         }
4489     }
4490       
4491   size = max (AOP_SIZE (left), AOP_SIZE (right));
4492   
4493   if ((size == 2)
4494       && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4495       && ((AOP_TYPE (right) == AOP_LIT) || 
4496           ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4497       && hc08_reg_hx->isFree)
4498     {
4499       loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4500       emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4501       hc08_freeReg (hc08_reg_hx);
4502     }
4503   else
4504     {
4505       offset = 0;
4506       sub = "cmp";
4507       while (size--)
4508         {
4509           loadRegFromAop (hc08_reg_a, AOP (left), offset);
4510           accopWithAop (sub, AOP (right), offset);
4511           if (size)
4512             {
4513               if (!tlbl_NE)
4514                 tlbl_NE = newiTempLabel (NULL);
4515               emitBranch ("bne", tlbl_NE);
4516             }
4517           hc08_freeReg (hc08_reg_a);
4518           offset++;
4519         }
4520     }
4521   freeAsmop (right, NULL, ic, FALSE);
4522   freeAsmop (left, NULL, ic, FALSE);
4523
4524   if (ifx)
4525     {
4526       freeAsmop (result, NULL, ic, TRUE);      
4527       
4528       if (opcode == EQ_OP)
4529         {
4530           if (!tlbl_EQ)
4531             tlbl_EQ = newiTempLabel (NULL);
4532           emitBranch ("beq", tlbl_EQ);
4533           if (tlbl_NE)
4534             emitLabel (tlbl_NE);
4535           emitBranch ("jmp", jlbl);
4536           emitLabel (tlbl_EQ);
4537         }
4538       else
4539         {
4540           if (!tlbl_NE)
4541             tlbl_NE = newiTempLabel (NULL);
4542           emitBranch ("bne", tlbl_NE);
4543           emitBranch ("jmp", jlbl);
4544           emitLabel (tlbl_NE);
4545         }
4546
4547       /* mark the icode as generated */
4548       ifx->generated = 1;
4549     }
4550   else
4551     {
4552       symbol *tlbl = newiTempLabel (NULL);
4553       
4554       if (opcode == EQ_OP)
4555         {
4556           if (!tlbl_EQ)
4557             tlbl_EQ = newiTempLabel (NULL);
4558           emitBranch ("beq", tlbl_EQ);
4559           if (tlbl_NE)
4560             emitLabel (tlbl_NE);
4561           loadRegFromConst (hc08_reg_a, zero);
4562           emitBranch ("bra", tlbl);
4563           emitLabel (tlbl_EQ);
4564           loadRegFromConst (hc08_reg_a, one);
4565         }
4566       else
4567         {
4568           if (!tlbl_NE)
4569             tlbl_NE = newiTempLabel (NULL);
4570           emitBranch ("bne", tlbl_NE);
4571           loadRegFromConst (hc08_reg_a, zero);
4572           emitBranch ("bra", tlbl);
4573           emitLabel (tlbl_NE);
4574           loadRegFromConst (hc08_reg_a, one);
4575         }
4576       
4577       emitLabel (tlbl);
4578       storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4579       freeAsmop (result, NULL, ic, TRUE);      
4580     }
4581         
4582 }
4583
4584
4585 /*-----------------------------------------------------------------*/
4586 /* ifxForOp - returns the icode containing the ifx for operand     */
4587 /*-----------------------------------------------------------------*/
4588 static iCode *
4589 ifxForOp (operand * op, iCode * ic)
4590 {
4591   /* if true symbol then needs to be assigned */
4592   if (IS_TRUE_SYMOP (op))
4593     return NULL;
4594
4595   /* if this has register type condition and
4596      the next instruction is ifx with the same operand
4597      and live to of the operand is upto the ifx only then */
4598   if (ic->next &&
4599       ic->next->op == IFX &&
4600       IC_COND (ic->next)->key == op->key &&
4601       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4602     return ic->next;
4603
4604   return NULL;
4605 }
4606
4607 static bool
4608 genPointerGetSetOfs (iCode *ic)
4609 {
4610   iCode *lic = ic->next;
4611   bool pset, pget;
4612   int size;
4613   symbol *sym;
4614   asmop *derefaop;
4615
4616   /* Make sure we have a next iCode */
4617   DD(emitcode("","; checking lic"));
4618   if (!lic)
4619     return FALSE;
4620
4621   /* Make sure the result of the addition is an iCode */
4622   DD(emitcode("","; checking IS_ITEMP"));
4623   if (!IS_ITEMP (IC_RESULT (ic)))
4624     return FALSE;
4625
4626   /* Make sure the next iCode is a pointer set or get */
4627   pset = POINTER_SET(lic);
4628   pget = POINTER_GET(lic);
4629   DD(emitcode("","; pset=%d, pget=%d",pset,pget));
4630   if (!pset && !pget)
4631     return FALSE;
4632
4633   /* Make sure this is the only use of the pointer */
4634   if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4635     return FALSE;
4636     
4637   DD(emitcode("", "; checking pset operandsEqu"));
4638   if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4639     return FALSE;
4640
4641   DD(emitcode("", "; checking pget operandsEqu"));
4642   if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4643     return FALSE;
4644
4645   DD(emitcode("", "; checking IS_SYMOP"));
4646   if (!IS_SYMOP (IC_LEFT (ic)))
4647     return FALSE;
4648
4649   DD(emitcode("", "; checking !IS_TRUE_SYMOP"));
4650   if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4651     return FALSE;
4652
4653   sym = OP_SYMBOL (IC_LEFT (ic));
4654   
4655   DD(emitcode("", "; checking remat"));
4656   if (!sym->remat)
4657     return FALSE;
4658     
4659   
4660   if (pget)
4661     {
4662       D(emitcode (";     genPointerGetOfs",""));
4663       aopOp (IC_LEFT(ic), ic, FALSE);
4664       derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4665       freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4666       
4667       aopOp (IC_RIGHT(ic), ic, FALSE);
4668       aopOp (IC_RESULT(lic), lic, FALSE);
4669
4670       if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4671         {
4672           if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4673             {
4674               loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4675               loadRegFromConst (hc08_reg_h, zero);
4676             }
4677           else
4678             {
4679               loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4680               transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4681               emitcode ("rola","");
4682               emitcode ("clra","");
4683               emitcode ("sbc", "#0");
4684               hc08_useReg (hc08_reg_a);
4685               transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4686            }
4687         }
4688       else
4689         loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4690       size = AOP_SIZE (IC_RESULT(lic));
4691       derefaop->size = size;
4692       
4693       while (size--)
4694         {
4695           emitcode ("lda", "%s,x",
4696                     aopAdrStr (derefaop, size, TRUE));
4697           hc08_useReg (hc08_reg_a);
4698           storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
4699           hc08_freeReg (hc08_reg_a);
4700         }
4701
4702       lic->generated = 1;
4703       hc08_freeReg (hc08_reg_hx);
4704
4705       freeAsmop (NULL, derefaop, ic, TRUE);
4706       freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4707       freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4708       
4709       return TRUE;
4710     }
4711
4712   if (pset)
4713     {
4714       D(emitcode (";     genPointerSetOfs",""));
4715       aopOp (IC_LEFT(ic), ic, FALSE);
4716       derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4717       freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4718
4719       aopOp (IC_RIGHT(ic), ic, FALSE);
4720       aopOp (IC_RIGHT(lic), lic, FALSE);
4721       
4722       if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4723         {
4724           if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4725             {
4726               loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4727               loadRegFromConst (hc08_reg_h, zero);
4728             }
4729           else
4730             {
4731               loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4732               transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4733               emitcode ("rola","");
4734               emitcode ("clra","");
4735               emitcode ("sbc", "#0");
4736               hc08_useReg (hc08_reg_a);
4737               transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4738            }
4739         }
4740       else
4741         loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4742       size = AOP_SIZE (IC_RIGHT(lic));
4743       derefaop->size = size;
4744       
4745       while (size--)
4746         {
4747           loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
4748           emitcode ("sta", "%s,x",
4749                     aopAdrStr (derefaop, size, TRUE));
4750           hc08_freeReg (hc08_reg_a);
4751         }
4752
4753       lic->generated = 1;
4754       hc08_freeReg (hc08_reg_hx);
4755
4756       freeAsmop (NULL, derefaop, ic, TRUE);
4757       freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4758       freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4759       
4760       return TRUE;
4761     }
4762     
4763   return FALSE;
4764 }
4765
4766
4767 /*-----------------------------------------------------------------*/
4768 /* hasInc - operand is incremented before any other use            */
4769 /*-----------------------------------------------------------------*/
4770 static iCode *
4771 hasInc (operand *op, iCode *ic,int osize)
4772 {
4773   sym_link *type = operandType(op);
4774   sym_link *retype = getSpec (type);
4775   iCode *lic = ic->next;
4776   int isize ;
4777   
4778   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4779   if (!IS_SYMOP(op)) return NULL;
4780
4781   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4782   if (IS_AGGREGATE(type->next)) return NULL;
4783   if (osize != (isize = getSize(type->next))) return NULL;
4784
4785   while (lic) {
4786     /* if operand of the form op = op + <sizeof *op> */
4787     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4788         isOperandEqual(IC_RESULT(lic),op) && 
4789         isOperandLiteral(IC_RIGHT(lic)) &&
4790         operandLitValue(IC_RIGHT(lic)) == isize) {
4791       return lic;
4792     }
4793     /* if the operand used or deffed */
4794     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
4795       return NULL;
4796     }
4797     /* if GOTO or IFX */
4798     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4799     lic = lic->next;
4800   }
4801   return NULL;
4802 }
4803
4804 /*-----------------------------------------------------------------*/
4805 /* genAndOp - for && operation                                     */
4806 /*-----------------------------------------------------------------*/
4807 static void
4808 genAndOp (iCode * ic)
4809 {
4810   operand *left, *right, *result;
4811   symbol *tlbl, *tlbl0;
4812
4813   D(emitcode (";     genAndOp",""));
4814
4815   /* note here that && operations that are in an
4816      if statement are taken away by backPatchLabels
4817      only those used in arthmetic operations remain */
4818   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4819   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4820   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4821
4822   tlbl = newiTempLabel (NULL);
4823   tlbl0 = newiTempLabel (NULL);
4824   
4825   asmopToBool (AOP (left), FALSE);
4826   emitBranch ("beq", tlbl0);
4827   asmopToBool (AOP (right), FALSE);
4828   emitBranch ("beq", tlbl0);
4829   loadRegFromConst (hc08_reg_a,one);
4830   emitBranch ("bra", tlbl);
4831   emitLabel (tlbl0);
4832   loadRegFromConst (hc08_reg_a,zero);
4833   emitLabel (tlbl);
4834
4835   hc08_useReg (hc08_reg_a);
4836   hc08_freeReg (hc08_reg_a);
4837   
4838   storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4839
4840   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4841   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4842   freeAsmop (result, NULL, ic, TRUE);
4843 }
4844
4845
4846 /*-----------------------------------------------------------------*/
4847 /* genOrOp - for || operation                                      */
4848 /*-----------------------------------------------------------------*/
4849 static void
4850 genOrOp (iCode * ic)
4851 {
4852   operand *left, *right, *result;
4853   symbol *tlbl, *tlbl0;
4854
4855   D(emitcode (";     genOrOp",""));
4856
4857   /* note here that || operations that are in an
4858      if statement are taken away by backPatchLabels
4859      only those used in arthmetic operations remain */
4860   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4861   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4862   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4863
4864   tlbl = newiTempLabel (NULL);
4865   tlbl0 = newiTempLabel (NULL);
4866   
4867   asmopToBool (AOP (left), FALSE);
4868   emitBranch ("bne", tlbl0);
4869   asmopToBool (AOP (right), FALSE);
4870   emitBranch ("bne", tlbl0);
4871   loadRegFromConst (hc08_reg_a,zero);
4872   emitBranch ("bra", tlbl);
4873   emitLabel (tlbl0);
4874   loadRegFromConst (hc08_reg_a,one);
4875   emitLabel (tlbl);
4876
4877   hc08_useReg (hc08_reg_a);
4878   hc08_freeReg (hc08_reg_a);
4879   
4880   storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4881
4882
4883   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4884   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4885   freeAsmop (result, NULL, ic, TRUE);
4886 }
4887
4888 /*-----------------------------------------------------------------*/
4889 /* isLiteralBit - test if lit == 2^n                               */
4890 /*-----------------------------------------------------------------*/
4891 static int
4892 isLiteralBit (unsigned long lit)
4893 {
4894   unsigned long pw[32] =
4895   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4896    0x100L, 0x200L, 0x400L, 0x800L,
4897    0x1000L, 0x2000L, 0x4000L, 0x8000L,
4898    0x10000L, 0x20000L, 0x40000L, 0x80000L,
4899    0x100000L, 0x200000L, 0x400000L, 0x800000L,
4900    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4901    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4902   int idx;
4903
4904   for (idx = 0; idx < 32; idx++)
4905     if (lit == pw[idx])
4906       return idx + 1;
4907   return 0;
4908 }
4909
4910 #if 0
4911 /*-----------------------------------------------------------------*/
4912 /* continueIfTrue -                                                */
4913 /*-----------------------------------------------------------------*/
4914 static void
4915 continueIfTrue (iCode * ic)
4916 {
4917   if (IC_TRUE (ic))
4918     emitBranch ("jmp", IC_TRUE (ic));
4919   ic->generated = 1;
4920 }
4921
4922 /*-----------------------------------------------------------------*/
4923 /* jmpIfTrue -                                                     */
4924 /*-----------------------------------------------------------------*/
4925 static void
4926 jumpIfTrue (iCode * ic)
4927 {
4928   if (!IC_TRUE (ic))
4929     emitBranch ("jmp", IC_FALSE (ic));
4930   ic->generated = 1;
4931 }
4932
4933 /*-----------------------------------------------------------------*/
4934 /* jmpTrueOrFalse -                                                */
4935 /*-----------------------------------------------------------------*/
4936 static void
4937 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4938 {
4939   // ugly but optimized by peephole
4940   if (IC_TRUE (ic))
4941     {
4942       symbol *nlbl = newiTempLabel (NULL);
4943       emitBranch ("bra", nlbl);
4944       emitLabel (tlbl);
4945       emitBranch ("jmp", IC_TRUE (ic));
4946       emitLabel (nlbl);
4947     }
4948   else
4949     {
4950       emitBranch ("jmp", IC_FALSE (ic));
4951       emitLabel (tlbl);
4952     }
4953   ic->generated = 1;
4954 }
4955 #endif
4956
4957 /*-----------------------------------------------------------------*/
4958 /* genAnd  - code for and                                          */
4959 /*-----------------------------------------------------------------*/
4960 static void
4961 genAnd (iCode * ic, iCode * ifx)
4962 {
4963   operand *left, *right, *result;
4964   int size, offset = 0;
4965   unsigned long lit = 0L;
4966   unsigned long litinv;
4967   unsigned char bytemask;
4968
4969   
4970 //  int bytelit = 0;
4971 //  char buffer[10];
4972
4973   D(emitcode (";     genAnd",""));
4974
4975   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4976   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4977   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4978
4979 #ifdef DEBUG_TYPE
4980   DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4981             AOP_TYPE (result),
4982             AOP_TYPE (left), AOP_TYPE (right)));
4983   DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4984             AOP_SIZE (result),
4985             AOP_SIZE (left), AOP_SIZE (right)));
4986 #endif
4987
4988   /* if left is a literal & right is not then exchange them */
4989   if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4990     {
4991       operand *tmp = right;
4992       right = left;
4993       left = tmp;
4994     }
4995
4996   /* if right is accumulator & left is not then exchange them */
4997   if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4998     {
4999       operand *tmp = right;
5000       right = left;
5001       left = tmp;
5002     }
5003
5004   if (AOP_TYPE (right) == AOP_LIT)
5005     lit = ulFromVal (AOP (right)->aopu.aop_lit);
5006       
5007   size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5008   
5009   if (AOP_TYPE (result) == AOP_CRY
5010       && size > 1
5011       && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5012     {
5013       /* this generates ugly code, but meets volatility requirements */
5014       loadRegFromConst (hc08_reg_a, zero);
5015       pushReg (hc08_reg_a, TRUE);
5016       
5017       offset = 0;
5018       while (size--)
5019         {
5020           loadRegFromAop (hc08_reg_a, AOP (left), offset);
5021           accopWithAop ("and", AOP (right), offset);
5022           emitcode ("ora", "1,s");
5023           emitcode ("sta", "1,s");
5024           offset++;
5025         }
5026       
5027       pullReg (hc08_reg_a);
5028       emitcode ("tsta", "");
5029       genIfxJump (ifx, "a");
5030       goto release;
5031     }
5032   
5033   if (AOP_TYPE (result) == AOP_CRY)
5034     {
5035       symbol *tlbl = NULL;
5036       wassertl (ifx, "AOP_CRY result without ifx");
5037       
5038       offset = 0;
5039       while (size--)
5040         {
5041           bytemask = (lit >> (offset*8)) & 0xff;
5042           
5043           if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5044             {
5045               /* do nothing */
5046             }
5047           else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5048             {
5049               rmwWithAop ("tst", AOP (left), offset);
5050               if (size)
5051                 {
5052                   if (!tlbl)
5053                     tlbl = newiTempLabel (NULL);
5054                   emitBranch ("bne", tlbl);
5055                 }
5056             }
5057           else
5058             {
5059               loadRegFromAop (hc08_reg_a, AOP (left), offset);
5060               accopWithAop ("and", AOP (right), offset);
5061               hc08_freeReg( hc08_reg_a);
5062               if (size)
5063                 {
5064                   if (!tlbl)
5065                     tlbl = newiTempLabel (NULL);
5066                   emitBranch ("bne", tlbl);
5067                 }
5068             }
5069           offset++;
5070         }
5071         if (tlbl)
5072           emitLabel (tlbl);
5073         genIfxJump (ifx, "a");
5074         goto release;
5075     }
5076   
5077   size = AOP_SIZE (result);
5078
5079   if (AOP_TYPE (right) == AOP_LIT)
5080     {
5081       litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
5082       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5083           (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
5084         {
5085           int bitpos = isLiteralBit(litinv)-1;
5086           emitcode ("bclr","#%d,%s",bitpos & 7,
5087                     aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5088           goto release;
5089         }
5090     }
5091     
5092   offset = 0;
5093   while (size--)
5094     {
5095       bytemask = (lit >> (offset*8)) & 0xff;
5096       
5097       if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5098         {
5099           if (isOperandVolatile (left, FALSE))
5100             {
5101               loadRegFromAop (hc08_reg_a, AOP (left), offset);
5102               hc08_freeReg( hc08_reg_a);      
5103             }
5104           storeConstToAop (zero, AOP (result), offset);
5105         }
5106       else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5107         {
5108           transferAopAop (AOP (left), offset, AOP (result), offset);
5109         }
5110       else
5111         {
5112           loadRegFromAop (hc08_reg_a, AOP (left), offset);
5113           accopWithAop ("and", AOP (right), offset);
5114           storeRegToAop (hc08_reg_a, AOP (result), offset);
5115           hc08_freeReg (hc08_reg_a);      
5116         }
5117       offset++;
5118     }
5119
5120 release:
5121   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5122   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5123   freeAsmop (result, NULL, ic, TRUE);
5124 }
5125
5126 /*-----------------------------------------------------------------*/
5127 /* genOr  - code for or                                            */
5128 /*-----------------------------------------------------------------*/
5129 static void
5130 genOr (iCode * ic, iCode * ifx)
5131 {
5132   operand *left, *right, *result;
5133   int size, offset = 0;
5134   unsigned long lit = 0L;
5135   unsigned char bytemask;
5136
5137   D(emitcode (";     genOr",""));
5138
5139   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5140   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5141   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5142
5143 #ifdef DEBUG_TYPE
5144   DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5145             AOP_TYPE (result),
5146             AOP_TYPE (left), AOP_TYPE (right)));
5147   DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5148             AOP_SIZE (result),
5149             AOP_SIZE (left), AOP_SIZE (right)));
5150 #endif
5151
5152   /* if left is a literal & right is not then exchange them */
5153   if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5154     {
5155       operand *tmp = right;
5156       right = left;
5157       left = tmp;
5158     }
5159
5160   /* if left is accumulator & right is not then exchange them */
5161   if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5162     {
5163       operand *tmp = right;
5164       right = left;
5165       left = tmp;
5166     }
5167
5168   if (AOP_TYPE (right) == AOP_LIT)
5169     lit = ulFromVal (AOP (right)->aopu.aop_lit);
5170       
5171   size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5172   
5173   if (AOP_TYPE (result) == AOP_CRY
5174       && size > 1
5175       && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5176     {
5177       /* this generates ugly code, but meets volatility requirements */
5178       loadRegFromConst (hc08_reg_a, zero);
5179       pushReg (hc08_reg_a, TRUE);
5180       
5181       offset = 0;
5182       while (size--)
5183         {
5184           loadRegFromAop (hc08_reg_a, AOP (left), offset);
5185           accopWithAop ("ora", AOP (right), offset);
5186           emitcode ("ora", "1,s");
5187           emitcode ("sta", "1,s");
5188           offset++;
5189         }
5190       
5191       pullReg (hc08_reg_a);
5192       emitcode ("tsta", "");
5193       genIfxJump (ifx, "a");
5194       goto release;
5195     }
5196   
5197   if (AOP_TYPE (result) == AOP_CRY)
5198     {
5199       symbol *tlbl = NULL;
5200       wassertl (ifx, "AOP_CRY result without ifx");
5201       
5202       offset = 0;
5203       while (size--)
5204         {
5205           bytemask = (lit >> (offset*8)) & 0xff;
5206           
5207           if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5208             {
5209               rmwWithAop ("tst", AOP (left), offset);
5210               if (size)
5211                 {
5212                   if (!tlbl)
5213                     tlbl = newiTempLabel (NULL);
5214                   emitBranch ("bne", tlbl);
5215                 }
5216             }
5217           else
5218             {
5219               loadRegFromAop (hc08_reg_a, AOP (left), offset);
5220               accopWithAop ("ora", AOP (right), offset);
5221               hc08_freeReg( hc08_reg_a);
5222               if (size)
5223                 {
5224                   if (!tlbl)
5225                     tlbl = newiTempLabel (NULL);
5226                   emitBranch ("bne", tlbl);
5227                 }
5228             }
5229           offset++;
5230         }
5231         if (tlbl)
5232           emitLabel (tlbl);
5233         genIfxJump (ifx, "a");
5234     }
5235   
5236   if (AOP_TYPE (right) == AOP_LIT)
5237     lit = ulFromVal (AOP (right)->aopu.aop_lit);
5238
5239   size = AOP_SIZE (result);
5240
5241   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5242       (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5243       (AOP_TYPE (left) == AOP_DIR))
5244     {
5245       int bitpos = isLiteralBit(lit)-1;
5246       emitcode ("bset","#%d,%s",bitpos & 7,
5247                 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5248       goto release;
5249     }
5250     
5251   offset = 0;
5252   while (size--)
5253     {
5254       bytemask = (lit >> (offset*8)) & 0xff;
5255       
5256       if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5257         {
5258           if (isOperandVolatile (left, FALSE))
5259             {
5260               loadRegFromAop (hc08_reg_a, AOP (left), offset);
5261               hc08_freeReg( hc08_reg_a);      
5262             }
5263           transferAopAop (AOP (right), offset, AOP (result), offset);
5264         }
5265       else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5266         {
5267           transferAopAop (AOP (left), offset, AOP (result), offset);
5268         }
5269       else
5270         {
5271           loadRegFromAop (hc08_reg_a, AOP (left), offset);
5272           accopWithAop ("ora", AOP (right), offset);
5273           storeRegToAop (hc08_reg_a, AOP (result), offset);
5274           hc08_freeReg (hc08_reg_a);      
5275         }
5276       offset++;
5277     }
5278
5279
5280 release:
5281   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5282   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5283   freeAsmop (result, NULL, ic, TRUE);
5284 }
5285
5286 /*-----------------------------------------------------------------*/
5287 /* genXor - code for xclusive or                                   */
5288 /*-----------------------------------------------------------------*/
5289 static void
5290 genXor (iCode * ic, iCode * ifx)
5291 {
5292   operand *left, *right, *result;
5293   int size, offset = 0;
5294   unsigned long lit = 0L;
5295
5296   D(emitcode (";     genXor",""));
5297
5298   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5299   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5300   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5301
5302 #ifdef DEBUG_TYPE
5303   DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5304             AOP_TYPE (result),
5305             AOP_TYPE (left), AOP_TYPE (right)));
5306   DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5307             AOP_SIZE (result),
5308             AOP_SIZE (left), AOP_SIZE (right)));
5309 #endif
5310
5311   /* if left is a literal & right is not ||
5312      if left needs acc & right does not */
5313   if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5314     {
5315       operand *tmp = right;
5316       right = left;
5317       left = tmp;
5318     }
5319
5320   /* if left is accumulator & right is not then exchange them */
5321   if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5322     {
5323       operand *tmp = right;
5324       right = left;
5325       left = tmp;
5326     }
5327
5328   if (AOP_TYPE (result) == AOP_CRY)
5329     {
5330       symbol *tlbl;
5331       wassertl (ifx, "AOP_CPY result without ifx");
5332       
5333       tlbl = newiTempLabel (NULL);
5334       size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5335       offset = 0;
5336       while (size--)
5337         {
5338           loadRegFromAop (hc08_reg_a, AOP (left), offset);
5339           if ((AOP_TYPE (right) == AOP_LIT)
5340               && (((lit >> (offset*8)) & 0xff) == 0))
5341             emitcode ("tsta","");
5342           else
5343             accopWithAop ("eor", AOP (right), offset);
5344           hc08_freeReg( hc08_reg_a);      
5345           if (size)
5346             emitBranch ("bne", tlbl);
5347           else
5348             {
5349               emitLabel (tlbl);
5350               genIfxJump (ifx, "a");
5351             }
5352           offset++;
5353         }
5354     }
5355     
5356   if (AOP_TYPE (right) == AOP_LIT)
5357     lit = ulFromVal (AOP (right)->aopu.aop_lit);
5358
5359   size = AOP_SIZE (result);
5360   offset = 0;
5361   while (size--)
5362     {
5363       loadRegFromAop (hc08_reg_a, AOP (left), offset);
5364       accopWithAop ("eor", AOP (right), offset);
5365       storeRegToAop (hc08_reg_a, AOP (result), offset++);
5366       hc08_freeReg( hc08_reg_a);      
5367     }
5368
5369 //release:
5370   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5371   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5372   freeAsmop (result, NULL, ic, TRUE);
5373 }
5374
5375 static void
5376 emitinline (iCode * ic, char *inlin)
5377 {
5378   char buffer[512];
5379   char *symname;
5380   char c;
5381   char *bp=buffer;
5382   symbol *sym, *tempsym;
5383   asmop *aop;
5384   char *l;
5385   
5386   while (*inlin)
5387     {
5388       if (*inlin == '_')
5389         {
5390           symname = ++inlin;
5391           while (isalnum((unsigned char)*inlin) || (*inlin == '_'))
5392             inlin++;
5393           c = *inlin;
5394           *inlin = '\0';
5395           //printf("Found possible symbol '%s'\n",symname);
5396           tempsym = newSymbol (symname, ic->level);
5397           tempsym->block = ic->block;
5398           sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5399           *inlin = c;
5400           if (!sym)
5401             {
5402               *bp++ = '_';
5403               inlin = symname;
5404             }
5405           else
5406             {
5407               aop = aopForSym (ic, sym, FALSE);
5408               l = aopAdrStr (aop, aop->size - 1, TRUE);
5409               if (*l=='#')
5410                 l++;
5411               sym->isref = 1;
5412               if (sym->level && !sym->allocreq && !sym->ismyparm)
5413                 {
5414                   werror (E_ID_UNDEF, sym->name);
5415                   werror (W_CONTINUE,
5416                           "  Add 'volatile' to the variable declaration so that it\n"
5417                           "  can be referenced within inline assembly");
5418                 }
5419               //printf("Replacing with '%s'\n",l);
5420               while (*l)
5421                 {
5422                   *bp++ = *l++;
5423                   if ((2+bp-buffer)>sizeof(buffer))
5424                     goto endofline;
5425                 }
5426             }
5427         }
5428       else
5429         {
5430           *bp++ = *inlin++;
5431         }
5432       if ((2+bp-buffer)>sizeof(buffer))
5433         goto endofline;
5434     }
5435
5436 endofline:
5437   *bp = '\0';
5438
5439   if ((2+bp-buffer)>sizeof(buffer))
5440     fprintf(stderr, "Inline assembly buffer overflow\n");
5441   
5442   //printf("%s\n",buffer);
5443   emitcode (buffer,"");
5444 }
5445
5446
5447 /*-----------------------------------------------------------------*/
5448 /* genInline - write the inline code out                           */
5449 /*-----------------------------------------------------------------*/
5450 static void
5451 genInline (iCode * ic)
5452 {
5453   char *buffer, *bp, *bp1;
5454   bool inComment = FALSE;
5455
5456   D(emitcode (";     genInline",""));
5457
5458   _G.inLine += (!options.asmpeep);
5459
5460   buffer = bp = bp1 = Safe_strdup (IC_INLINE(ic));
5461
5462   /* emit each line as a code */
5463   while (*bp)
5464     {
5465       switch (*bp)
5466         {
5467         case ';':
5468           inComment = TRUE;
5469           ++bp;
5470           break;
5471
5472         case '\n':
5473           inComment = FALSE;
5474           *bp++ = '\0';
5475           emitinline (ic, bp1);
5476           bp1 = bp;
5477           break;
5478
5479         default:
5480           /* Add \n for labels, not dirs such as c:\mydir */
5481           if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
5482             {
5483               ++bp;
5484               *bp = '\0';
5485               ++bp;
5486               emitcode (bp1, "");
5487               bp1 = bp;
5488             }
5489           else
5490             ++bp;
5491           break;
5492         }
5493     }
5494   if (bp1 != bp)
5495     emitinline (ic, bp1);
5496
5497   Safe_free (buffer);
5498
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) || sameRegs (AOP (left), AOP (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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 = ulFromVal (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, codeOutBuf);
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         char *iLine;
8420
8421         for (i=0; i<6; i++) {
8422           sprintf (&regsInUse[i],
8423                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); 
8424         }
8425         regsInUse[i]=0;
8426         iLine = printILine(ic);
8427         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8428         dbuf_free(iLine);
8429       }
8430       /* if the result is marked as
8431          spilt and rematerializable or code for
8432          this has already been generated then
8433          do nothing */
8434       if (resultRemat (ic) || ic->generated)
8435         continue;
8436
8437       {
8438         int i;
8439         regs *reg;
8440         symbol *sym;
8441         
8442         for (i=A_IDX;i<=XA_IDX;i++)
8443           {
8444             reg = hc08_regWithIdx(i);
8445             if (reg->aop)
8446               emitcode("","; %s = %s offset %d", reg->name,
8447                        aopName(reg->aop), reg->aopofs);
8448             reg->isFree = TRUE;
8449           }
8450         if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8451           {
8452             sym = OP_SYMBOL (IC_LEFT (ic));
8453             if (sym->accuse == ACCUSE_HX)
8454               {
8455                 hc08_reg_h->isFree = FALSE;
8456                 hc08_reg_x->isFree = FALSE;
8457               }
8458             else if (sym->accuse == ACCUSE_XA)
8459               {
8460                 hc08_reg_a->isFree = FALSE;
8461                 if (sym->nRegs>1)
8462                   hc08_reg_x->isFree = FALSE;
8463               }
8464           }
8465         if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8466           {
8467             sym = OP_SYMBOL (IC_RIGHT (ic));
8468             if (sym->accuse == ACCUSE_HX)
8469               {
8470                 hc08_reg_h->isFree = FALSE;
8471                 hc08_reg_x->isFree = FALSE;
8472               }
8473             else if (sym->accuse == ACCUSE_XA)
8474               {
8475                 hc08_reg_a->isFree = FALSE;
8476                 if (sym->nRegs>1)
8477                   hc08_reg_x->isFree = FALSE;
8478               }
8479           }
8480       }
8481       
8482       /* depending on the operation */
8483       switch (ic->op)
8484         {
8485         case '!':
8486           genNot (ic);
8487           break;
8488
8489         case '~':
8490           genCpl (ic);
8491           break;
8492
8493         case UNARYMINUS:
8494           genUminus (ic);
8495           break;
8496
8497         case IPUSH:
8498           genIpush (ic);
8499           break;
8500
8501         case IPOP:
8502           /* IPOP happens only when trying to restore a
8503              spilt live range, if there is an ifx statement
8504              following this pop then the if statement might
8505              be using some of the registers being popped which
8506              would destory the contents of the register so
8507              we need to check for this condition and handle it */
8508           if (ic->next &&
8509               ic->next->op == IFX &&
8510               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8511             genIfx (ic->next, ic);
8512           else
8513             genIpop (ic);
8514           break;
8515
8516         case CALL:
8517           genCall (ic);
8518           break;
8519
8520         case PCALL:
8521           genPcall (ic);
8522           break;
8523
8524         case FUNCTION:
8525           genFunction (ic);
8526           break;
8527
8528         case ENDFUNCTION:
8529           genEndFunction (ic);
8530           break;
8531
8532         case RETURN:
8533           genRet (ic);
8534           break;
8535
8536         case LABEL:
8537           genLabel (ic);
8538           break;
8539
8540         case GOTO:
8541           genGoto (ic);
8542           break;
8543
8544         case '+':
8545           if (!genPointerGetSetOfs (ic))
8546             genPlus (ic);
8547           break;
8548
8549         case '-':
8550           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8551             genMinus (ic);
8552           break;
8553
8554         case '*':
8555           genMult (ic);
8556           break;
8557
8558         case '/':
8559           genDiv (ic);
8560           break;
8561
8562         case '%':
8563           genMod (ic);
8564           break;
8565
8566         case '>':
8567         case '<':
8568         case LE_OP:
8569         case GE_OP:
8570           genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
8571           break;
8572
8573         case NE_OP:
8574         case EQ_OP:
8575           genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
8576           break;
8577
8578         case AND_OP:
8579           genAndOp (ic);
8580           break;
8581
8582         case OR_OP:
8583           genOrOp (ic);
8584           break;
8585
8586         case '^':
8587           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8588           break;
8589
8590         case '|':
8591           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8592           break;
8593
8594         case BITWISEAND:
8595           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8596           break;
8597
8598         case INLINEASM:
8599           genInline (ic);
8600           break;
8601
8602         case RRC:
8603           genRRC (ic);
8604           break;
8605
8606         case RLC:
8607           genRLC (ic);
8608           break;
8609
8610         case GETHBIT:
8611           genGetHbit (ic);
8612           break;
8613
8614         case LEFT_OP:
8615           genLeftShift (ic);
8616           break;
8617
8618         case RIGHT_OP:
8619           genRightShift (ic);
8620           break;
8621
8622         case GET_VALUE_AT_ADDRESS:
8623           genPointerGet (ic,
8624                          hasInc (IC_LEFT (ic), ic,
8625                                  getSize (operandType (IC_RESULT (ic)))),
8626                          ifxForOp (IC_RESULT (ic), ic) );
8627           break;
8628
8629         case '=':
8630           if (POINTER_SET (ic))
8631             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8632           else
8633             genAssign (ic);
8634           break;
8635
8636         case IFX:
8637           genIfx (ic, NULL);
8638           break;
8639
8640         case ADDRESS_OF:
8641           genAddrOf (ic);
8642           break;
8643
8644         case JUMPTABLE:
8645           genJumpTab (ic);
8646           break;
8647
8648         case CAST:
8649           genCast (ic);
8650           break;
8651
8652         case RECEIVE:
8653           genReceive (ic);
8654           break;
8655
8656         case SEND:
8657           addSet (&_G.sendSet, ic);
8658           break;
8659
8660         case DUMMY_READ_VOLATILE:
8661           genDummyRead (ic);
8662           break;
8663
8664         case CRITICAL:
8665           genCritical (ic);
8666           break;
8667
8668         case ENDCRITICAL:
8669           genEndCritical (ic);
8670           break;
8671         
8672         case SWAP:
8673           genSwap (ic);
8674           break;
8675
8676         default:
8677           ic = ic;
8678         }
8679
8680       if (!hc08_reg_a->isFree)
8681         DD(emitcode("","; forgot to free a"));
8682       if (!hc08_reg_x->isFree)
8683         DD(emitcode("","; forgot to free x"));
8684       if (!hc08_reg_h->isFree)
8685         DD(emitcode("","; forgot to free h"));
8686       if (!hc08_reg_hx->isFree)
8687         DD(emitcode("","; forgot to free hx"));
8688       if (!hc08_reg_xa->isFree)
8689         DD(emitcode("","; forgot to free xa"));
8690     }
8691
8692   debugFile->writeFrameAddress (NULL, NULL, 0);  /* have no idea where frame is now */
8693     
8694
8695   /* now we are ready to call the
8696      peep hole optimizer */
8697   if (!options.nopeep)
8698     peepHole (&lineHead);
8699
8700   /* now do the actual printing */
8701   printLine (lineHead, codeOutBuf);
8702   return;
8703 }