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