1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for the 68HC08
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)
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
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.
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.
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!
28 -------------------------------------------------------------------------*/
30 /* Use the D macro for basic (unobtrusive) debugging messages */
33 /* Use the DD macro for detailed debugging messages */
41 #include "SDCCglobl.h"
45 #include "SDCCpeeph.h"
49 char *aopLiteral (value * val, int offset);
50 char *aopLiteralLong (value * val, int offset, int size);
52 static int pushReg (regs *reg, bool freereg);
53 static void pullReg (regs *reg);
54 static void transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs);
56 static char *zero = "#0x00";
57 static char *one = "#0x01";
61 {"a", "x", "_ret2", "_ret3"};
62 unsigned fReturnSizeHC08 = 4; /* shared with ralloc.c */
63 char **fReturn2 = fReturnhc08;
82 static asmop *hc08_aop_pass[4];
84 extern int hc08_ptrRegReq;
85 extern int hc08_nRegs;
86 extern struct dbuf_s *codeOutBuf;
87 //static void saveRBank (int, iCode *, bool);
88 static bool operandsEqu (operand * op1, operand * op2);
89 static void loadRegFromConst (regs *reg, char *c);
90 static char *aopName (asmop *aop);
91 static asmop * newAsmop (short type);
92 static char * aopAdrStr (asmop * aop, int loffset, bool bit16);
93 #define RESULTONSTACK(x) \
94 (IC_RESULT(x) && IC_RESULT(x)->aop && \
95 IC_RESULT(x)->aop->type == AOP_STK )
97 #define IS_AOP_HX(x) \
98 (((x)->type == AOP_REG) \
99 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
100 && ((x)->aopu.aop_reg[1] == hc08_reg_h) )
102 #define IS_AOP_XA(x) \
103 (((x)->type == AOP_REG) \
104 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
105 && ((x)->aopu.aop_reg[1] == hc08_reg_x) )
107 #define IS_AOP_A(x) \
108 (((x)->type == AOP_REG) \
109 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
110 && ((x)->size == 1) )
112 #define IS_AOP_X(x) \
113 (((x)->type == AOP_REG) \
114 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
115 && ((x)->size == 1) )
117 #define IS_AOP_H(x) \
118 (((x)->type == AOP_REG) \
119 && ((x)->aopu.aop_reg[0] == hc08_reg_h) \
120 && ((x)->size == 1) )
122 #define CLRC emitcode("clc","")
124 static lineNode *lineHead = NULL;
125 static lineNode *lineCurr = NULL;
128 static unsigned char SLMask[] =
129 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
130 0xE0, 0xC0, 0x80, 0x00};
131 static unsigned char SRMask[] =
132 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
133 0x07, 0x03, 0x01, 0x00};
141 #define AOP(op) op->aop
142 #define AOP_TYPE(op) AOP(op)->type
143 #define AOP_SIZE(op) AOP(op)->size
144 #define AOP_OP(aop) aop->op
147 /*-----------------------------------------------------------------*/
148 /* emitcode - writes the code into a file : for now it is simple */
149 /*-----------------------------------------------------------------*/
151 emitcode (char *inst, char *fmt,...)
154 char lb[INITIAL_INLINEASM];
162 sprintf (lb, "%s\t", inst);
164 sprintf (lb, "%s", inst);
165 vsprintf (lb + (strlen (lb)), fmt, ap);
168 vsprintf (lb, fmt, ap);
170 while (isspace ((unsigned char)*lbp))
174 lineCurr = (lineCurr ?
175 connectLine (lineCurr, newLineNode (lb)) :
176 (lineHead = newLineNode (lb)));
177 lineCurr->isInline = _G.inLine;
178 lineCurr->isDebug = _G.debugLine;
179 lineCurr->ic = _G.current_iCode;
180 lineCurr->isComment = (*lbp==';');
182 //printf("%s\n", lb);
187 emitBranch (char *branchop, symbol *tlbl)
189 emitcode (branchop, "%05d$", (tlbl->key + 100));
193 emitLabel (symbol *tlbl)
195 emitcode ("", "%05d$:", (tlbl->key +100));
196 lineCurr->isLabel = 1;
199 /*-----------------------------------------------------------------*/
200 /* hc08_emitDebuggerSymbol - associate the current code location */
201 /* with a debugger symbol */
202 /*-----------------------------------------------------------------*/
204 hc08_emitDebuggerSymbol (char * debugSym)
207 emitcode ("", "%s ==.", debugSym);
212 /*--------------------------------------------------------------------------*/
213 /* transferRegReg - Transfer from register(s) sreg to register(s) dreg. If */
214 /* freesrc is true, sreg is marked free and available for */
215 /* reuse. sreg and dreg must be of equal size */
216 /*--------------------------------------------------------------------------*/
218 transferRegReg (regs *sreg, regs *dreg, bool freesrc)
224 /* Nothing to do if no destination. */
228 /* But it's definately an error if there's no source. */
231 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
232 "NULL sreg in transferRegReg");
236 DD(emitcode ("", "; transferRegReg(%s,%s)",
237 sreg->name, dreg->name));
250 case H_IDX: /* H to A */
251 pushReg (hc08_reg_h, FALSE);
252 pullReg (hc08_reg_a);
254 case X_IDX: /* X to A */
255 emitcode ("txa", "");
264 case A_IDX: /* A to H */
265 pushReg (hc08_reg_a, FALSE);
266 pullReg (hc08_reg_h);
268 case X_IDX: /* X to H */
269 pushReg (hc08_reg_x, FALSE);
270 pullReg (hc08_reg_h);
279 case A_IDX: /* A to X */
280 emitcode ("tax", "");
282 case H_IDX: /* H to X */
283 pushReg (hc08_reg_h, FALSE);
284 pullReg (hc08_reg_x);
293 case XA_IDX: /* XA to HX */
294 pushReg (hc08_reg_x, FALSE);
295 pullReg (hc08_reg_h);
296 emitcode ("tax", "");
305 case HX_IDX: /* HX to XA */
306 emitcode ("txa", "");
307 pushReg (hc08_reg_h, FALSE);
308 pullReg (hc08_reg_x);
318 wassertl (!error, "bad combo in transferRegReg");
323 dreg->aop = sreg->aop;
324 dreg->aopofs = sreg->aopofs;
325 dreg->isFree = FALSE;
329 /*--------------------------------------------------------------------------*/
330 /* updateCFA - update the debugger information to reflect the current */
331 /* connonical frame address relative to the stack pointer */
332 /*--------------------------------------------------------------------------*/
336 /* there is no frame unless there is a function */
340 debugFile->writeFrameAddress (NULL, hc08_reg_sp,
341 1 + _G.stackOfs + _G.stackPushes);
344 /*--------------------------------------------------------------------------*/
345 /* pushReg - Push register reg onto the stack. If freereg is true, reg is */
346 /* marked free and available for reuse. */
347 /*--------------------------------------------------------------------------*/
349 pushReg (regs *reg, bool freereg)
351 int regidx = reg->rIdx;
356 emitcode ("psha", "");
361 emitcode ("pshx", "");
366 emitcode ("pshh", "");
371 emitcode ("pshx", "");
374 emitcode ("pshh", "");
379 emitcode ("psha", "");
382 emitcode ("pshx", "");
391 return -_G.stackOfs-_G.stackPushes;
394 /*--------------------------------------------------------------------------*/
395 /* pullReg - Pull register reg off the stack. */
396 /*--------------------------------------------------------------------------*/
400 int regidx = reg->rIdx;
405 emitcode ("pula", "");
410 emitcode ("pulx", "");
415 emitcode ("pulh", "");
420 emitcode ("pulh", "");
423 emitcode ("pulx", "");
428 emitcode ("pulx", "");
431 emitcode ("pula", "");
439 hc08_dirtyReg(reg, FALSE);
442 /*--------------------------------------------------------------------------*/
443 /* pullNull - Discard n bytes off the top of the stack */
444 /*--------------------------------------------------------------------------*/
450 emitcode("ais","#%d",n);
456 /*--------------------------------------------------------------------------*/
457 /* pushRegIfUsed - Push register reg if marked in use. Returns true if the */
458 /* push was performed, false otherwise. */
459 /*--------------------------------------------------------------------------*/
461 pushRegIfUsed (regs *reg)
472 /*--------------------------------------------------------------------------*/
473 /* pullOrFreeReg - If needpull is true, register reg is pulled from the */
474 /* stack. Otherwise register reg is marked as free. */
475 /*--------------------------------------------------------------------------*/
477 pullOrFreeReg (regs *reg, bool needpull)
485 /*--------------------------------------------------------------------------*/
486 /* adjustStack - Adjust the stack pointer by n bytes. */
487 /*--------------------------------------------------------------------------*/
495 emitcode ("ais","#127");
497 _G.stackPushes -= 127;
502 emitcode ("ais","#-128");
504 _G.stackPushes += 128;
509 emitcode ("ais", "#%d", n);
518 /*--------------------------------------------------------------------------*/
519 /* aopName - Return a string with debugging information about an asmop. */
520 /*--------------------------------------------------------------------------*/
524 static char buffer[256];
528 return "(asmop*)NULL";
533 sprintf (buf,"IMMD(%s)", aop->aopu.aop_immd.aop_immd1);
536 sprintf (buf,"LIT(%s)", aopLiteral (aop->aopu.aop_lit, 0));
539 sprintf (buf,"DIR(%s)", aop->aopu.aop_dir);
542 sprintf (buf,"EXT(%s)", aop->aopu.aop_dir);
545 sprintf (buf,"SOF(%s)", OP_SYMBOL (aop->op)->name);
548 sprintf (buf, "REG(%s,%s,%s,%s)",
549 aop->aopu.aop_reg[3] ? aop->aopu.aop_reg[3]->name : "-",
550 aop->aopu.aop_reg[2] ? aop->aopu.aop_reg[2]->name : "-",
551 aop->aopu.aop_reg[1] ? aop->aopu.aop_reg[1]->name : "-",
552 aop->aopu.aop_reg[0] ? aop->aopu.aop_reg[0]->name : "-");
559 sprintf (buf,"?%d", aop->type);
567 /*--------------------------------------------------------------------------*/
568 /* loadRegFromAop - Load register reg from logical offset loffset of aop. */
569 /*--------------------------------------------------------------------------*/
571 loadRegFromAop (regs *reg, asmop *aop, int loffset)
573 int regidx = reg->rIdx;
575 if (aop->stacked && aop->stk_aop[loffset])
577 loadRegFromAop (reg, aop->stk_aop[loffset], 0);
582 printf("loadRegFromAop called\n");
585 printf(" reg = NULL\n");
588 printf(" reg = %s\n", reg->name);
591 printf(" aop = NULL\n");
594 printf(" aop->type = %d\n", aop->type);
595 printf(" loffset = %d\n", loffset);
598 printf(" aop has operand link\n");
600 printf(" aop missing operand link\n");
602 printf(" reg has operand link\n");
604 printf(" reg missing operand link\n");
607 DD(emitcode ("", "; loadRegFromAop (%s, %s, %d)",
608 reg->name, aopName (aop), loffset));
610 /* If operand is volatile, we cannot optimize. */
611 if (!aop->op || isOperandVolatile (aop->op, FALSE))
615 /* If this register already has this offset of the operand
616 then we need only mark it as in use. */
617 if (reg->aop && reg->aop->op && aop->op
618 && operandsEqu(reg->aop->op,aop->op)
619 && (reg->aopofs == loffset))
622 DD(emitcode ("","; already had correct value for %s", reg->name));
626 /* TODO: check to see if we can transfer from another register */
628 if (hc08_reg_h->aop && hc08_reg_h->aop->op && aop->op
629 && operandsEqu(hc08_reg_h->aop->op,aop->op)
630 && (hc08_reg_h->aopofs == loffset))
632 DD(emitcode ("","; found correct value for %s in h", reg->name));
633 transferRegReg (hc08_reg_h, reg, FALSE);
639 if (hc08_reg_x->aop && hc08_reg_x->aop->op && aop->op
640 && operandsEqu(hc08_reg_x->aop->op,aop->op)
641 && (hc08_reg_x->aopofs == loffset))
643 DD(emitcode ("","; found correct value for %s in x", reg->name));
644 transferRegReg (hc08_reg_x, reg, FALSE);
649 if (hc08_reg_a->aop && hc08_reg_a->aop->op && aop->op
650 && operandsEqu(hc08_reg_a->aop->op,aop->op)
651 && (hc08_reg_a->aopofs == loffset))
653 DD(emitcode ("","; found correct value for %s in a", reg->name));
654 transferRegReg (hc08_reg_a, reg, FALSE);
664 if (aop->type == AOP_REG)
666 if (loffset < aop->size)
667 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
669 emitcode ("clra", ""); /* TODO: handle sign extension */
673 char * l = aopAdrStr (aop, loffset, FALSE);
674 if (!strcmp (l, zero))
675 emitcode ("clra", "");
677 emitcode ("lda", "%s", l);
681 if (aop->type == AOP_REG)
683 if (loffset < aop->size)
684 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
686 emitcode ("clrx", ""); /* TODO: handle sign extension */
690 char * l = aopAdrStr (aop, loffset, FALSE);
691 if (!strcmp (l, zero))
692 emitcode ("clrx", "");
694 emitcode ("ldx", "%s", l);
699 char * l = aopAdrStr (aop, loffset, FALSE);
700 if (!strcmp (l, zero))
702 emitcode ("clrh", "");
706 if (hc08_reg_a->isFree)
708 loadRegFromAop (hc08_reg_a, aop, loffset);
709 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
711 else if (hc08_reg_x->isFree)
713 loadRegFromAop (hc08_reg_x, aop, loffset);
714 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
718 pushReg (hc08_reg_a, TRUE);
719 loadRegFromAop (hc08_reg_a, aop, loffset);
720 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
721 pullReg (hc08_reg_a);
727 else if (IS_AOP_XA(aop))
728 transferRegReg (hc08_reg_xa, hc08_reg_hx, FALSE);
729 else if ((aop->type == AOP_DIR))
731 if (aop->size>(loffset+1))
732 emitcode ("ldhx","%s", aopAdrStr (aop, loffset+1, TRUE));
735 loadRegFromAop (hc08_reg_x, aop, loffset);
736 loadRegFromConst (hc08_reg_h, zero);
739 else if ((aop->type == AOP_LIT) || (aop->type == AOP_IMMD))
741 emitcode ("ldhx","%s", aopAdrStr (aop, loffset, TRUE));
746 needpula = pushRegIfUsed (hc08_reg_a);
747 loadRegFromAop (hc08_reg_a, aop, loffset+1);
748 loadRegFromAop (hc08_reg_x, aop, loffset);
749 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
750 pullOrFreeReg (hc08_reg_a, needpula);
756 else if (IS_AOP_HX(aop))
757 transferRegReg (hc08_reg_hx, hc08_reg_xa, FALSE);
760 loadRegFromAop (hc08_reg_a, aop, loffset);
761 loadRegFromAop (hc08_reg_x, aop, loffset+1);
766 // ignore caching for now
769 reg->aopofs = loffset;
774 /*--------------------------------------------------------------------------*/
775 /* forceStackedAop - Reserve space on the stack for asmop aop; when */
776 /* freeAsmop is called with aop, the stacked data will */
777 /* be copied to the original aop location. */
778 /*--------------------------------------------------------------------------*/
780 forceStackedAop (asmop *aop, bool copyOrig)
784 asmop *newaop = newAsmop (aop->type);
785 memcpy (newaop, aop, sizeof(*newaop));
787 DD(emitcode("", "; forcedStackAop %s", aopName(aop)));
789 if (copyOrig && hc08_reg_a->isFree)
791 else if (copyOrig && hc08_reg_x->isFree)
796 for (loffset=0; loffset < newaop->size; loffset++)
798 asmop *aopsof = newAsmop (AOP_SOF);
802 loadRegFromAop (reg, aop, loffset);
803 aopsof->aopu.aop_stk = pushReg (reg, FALSE);
807 aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE);
809 aopsof->op = aop->op;
810 newaop->stk_aop[loffset] = aopsof;
814 if (!reg && copyOrig)
816 for (loffset=0; loffset < newaop->size; loffset++)
818 transferAopAop (aop, loffset, newaop, loffset);
826 /*--------------------------------------------------------------------------*/
827 /* storeRegToAop - Store register reg to logical offset loffset of aop. */
828 /*--------------------------------------------------------------------------*/
830 storeRegToAop (regs *reg, asmop *aop, int loffset)
832 int regidx = reg->rIdx;
838 DD(emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
839 reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr));
841 if ((reg->rIdx == HX_IDX) && aop->stacked
842 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
844 storeRegToAop (hc08_reg_h, aop, loffset+1);
845 storeRegToAop (hc08_reg_x, aop, loffset);
849 if ((reg->rIdx == XA_IDX) && aop->stacked
850 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
852 storeRegToAop (hc08_reg_x, aop, loffset+1);
853 storeRegToAop (hc08_reg_a, aop, loffset);
857 if (aop->stacked && aop->stk_aop[loffset])
859 storeRegToAop (reg, aop->stk_aop[loffset], 0);
863 if (aop->type == AOP_STR)
866 transferRegReg (reg, hc08_reg_x, FALSE);
868 transferRegReg (reg, hc08_reg_h, FALSE);
872 if (aop->type == AOP_DUMMY)
875 if (aop->type == AOP_CRY) /* This can only happen if IFX was optimized */
876 return; /* away, so just toss the result */
881 if ((aop->type == AOP_REG) && (loffset < aop->size))
882 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
884 emitcode ("sta","%s", aopAdrStr (aop, loffset, FALSE));
887 if ((aop->type == AOP_REG) && (loffset < aop->size))
888 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
890 emitcode ("stx","%s", aopAdrStr (aop, loffset, FALSE));
893 if (hc08_reg_a->isFree)
895 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
896 storeRegToAop (hc08_reg_a, aop, loffset);
897 hc08_freeReg (hc08_reg_a);
899 else if (hc08_reg_x->isFree)
901 transferRegReg (hc08_reg_h, hc08_reg_x, FALSE);
902 storeRegToAop (hc08_reg_x, aop, loffset);
903 hc08_freeReg (hc08_reg_x);
907 pushReg (hc08_reg_a, TRUE);
908 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
909 storeRegToAop (hc08_reg_a, aop, loffset);
910 pullReg (hc08_reg_a);
914 if ((aop->type == AOP_DIR) )
916 emitcode("sthx","%s", aopAdrStr (aop, loffset+1, TRUE));
918 else if (IS_AOP_XA(aop))
919 transferRegReg(reg, hc08_reg_xa, FALSE);
920 else if (IS_AOP_HX(aop))
925 needpula = pushRegIfUsed (hc08_reg_a);
926 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
927 storeRegToAop (hc08_reg_a, aop, loffset+1);
928 storeRegToAop (hc08_reg_x, aop, loffset);
929 pullOrFreeReg (hc08_reg_a, needpula);
934 transferRegReg(reg, hc08_reg_hx, FALSE);
935 else if (IS_AOP_XA(aop))
939 storeRegToAop (hc08_reg_a, aop, loffset);
940 storeRegToAop (hc08_reg_x, aop, loffset+1);
945 /* Disable the register tracking for now */
947 //if (!reg->aop || (reg->aop && (reg->aop != aop)))
950 for (otheridx=0;otheridx<hc08_nRegs;otheridx++)
952 otherreg=hc08_regWithIdx(otheridx);
953 if (otherreg && otherreg->aop
954 && otherreg->aop->op && aop->op
955 && operandsEqu(otherreg->aop->op,aop->op)
956 && (otherreg->aopofs == loffset))
958 DD(emitcode("","; marking %s stale", otherreg->name));
962 if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
964 hc08_reg_hx->aop = NULL;
965 DD(emitcode("","; marking hx stale"));
967 if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
969 hc08_reg_xa->aop = NULL;
970 DD(emitcode("","; marking xa stale"));
974 reg->aopofs = loffset;
979 /*--------------------------------------------------------------------------*/
980 /* loadRegFromConst - Load register reg from constant c. */
981 /*--------------------------------------------------------------------------*/
983 loadRegFromConst (regs *reg, char *c)
989 emitcode ("clra", "");
991 emitcode ("lda", "%s", c);
995 emitcode ("clrx", "");
997 emitcode ("ldx", "%s", c);
1000 if (!strcmp(c,zero))
1001 emitcode ("clrh", "");
1002 else if (hc08_reg_a->isFree)
1004 loadRegFromConst (hc08_reg_a, c);
1005 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
1007 else if (hc08_reg_x->isFree)
1009 loadRegFromConst (hc08_reg_x, c);
1010 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
1014 pushReg (hc08_reg_a, TRUE);
1015 loadRegFromConst (hc08_reg_a, c);
1016 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
1017 pullReg (hc08_reg_a);
1021 emitcode ("ldhx", "%s", c);
1024 emitcode ("lda", "%s", c);
1025 emitcode ("ldx", "%s >> 8", c);
1028 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1029 "Bad rIdx in loadRegFromConst");
1036 /*--------------------------------------------------------------------------*/
1037 /* storeConstToAop- Store constant c to logical offset loffset of asmop aop.*/
1038 /*--------------------------------------------------------------------------*/
1040 storeConstToAop (char *c, asmop *aop, int loffset)
1042 if (aop->stacked && aop->stk_aop[loffset])
1044 storeConstToAop (c, aop->stk_aop[loffset], 0);
1051 if (!strcmp(c,zero))
1052 emitcode ("clr", "%s", aopAdrStr (aop, loffset, FALSE));
1054 emitcode ("mov", "%s,%s", c, aopAdrStr (aop, loffset, FALSE));
1057 if (loffset>(aop->size-1))
1059 loadRegFromConst (aop->aopu.aop_reg[loffset], c);
1064 if (hc08_reg_a->isFree)
1066 loadRegFromConst (hc08_reg_a, c);
1067 storeRegToAop( hc08_reg_a, aop, loffset);
1068 hc08_freeReg (hc08_reg_a);
1070 else if (hc08_reg_x->isFree)
1072 loadRegFromConst (hc08_reg_x, c);
1073 storeRegToAop( hc08_reg_x, aop, loffset);
1074 hc08_freeReg (hc08_reg_x);
1078 pushReg (hc08_reg_a, TRUE);
1079 loadRegFromConst (hc08_reg_a, c);
1080 storeRegToAop( hc08_reg_a, aop, loffset);
1081 pullReg (hc08_reg_a);
1087 /*--------------------------------------------------------------------------*/
1088 /* storeRegSignToUpperAop - If isSigned is true, the sign bit of register */
1089 /* reg is extended to fill logical offsets loffset */
1090 /* and above of asmop aop. Otherwise, logical */
1091 /* offsets loffset and above of asmop aop are */
1092 /* zeroed. reg must be an 8-bit register. */
1093 /*--------------------------------------------------------------------------*/
1095 storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned)
1097 // int regidx = reg->rIdx;
1098 int size = aop->size;
1106 while (loffset<size)
1107 storeConstToAop(zero, aop, loffset++);
1112 transferRegReg (reg, hc08_reg_a, FALSE);
1113 emitcode ("rola","");
1114 emitcode ("clra","");
1115 emitcode ("sbc", "#0");
1116 hc08_useReg (hc08_reg_a);
1117 while (loffset<size)
1118 storeRegToAop (hc08_reg_a, aop, loffset++);
1119 hc08_freeReg (hc08_reg_a);
1123 /*--------------------------------------------------------------------------*/
1124 /* storeRegToFullAop - Store register reg to asmop aop with appropriate */
1125 /* padding and/or truncation as needed. If isSigned is */
1126 /* true, sign extension will take place in the padding. */
1127 /*--------------------------------------------------------------------------*/
1129 storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
1131 int regidx = reg->rIdx;
1132 int size = aop->size;
1139 storeRegToAop (reg, aop, 0);
1140 storeRegSignToUpperAop (reg, aop, 1, isSigned);
1145 storeRegToAop (hc08_reg_x, aop, 0);
1149 storeRegToAop (reg, aop, 0);
1150 storeRegSignToUpperAop (hc08_reg_h, aop, 2, isSigned);
1156 storeRegToAop (hc08_reg_a, aop, 0);
1160 storeRegToAop (reg, aop, 0);
1161 storeRegSignToUpperAop (hc08_reg_x, aop, 2, isSigned);
1167 /*--------------------------------------------------------------------------*/
1168 /* transferAopAop - Transfer the value at logical offset srcofs of asmop */
1169 /* srcaop to logical offset dstofs of asmop dstaop. */
1170 /*--------------------------------------------------------------------------*/
1172 transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
1174 bool needpula = FALSE;
1177 bool keepreg = FALSE;
1179 /* ignore transfers at the same byte, unless its volatile */
1180 if (srcaop->op && !isOperandVolatile (srcaop->op, FALSE)
1181 && dstaop->op && !isOperandVolatile (dstaop->op, FALSE)
1182 && operandsEqu(srcaop->op, dstaop->op) && srcofs == dstofs
1183 && dstaop->type == srcaop->type)
1186 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1188 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1192 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1194 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1198 // DD(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1199 // aopName (srcaop), srcofs, aopName (dstaop), dstofs));
1200 // DD(emitcode ("", "; srcaop->type = %d", srcaop->type));
1201 // DD(emitcode ("", "; dstaop->type = %d", dstaop->type));
1203 if (dstofs >= dstaop->size)
1206 if ((dstaop->type == AOP_DIR)
1207 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1209 if (srcaop->type == AOP_LIT)
1212 unsigned long bytemask;
1214 lit = (unsigned long) floatFromVal (srcaop->aopu.aop_lit);
1215 bytemask = (lit >> (srcofs*8)) & 0xff;
1219 emitcode ("clr", "%s", aopAdrStr(dstaop, dstofs, FALSE));
1224 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1225 aopAdrStr(dstaop, dstofs, FALSE));
1229 if (dstaop->type == AOP_REG)
1231 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1232 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1234 reg = dstaop->aopu.aop_reg[dstofs];
1239 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1241 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1242 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1244 reg = srcaop->aopu.aop_reg[srcofs];
1251 if (hc08_reg_a->isFree)
1253 else if (hc08_reg_x->isFree)
1257 pushReg (hc08_reg_a, TRUE);
1263 loadRegFromAop (reg, srcaop, srcofs);
1264 storeRegToAop (reg, dstaop, dstofs);
1267 pullOrFreeReg (hc08_reg_a, needpula);
1271 /*--------------------------------------------------------------------------*/
1272 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1273 /* parameter param. */
1274 /*--------------------------------------------------------------------------*/
1276 accopWithMisc (char *accop, char *param)
1278 emitcode (accop, "%s", param);
1279 hc08_dirtyReg (hc08_reg_a, FALSE);
1282 /*--------------------------------------------------------------------------*/
1283 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1284 /* byte at logical offset loffset of asmop aop. */
1285 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1286 /*--------------------------------------------------------------------------*/
1288 accopWithAop (char *accop, asmop *aop, int loffset)
1290 if (aop->stacked && aop->stk_aop[loffset])
1292 accopWithAop (accop, aop->stk_aop[loffset], 0);
1296 if (aop->type == AOP_DUMMY)
1299 if (aop->type == AOP_REG)
1301 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1302 emitcode (accop, "1,s");
1306 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1308 hc08_dirtyReg (hc08_reg_a, FALSE);
1312 /*--------------------------------------------------------------------------*/
1313 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1314 /* byte at logical offset loffset of asmop aop. Register reg */
1315 /* must be 8-bit. */
1316 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1317 /*--------------------------------------------------------------------------*/
1319 rmwWithReg (char *rmwop, regs *reg)
1322 char *rmwaop = rmwbuf;
1324 if (reg->rIdx == A_IDX)
1326 sprintf(rmwaop,"%sa", rmwop);
1327 emitcode (rmwaop, "");
1328 hc08_dirtyReg (hc08_reg_a, FALSE);
1330 else if (reg->rIdx == X_IDX)
1332 sprintf(rmwaop,"%sx", rmwop);
1333 emitcode (rmwaop, "");
1334 hc08_dirtyReg (hc08_reg_a, FALSE);
1336 else if (hc08_reg_a->isFree)
1338 transferRegReg(reg, hc08_reg_a, FALSE);
1339 sprintf(rmwaop,"%sa", rmwop);
1340 emitcode (rmwaop, "");
1341 hc08_dirtyReg (hc08_reg_a, FALSE);
1342 transferRegReg(hc08_reg_a, reg, TRUE);
1346 pushReg (reg, FALSE);
1347 emitcode (rmwop, "1,s");
1349 hc08_dirtyReg (reg, FALSE);
1353 /*--------------------------------------------------------------------------*/
1354 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1355 /* logical offset loffset of asmop aop. */
1356 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror, tst */
1357 /*--------------------------------------------------------------------------*/
1359 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1361 bool needpula = FALSE;
1363 if (aop->stacked && aop->stk_aop[loffset])
1365 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1372 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1375 needpula = pushRegIfUsed (hc08_reg_a);
1376 loadRegFromAop (hc08_reg_a, aop, loffset);
1377 rmwWithReg (rmwop, hc08_reg_a);
1378 if (strcmp ("tst", rmwop))
1379 storeRegToAop (hc08_reg_a, aop, loffset);
1380 pullOrFreeReg (hc08_reg_a, needpula);
1385 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1391 /*-----------------------------------------------------------------*/
1392 /* newAsmop - creates a new asmOp */
1393 /*-----------------------------------------------------------------*/
1395 newAsmop (short type)
1399 aop = Safe_calloc (1, sizeof (asmop));
1406 /*-----------------------------------------------------------------*/
1407 /* pointerCode - returns the code for a pointer type */
1408 /*-----------------------------------------------------------------*/
1410 pointerCode (sym_link * etype)
1413 return PTR_TYPE (SPEC_OCLS (etype));
1418 /*-----------------------------------------------------------------*/
1419 /* aopForSym - for a true symbol */
1420 /*-----------------------------------------------------------------*/
1422 aopForSym (iCode * ic, symbol * sym, bool result)
1427 wassertl (ic != NULL, "Got a null iCode");
1428 wassertl (sym != NULL, "Got a null symbol");
1430 // printf("in aopForSym for symbol %s\n", sym->name);
1432 space = SPEC_OCLS (sym->etype);
1434 /* if already has one */
1440 /* special case for a function */
1441 if (IS_FUNC (sym->type))
1443 sym->aop = aop = newAsmop (AOP_IMMD);
1444 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1445 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1446 aop->size = FPTRSIZE;
1450 /* if it is in direct space */
1451 if (IN_DIRSPACE (space))
1453 sym->aop = aop = newAsmop (AOP_DIR);
1454 aop->aopu.aop_dir = sym->rname;
1455 aop->size = getSize (sym->type);
1459 /* if it is in far space */
1460 if (IN_FARSPACE (space))
1462 sym->aop = aop = newAsmop (AOP_EXT);
1463 aop->aopu.aop_dir = sym->rname;
1464 aop->size = getSize (sym->type);
1468 if (IN_STACK (sym->etype))
1470 sym->aop = aop = newAsmop (AOP_SOF);
1471 aop->aopu.aop_dir = sym->rname;
1472 aop->size = getSize (sym->type);
1473 aop->aopu.aop_stk = sym->stack;
1479 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1480 "aopForSym should never reach here");
1484 /* if it is in code space */
1485 if (IN_CODESPACE (space))
1491 /*-----------------------------------------------------------------*/
1492 /* aopForRemat - rematerialzes an object */
1493 /*-----------------------------------------------------------------*/
1495 aopForRemat (symbol * sym)
1497 iCode *ic = sym->rematiCode;
1505 val += (int) operandLitValue (IC_RIGHT (ic));
1506 else if (ic->op == '-')
1507 val -= (int) operandLitValue (IC_RIGHT (ic));
1508 else if (IS_CAST_ICODE(ic)) {
1509 sym_link *from_type = operandType(IC_RIGHT(ic));
1510 aop->aopu.aop_immd.from_cast_remat = 1;
1511 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1512 ptr_type = DCL_TYPE(from_type);
1513 if (ptr_type == IPOINTER) {
1520 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1523 if (ic->op == ADDRESS_OF)
1526 sprintf (buffer, "(%s %c 0x%04x)",
1527 OP_SYMBOL (IC_LEFT (ic))->rname,
1528 val >= 0 ? '+' : '-',
1529 abs (val) & 0xffff);
1531 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1533 aop = newAsmop (AOP_IMMD);
1534 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1535 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1536 /* set immd2 field if required */
1537 if (aop->aopu.aop_immd.from_cast_remat)
1539 sprintf(buffer,"#0x%02x",ptr_type);
1540 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1541 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1544 else if (ic->op == '=')
1546 val += (int) operandLitValue (IC_RIGHT (ic));
1548 sprintf (buffer, "0x%04x", val);
1549 aop = newAsmop (AOP_LIT);
1550 aop->aopu.aop_lit = constVal (buffer);
1553 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1554 "unexpected rematerialization");
1561 /*-----------------------------------------------------------------*/
1562 /* regsInCommon - two operands have some registers in common */
1563 /*-----------------------------------------------------------------*/
1565 regsInCommon (operand * op1, operand * op2)
1567 symbol *sym1, *sym2;
1570 /* if they have registers in common */
1571 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1574 sym1 = OP_SYMBOL (op1);
1575 sym2 = OP_SYMBOL (op2);
1577 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1580 for (i = 0; i < sym1->nRegs; i++)
1586 for (j = 0; j < sym2->nRegs; j++)
1591 if (sym2->regs[j] == sym1->regs[i])
1599 /*-----------------------------------------------------------------*/
1600 /* operandsEqu - equivalent */
1601 /*-----------------------------------------------------------------*/
1603 operandsEqu (operand * op1, operand * op2)
1605 symbol *sym1, *sym2;
1607 /* if they not symbols */
1608 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1611 sym1 = OP_SYMBOL (op1);
1612 sym2 = OP_SYMBOL (op2);
1614 /* if both are itemps & one is spilt
1615 and the other is not then false */
1616 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1617 sym1->isspilt != sym2->isspilt)
1620 /* if they are the same */
1624 if (sym1->rname[0] && sym2->rname[0]
1625 && strcmp (sym1->rname, sym2->rname) == 0)
1628 /* if left is a tmp & right is not */
1629 if (IS_ITEMP (op1) &&
1632 (sym1->usl.spillLoc == sym2))
1635 if (IS_ITEMP (op2) &&
1639 (sym2->usl.spillLoc == sym1))
1645 /*-----------------------------------------------------------------*/
1646 /* sameRegs - two asmops have the same registers */
1647 /*-----------------------------------------------------------------*/
1649 sameRegs (asmop * aop1, asmop * aop2)
1656 // if (aop1->size != aop2->size)
1659 if (aop1->type == aop2->type)
1664 for (i = 0; i < aop1->size; i++)
1665 if (aop1->aopu.aop_reg[i] !=
1666 aop2->aopu.aop_reg[i])
1670 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1673 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1680 /*-----------------------------------------------------------------*/
1681 /* aopOp - allocates an asmop for an operand : */
1682 /*-----------------------------------------------------------------*/
1684 aopOp (operand * op, iCode * ic, bool result)
1693 // Is this a pointer set result?
1695 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1699 // printf("checking literal\n");
1700 /* if this a literal */
1701 if (IS_OP_LITERAL (op))
1703 op->aop = aop = newAsmop (AOP_LIT);
1704 aop->aopu.aop_lit = op->operand.valOperand;
1705 aop->size = getSize (operandType (op));
1707 aop->isaddr = op->isaddr;
1711 // printf("checking pre-existing\n");
1712 /* if already has a asmop then continue */
1716 op->aop->isaddr = op->isaddr;
1720 // printf("checking underlying sym\n");
1721 /* if the underlying symbol has a aop */
1722 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1724 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1725 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1726 //op->aop = aop = OP_SYMBOL (op)->aop;
1727 aop->size = getSize( operandType (op));
1728 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1729 //printf (" with size = %d\n", aop->size);
1732 aop->isaddr = op->isaddr;
1733 /* if (aop->isaddr & IS_ITEMP (op))
1735 aop->psize=aop->size;
1736 aop->size = getSize( operandType (op)->next);
1741 // printf("checking true sym\n");
1742 /* if this is a true symbol */
1743 if (IS_TRUE_SYMOP (op))
1745 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1747 aop->isaddr = op->isaddr;
1748 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1749 //printf (" with size = %d\n", aop->size);
1753 /* this is a temporary : this has
1759 e) can be a return use only */
1761 sym = OP_SYMBOL (op);
1763 // printf("checking conditional\n");
1764 /* if the type is a conditional */
1765 if (sym->regType == REG_CND)
1767 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1770 aop->isaddr = op->isaddr;
1774 // printf("checking spilt\n");
1775 /* if it is spilt then two situations
1777 b) has a spill location */
1778 if (sym->isspilt || sym->nRegs == 0)
1781 // printf("checking remat\n");
1782 /* rematerialize it NOW */
1785 sym->aop = op->aop = aop =
1787 aop->size = getSize (sym->type);
1789 aop->isaddr = op->isaddr;
1790 /* if (aop->isaddr & IS_ITEMP (op))
1792 aop->psize=aop->size;
1793 aop->size = getSize( operandType (op)->next);
1798 // printf("checking accuse\n");
1801 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1802 aop->size = getSize (sym->type);
1803 switch (sym->accuse)
1806 aop->aopu.aop_reg[0] = hc08_reg_a;
1807 aop->aopu.aop_reg[1] = hc08_reg_x;
1810 aop->aopu.aop_reg[0] = hc08_reg_x;
1811 aop->aopu.aop_reg[1] = hc08_reg_h;
1815 aop->isaddr = op->isaddr;
1819 // printf("checking ruonly\n");
1825 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1826 aop->size = getSize (sym->type);
1827 for (i = 0; i < fReturnSizeHC08; i++)
1828 aop->aopu.aop_str[i] = fReturn2[i];
1830 aop->isaddr = op->isaddr;
1834 /* else spill location */
1835 if (sym->usl.spillLoc)
1837 asmop *oldAsmOp = NULL;
1839 if (sym->usl.spillLoc->aop
1840 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1842 /* force a new aop if sizes differ */
1843 oldAsmOp = sym->usl.spillLoc->aop;
1844 sym->usl.spillLoc->aop = NULL;
1845 //printf ("forcing new aop\n");
1847 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1848 if (sym->usl.spillLoc->aop->size != getSize (sym->type))
1850 /* Don't reuse the new aop, go with the last one */
1851 sym->usl.spillLoc->aop = oldAsmOp;
1853 aop->size = getSize (sym->type);
1855 aop->isaddr = op->isaddr;
1856 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1857 //printf (" with size = %d\n", aop->size);
1861 /* else must be a dummy iTemp */
1862 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1863 aop->size = getSize (sym->type);
1867 // printf("assuming register\n");
1868 /* must be in a register */
1869 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1870 aop->size = sym->nRegs;
1871 for (i = 0; i < sym->nRegs; i++)
1872 aop->aopu.aop_reg[i] = sym->regs[i];
1874 aop->isaddr = op->isaddr;
1878 /*-----------------------------------------------------------------*/
1879 /* freeAsmop - free up the asmop given to an operand */
1880 /*----------------------------------------------------------------*/
1882 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1904 DD(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1907 for (loffset=0; loffset<aop->size; loffset++)
1908 if (aop->stk_aop[loffset])
1910 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1913 pullNull (stackAdjust);
1917 /* all other cases just dealloc */
1923 OP_SYMBOL (op)->aop = NULL;
1924 /* if the symbol has a spill */
1926 SPIL_LOC (op)->aop = NULL;
1932 /*-----------------------------------------------------------------*/
1933 /* aopDerefAop - treating the aop parameter as a pointer, return */
1934 /* an asmop for the object it references */
1935 /*-----------------------------------------------------------------*/
1937 aopDerefAop (asmop *aop)
1942 asmop *newaop = NULL;
1943 sym_link *type, *etype;
1946 DD(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1950 type = operandType (aop->op);
1951 etype = getSpec (type);
1952 /* if op is of type of pointer then it is simple */
1953 if (IS_PTR (type) && !IS_FUNC (type->next))
1954 p_type = DCL_TYPE (type);
1957 /* we have to go by the storage class */
1958 p_type = PTR_TYPE (SPEC_OCLS (etype));
1967 if (p_type == POINTER)
1968 newaop = newAsmop (AOP_DIR);
1970 newaop = newAsmop (AOP_EXT);
1971 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1974 adr = (int) floatFromVal (aop->aopu.aop_lit);
1975 if (p_type == POINTER)
1980 newaop = newAsmop (AOP_DIR);
1981 sprintf (s, "0x%02x",adr);
1985 newaop = newAsmop (AOP_EXT);
1986 sprintf (s, "0x%04x",adr);
1988 rs = Safe_calloc (1, strlen (s) + 1);
1990 newaop->aopu.aop_dir = rs;
1993 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1994 "unsupported asmop");
2004 /*-----------------------------------------------------------------*/
2005 /* aopAdrStr - for referencing the address of the aop */
2006 /*-----------------------------------------------------------------*/
2008 aopAdrStr (asmop * aop, int loffset, bool bit16)
2012 int offset = aop->size - 1 - loffset;
2015 /* offset is greater than
2017 if (loffset > (aop->size - 1) &&
2018 aop->type != AOP_LIT)
2021 /* depending on type */
2029 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
2030 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
2032 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
2036 sprintf (s, "#(%s >> %d)",
2037 aop->aopu.aop_immd.aop_immd1,
2041 aop->aopu.aop_immd.aop_immd1);
2045 aop->aopu.aop_immd.aop_immd1);
2046 rs = Safe_calloc (1, strlen (s) + 1);
2052 sprintf (s, "*(%s + %d)",
2056 sprintf (s, "*%s", aop->aopu.aop_dir);
2057 rs = Safe_calloc (1, strlen (s) + 1);
2063 sprintf (s, "(%s + %d)",
2067 sprintf (s, "%s", aop->aopu.aop_dir);
2068 rs = Safe_calloc (1, strlen (s) + 1);
2073 return aop->aopu.aop_reg[loffset]->name;
2077 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
2079 return aopLiteral (aop->aopu.aop_lit, loffset);
2083 return aop->aopu.aop_str[loffset];
2086 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2088 rs = Safe_calloc (1, strlen (s) + 1);
2094 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2095 "aopAdrStr got unsupported aop->type");
2104 /*-----------------------------------------------------------------*/
2105 /* opIsGptr: returns non-zero if the passed operand is */
2106 /* a generic pointer type. */
2107 /*-----------------------------------------------------------------*/
2109 opIsGptr (operand * op)
2111 sym_link *type = operandType (op);
2113 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2121 /*-----------------------------------------------------------------*/
2122 /* getDataSize - get the operand data size */
2123 /*-----------------------------------------------------------------*/
2125 getDataSize (operand * op)
2128 size = AOP_SIZE (op);
2133 /*-----------------------------------------------------------------*/
2134 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2135 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2136 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2137 /*-----------------------------------------------------------------*/
2139 asmopToBool (asmop *aop, bool resultInA)
2141 symbol *tlbl, *tlbl1;
2142 int size = aop->size;
2143 bool needpula = FALSE;
2144 bool flagsonly = TRUE;
2149 hc08_freeReg(hc08_reg_a);
2156 emitcode ("tsta", "");
2159 else if (IS_AOP_X(aop))
2160 emitcode ("tstx", "");
2161 else if (IS_AOP_H(aop))
2163 if (hc08_reg_a->isFree)
2165 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2166 emitcode ("tsta", "");
2168 hc08_freeReg(hc08_reg_a);
2170 else if (hc08_reg_x->isFree)
2172 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2173 emitcode ("tstx", "");
2174 hc08_freeReg(hc08_reg_x);
2178 emitcode ("pshh", "");
2179 emitcode ("tst", "1,s");
2180 emitcode ("ais", "#1");
2183 else if (IS_AOP_HX(aop))
2184 emitcode ("cphx", zero);
2185 else if (IS_AOP_XA(aop))
2187 symbol *tlbl = newiTempLabel (NULL);
2188 emitcode ("tsta", "");
2189 emitcode ("bne", "%05d$", (tlbl->key + 100));
2190 emitcode ("tstx", "");
2195 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2196 "Bad rIdx in asmToBool");
2204 needpula = pushRegIfUsed (hc08_reg_a);
2205 loadRegFromAop (hc08_reg_a, aop, 0);
2206 for (offset=1; offset<size; offset++)
2207 accopWithAop ("ora", aop, offset);
2209 pullReg (hc08_reg_a);
2212 hc08_freeReg (hc08_reg_a);
2217 /* Higher levels should optimize this case away but let's be safe */
2218 if ((unsigned long) floatFromVal (aop->aopu.aop_lit))
2219 loadRegFromConst (hc08_reg_a, one);
2221 loadRegFromConst (hc08_reg_a, zero);
2222 hc08_freeReg(hc08_reg_a);
2229 loadRegFromAop (hc08_reg_a, aop, 0);
2230 hc08_freeReg (hc08_reg_a);
2234 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2239 if (hc08_reg_a->isFree)
2241 loadRegFromAop (hc08_reg_a, aop, 0);
2242 accopWithAop ("ora", aop, 1);
2243 hc08_freeReg (hc08_reg_a);
2248 tlbl = newiTempLabel (NULL);
2249 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2250 emitcode ("bne", "%05d$", (tlbl->key + 100));
2251 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2258 needpula = pushRegIfUsed (hc08_reg_a);
2259 loadRegFromAop (hc08_reg_a, aop, 0);
2260 for (offset=1; offset<size; offset++)
2261 accopWithAop ("ora", aop, offset);
2263 pullReg (hc08_reg_a);
2266 hc08_freeReg (hc08_reg_a);
2274 tlbl = newiTempLabel (NULL);
2278 tlbl1 = newiTempLabel (NULL);
2279 emitBranch ("bne", tlbl1);
2280 loadRegFromConst (hc08_reg_a, zero);
2281 emitBranch ("bra", tlbl);
2283 loadRegFromConst (hc08_reg_a, one);
2287 emitBranch ("beq", tlbl);
2288 loadRegFromConst (hc08_reg_a, one);
2291 hc08_useReg (hc08_reg_a);
2297 /*-----------------------------------------------------------------*/
2298 /* genNot - generate code for ! operation */
2299 /*-----------------------------------------------------------------*/
2303 D(emitcode ("; genNot",""));
2305 /* assign asmOps to operand & result */
2306 aopOp (IC_LEFT (ic), ic, FALSE);
2307 aopOp (IC_RESULT (ic), ic, TRUE);
2309 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2310 emitcode ("eor", one);
2311 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2313 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2314 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2318 /*-----------------------------------------------------------------*/
2319 /* genCpl - generate code for complement */
2320 /*-----------------------------------------------------------------*/
2326 regs* reg = hc08_reg_a;
2330 D(emitcode ("; genCpl",""));
2332 /* assign asmOps to operand & result */
2333 aopOp (IC_LEFT (ic), ic, FALSE);
2334 aopOp (IC_RESULT (ic), ic, TRUE);
2336 size = AOP_SIZE (IC_RESULT (ic));
2339 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2340 rmwWithReg ("com", reg);
2342 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2347 /* release the aops */
2348 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2349 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2352 /*-----------------------------------------------------------------*/
2353 /* genUminusFloat - unary minus for floating points */
2354 /*-----------------------------------------------------------------*/
2356 genUminusFloat (operand * op, operand * result)
2358 int size, offset = 0;
2361 D(emitcode ("; genUminusFloat",""));
2363 /* for this we just copy and then flip the bit */
2365 size = AOP_SIZE (op) - 1;
2369 transferAopAop (AOP (op), offset, AOP (result), offset);
2373 needpula = pushRegIfUsed (hc08_reg_a);
2374 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2375 emitcode ("eor", "#0x80");
2376 hc08_useReg (hc08_reg_a);
2377 storeRegToAop (hc08_reg_a, AOP (result), offset);
2378 pullOrFreeReg (hc08_reg_a, needpula);
2381 /*-----------------------------------------------------------------*/
2382 /* genUminus - unary minus code generation */
2383 /*-----------------------------------------------------------------*/
2385 genUminus (iCode * ic)
2388 sym_link *optype, *rtype;
2393 D(emitcode ("; genUminus",""));
2396 aopOp (IC_LEFT (ic), ic, FALSE);
2397 aopOp (IC_RESULT (ic), ic, TRUE);
2399 optype = operandType (IC_LEFT (ic));
2400 rtype = operandType (IC_RESULT (ic));
2402 /* if float then do float stuff */
2403 if (IS_FLOAT (optype))
2405 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2409 /* otherwise subtract from zero */
2410 size = AOP_SIZE (IC_LEFT (ic));
2415 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2416 needpula = pushRegIfUsed (hc08_reg_a);
2419 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2420 emitcode ("nega", "");
2421 hc08_freeReg (hc08_reg_a);
2422 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2423 SPEC_USIGN (operandType (IC_LEFT (ic))));
2424 pullOrFreeReg (hc08_reg_a, needpula);
2428 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2429 result = forceStackedAop (AOP (IC_RESULT (ic)), FALSE);
2431 result = AOP (IC_RESULT (ic));
2433 needpula = pushRegIfUsed (hc08_reg_a);
2437 loadRegFromConst (hc08_reg_a, zero);
2438 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2439 storeRegToAop (hc08_reg_a, result, offset++);
2442 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2443 SPEC_USIGN (operandType (IC_LEFT (ic))));
2444 pullOrFreeReg (hc08_reg_a, needpula);
2446 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2447 freeAsmop (NULL, result, ic, TRUE);
2453 /* release the aops */
2454 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2455 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2458 /*-----------------------------------------------------------------*/
2459 /* saveRegisters - will look for a call and save the registers */
2460 /*-----------------------------------------------------------------*/
2462 saveRegisters (iCode * lic)
2469 for (ic = lic; ic; ic = ic->next)
2470 if (ic->op == CALL || ic->op == PCALL)
2475 fprintf (stderr, "found parameter push with no function call\n");
2479 /* if the registers have been saved already or don't need to be then
2483 if (IS_SYMOP(IC_LEFT(ic)) &&
2484 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2485 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2488 /* safe the registers in use at this time but skip the
2489 ones for the result */
2490 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2491 hc08_rUmaskForOp (IC_RESULT(ic)));
2494 for (i = 0; i < hc08_nRegs; i++)
2496 if (bitVectBitValue (rsave, i))
2497 pushReg ( hc08_regWithIdx (i), FALSE);
2501 /*-----------------------------------------------------------------*/
2502 /* unsaveRegisters - pop the pushed registers */
2503 /*-----------------------------------------------------------------*/
2505 unsaveRegisters (iCode * ic)
2510 /* restore the registers in use at this time but skip the
2511 ones for the result */
2512 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2513 hc08_rUmaskForOp (IC_RESULT(ic)));
2515 for (i = hc08_nRegs; i >= 0; i--)
2517 if (bitVectBitValue (rsave, i))
2518 pullReg ( hc08_regWithIdx (i));
2524 /*-----------------------------------------------------------------*/
2526 /*-----------------------------------------------------------------*/
2528 pushSide (operand * oper, int size)
2533 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2534 pushReg ( hc08_reg_a, TRUE);
2538 /*-----------------------------------------------------------------*/
2539 /* assignResultValue - */
2540 /*-----------------------------------------------------------------*/
2542 assignResultValue (operand * oper)
2544 int size = AOP_SIZE (oper);
2548 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2549 if (hc08_aop_pass[offset]->type == AOP_REG)
2550 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2557 /*-----------------------------------------------------------------*/
2558 /* genIpush - genrate code for pushing this gets a little complex */
2559 /*-----------------------------------------------------------------*/
2561 genIpush (iCode * ic)
2563 int size, offset = 0;
2566 D(emitcode ("; genIpush",""));
2568 /* if this is not a parm push : ie. it is spill push
2569 and spill push is always done on the local stack */
2573 /* and the item is spilt then do nothing */
2574 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2577 aopOp (IC_LEFT (ic), ic, FALSE);
2578 size = AOP_SIZE (IC_LEFT (ic));
2580 /* push it on the stack */
2583 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2584 pushReg ( hc08_reg_a, TRUE);
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 */
2595 /* then do the push */
2596 aopOp (IC_LEFT (ic), ic, FALSE);
2599 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2600 size = AOP_SIZE (IC_LEFT (ic));
2603 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2604 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2606 if ((size==2) && hc08_reg_hx->isFree)
2608 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2609 pushReg (hc08_reg_hx, TRUE);
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);
2623 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2626 /*-----------------------------------------------------------------*/
2627 /* genIpop - recover the registers: can happen only for spilling */
2628 /*-----------------------------------------------------------------*/
2630 genIpop (iCode * ic)
2634 D(emitcode ("; genIpop",""));
2636 /* if the temp was not pushed then */
2637 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2640 aopOp (IC_LEFT (ic), ic, FALSE);
2641 size = AOP_SIZE (IC_LEFT (ic));
2645 pullReg (hc08_reg_a);
2646 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2648 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2652 /*-----------------------------------------------------------------*/
2653 /* genSend - gen code for SEND */
2654 /*-----------------------------------------------------------------*/
2655 static void genSend(set *sendSet)
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));
2668 transferAopAop( AOP (IC_LEFT (sic)), offset,
2669 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2673 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2677 /*-----------------------------------------------------------------*/
2678 /* genCall - generates a call statement */
2679 /*-----------------------------------------------------------------*/
2681 genCall (iCode * ic)
2684 // bool restoreBank = FALSE;
2685 // bool swapBanks = FALSE;
2687 D(emitcode("; genCall",""));
2689 dtype = operandType (IC_LEFT (ic));
2690 /* if send set is not empty then assign */
2693 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2694 genSend(reverseSet(_G.sendSet));
2696 genSend(_G.sendSet);
2702 /* if caller saves & we have not saved then */
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));
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)))
2722 aopOp (IC_RESULT (ic), ic, FALSE);
2725 assignResultValue (IC_RESULT (ic));
2727 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2730 /* adjust the stack for parameters if
2734 pullNull (ic->parmBytes);
2737 /* if we had saved some registers then unsave them */
2738 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2739 unsaveRegisters (ic);
2743 /*-----------------------------------------------------------------*/
2744 /* -10l - generates a call by pointer statement */
2745 /*-----------------------------------------------------------------*/
2747 genPcall (iCode * ic)
2750 symbol *rlbl = newiTempLabel (NULL);
2751 symbol *tlbl = newiTempLabel (NULL);
2752 // bool restoreBank=FALSE;
2753 // bool swapBanks = FALSE;
2755 D(emitcode("; genPCall",""));
2757 /* if caller saves & we have not saved then */
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;
2766 /* now push the calling address */
2767 emitBranch ("bsr", tlbl);
2768 emitBranch ("bra", rlbl);
2770 _G.stackPushes += 2; /* account for the bsr return address now on stack */
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);
2778 /* if send set is not empty the assign */
2781 genSend(reverseSet(_G.sendSet));
2787 emitcode ("rts", "");
2790 _G.stackPushes -= 4; /* account for rts here & in called function */
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)))
2802 aopOp (IC_RESULT (ic), ic, FALSE);
2805 assignResultValue (IC_RESULT (ic));
2807 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2810 /* adjust the stack for parameters if
2814 pullNull (ic->parmBytes);
2817 /* if we hade saved some registers then
2819 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2820 unsaveRegisters (ic);
2823 /*-----------------------------------------------------------------*/
2824 /* resultRemat - result is rematerializable */
2825 /*-----------------------------------------------------------------*/
2827 resultRemat (iCode * ic)
2829 if (SKIP_IC (ic) || ic->op == IFX)
2832 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2834 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2835 if (sym->remat && !POINTER_SET (ic))
2842 /*-----------------------------------------------------------------*/
2843 /* inExcludeList - return 1 if the string is in exclude Reg list */
2844 /*-----------------------------------------------------------------*/
2846 regsCmp(void *p1, void *p2)
2848 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2852 inExcludeList (char *s)
2854 const char *p = setFirstItem(options.excludeRegsSet);
2856 if (p == NULL || STRCASECMP(p, "none") == 0)
2860 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2863 /*-----------------------------------------------------------------*/
2864 /* genFunction - generated code for function entry */
2865 /*-----------------------------------------------------------------*/
2867 genFunction (iCode * ic)
2869 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2871 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2872 int stackAdjust = sym->stack;
2873 int accIsFree = sym->recvSize == 0;
2877 /* create the function header */
2878 emitcode (";", "-----------------------------------------");
2879 emitcode (";", " function %s", sym->name);
2880 emitcode (";", "-----------------------------------------");
2882 emitcode ("", "%s:", sym->rname);
2883 lineCurr->isLabel = 1;
2884 ftype = operandType (IC_LEFT (ic));
2888 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2890 if (IFFUNC_ISNAKED(ftype))
2892 emitcode(";", "naked function: no prologue.");
2896 /* if this is an interrupt service routine then
2898 if (IFFUNC_ISISR (sym->type))
2901 if (!inExcludeList ("h"))
2902 pushReg (hc08_reg_h, FALSE);
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)
2909 while (ric && IC_RESULT (ric))
2911 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2912 int rsymSize = rsym ? getSize(rsym->type) : 0;
2916 if (rsym && rsym->regType == REG_CND)
2918 if (rsym && (rsym->accuse || rsym->ruonly))
2920 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2921 rsym = rsym->usl.spillLoc;
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)
2930 _G.current_iCode = ric;
2931 D(emitcode ("; genReceive",""));
2932 for (ofs=0; ofs < rsymSize; ofs++)
2934 regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
2935 pushReg (reg, TRUE);
2936 if (reg->rIdx == A_IDX)
2940 _G.current_iCode = ic;
2943 ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
2946 /* adjust the stack for the function */
2949 adjustStack (-stackAdjust);
2951 _G.stackOfs = sym->stack;
2954 /* if critical function then turn interrupts off */
2955 if (IFFUNC_ISCRITICAL (ftype))
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);
2969 /* No passed parameters, so A can be freely modified */
2970 emitcode ("tpa", "");
2971 pushReg (hc08_reg_a, TRUE);
2972 emitcode ("sei", "");
2978 /*-----------------------------------------------------------------*/
2979 /* genEndFunction - generates epilogue for functions */
2980 /*-----------------------------------------------------------------*/
2982 genEndFunction (iCode * ic)
2984 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2986 if (IFFUNC_ISNAKED(sym->type))
2988 emitcode(";", "naked function: no epilogue.");
2989 if (options.debug && currFunc)
2990 debugFile->writeEndFunction (currFunc, ic, 0);
2994 if (IFFUNC_ISCRITICAL (sym->type))
2996 if (!IS_VOID(sym->type->next))
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);
3007 /* Function returns void, so A can be freely modified */
3008 pullReg (hc08_reg_a);
3009 emitcode ("tap", "");
3013 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
3019 _G.stackPushes += sym->stack;
3020 adjustStack (sym->stack);
3024 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3028 if (IFFUNC_ISISR (sym->type))
3031 if (!inExcludeList ("h"))
3032 pullReg (hc08_reg_h);
3035 /* if debug then send end of function */
3036 if (options.debug && currFunc)
3038 debugFile->writeEndFunction (currFunc, ic, 1);
3041 emitcode ("rti", "");
3045 if (IFFUNC_CALLEESAVES(sym->type))
3049 /* if any registers used */
3052 /* save the registers used */
3053 for (i = sym->regsUsed->size; i >= 0; i--)
3055 if (bitVectBitValue (sym->regsUsed, i) ||
3056 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3057 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3063 /* if debug then send end of function */
3064 if (options.debug && currFunc)
3066 debugFile->writeEndFunction (currFunc, ic, 1);
3069 emitcode ("rts", "");
3074 /*-----------------------------------------------------------------*/
3075 /* genRet - generate code for return statement */
3076 /*-----------------------------------------------------------------*/
3080 int size, offset = 0;
3083 D(emitcode ("; genRet",""));
3085 /* if we have no return value then
3086 just generate the "ret" */
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));
3099 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3106 /* 4 byte return: store value in the global return variable */
3110 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3111 STA (fReturn2[offset--], FALSE);
3112 hc08_freeReg (hc08_reg_a);
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);
3121 /* 1 byte return: store value in a */
3122 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3123 hc08_freeReg (hc08_reg_a);
3128 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
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))
3136 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3140 /*-----------------------------------------------------------------*/
3141 /* genLabel - generates a label */
3142 /*-----------------------------------------------------------------*/
3144 genLabel (iCode * ic)
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++)
3153 reg = hc08_regWithIdx(i);
3158 /* special case never generate */
3159 if (IC_LABEL (ic) == entryLabel)
3162 debugFile->writeLabel(IC_LABEL (ic), ic);
3164 emitLabel (IC_LABEL (ic));
3168 /*-----------------------------------------------------------------*/
3169 /* genGoto - generates a jmp */
3170 /*-----------------------------------------------------------------*/
3172 genGoto (iCode * ic)
3174 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
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 /*-----------------------------------------------------------------*/
3185 findLabelBackwards (iCode * ic, int key)
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
3197 if (ic->op == IPUSH || ic->op == IPOP) {
3201 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3211 /*-----------------------------------------------------------------*/
3212 /* genPlusIncr :- does addition with increment if possible */
3213 /*-----------------------------------------------------------------*/
3215 genPlusIncr (iCode * ic)
3223 unsigned int size = getDataSize (IC_RESULT (ic));
3224 unsigned int offset;
3225 symbol *tlbl = NULL;
3227 left = IC_LEFT (ic);
3228 result = IC_RESULT (ic);
3230 /* will try to generate an increment */
3231 /* if the right side is not a literal
3233 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3236 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3238 DD(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3240 if ((IS_AOP_HX (AOP (left)) ||
3241 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3243 && (icount>=-128) && (icount<=127) && (size==2))
3245 if (!IS_AOP_HX (AOP (left)))
3247 needpulx = pushRegIfUsed (hc08_reg_x);
3248 needpulh = pushRegIfUsed (hc08_reg_h);
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);
3264 DD(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3265 sameRegs (AOP (left), AOP (result))));
3267 if ((icount > 255) || (icount<0))
3270 if (!sameRegs (AOP (left), AOP (result)))
3273 D(emitcode ("; genPlusIncr",""));
3276 tlbl = newiTempLabel (NULL);
3281 rmwWithAop ("inc", AOP (result), 0);
3283 emitBranch ("bne", tlbl);
3287 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3288 needpula = pushRegIfUsed (hc08_reg_a);
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);
3297 emitBranch ("bcc", tlbl);
3299 for (offset=1; offset<size; offset++)
3301 rmwWithAop ("inc", AOP (result), offset);
3302 if ((offset+1)<size)
3303 emitBranch ("bne", tlbl);
3309 pullOrFreeReg (hc08_reg_a, needpula);
3316 /*-----------------------------------------------------------------*/
3317 /* genPlus - generates code for addition */
3318 /*-----------------------------------------------------------------*/
3320 genPlus (iCode * ic)
3322 int size, offset = 0;
3324 asmop *leftOp, *rightOp;
3326 /* special cases :- */
3328 D(emitcode ("; genPlus",""));
3330 aopOp (IC_LEFT (ic), ic, FALSE);
3331 aopOp (IC_RIGHT (ic), ic, FALSE);
3332 aopOp (IC_RESULT (ic), ic, TRUE);
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))
3338 operand *t = IC_RIGHT (ic);
3339 IC_RIGHT (ic) = IC_LEFT (ic);
3344 /* if I can do an increment instead
3345 of add then GOOD for ME */
3346 if (genPlusIncr (ic) == TRUE)
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))));
3353 size = getDataSize (IC_RESULT (ic));
3355 leftOp = AOP(IC_LEFT(ic));
3356 rightOp = AOP(IC_RIGHT(ic));
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 */
3370 // adjustArithmeticResult (ic);
3373 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3374 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3375 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3378 /*-----------------------------------------------------------------*/
3379 /* genMinusDec :- does subtraction with decrement if possible */
3380 /*-----------------------------------------------------------------*/
3382 genMinusDec (iCode * ic)
3384 unsigned int icount;
3389 unsigned int size = getDataSize (IC_RESULT (ic));
3393 left = IC_LEFT (ic);
3394 result = IC_RESULT (ic);
3396 /* will try to generate an increment */
3397 /* if the right side is not a literal
3399 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3402 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3404 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3405 && (icount>=-127) && (icount<=128) && (size==2))
3407 if (!IS_AOP_HX (AOP (left)))
3409 needpulx = pushRegIfUsed (hc08_reg_x);
3410 needpulh = pushRegIfUsed (hc08_reg_h);
3417 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3418 emitcode ("aix","#%d", -icount);
3419 hc08_dirtyReg (hc08_reg_hx, FALSE);
3420 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3421 pullOrFreeReg (hc08_reg_h, needpulh);
3422 pullOrFreeReg (hc08_reg_x, needpulx);
3426 if ((icount > 1) || (icount<0))
3429 if (!sameRegs (AOP (left), AOP (result)))
3435 D(emitcode ("; genMinusDec",""));
3437 rmwWithAop ("dec", AOP (result), 0);
3442 /*-----------------------------------------------------------------*/
3443 /* addSign - complete with sign */
3444 /*-----------------------------------------------------------------*/
3446 addSign (operand * result, int offset, int sign)
3448 int size = (getDataSize (result) - offset);
3453 emitcode ("rola", "");
3454 emitcode ("clra", "");
3455 emitcode ("sbc", zero);
3457 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3461 storeConstToAop (zero, AOP (result), offset++);
3466 /*-----------------------------------------------------------------*/
3467 /* genMinus - generates code for subtraction */
3468 /*-----------------------------------------------------------------*/
3470 genMinus (iCode * ic)
3473 int size, offset = 0;
3475 asmop *leftOp, *rightOp;
3477 D(emitcode ("; genMinus",""));
3479 aopOp (IC_LEFT (ic), ic, FALSE);
3480 aopOp (IC_RIGHT (ic), ic, FALSE);
3481 aopOp (IC_RESULT (ic), ic, TRUE);
3483 /* special cases :- */
3484 /* if I can do an decrement instead
3485 of subtract then GOOD for ME */
3486 if (genMinusDec (ic) == TRUE)
3489 size = getDataSize (IC_RESULT (ic));
3492 leftOp = AOP(IC_LEFT(ic));
3493 rightOp = AOP(IC_RIGHT(ic));
3497 if (IS_AOP_A (rightOp))
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++);
3508 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3509 accopWithAop (sub, rightOp, offset);
3510 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3515 // adjustArithmeticResult (ic);
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);
3525 /*-----------------------------------------------------------------*/
3526 /* genMultOneByte : 8*8=8/16 bit multiplication */
3527 /*-----------------------------------------------------------------*/
3529 genMultOneByte (operand * left,
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;
3539 D(emitcode ("; genMultOneByte",""));
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);
3548 /* (if two literals: the value is computed before) */
3549 /* if one literal, literal on the right */
3550 if (AOP_TYPE (left) == AOP_LIT)
3556 /* if an operand is in A, make sure it is on the left */
3557 if (IS_AOP_A (AOP (right)))
3564 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3565 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
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 */
3579 || (lUnsigned && rUnsigned))
3581 // just an unsigned 8*8=8/16 multiply
3582 //DD(emitcode (";","unsigned"));
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);
3594 // we have to do a signed multiply
3597 /* left unsigned, right signed literal -- literal determines sign handling */
3598 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3600 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3602 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3604 emitcode ("ldx", "#0x%02x", -val);
3606 emitcode ("ldx", "#0x%02x", val);
3608 emitcode ("mul", "");
3612 rmwWithReg ("neg", hc08_reg_a);
3613 tlbl4 = newiTempLabel (NULL);
3614 emitBranch ("bcc", tlbl4);
3615 rmwWithReg ("inc", hc08_reg_x);
3617 rmwWithReg ("neg", hc08_reg_x);
3620 hc08_dirtyReg (hc08_reg_xa, FALSE);
3621 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3622 hc08_freeReg (hc08_reg_xa);
3629 emitcode ("clr", "1,s");
3631 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3634 tlbl1 = newiTempLabel (NULL);
3635 emitcode ("tsta","");
3636 emitBranch ("bpl", tlbl1);
3637 emitcode ("inc", "1,s");
3638 rmwWithReg ("neg", hc08_reg_a);
3642 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3644 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3645 /* AND literal negative */
3647 emitcode ("ldx", "#0x%02x", -val);
3650 emitcode ("ldx", "#0x%02x", val);
3652 hc08_useReg (hc08_reg_x);
3656 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3659 tlbl2 = newiTempLabel (NULL);
3660 emitcode ("tstx", "");
3661 emitBranch ("bpl", tlbl2);
3662 emitcode ("inc", "1,s");
3663 rmwWithReg ("neg", hc08_reg_x);
3668 emitcode ("mul", "");
3669 hc08_dirtyReg (hc08_reg_xa, FALSE);
3671 tlbl3 = newiTempLabel (NULL);
3672 emitcode ("dec", "1,s");
3673 if (!lUnsigned && !rUnsigned && negLiteral)
3674 emitBranch ("beq", tlbl3);
3676 emitBranch ("bne", tlbl3);
3678 rmwWithReg ("neg", hc08_reg_a);
3679 tlbl4 = newiTempLabel (NULL);
3680 emitBranch ("bcc", tlbl4);
3681 rmwWithReg ("inc", hc08_reg_x);
3683 rmwWithReg ("neg", hc08_reg_x);
3687 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3688 hc08_freeReg (hc08_reg_xa);
3692 /*-----------------------------------------------------------------*/
3693 /* genMult - generates code for multiplication */
3694 /*-----------------------------------------------------------------*/
3696 genMult (iCode * ic)
3698 operand *left = IC_LEFT (ic);
3699 operand *right = IC_RIGHT (ic);
3700 operand *result = IC_RESULT (ic);
3702 D(emitcode ("; genMult",""));
3704 /* assign the amsops */
3705 aopOp (left, ic, FALSE);
3706 aopOp (right, ic, FALSE);
3707 aopOp (result, ic, TRUE);
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)
3716 genMultOneByte (left, right, result);
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),
3728 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3729 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3730 freeAsmop (result, NULL, ic, TRUE);
3733 /*-----------------------------------------------------------------*/
3734 /* genDivOneByte : 8 bit division */
3735 /*-----------------------------------------------------------------*/
3737 genDivOneByte (operand * left,
3741 symbol *tlbl1, *tlbl2, *tlbl3;
3744 bool lUnsigned, rUnsigned;
3745 bool runtimeSign, compiletimeSign;
3747 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3748 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3750 D(emitcode ("; genDivOneByte",""));
3752 size = AOP_SIZE (result);
3753 /* signed or unsigned */
3754 if (lUnsigned && rUnsigned)
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);
3770 /* signed is a little bit more difficult */
3772 /* now sign adjust for both left & right */
3774 /* let's see what's needed: */
3775 /* apply negative sign during runtime */
3776 runtimeSign = FALSE;
3777 /* negative sign from literals */
3778 compiletimeSign = FALSE;
3782 if (AOP_TYPE(left) == AOP_LIT)
3784 /* signed literal */
3785 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3787 compiletimeSign = TRUE;
3790 /* signed but not literal */
3796 if (AOP_TYPE(right) == AOP_LIT)
3798 /* signed literal */
3799 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3801 compiletimeSign ^= TRUE;
3804 /* signed but not literal */
3808 /* initialize the runtime sign */
3811 if (compiletimeSign)
3812 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3814 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3815 pushReg (hc08_reg_x, TRUE);
3818 /* save the signs of the operands */
3819 if (AOP_TYPE(right) == AOP_LIT)
3821 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3823 if (!rUnsigned && val < 0)
3824 emitcode ("ldx", "#0x%02x", -val);
3826 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3828 else /* ! literal */
3830 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3833 tlbl1 = newiTempLabel (NULL);
3834 emitcode ("tstx", "");
3835 emitBranch ("bpl", tlbl1);
3836 emitcode ("inc", "1,s");
3837 rmwWithReg ("neg", hc08_reg_x);
3842 if (AOP_TYPE(left) == AOP_LIT)
3844 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3846 if (!lUnsigned && val < 0)
3847 emitcode ("lda", "#0x%02x", -val);
3849 emitcode ("lda", "#0x%02x", (unsigned char) val);
3851 else /* ! literal */
3853 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3856 tlbl2 = newiTempLabel (NULL);
3857 emitcode ("tsta", "");
3858 emitBranch ("bpl", tlbl2);
3859 emitcode ("inc", "1,s");
3860 rmwWithReg ("neg", hc08_reg_a);
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);
3871 if (runtimeSign || compiletimeSign)
3873 tlbl3 = newiTempLabel (NULL);
3876 pullReg (hc08_reg_x);
3877 rmwWithReg ("lsr", hc08_reg_x);
3878 rmwWithReg ("ror", hc08_reg_x);
3879 emitBranch ("bpl", tlbl3);
3882 rmwWithReg ("neg", hc08_reg_a);
3886 storeRegToAop (hc08_reg_a, AOP (result), 0);
3890 /* msb is 0x00 or 0xff depending on the sign */
3893 rmwWithReg ("lsl", hc08_reg_x);
3894 emitcode ("clra", "");
3895 emitcode ("sbc", "#0");
3897 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3899 else /* compiletimeSign */
3901 storeConstToAop ("#0xff", AOP (result), ++offset);
3906 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3909 hc08_freeReg (hc08_reg_a);
3910 hc08_freeReg (hc08_reg_x);
3911 hc08_freeReg (hc08_reg_h);
3914 /*-----------------------------------------------------------------*/
3915 /* genDiv - generates code for division */
3916 /*-----------------------------------------------------------------*/
3920 operand *left = IC_LEFT (ic);
3921 operand *right = IC_RIGHT (ic);
3922 operand *result = IC_RESULT (ic);
3924 D(emitcode ("; genDiv",""));
3926 /* assign the amsops */
3927 aopOp (left, ic, FALSE);
3928 aopOp (right, ic, FALSE);
3929 aopOp (result, ic, TRUE);
3931 /* special cases first */
3932 /* if both are of size == 1 */
3933 if (AOP_SIZE (left) <= 2 &&
3934 AOP_SIZE (right) == 1)
3936 genDivOneByte (left, right, result);
3940 /* should have been converted to function call */
3943 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3944 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3945 freeAsmop (result, NULL, ic, TRUE);
3948 /*-----------------------------------------------------------------*/
3949 /* genModOneByte : 8 bit modulus */
3950 /*-----------------------------------------------------------------*/
3952 genModOneByte (operand * left,
3956 symbol *tlbl1, *tlbl2, *tlbl3;
3959 bool lUnsigned, rUnsigned;
3960 bool runtimeSign, compiletimeSign;
3962 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3963 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3965 D(emitcode ("; genModOneByte",""));
3967 size = AOP_SIZE (result);
3969 if (lUnsigned && rUnsigned)
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);
3984 /* signed is a little bit more difficult */
3986 if (AOP_TYPE(right) == AOP_LIT)
3988 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3990 if (!rUnsigned && val < 0)
3991 emitcode ("ldx", "#0x%02x", -val);
3993 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3995 else /* ! literal */
3997 loadRegFromAop (hc08_reg_x, AOP (right), 0);
4000 tlbl1 = newiTempLabel (NULL);
4001 emitcode ("tstx", "");
4002 emitBranch ("bpl", tlbl1);
4003 rmwWithReg ("neg", hc08_reg_x);
4008 /* let's see what's needed: */
4009 /* apply negative sign during runtime */
4010 runtimeSign = FALSE;
4011 /* negative sign from literals */
4012 compiletimeSign = FALSE;
4014 /* sign adjust left side */
4015 if (AOP_TYPE(left) == AOP_LIT)
4017 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4019 if (!lUnsigned && val < 0)
4021 compiletimeSign = TRUE; /* set sign flag */
4022 emitcode ("lda", "#0x%02x", -val);
4025 emitcode ("lda", "#0x%02x", (unsigned char) val);
4027 else /* ! literal */
4030 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4035 emitcode ("clr", "1,s");
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);
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);
4053 if (runtimeSign || compiletimeSign)
4055 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4056 tlbl3 = newiTempLabel (NULL);
4059 pullReg (hc08_reg_x);
4060 rmwWithReg ("lsr", hc08_reg_x);
4061 rmwWithReg ("ror", hc08_reg_x);
4062 emitBranch ("bpl", tlbl3);
4065 rmwWithReg ("neg", hc08_reg_a);
4069 storeRegToAop (hc08_reg_a, AOP (result), 0);
4073 /* msb is 0x00 or 0xff depending on the sign */
4076 rmwWithReg ("lsl", hc08_reg_x);
4077 emitcode ("clra", "");
4078 emitcode ("sbc", "#0");
4080 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4082 else /* compiletimeSign */
4084 storeConstToAop ("#0xff", AOP (result), ++offset);
4089 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4092 hc08_freeReg (hc08_reg_a);
4093 hc08_freeReg (hc08_reg_x);
4094 hc08_freeReg (hc08_reg_h);
4097 /*-----------------------------------------------------------------*/
4098 /* genMod - generates code for division */
4099 /*-----------------------------------------------------------------*/
4103 operand *left = IC_LEFT (ic);
4104 operand *right = IC_RIGHT (ic);
4105 operand *result = IC_RESULT (ic);
4107 D(emitcode ("; genMod",""));
4109 /* assign the amsops */
4110 aopOp (left, ic, FALSE);
4111 aopOp (right, ic, FALSE);
4112 aopOp (result, ic, TRUE);
4114 /* special cases first */
4115 /* if both are of size == 1 */
4116 if (AOP_SIZE (left) <= 2 &&
4117 AOP_SIZE (right) == 1)
4119 genModOneByte (left, right, result);
4123 /* should have been converted to function call */
4127 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4128 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4129 freeAsmop (result, NULL, ic, TRUE);
4132 /*-----------------------------------------------------------------*/
4133 /* genIfxJump :- will create a jump depending on the ifx */
4134 /*-----------------------------------------------------------------*/
4136 genIfxJump (iCode * ic, char *jval)
4139 symbol *tlbl = newiTempLabel (NULL);
4142 D(emitcode ("; genIfxJump",""));
4144 /* if true label then we jump if condition
4148 jlbl = IC_TRUE (ic);
4149 if (!strcmp (jval, "a"))
4151 else if (!strcmp (jval, "c"))
4158 /* false label is present */
4159 jlbl = IC_FALSE (ic);
4160 if (!strcmp (jval, "a"))
4162 else if (!strcmp (jval, "c"))
4167 emitBranch (inst, tlbl);
4168 emitBranch ("jmp", jlbl);
4171 /* mark the icode as generated */
4176 /*-----------------------------------------------------------------*/
4177 /* exchangedCmp : returns the opcode need if the two operands are */
4178 /* exchanged in a comparison */
4179 /*-----------------------------------------------------------------*/
4181 exchangedCmp (int opcode)
4198 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4199 "opcode not a comparison");
4201 return EQ_OP; /* shouldn't happen, but need to return something */
4204 /*------------------------------------------------------------------*/
4205 /* negatedCmp : returns the equivalent opcode for when a comparison */
4207 /*------------------------------------------------------------------*/
4209 negatedCmp (int opcode)
4226 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4227 "opcode not a comparison");
4229 return EQ_OP; /* shouldn't happen, but need to return something */
4232 /* compile only if the debugging macro D is enabled */
4235 nameCmp (int opcode)
4257 /*------------------------------------------------------------------*/
4258 /* branchInstCmp : returns the conditional branch instruction that */
4259 /* will branch if the comparison is true */
4260 /*------------------------------------------------------------------*/
4262 branchInstCmp (int opcode, int sign)
4270 return "bcs"; /* same as blo */
4285 return "bcc"; /* same as bhs */
4291 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4292 "opcode not a comparison");
4298 /*------------------------------------------------------------------*/
4299 /* genCmp :- greater or less than (and maybe with equal) comparison */
4300 /*------------------------------------------------------------------*/
4302 genCmp (iCode * ic, iCode * ifx)
4304 operand *left, *right, *result;
4305 sym_link *letype, *retype;
4307 int size, offset = 0;
4308 unsigned long lit = 0L;
4310 symbol *jlbl = NULL;
4314 D(emitcode ("; genCmp", "(%s)",nameCmp (opcode)));
4316 result = IC_RESULT (ic);
4317 left = IC_LEFT (ic);
4318 right = IC_RIGHT (ic);
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);
4328 /* need register operand on left, prefer literal operand on right */
4329 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4331 operand *temp = left;
4334 opcode = exchangedCmp (opcode);
4341 jlbl = IC_TRUE (ifx);
4342 opcode = negatedCmp (opcode);
4346 /* false label is present */
4347 jlbl = IC_FALSE (ifx);
4351 size = max (AOP_SIZE (left), AOP_SIZE (right));
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)
4359 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4360 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4361 hc08_freeReg (hc08_reg_hx);
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))
4380 operand *temp = left;
4383 opcode = exchangedCmp (opcode);
4386 if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
4388 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4389 while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
4398 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4399 accopWithAop (sub, AOP (right), offset);
4400 hc08_freeReg (hc08_reg_a);
4405 freeAsmop (right, NULL, ic, FALSE);
4406 freeAsmop (left, NULL, ic, FALSE);
4410 symbol *tlbl = newiTempLabel (NULL);
4413 freeAsmop (result, NULL, ic, TRUE);
4415 inst = branchInstCmp (opcode, sign);
4416 emitBranch (inst, tlbl);
4417 emitBranch ("jmp", jlbl);
4420 /* mark the icode as generated */
4425 symbol *tlbl1 = newiTempLabel (NULL);
4426 symbol *tlbl2 = newiTempLabel (NULL);
4428 emitBranch (branchInstCmp (opcode, sign), tlbl1);
4429 loadRegFromConst (hc08_reg_a, zero);
4430 emitBranch ("bra", tlbl2);
4432 loadRegFromConst (hc08_reg_a, one);
4434 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4435 freeAsmop (result, NULL, ic, TRUE);
4440 /*-----------------------------------------------------------------*/
4441 /* genCmpEQorNE - equal or not equal comparison */
4442 /*-----------------------------------------------------------------*/
4444 genCmpEQorNE (iCode * ic, iCode * ifx)
4446 operand *left, *right, *result;
4447 sym_link *letype, *retype;
4449 int size, offset = 0;
4451 symbol *jlbl = NULL;
4452 symbol *tlbl_NE = NULL;
4453 symbol *tlbl_EQ = NULL;
4457 D(emitcode ("; genCmpEQorNE", "(%s)",nameCmp (opcode)));
4459 result = IC_RESULT (ic);
4460 left = IC_LEFT (ic);
4461 right = IC_RIGHT (ic);
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);
4471 /* need register operand on left, prefer literal operand on right */
4472 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4474 operand *temp = left;
4477 opcode = exchangedCmp (opcode);
4484 jlbl = IC_TRUE (ifx);
4485 opcode = negatedCmp (opcode);
4489 /* false label is present */
4490 jlbl = IC_FALSE (ifx);
4494 size = max (AOP_SIZE (left), AOP_SIZE (right));
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)
4502 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4503 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4504 hc08_freeReg (hc08_reg_hx);
4512 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4513 accopWithAop (sub, AOP (right), offset);
4517 tlbl_NE = newiTempLabel (NULL);
4518 emitBranch ("bne", tlbl_NE);
4520 hc08_freeReg (hc08_reg_a);
4524 freeAsmop (right, NULL, ic, FALSE);
4525 freeAsmop (left, NULL, ic, FALSE);
4529 freeAsmop (result, NULL, ic, TRUE);
4531 if (opcode == EQ_OP)
4534 tlbl_EQ = newiTempLabel (NULL);
4535 emitBranch ("beq", tlbl_EQ);
4537 emitLabel (tlbl_NE);
4538 emitBranch ("jmp", jlbl);
4539 emitLabel (tlbl_EQ);
4544 tlbl_NE = newiTempLabel (NULL);
4545 emitBranch ("bne", tlbl_NE);
4546 emitBranch ("jmp", jlbl);
4547 emitLabel (tlbl_NE);
4550 /* mark the icode as generated */
4555 symbol *tlbl = newiTempLabel (NULL);
4557 if (opcode == EQ_OP)
4560 tlbl_EQ = newiTempLabel (NULL);
4561 emitBranch ("beq", tlbl_EQ);
4563 emitLabel (tlbl_NE);
4564 loadRegFromConst (hc08_reg_a, zero);
4565 emitBranch ("bra", tlbl);
4566 emitLabel (tlbl_EQ);
4567 loadRegFromConst (hc08_reg_a, one);
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);
4581 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4582 freeAsmop (result, NULL, ic, TRUE);
4588 /*-----------------------------------------------------------------*/
4589 /* ifxForOp - returns the icode containing the ifx for operand */
4590 /*-----------------------------------------------------------------*/
4592 ifxForOp (operand * op, iCode * ic)
4594 /* if true symbol then needs to be assigned */
4595 if (IS_TRUE_SYMOP (op))
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 */
4602 ic->next->op == IFX &&
4603 IC_COND (ic->next)->key == op->key &&
4604 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4611 genPointerGetSetOfs (iCode *ic)
4613 iCode *lic = ic->next;
4619 /* Make sure we have a next iCode */
4620 DD(emitcode("","; checking lic"));
4624 /* Make sure the result of the addition is an iCode */
4625 DD(emitcode("","; checking IS_ITEMP"));
4626 if (!IS_ITEMP (IC_RESULT (ic)))
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));
4636 /* Make sure this is the only use of the pointer */
4637 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4640 DD(emitcode("", "; checking pset operandsEqu"));
4641 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4644 DD(emitcode("", "; checking pget operandsEqu"));
4645 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4648 DD(emitcode("", "; checking IS_SYMOP"));
4649 if (!IS_SYMOP (IC_LEFT (ic)))
4652 DD(emitcode("", "; checking !IS_TRUE_SYMOP"));
4653 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4656 sym = OP_SYMBOL (IC_LEFT (ic));
4658 DD(emitcode("", "; checking remat"));
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);
4670 aopOp (IC_RIGHT(ic), ic, FALSE);
4671 aopOp (IC_RESULT(lic), lic, FALSE);
4673 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4675 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4677 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4678 loadRegFromConst (hc08_reg_h, zero);
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);
4692 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4693 size = AOP_SIZE (IC_RESULT(lic));
4694 derefaop->size = size;
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);
4706 hc08_freeReg (hc08_reg_hx);
4708 freeAsmop (NULL, derefaop, ic, TRUE);
4709 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4710 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
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);
4722 aopOp (IC_RIGHT(ic), ic, FALSE);
4723 aopOp (IC_RIGHT(lic), lic, FALSE);
4725 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4727 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4729 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4730 loadRegFromConst (hc08_reg_h, zero);
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);
4744 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4745 size = AOP_SIZE (IC_RIGHT(lic));
4746 derefaop->size = size;
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);
4757 hc08_freeReg (hc08_reg_hx);
4759 freeAsmop (NULL, derefaop, ic, TRUE);
4760 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4761 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4770 /*-----------------------------------------------------------------*/
4771 /* hasInc - operand is incremented before any other use */
4772 /*-----------------------------------------------------------------*/
4774 hasInc (operand *op, iCode *ic,int osize)
4776 sym_link *type = operandType(op);
4777 sym_link *retype = getSpec (type);
4778 iCode *lic = ic->next;
4781 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4782 if (!IS_SYMOP(op)) return NULL;
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;
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) {
4796 /* if the operand used or deffed */
4797 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
4800 /* if GOTO or IFX */
4801 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4807 /*-----------------------------------------------------------------*/
4808 /* genAndOp - for && operation */
4809 /*-----------------------------------------------------------------*/
4811 genAndOp (iCode * ic)
4813 operand *left, *right, *result;
4814 symbol *tlbl, *tlbl0;
4816 D(emitcode ("; genAndOp",""));
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);
4825 tlbl = newiTempLabel (NULL);
4826 tlbl0 = newiTempLabel (NULL);
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);
4835 loadRegFromConst (hc08_reg_a,zero);
4838 hc08_useReg (hc08_reg_a);
4839 hc08_freeReg (hc08_reg_a);
4841 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4843 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4844 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4845 freeAsmop (result, NULL, ic, TRUE);
4849 /*-----------------------------------------------------------------*/
4850 /* genOrOp - for || operation */
4851 /*-----------------------------------------------------------------*/
4853 genOrOp (iCode * ic)
4855 operand *left, *right, *result;
4856 symbol *tlbl, *tlbl0;
4858 D(emitcode ("; genOrOp",""));
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);
4867 tlbl = newiTempLabel (NULL);
4868 tlbl0 = newiTempLabel (NULL);
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);
4877 loadRegFromConst (hc08_reg_a,one);
4880 hc08_useReg (hc08_reg_a);
4881 hc08_freeReg (hc08_reg_a);
4883 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4886 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4887 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4888 freeAsmop (result, NULL, ic, TRUE);
4891 /*-----------------------------------------------------------------*/
4892 /* isLiteralBit - test if lit == 2^n */
4893 /*-----------------------------------------------------------------*/
4895 isLiteralBit (unsigned long lit)
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};
4907 for (idx = 0; idx < 32; idx++)
4914 /*-----------------------------------------------------------------*/
4915 /* continueIfTrue - */
4916 /*-----------------------------------------------------------------*/
4918 continueIfTrue (iCode * ic)
4921 emitBranch ("jmp", IC_TRUE (ic));
4925 /*-----------------------------------------------------------------*/
4927 /*-----------------------------------------------------------------*/
4929 jumpIfTrue (iCode * ic)
4932 emitBranch ("jmp", IC_FALSE (ic));
4936 /*-----------------------------------------------------------------*/
4937 /* jmpTrueOrFalse - */
4938 /*-----------------------------------------------------------------*/
4940 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4942 // ugly but optimized by peephole
4945 symbol *nlbl = newiTempLabel (NULL);
4946 emitBranch ("bra", nlbl);
4948 emitBranch ("jmp", IC_TRUE (ic));
4953 emitBranch ("jmp", IC_FALSE (ic));
4960 /*-----------------------------------------------------------------*/
4961 /* genAnd - code for and */
4962 /*-----------------------------------------------------------------*/
4964 genAnd (iCode * ic, iCode * ifx)
4966 operand *left, *right, *result;
4967 int size, offset = 0;
4968 unsigned long lit = 0L;
4969 unsigned long litinv;
4970 unsigned char bytemask;
4976 D(emitcode ("; genAnd",""));
4978 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4979 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4980 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4983 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4985 AOP_TYPE (left), AOP_TYPE (right)));
4986 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4988 AOP_SIZE (left), AOP_SIZE (right)));
4991 /* if left is a literal & right is not then exchange them */
4992 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4994 operand *tmp = right;
4999 /* if right is accumulator & left is not then exchange them */
5000 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5002 operand *tmp = right;
5007 if (AOP_TYPE (right) == AOP_LIT)
5008 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5010 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5012 if (AOP_TYPE (result) == AOP_CRY
5014 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5016 /* this generates ugly code, but meets volatility requirements */
5017 loadRegFromConst (hc08_reg_a, zero);
5018 pushReg (hc08_reg_a, TRUE);
5023 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5024 accopWithAop ("and", AOP (right), offset);
5025 emitcode ("ora", "1,s");
5026 emitcode ("sta", "1,s");
5030 pullReg (hc08_reg_a);
5031 emitcode ("tsta", "");
5032 genIfxJump (ifx, "a");
5036 if (AOP_TYPE (result) == AOP_CRY)
5038 symbol *tlbl = NULL;
5039 wassertl (ifx, "AOP_CRY result without ifx");
5044 bytemask = (lit >> (offset*8)) & 0xff;
5046 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5050 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5052 rmwWithAop ("tst", AOP (left), offset);
5056 tlbl = newiTempLabel (NULL);
5057 emitBranch ("bne", tlbl);
5062 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5063 accopWithAop ("and", AOP (right), offset);
5064 hc08_freeReg( hc08_reg_a);
5068 tlbl = newiTempLabel (NULL);
5069 emitBranch ("bne", tlbl);
5076 genIfxJump (ifx, "a");
5080 size = AOP_SIZE (result);
5082 if (AOP_TYPE (right) == AOP_LIT)
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))
5088 int bitpos = isLiteralBit(litinv)-1;
5089 emitcode ("bclr","#%d,%s",bitpos & 7,
5090 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5098 bytemask = (lit >> (offset*8)) & 0xff;
5100 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5102 if (isOperandVolatile (left, FALSE))
5104 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5105 hc08_freeReg( hc08_reg_a);
5107 storeConstToAop (zero, AOP (result), offset);
5109 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5111 transferAopAop (AOP (left), offset, AOP (result), offset);
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);
5124 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5125 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5126 freeAsmop (result, NULL, ic, TRUE);
5129 /*-----------------------------------------------------------------*/
5130 /* genOr - code for or */
5131 /*-----------------------------------------------------------------*/
5133 genOr (iCode * ic, iCode * ifx)
5135 operand *left, *right, *result;
5136 int size, offset = 0;
5137 unsigned long lit = 0L;
5138 unsigned char bytemask;
5140 D(emitcode ("; genOr",""));
5142 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5143 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5144 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5147 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5149 AOP_TYPE (left), AOP_TYPE (right)));
5150 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5152 AOP_SIZE (left), AOP_SIZE (right)));
5155 /* if left is a literal & right is not then exchange them */
5156 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5158 operand *tmp = right;
5163 /* if left is accumulator & right is not then exchange them */
5164 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5166 operand *tmp = right;
5171 if (AOP_TYPE (right) == AOP_LIT)
5172 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5174 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5176 if (AOP_TYPE (result) == AOP_CRY
5178 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5180 /* this generates ugly code, but meets volatility requirements */
5181 loadRegFromConst (hc08_reg_a, zero);
5182 pushReg (hc08_reg_a, TRUE);
5187 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5188 accopWithAop ("ora", AOP (right), offset);
5189 emitcode ("ora", "1,s");
5190 emitcode ("sta", "1,s");
5194 pullReg (hc08_reg_a);
5195 emitcode ("tsta", "");
5196 genIfxJump (ifx, "a");
5200 if (AOP_TYPE (result) == AOP_CRY)
5202 symbol *tlbl = NULL;
5203 wassertl (ifx, "AOP_CRY result without ifx");
5208 bytemask = (lit >> (offset*8)) & 0xff;
5210 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5212 rmwWithAop ("tst", AOP (left), offset);
5216 tlbl = newiTempLabel (NULL);
5217 emitBranch ("bne", tlbl);
5222 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5223 accopWithAop ("ora", AOP (right), offset);
5224 hc08_freeReg( hc08_reg_a);
5228 tlbl = newiTempLabel (NULL);
5229 emitBranch ("bne", tlbl);
5236 genIfxJump (ifx, "a");
5239 if (AOP_TYPE (right) == AOP_LIT)
5240 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5242 size = AOP_SIZE (result);
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))
5248 int bitpos = isLiteralBit(lit)-1;
5249 emitcode ("bset","#%d,%s",bitpos & 7,
5250 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5257 bytemask = (lit >> (offset*8)) & 0xff;
5259 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5261 if (isOperandVolatile (left, FALSE))
5263 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5264 hc08_freeReg( hc08_reg_a);
5266 transferAopAop (AOP (right), offset, AOP (result), offset);
5268 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5270 transferAopAop (AOP (left), offset, AOP (result), offset);
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);
5284 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5285 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5286 freeAsmop (result, NULL, ic, TRUE);
5289 /*-----------------------------------------------------------------*/
5290 /* genXor - code for xclusive or */
5291 /*-----------------------------------------------------------------*/
5293 genXor (iCode * ic, iCode * ifx)
5295 operand *left, *right, *result;
5296 int size, offset = 0;
5297 unsigned long lit = 0L;
5299 D(emitcode ("; genXor",""));
5301 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5302 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5303 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5306 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5308 AOP_TYPE (left), AOP_TYPE (right)));
5309 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5311 AOP_SIZE (left), AOP_SIZE (right)));
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)
5318 operand *tmp = right;
5323 /* if left is accumulator & right is not then exchange them */
5324 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5326 operand *tmp = right;
5331 if (AOP_TYPE (result) == AOP_CRY)
5334 wassertl (ifx, "AOP_CPY result without ifx");
5336 tlbl = newiTempLabel (NULL);
5337 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5341 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5342 if ((AOP_TYPE (right) == AOP_LIT)
5343 && (((lit >> (offset*8)) & 0xff) == 0))
5344 emitcode ("tsta","");
5346 accopWithAop ("eor", AOP (right), offset);
5347 hc08_freeReg( hc08_reg_a);
5349 emitBranch ("bne", tlbl);
5353 genIfxJump (ifx, "a");
5359 if (AOP_TYPE (right) == AOP_LIT)
5360 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5362 size = AOP_SIZE (result);
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);
5373 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5374 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5375 freeAsmop (result, NULL, ic, TRUE);
5379 emitinline (iCode * ic, char *inlin)
5385 symbol *sym, *tempsym;
5394 while (isalnum((unsigned char)*inlin) || (*inlin == '_'))
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);
5410 aop = aopForSym (ic, sym, FALSE);
5411 l = aopAdrStr (aop, aop->size - 1, TRUE);
5415 if (sym->level && !sym->allocreq && !sym->ismyparm)
5417 werror (E_ID_UNDEF, sym->name);
5419 " Add 'volatile' to the variable declaration so that it\n"
5420 " can be referenced within inline assembly");
5422 //printf("Replacing with '%s'\n",l);
5426 if ((2+bp-buffer)>sizeof(buffer))
5435 if ((2+bp-buffer)>sizeof(buffer))
5442 if ((2+bp-buffer)>sizeof(buffer))
5443 fprintf(stderr, "Inline assembly buffer overflow\n");
5445 //printf("%s\n",buffer);
5446 emitcode (buffer,"");
5450 /*-----------------------------------------------------------------*/
5451 /* genInline - write the inline code out */
5452 /*-----------------------------------------------------------------*/
5454 genInline (iCode * ic)
5456 char *buffer, *bp, *bp1;
5458 D(emitcode ("; genInline",""));
5460 _G.inLine += (!options.asmpeep);
5462 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5463 strcpy (buffer, IC_INLINE (ic));
5465 /* emit each line as a code */
5471 /* emitcode (bp1, ""); */
5472 emitinline (ic, bp1);
5491 /* emitcode (bp1, ""); */
5492 emitinline (ic, bp1);
5494 /* emitcode("",buffer); */
5495 _G.inLine -= (!options.asmpeep);
5498 /*-----------------------------------------------------------------*/
5499 /* genRRC - rotate right with carry */
5500 /*-----------------------------------------------------------------*/
5504 operand *left, *result;
5505 int size, offset = 0;
5506 bool needpula = FALSE;
5507 bool resultInA = FALSE;
5510 D(emitcode ("; genRRC",""));
5512 /* rotate right with carry */
5513 left = IC_LEFT (ic);
5514 result = IC_RESULT (ic);
5515 aopOp (left, ic, FALSE);
5516 aopOp (result, ic, FALSE);
5518 if ((AOP_TYPE (result) == AOP_REG)
5519 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5522 size = AOP_SIZE (result);
5526 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5530 rmwWithAop (shift, AOP (result), offset--);
5538 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5539 rmwWithReg (shift, hc08_reg_a);
5540 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5541 hc08_freeReg (hc08_reg_a);
5546 if ((!hc08_reg_a->isFree) || resultInA)
5548 pushReg (hc08_reg_a, TRUE);
5552 /* now we need to put the carry into the
5553 highest order byte of the result */
5554 offset = AOP_SIZE (result) - 1;
5555 emitcode ("clra","");
5556 emitcode ("rora","");
5557 hc08_dirtyReg (hc08_reg_a, FALSE);
5560 emitcode ("ora", "1,s");
5561 emitcode ("ais", "#1");
5562 hc08_dirtyReg (hc08_reg_a, FALSE);
5566 accopWithAop ("ora", AOP (result), offset);
5567 storeRegToAop (hc08_reg_a, AOP (result), offset);
5569 pullOrFreeReg (hc08_reg_a, needpula);
5571 freeAsmop (left, NULL, ic, TRUE);
5572 freeAsmop (result, NULL, ic, TRUE);
5575 /*-----------------------------------------------------------------*/
5576 /* genRLC - generate code for rotate left with carry */
5577 /*-----------------------------------------------------------------*/
5581 operand *left, *result;
5582 int size, offset = 0;
5584 bool resultInA = FALSE;
5585 bool needpula = FALSE;
5587 D(emitcode ("; genRLC",""));
5589 /* rotate right with carry */
5590 left = IC_LEFT (ic);
5591 result = IC_RESULT (ic);
5592 aopOp (left, ic, FALSE);
5593 aopOp (result, ic, FALSE);
5595 if ((AOP_TYPE (result) == AOP_REG)
5596 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5599 size = AOP_SIZE (result);
5603 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5607 rmwWithAop (shift, AOP (result), offset--);
5615 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5616 rmwWithReg (shift, hc08_reg_a);
5617 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5618 hc08_freeReg (hc08_reg_a);
5623 if ((!hc08_reg_a->isFree) || resultInA)
5625 pushReg (hc08_reg_a, TRUE);
5629 /* now we need to put the carry into the
5630 lowest order byte of the result */
5632 emitcode ("clra","");
5633 emitcode ("rola","");
5634 hc08_dirtyReg (hc08_reg_a, FALSE);
5637 emitcode ("ora", "1,s");
5638 emitcode ("ais", "#1");
5639 hc08_dirtyReg (hc08_reg_a, FALSE);
5643 accopWithAop ("ora", AOP (result), offset);
5644 storeRegToAop (hc08_reg_a, AOP (result), offset);
5646 pullOrFreeReg (hc08_reg_a, needpula);
5648 freeAsmop (left, NULL, ic, TRUE);
5649 freeAsmop (result, NULL, ic, TRUE);
5652 /*-----------------------------------------------------------------*/
5653 /* genGetHbit - generates code get highest order bit */
5654 /*-----------------------------------------------------------------*/
5656 genGetHbit (iCode * ic)
5658 operand *left, *result;
5660 D(emitcode ("; genGetHbit",""));
5662 left = IC_LEFT (ic);
5663 result = IC_RESULT (ic);
5664 aopOp (left, ic, FALSE);
5665 aopOp (result, ic, FALSE);
5667 /* get the highest order byte into a */
5668 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5669 emitcode ("rola", "");
5670 emitcode ("clra", "");
5671 emitcode ("rola", "");
5672 hc08_dirtyReg (hc08_reg_a, FALSE);
5673 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5674 hc08_freeReg (hc08_reg_a);
5676 freeAsmop (left, NULL, ic, TRUE);
5677 freeAsmop (result, NULL, ic, TRUE);
5680 /*-----------------------------------------------------------------*/
5681 /* genSwap - generates code to swap nibbles or bytes */
5682 /*-----------------------------------------------------------------*/
5684 genSwap (iCode * ic)
5686 operand *left, *result;
5688 D(emitcode ("; genSwap",""));
5690 left = IC_LEFT (ic);
5691 result = IC_RESULT (ic);
5692 aopOp (left, ic, FALSE);
5693 aopOp (result, ic, FALSE);
5695 switch (AOP_SIZE (left))
5697 case 1: /* swap nibbles in byte */
5698 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5699 emitcode ("nsa", "");
5700 hc08_dirtyReg (hc08_reg_a, FALSE);
5701 storeRegToAop (hc08_reg_a, AOP (result), 0);
5702 hc08_freeReg (hc08_reg_a);
5704 case 2: /* swap bytes in a word */
5705 if (operandsEqu (left, result))
5707 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5708 hc08_useReg (hc08_reg_a);
5709 transferAopAop (AOP (left), 1, AOP (result), 0);
5710 storeRegToAop (hc08_reg_a, AOP (result), 1);
5711 hc08_freeReg (hc08_reg_a);
5715 transferAopAop (AOP (left), 0, AOP (result), 1);
5716 transferAopAop (AOP (left), 1, AOP (result), 0);
5720 wassertl(FALSE, "unsupported SWAP operand size");
5723 freeAsmop (left, NULL, ic, TRUE);
5724 freeAsmop (result, NULL, ic, TRUE);
5728 /*-----------------------------------------------------------------*/
5729 /* AccRol - rotate left accumulator by known count */
5730 /*-----------------------------------------------------------------*/
5732 AccRol (int shCount)
5734 shCount &= 0x0007; // shCount : 0..7
5741 emitcode ("rola", ""); /* 1 cycle */
5744 emitcode ("rola", ""); /* 1 cycle */
5745 emitcode ("rola", ""); /* 1 cycle */
5748 emitcode ("nsa", "");
5749 emitcode ("rora", "");
5752 emitcode ("nsa", ""); /* 3 cycles */
5755 emitcode ("nsa", ""); /* 3 cycles */
5756 emitcode ("rola", ""); /* 1 cycle */
5759 emitcode ("nsa", ""); /* 3 cycles */
5760 emitcode ("rola", ""); /* 1 cycle */
5761 emitcode ("rola", ""); /* 1 cycle */
5764 emitcode ("nsa", ""); /* 3 cycles */
5765 emitcode ("rola", ""); /* 1 cycle */
5766 emitcode ("rola", ""); /* 1 cycle */
5767 emitcode ("rola", ""); /* 1 cycle */
5774 /*-----------------------------------------------------------------*/
5775 /* AccLsh - left shift accumulator by known count */
5776 /*-----------------------------------------------------------------*/
5778 AccLsh (int shCount)
5782 shCount &= 0x0007; // shCount : 0..7
5784 /* Shift counts of 4 and 5 are currently optimized for code size. */
5785 /* Falling through to the unrolled loop would be optimal for code speed. */
5786 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5790 if (optimize.codeSpeed)
5792 accopWithMisc ("nsa", "");
5793 accopWithMisc ("and", "#0xf0");
5794 /* total: 5 cycles, 3 bytes */
5797 if (optimize.codeSpeed)
5799 accopWithMisc ("nsa", "");
5800 accopWithMisc ("and", "#0xf0");
5801 accopWithMisc ("lsla", "");
5802 /* total: 6 cycles, 4 bytes */
5805 accopWithMisc ("rora", "");
5806 accopWithMisc ("rora", "");
5807 accopWithMisc ("rora", "");
5808 accopWithMisc ("and", "#0xc0");
5809 /* total: 5 cycles, 5 bytes */
5812 accopWithMisc ("rora", "");
5813 accopWithMisc ("clra", "");
5814 accopWithMisc ("rora", "");
5815 /* total: 3 cycles, 3 bytes */
5819 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5820 /* the fastest (shCount<6) and shortest (shCount<4). */
5821 for (i=0;i<shCount;i++)
5822 accopWithMisc ("lsla", "");
5826 /*-----------------------------------------------------------------*/
5827 /* AccSRsh - signed right shift accumulator by known count */
5828 /*-----------------------------------------------------------------*/
5830 AccSRsh (int shCount)
5834 shCount &= 0x0007; // shCount : 0..7
5838 accopWithMisc ("rola", "");
5839 accopWithMisc ("clra", "");
5840 accopWithMisc ("sbc", zero);
5841 /* total: 4 cycles, 4 bytes */
5845 for (i=0;i<shCount;i++)
5846 accopWithMisc ("asra", "");
5849 /*-----------------------------------------------------------------*/
5850 /* AccRsh - right shift accumulator by known count */
5851 /*-----------------------------------------------------------------*/
5853 AccRsh (int shCount, bool sign)
5863 shCount &= 0x0007; // shCount : 0..7
5865 /* Shift counts of 4 and 5 are currently optimized for code size. */
5866 /* Falling through to the unrolled loop would be optimal for code speed. */
5867 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5871 if (optimize.codeSpeed)
5873 accopWithMisc ("nsa", "");
5874 accopWithMisc ("and", "#0x0f");
5875 /* total: 5 cycles, 3 bytes */
5878 if (optimize.codeSpeed)
5880 accopWithMisc ("nsa", "");
5881 accopWithMisc ("and", "#0x0f");
5882 accopWithMisc ("lsra", "");
5883 /* total: 6 cycles, 4 bytes */
5886 accopWithMisc ("rola", "");
5887 accopWithMisc ("rola", "");
5888 accopWithMisc ("rola", "");
5889 accopWithMisc ("and", "#0x03");
5890 /* total: 5 cycles, 5 bytes */
5893 accopWithMisc ("rola", "");
5894 accopWithMisc ("clra", "");
5895 accopWithMisc ("rola", "");
5896 /* total: 3 cycles, 3 bytes */
5900 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5901 /* the fastest (shCount<6) and shortest (shCount<4). */
5902 for (i=0;i<shCount;i++)
5903 accopWithMisc ("lsra", "");
5907 /*-----------------------------------------------------------------*/
5908 /* XAccLsh - left shift register pair XA by known count */
5909 /*-----------------------------------------------------------------*/
5911 XAccLsh (int shCount)
5915 shCount &= 0x000f; // shCount : 0..15
5920 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5921 loadRegFromConst (hc08_reg_a, zero);
5925 /* if we can beat 2n cycles or bytes for some special case, do it here */
5929 /* bytes cycles reg x reg a carry
5930 ** abcd efgh ijkl mnop ?
5931 ** lsrx 1 1 0abc defg ijkl mnop h
5932 ** rora 1 1 0abc defg hijk lmno p
5933 ** tax 1 1 hijk lmno hijk lmno p
5934 ** clra 1 1 hijk lmno 0000 0000 p
5935 ** rora 1 1 hijk lmno p000 0000 0
5936 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5938 rmwWithReg ("lsr", hc08_reg_x);
5939 rmwWithReg ("ror", hc08_reg_a);
5940 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5941 loadRegFromConst (hc08_reg_a, zero);
5942 rmwWithReg ("ror", hc08_reg_a);
5949 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5950 /* the fastest and shortest. */
5951 for (i=0;i<shCount;i++)
5953 rmwWithReg ("lsl", hc08_reg_a);
5954 rmwWithReg ("rol", hc08_reg_x);
5958 /*-----------------------------------------------------------------*/
5959 /* XAccSRsh - signed right shift register pair XA by known count */
5960 /*-----------------------------------------------------------------*/
5962 XAccSRsh (int shCount)
5966 shCount &= 0x000f; // shCount : 0..7
5968 /* if we can beat 2n cycles or bytes for some special case, do it here */
5972 /* bytes cycles reg x reg a carry
5973 ** abcd efgh ijkl mnop ?
5974 ** lslx 1 1 bcde fgh0 ijkl mnop a
5975 ** clra 1 1 bcde fgh0 0000 0000 a
5976 ** rola 1 1 bcde fgh0 0000 000a 0
5977 ** nega 1 1 bcde fgh0 aaaa aaaa a
5978 ** tax 1 1 aaaa aaaa aaaa aaaa a
5979 ** total: 5 cycles, 5 bytes
5981 rmwWithReg ("lsl", hc08_reg_x);
5982 loadRegFromConst (hc08_reg_a, zero);
5983 rmwWithReg ("rol", hc08_reg_a);
5984 rmwWithReg ("neg", hc08_reg_a);
5985 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5995 /* bytes cycles reg x reg a carry
5996 ** abcd efgh ijkl mnop ?
5997 ** txa 1 1 abcd efgh abcd efgh ?
5998 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5999 ** lsla 1 1 abcd efgh ???? ???? a
6000 ** clrx 1 1 0000 0000 ???? ???? a
6001 ** rolx 1 1 0000 000a ???? ???? 0
6002 ** negx 1 1 aaaa aaaa ???? ???? a
6003 ** rora 1 1 aaaa aaaa LSBresult 0
6004 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
6006 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6007 AccSRsh (shCount-8);
6008 rmwWithReg ("lsl", hc08_reg_a);
6009 loadRegFromConst (hc08_reg_x, zero);
6010 rmwWithReg ("rol", hc08_reg_x);
6011 rmwWithReg ("neg", hc08_reg_x);
6012 rmwWithReg ("ror", hc08_reg_a);
6019 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6020 /* the fastest and shortest. */
6021 for (i=0;i<shCount;i++)
6023 rmwWithReg ("asr", hc08_reg_x);
6024 rmwWithReg ("ror", hc08_reg_a);
6028 /*-----------------------------------------------------------------*/
6029 /* XAccRsh - right shift register pair XA by known count */
6030 /*-----------------------------------------------------------------*/
6032 XAccRsh (int shCount, bool sign)
6042 shCount &= 0x000f; // shCount : 0..f
6044 /* if we can beat 2n cycles or bytes for some special case, do it here */
6048 /* bytes cycles reg x reg a carry
6049 ** abcd efgh ijkl mnop ?
6050 ** clra 1 1 abcd efgh 0000 0000 a
6051 ** lslx 1 1 bcde fgh0 0000 0000 a
6052 ** rola 1 1 bcde fgh0 0000 000a 0
6053 ** clrx 1 1 0000 0000 0000 000a 0
6054 ** total: 4 cycles, 4 bytes
6056 loadRegFromConst (hc08_reg_x, zero);
6057 rmwWithReg ("lsl", hc08_reg_x);
6058 rmwWithReg ("rol", hc08_reg_a);
6059 loadRegFromConst (hc08_reg_a, zero);
6063 /* bytes cycles reg x reg a carry
6064 ** abcd efgh ijkl mnop ?
6065 ** clra 1 1 abcd efgh 0000 0000 a
6066 ** lslx 1 1 bcde fgh0 0000 0000 a
6067 ** rola 1 1 bcde fgh0 0000 000a 0
6068 ** lslx 1 1 cdef gh00 0000 000a b
6069 ** rola 1 1 cdef gh00 0000 00ab 0
6070 ** clrx 1 1 0000 0000 0000 00ab 0
6071 ** total: 6 cycles, 6 bytes
6073 loadRegFromConst (hc08_reg_x, zero);
6074 rmwWithReg ("lsl", hc08_reg_x);
6075 rmwWithReg ("rol", hc08_reg_a);
6076 rmwWithReg ("lsl", hc08_reg_x);
6077 rmwWithReg ("rol", hc08_reg_a);
6078 loadRegFromConst (hc08_reg_a, zero);
6087 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6088 AccRsh (shCount-8, FALSE);
6089 loadRegFromConst (hc08_reg_x, zero);
6093 /* bytes cycles reg x reg a carry
6094 ** abcd efgh ijkl mnop ?
6095 ** lsla 1 1 abcd efgh jklm nop0 i
6096 ** txa 1 1 abcd efgh abcd efgh i
6097 ** rola 1 1 abcd efgh bcde fghi a
6098 ** clrx 1 1 0000 0000 bcde fghi a
6099 ** rolx 1 1 0000 000a bcde fghi 0
6100 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
6102 rmwWithReg ("lsl", hc08_reg_a);
6103 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6104 rmwWithReg ("rol", hc08_reg_a);
6105 loadRegFromConst (hc08_reg_x, zero);
6106 rmwWithReg ("rol", hc08_reg_x);
6109 /* bytes cycles reg x reg a carry
6110 ** abcd efgh ijkl mnop ?
6111 ** lsla 1 1 abcd efgh jklm nop0 i
6112 ** rolx 1 1 bcde fghi jklm nop0 a
6113 ** rola 1 1 bcde fghi klmn op0a j
6114 ** rolx 1 1 cdef ghij klmn op0a b
6115 ** rola 1 1 cdef ghij lmno p0ab k
6116 ** and #3 2 2 cdef ghij 0000 00ab k
6117 ** psha 1 2 cdef ghij 0000 00ab k
6118 ** txa 1 1 cdef ghij cdef ghij k
6119 ** pula 1 2 0000 00ab cdef ghij k
6120 ** total: 12 cycles, 10 bytes (beats 12 bytes)
6126 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6127 /* the fastest and shortest. */
6128 for (i=0;i<shCount;i++)
6130 rmwWithReg ("lsr", hc08_reg_x);
6131 rmwWithReg ("ror", hc08_reg_a);
6138 /*-----------------------------------------------------------------*/
6139 /* shiftR1Left2Result - shift right one byte from left to result */
6140 /*-----------------------------------------------------------------*/
6142 shiftR1Left2Result (operand * left, int offl,
6143 operand * result, int offr,
6144 int shCount, int sign)
6146 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6147 /* shift right accumulator */
6148 AccRsh (shCount, sign);
6149 storeRegToAop (hc08_reg_a, AOP (result), offr);
6153 /*-----------------------------------------------------------------*/
6154 /* shiftL1Left2Result - shift left one byte from left to result */
6155 /*-----------------------------------------------------------------*/
6157 shiftL1Left2Result (operand * left, int offl,
6158 operand * result, int offr, int shCount)
6160 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6161 /* shift left accumulator */
6163 storeRegToAop (hc08_reg_a, AOP (result), offr);
6166 /*-----------------------------------------------------------------*/
6167 /* movLeft2Result - move byte from left to result */
6168 /*-----------------------------------------------------------------*/
6170 movLeft2Result (operand * left, int offl,
6171 operand * result, int offr, int sign)
6173 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6175 transferAopAop (AOP (left), offl, AOP (result), offr);
6180 /*-----------------------------------------------------------------*/
6181 /* shiftL2Left2Result - shift left two bytes from left to result */
6182 /*-----------------------------------------------------------------*/
6184 shiftL2Left2Result (operand * left, int offl,
6185 operand * result, int offr, int shCount)
6188 bool needpula = FALSE;
6189 bool needpulx = FALSE;
6191 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6192 needpula = pushRegIfUsed (hc08_reg_a);
6195 if (!IS_AOP_XA (AOP (left)))
6196 needpulx = pushRegIfUsed (hc08_reg_x);
6200 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6205 rmwWithReg ("lsr", hc08_reg_x);
6206 rmwWithReg ("ror", hc08_reg_a);
6207 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6208 rmwWithReg ("clr", hc08_reg_a);
6209 rmwWithReg ("ror", hc08_reg_a);
6212 for (i=0; i<shCount; i++)
6214 rmwWithReg ("lsl", hc08_reg_a);
6215 rmwWithReg ("rol", hc08_reg_x);
6218 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6220 pullOrFreeReg (hc08_reg_x, needpulx);
6221 pullOrFreeReg (hc08_reg_a, needpula);
6227 /*-----------------------------------------------------------------*/
6228 /* shiftR2Left2Result - shift right two bytes from left to result */
6229 /*-----------------------------------------------------------------*/
6231 shiftR2Left2Result (operand * left, int offl,
6232 operand * result, int offr,
6233 int shCount, int sign)
6236 bool needpula = FALSE;
6237 bool needpulx = FALSE;
6239 needpula = pushRegIfUsed (hc08_reg_a);
6240 needpulx = pushRegIfUsed (hc08_reg_x);
6242 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6243 for (i=0; i<shCount; i++)
6246 rmwWithReg ("asr", hc08_reg_x);
6248 rmwWithReg ("lsr", hc08_reg_x);
6249 rmwWithReg ("ror", hc08_reg_a);
6251 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6253 pullOrFreeReg (hc08_reg_x, needpulx);
6254 pullOrFreeReg (hc08_reg_a, needpula);
6259 /*-----------------------------------------------------------------*/
6260 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6261 /*-----------------------------------------------------------------*/
6263 shiftLLeftOrResult (operand * left, int offl,
6264 operand * result, int offr, int shCount)
6266 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6267 /* shift left accumulator */
6269 /* or with result */
6270 accopWithAop ("ora", AOP (result), offr);
6271 /* back to result */
6272 storeRegToAop (hc08_reg_a, AOP (result), offr);
6273 hc08_freeReg (hc08_reg_a);
6277 /*-----------------------------------------------------------------*/
6278 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6279 /*-----------------------------------------------------------------*/
6281 shiftRLeftOrResult (operand * left, int offl,
6282 operand * result, int offr, int shCount)
6284 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6285 /* shift left accumulator */
6286 AccRsh (shCount, FALSE);
6287 /* or with result */
6288 accopWithAop ("ora", AOP (result), offr);
6289 /* back to result */
6290 storeRegToAop (hc08_reg_a, AOP (result), offr);
6291 hc08_freeReg (hc08_reg_a);
6294 /*-----------------------------------------------------------------*/
6295 /* genlshOne - left shift a one byte quantity by known count */
6296 /*-----------------------------------------------------------------*/
6298 genlshOne (operand * result, operand * left, int shCount)
6300 D(emitcode ("; genlshOne",""));
6302 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6305 /*-----------------------------------------------------------------*/
6306 /* genlshTwo - left shift two bytes by known amount != 0 */
6307 /*-----------------------------------------------------------------*/
6309 genlshTwo (operand * result, operand * left, int shCount)
6313 D(emitcode ("; genlshTwo",""));
6316 size = getDataSize (result);
6318 /* if shCount >= 8 */
6325 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6327 storeRegToAop (hc08_reg_a, AOP (result), 1);
6329 storeConstToAop(zero, AOP (result), LSB);
6332 /* 1 <= shCount <= 7 */
6335 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6337 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6341 /*-----------------------------------------------------------------*/
6342 /* shiftLLong - shift left one long from left to result */
6343 /* offr = LSB or MSB16 */
6344 /*-----------------------------------------------------------------*/
6346 shiftLLong (operand * left, operand * result, int offr)
6349 // int size = AOP_SIZE (result);
6351 bool needpula = FALSE;
6352 bool needpulx = FALSE;
6354 needpula = pushRegIfUsed (hc08_reg_a);
6355 needpulx = pushRegIfUsed (hc08_reg_x);
6357 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6358 rmwWithReg ("lsl", hc08_reg_a);
6359 rmwWithReg ("rol", hc08_reg_x);
6363 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6364 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6365 rmwWithReg ("rol", hc08_reg_a);
6366 rmwWithReg ("rol", hc08_reg_x);
6367 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6369 else if (offr==MSB16)
6371 storeRegToAop (hc08_reg_a, AOP (result), offr);
6372 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6373 storeRegToAop (hc08_reg_x, AOP (result), offr+1);
6374 rmwWithReg ("rol", hc08_reg_a);
6375 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6376 storeConstToAop (zero, AOP (result), 0);
6379 pullOrFreeReg (hc08_reg_x, needpulx);
6380 pullOrFreeReg (hc08_reg_a, needpula);
6383 /*-----------------------------------------------------------------*/
6384 /* genlshFour - shift four byte by a known amount != 0 */
6385 /*-----------------------------------------------------------------*/
6387 genlshFour (operand * result, operand * left, int shCount)
6391 D(emitcode ("; genlshFour",""));
6393 size = AOP_SIZE (result);
6395 /* TODO: deal with the &result == &left case */
6397 /* if shifting more that 3 bytes */
6402 /* lowest order of left goes to the highest
6403 order of the destination */
6404 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6406 movLeft2Result (left, LSB, result, MSB32, 0);
6407 storeConstToAop (zero, AOP (result), LSB);
6408 storeConstToAop (zero, AOP (result), MSB16);
6409 storeConstToAop (zero, AOP (result), MSB24);
6413 /* more than two bytes */
6414 else if (shCount >= 16)
6416 /* lower order two bytes goes to higher order two bytes */
6418 /* if some more remaining */
6420 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6423 movLeft2Result (left, MSB16, result, MSB32, 0);
6424 movLeft2Result (left, LSB, result, MSB24, 0);
6426 storeConstToAop (zero, AOP (result), LSB);
6427 storeConstToAop (zero, AOP (result), MSB16);
6431 /* if more than 1 byte */
6432 else if (shCount >= 8)
6434 /* lower order three bytes goes to higher order three bytes */
6439 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6441 movLeft2Result (left, LSB, result, MSB16, 0);
6447 movLeft2Result (left, MSB24, result, MSB32, 0);
6448 movLeft2Result (left, MSB16, result, MSB24, 0);
6449 movLeft2Result (left, LSB, result, MSB16, 0);
6450 storeConstToAop (zero, AOP (result), LSB);
6452 else if (shCount == 1)
6453 shiftLLong (left, result, MSB16);
6456 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6457 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6458 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6459 storeConstToAop (zero, AOP (result), LSB);
6464 /* 1 <= shCount <= 7 */
6465 else if (shCount <= 2)
6467 shiftLLong (left, result, LSB);
6469 shiftLLong (result, result, LSB);
6471 /* 3 <= shCount <= 7, optimize */
6474 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6475 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6476 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6480 /*-----------------------------------------------------------------*/
6481 /* genLeftShiftLiteral - left shifting by known count */
6482 /*-----------------------------------------------------------------*/
6484 genLeftShiftLiteral (operand * left,
6489 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6492 D(emitcode ("; genLeftShiftLiteral",""));
6494 freeAsmop (right, NULL, ic, TRUE);
6496 aopOp (left, ic, FALSE);
6497 aopOp (result, ic, FALSE);
6499 // size = getSize (operandType (result));
6500 size = AOP_SIZE (result);
6503 DD(emitcode ("; shift left ", "result %d, left %d", size,
6510 transferAopAop( AOP(left), size, AOP(result), size);
6512 else if (shCount >= (size * 8))
6515 storeConstToAop (zero, AOP (result), size);
6522 genlshOne (result, left, shCount);
6526 genlshTwo (result, left, shCount);
6530 genlshFour (result, left, shCount);
6533 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6534 "*** ack! mystery literal shift!\n");
6538 freeAsmop (left, NULL, ic, TRUE);
6539 freeAsmop (result, NULL, ic, TRUE);
6542 /*-----------------------------------------------------------------*/
6543 /* genLeftShift - generates code for left shifting */
6544 /*-----------------------------------------------------------------*/
6546 genLeftShift (iCode * ic)
6548 operand *left, *right, *result;
6550 symbol *tlbl, *tlbl1;
6554 D(emitcode ("; genLeftShift",""));
6556 right = IC_RIGHT (ic);
6557 left = IC_LEFT (ic);
6558 result = IC_RESULT (ic);
6560 aopOp (right, ic, FALSE);
6562 /* if the shift count is known then do it
6563 as efficiently as possible */
6564 if (AOP_TYPE (right) == AOP_LIT)
6566 genLeftShiftLiteral (left, right, result, ic);
6570 /* shift count is unknown then we have to form
6571 a loop get the loop count in X : Note: we take
6572 only the lower order byte since shifting
6573 more that 32 bits make no sense anyway, ( the
6574 largest size of an object can be only 32 bits ) */
6576 aopOp (result, ic, FALSE);
6577 aopOp (left, ic, FALSE);
6578 aopResult = AOP (result);
6580 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result))
6581 || isOperandVolatile (result, FALSE))
6582 aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result)));
6584 /* now move the left to the result if they are not the
6586 if (!sameRegs (AOP (left), aopResult))
6588 size = AOP_SIZE (result);
6592 transferAopAop (AOP (left), offset, aopResult, offset);
6596 freeAsmop (left, NULL, ic, TRUE);
6597 AOP (result) = aopResult;
6599 tlbl = newiTempLabel (NULL);
6600 size = AOP_SIZE (result);
6602 tlbl1 = newiTempLabel (NULL);
6604 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6605 emitcode ("tstx", "");
6606 emitBranch ("beq", tlbl1);
6610 for (offset=0;offset<size;offset++)
6612 rmwWithAop (shift, AOP (result), offset);
6615 rmwWithReg ("dec", hc08_reg_x);
6616 emitBranch ("bne", tlbl);
6618 hc08_freeReg (hc08_reg_x);
6620 freeAsmop (result, NULL, ic, TRUE);
6621 freeAsmop (right, NULL, ic, TRUE);
6624 /*-----------------------------------------------------------------*/
6625 /* genrshOne - right shift a one byte quantity by known count */
6626 /*-----------------------------------------------------------------*/
6628 genrshOne (operand * result, operand * left,
6629 int shCount, int sign)
6631 D(emitcode ("; genrshOne",""));
6633 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6634 AccRsh (shCount, sign);
6635 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6638 /*-----------------------------------------------------------------*/
6639 /* genrshTwo - right shift two bytes by known amount != 0 */
6640 /*-----------------------------------------------------------------*/
6642 genrshTwo (operand * result, operand * left,
6643 int shCount, int sign)
6645 D(emitcode ("; genrshTwo",""));
6647 /* if shCount >= 8 */
6650 if (shCount || sign)
6652 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6653 AccRsh (shCount-8, sign);
6654 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6658 transferAopAop (AOP (left), 1, AOP (result), 0);
6659 storeConstToAop (zero, AOP (result), 1);
6663 /* 1 <= shCount <= 7 */
6666 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6667 XAccRsh (shCount, sign);
6668 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6672 /*-----------------------------------------------------------------*/
6673 /* shiftRLong - shift right one long from left to result */
6674 /* offl = LSB or MSB16 */
6675 /*-----------------------------------------------------------------*/
6677 shiftRLong (operand * left, int offl,
6678 operand * result, int sign)
6681 // int size = AOP_SIZE (result);
6683 bool needpula = FALSE;
6684 bool needpulx = FALSE;
6686 needpula = pushRegIfUsed (hc08_reg_a);
6687 needpulx = pushRegIfUsed (hc08_reg_x);
6691 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6693 rmwWithReg ("asr", hc08_reg_x);
6695 rmwWithReg ("lsr", hc08_reg_x);
6696 rmwWithReg ("ror", hc08_reg_a);
6697 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6698 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6700 else if (offl==MSB16)
6702 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6704 rmwWithReg ("asr", hc08_reg_a);
6706 rmwWithReg ("lsr", hc08_reg_a);
6707 loadRegFromAop (hc08_reg_x, AOP (left), MSB24);
6708 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6709 loadRegFromAop (hc08_reg_a, AOP (left), MSB16);
6712 rmwWithReg ("ror", hc08_reg_x);
6713 rmwWithReg ("ror", hc08_reg_a);
6714 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6720 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6721 storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
6725 storeConstToAop (zero, AOP (result), MSB32);
6729 pullOrFreeReg (hc08_reg_x, needpulx);
6730 pullOrFreeReg (hc08_reg_a, needpula);
6733 /*-----------------------------------------------------------------*/
6734 /* genrshFour - shift four byte by a known amount != 0 */
6735 /*-----------------------------------------------------------------*/
6737 genrshFour (operand * result, operand * left,
6738 int shCount, int sign)
6740 /* TODO: handle cases where left == result */
6742 D(emitcode ("; genrshFour",""));
6744 /* if shifting more that 3 bytes */
6747 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6748 AccRsh (shCount-24, sign);
6749 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6752 else if (shCount >= 16)
6754 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6755 XAccRsh (shCount-16, sign);
6756 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6759 else if (shCount >= 8)
6762 shiftRLong (left, MSB16, result, sign);
6763 else if (shCount == 8)
6765 transferAopAop (AOP (left), 1, AOP (result), 0);
6766 transferAopAop (AOP (left), 2, AOP (result), 1);
6767 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6768 storeRegToAop (hc08_reg_a, AOP (result), 2);
6769 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6771 else if (shCount == 9)
6773 shiftRLong (left, MSB16, result, sign);
6777 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6778 XAccRsh (shCount-8, FALSE);
6779 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6780 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6781 loadRegFromConst (hc08_reg_a, zero);
6782 XAccRsh (shCount-8, sign);
6783 accopWithAop ("ora", AOP (result), 1);
6784 storeRegToAop (hc08_reg_xa, AOP (result), 1);
6785 storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
6789 { /* 1 <= shCount <= 7 */
6792 shiftRLong (left, LSB, result, sign);
6796 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6797 XAccRsh (shCount, FALSE);
6798 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6799 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6801 accopWithAop ("ora", AOP (result), 1);
6802 storeRegToAop (hc08_reg_a, AOP (result), 1);
6803 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6804 XAccRsh (shCount, sign);
6805 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6810 /*-----------------------------------------------------------------*/
6811 /* genRightShiftLiteral - right shifting by known count */
6812 /*-----------------------------------------------------------------*/
6814 genRightShiftLiteral (operand * left,
6820 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6823 D(emitcode ("; genRightShiftLiteral",""));
6825 freeAsmop (right, NULL, ic, TRUE);
6827 aopOp (left, ic, FALSE);
6828 aopOp (result, ic, FALSE);
6831 DD(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6835 size = getDataSize (left);
6836 /* test the LEFT size !!! */
6838 /* I suppose that the left size >= result size */
6841 size = getDataSize (result);
6843 transferAopAop (AOP (left), size, AOP(result), size);
6845 else if (shCount >= (size * 8))
6848 /* get sign in acc.7 */
6849 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6851 addSign (result, LSB, sign);
6858 genrshOne (result, left, shCount, sign);
6862 genrshTwo (result, left, shCount, sign);
6866 genrshFour (result, left, shCount, sign);
6872 freeAsmop (left, NULL, ic, TRUE);
6873 freeAsmop (result, NULL, ic, TRUE);
6877 /*-----------------------------------------------------------------*/
6878 /* genRightShift - generate code for right shifting */
6879 /*-----------------------------------------------------------------*/
6881 genRightShift (iCode * ic)
6883 operand *right, *left, *result;
6886 symbol *tlbl, *tlbl1;
6891 D(emitcode ("; genRightShift",""));
6893 /* if signed then we do it the hard way preserve the
6894 sign bit moving it inwards */
6895 retype = getSpec (operandType (IC_RESULT (ic)));
6896 sign = !SPEC_USIGN (retype);
6898 /* signed & unsigned types are treated the same : i.e. the
6899 signed is NOT propagated inwards : quoting from the
6900 ANSI - standard : "for E1 >> E2, is equivalent to division
6901 by 2**E2 if unsigned or if it has a non-negative value,
6902 otherwise the result is implementation defined ", MY definition
6903 is that the sign does not get propagated */
6905 right = IC_RIGHT (ic);
6906 left = IC_LEFT (ic);
6907 result = IC_RESULT (ic);
6909 aopOp (right, ic, FALSE);
6911 /* if the shift count is known then do it
6912 as efficiently as possible */
6913 if (AOP_TYPE (right) == AOP_LIT)
6915 genRightShiftLiteral (left, right, result, ic, sign);
6919 /* shift count is unknown then we have to form
6920 a loop get the loop count in X : Note: we take
6921 only the lower order byte since shifting
6922 more that 32 bits make no sense anyway, ( the
6923 largest size of an object can be only 32 bits ) */
6925 aopOp (result, ic, FALSE);
6926 aopOp (left, ic, FALSE);
6927 aopResult = AOP (result);
6929 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result))
6930 || isOperandVolatile (result, FALSE))
6931 aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result)));
6933 /* now move the left to the result if they are not the
6935 if (!sameRegs (AOP (left), aopResult))
6937 size = AOP_SIZE (result);
6941 transferAopAop (AOP (left), offset, aopResult, offset);
6945 freeAsmop (left, NULL, ic, TRUE);
6946 AOP (result) = aopResult;
6948 tlbl = newiTempLabel (NULL);
6949 size = AOP_SIZE (result);
6951 tlbl1 = newiTempLabel (NULL);
6953 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6954 emitcode ("tstx", "");
6955 emitBranch ("beq", tlbl1);
6958 shift= sign ? "asr" : "lsr";
6959 for (offset=size-1;offset>=0;offset--)
6961 rmwWithAop (shift, AOP (result), offset);
6964 rmwWithReg ("dec", hc08_reg_x);
6965 emitBranch ("bne", tlbl);
6967 hc08_freeReg (hc08_reg_x);
6969 freeAsmop (result, NULL, ic, TRUE);
6970 freeAsmop (right, NULL, ic, TRUE);
6974 /*-----------------------------------------------------------------*/
6975 /* genUnpackBits - generates code for unpacking bits */
6976 /*-----------------------------------------------------------------*/
6978 genUnpackBits (operand * result, iCode *ifx)
6980 int offset = 0; /* result byte offset */
6981 int rsize; /* result size */
6982 int rlen = 0; /* remaining bitfield length */
6983 sym_link *etype; /* bitfield type information */
6984 int blen; /* bitfield length */
6985 int bstr; /* bitfield starting bit within byte */
6987 D(emitcode ("; genUnpackBits",""));
6989 etype = getSpec (operandType (result));
6990 rsize = getSize (operandType (result));
6991 blen = SPEC_BLEN (etype);
6992 bstr = SPEC_BSTR (etype);
6994 if (ifx && blen <= 8)
6996 emitcode ("lda", ",x");
6997 hc08_dirtyReg (hc08_reg_a, FALSE);
7000 emitcode ("and", "#0x%02x",
7001 (((unsigned char) -1) >> (8 - blen)) << bstr);
7003 genIfxJump (ifx, "a");
7008 /* If the bitfield length is less than a byte */
7011 emitcode ("lda", ",x");
7012 hc08_dirtyReg (hc08_reg_a, FALSE);
7013 AccRsh (bstr, FALSE);
7014 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7015 if (!SPEC_USIGN (etype))
7017 /* signed bitfield */
7018 symbol *tlbl = newiTempLabel (NULL);
7020 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7021 emitcode ("beq", "%05d$", tlbl->key + 100);
7022 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7025 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7029 /* Bit field did not fit in a byte. Copy all
7030 but the partial byte at the end. */
7031 for (rlen=blen;rlen>=8;rlen-=8)
7033 emitcode ("lda", ",x");
7034 hc08_dirtyReg (hc08_reg_a, FALSE);
7035 storeRegToAop (hc08_reg_a, AOP (result), offset);
7038 emitcode ("aix", "#1");
7041 /* Handle the partial byte at the end */
7044 emitcode ("lda", ",x");
7045 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7046 if (!SPEC_USIGN (etype))
7048 /* signed bitfield */
7049 symbol *tlbl = newiTempLabel (NULL);
7051 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7052 emitcode ("beq", "%05d$", tlbl->key + 100);
7053 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7056 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7063 if (SPEC_USIGN (etype))
7066 storeConstToAop (zero, AOP (result), offset++);
7070 /* signed bitfield: sign extension with 0x00 or 0xff */
7071 emitcode ("rola", "");
7072 emitcode ("clra", "");
7073 emitcode ("sbc", zero);
7076 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7082 /*-----------------------------------------------------------------*/
7083 /* genUnpackBitsImmed - generates code for unpacking bits */
7084 /*-----------------------------------------------------------------*/
7086 genUnpackBitsImmed (operand * left,
7092 int offset = 0; /* result byte offset */
7093 int rsize; /* result size */
7094 int rlen = 0; /* remaining bitfield length */
7095 sym_link *etype; /* bitfield type information */
7096 int blen; /* bitfield length */
7097 int bstr; /* bitfield starting bit within byte */
7100 D(emitcode ("; genUnpackBitsImmed",""));
7102 aopOp (result, ic, TRUE);
7103 size = AOP_SIZE (result);
7105 derefaop = aopDerefAop (AOP (left));
7106 freeAsmop (left, NULL, ic, TRUE);
7107 derefaop->size = size;
7109 etype = getSpec (operandType (result));
7110 rsize = getSize (operandType (result));
7111 blen = SPEC_BLEN (etype);
7112 bstr = SPEC_BSTR (etype);
7114 /* if the bitfield is a single bit in the direct page */
7115 if (blen == 1 && derefaop->type == AOP_DIR)
7119 symbol *tlbl = newiTempLabel (NULL);
7121 loadRegFromConst (hc08_reg_a, zero);
7122 emitcode ("brclr", "#%d,%s,%05d$",
7123 bstr, aopAdrStr (derefaop, 0, FALSE),
7125 if (SPEC_USIGN (etype))
7126 rmwWithReg ("inc", hc08_reg_a);
7128 rmwWithReg ("dec", hc08_reg_a);
7130 storeRegToAop (hc08_reg_a, AOP (result), offset);
7131 hc08_freeReg (hc08_reg_a);
7137 symbol *tlbl = newiTempLabel (NULL);
7143 jlbl = IC_TRUE (ifx);
7148 jlbl = IC_FALSE (ifx);
7151 emitcode (inst, "#%d,%s,%05d$",
7152 bstr, aopAdrStr (derefaop, 0, FALSE),
7154 emitBranch ("jmp", jlbl);
7162 /* If the bitfield length is less than a byte */
7165 loadRegFromAop (hc08_reg_a, derefaop, 0);
7168 AccRsh (bstr, FALSE);
7169 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7170 hc08_dirtyReg (hc08_reg_a, FALSE);
7171 if (!SPEC_USIGN (etype))
7173 /* signed bitfield */
7174 symbol *tlbl = newiTempLabel (NULL);
7176 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7177 emitcode ("beq", "%05d$", tlbl->key + 100);
7178 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7181 storeRegToAop (hc08_reg_a, AOP (result), offset);
7185 emitcode ("and", "#0x%02x",
7186 (((unsigned char) -1) >> (8 - blen)) << bstr);
7187 hc08_dirtyReg (hc08_reg_a, FALSE);
7193 /* Bit field did not fit in a byte. Copy all
7194 but the partial byte at the end. */
7195 for (rlen=blen;rlen>=8;rlen-=8)
7197 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7199 storeRegToAop (hc08_reg_a, AOP (result), offset);
7201 emitcode ("tsta", "");
7205 /* Handle the partial byte at the end */
7208 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7209 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7210 if (!SPEC_USIGN (etype))
7212 /* signed bitfield */
7213 symbol *tlbl = newiTempLabel (NULL);
7215 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7216 emitcode ("beq", "%05d$", tlbl->key + 100);
7217 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7220 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7227 if (SPEC_USIGN (etype))
7230 storeConstToAop (zero, AOP (result), offset++);
7234 /* signed bitfield: sign extension with 0x00 or 0xff */
7235 emitcode ("rola", "");
7236 emitcode ("clra", "");
7237 emitcode ("sbc", zero);
7240 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7244 freeAsmop (NULL, derefaop, ic, TRUE);
7245 freeAsmop (result, NULL, ic, TRUE);
7247 if (ifx && !ifx->generated)
7249 genIfxJump (ifx, "a");
7254 /*-----------------------------------------------------------------*/
7255 /* genDataPointerGet - generates code when ptr offset is known */
7256 /*-----------------------------------------------------------------*/
7258 genDataPointerGet (operand * left,
7266 D(emitcode ("; genDataPointerGet",""));
7268 aopOp (result, ic, TRUE);
7269 size = AOP_SIZE (result);
7271 derefaop = aopDerefAop (AOP (left));
7272 freeAsmop (left, NULL, ic, TRUE);
7273 derefaop->size = size;
7278 transferAopAop (derefaop, size, AOP (result), size);
7280 loadRegFromAop (hc08_reg_a, derefaop, size);
7283 freeAsmop (NULL, derefaop, ic, TRUE);
7284 freeAsmop (result, NULL, ic, TRUE);
7286 if (ifx && !ifx->generated)
7288 genIfxJump (ifx, "a");
7293 /*-----------------------------------------------------------------*/
7294 /* genPointerGet - generate code for pointer get */
7295 /*-----------------------------------------------------------------*/
7297 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7299 operand *left = IC_LEFT (ic);
7300 operand *result = IC_RESULT (ic);
7302 sym_link *retype = getSpec (operandType (result));
7304 D(emitcode ("; genPointerGet",""));
7306 if (getSize (operandType (result))>1)
7309 aopOp (left, ic, FALSE);
7311 /* if left is rematerialisable and
7312 result is not bit variable type */
7313 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7315 if (!IS_BITVAR (retype))
7317 genDataPointerGet (left, result, ic, ifx);
7322 genUnpackBitsImmed (left, result, ic, ifx);
7327 /* if the operand is already in hx
7328 then we do nothing else we move the value to hx */
7329 if (AOP_TYPE (left) != AOP_STR)
7331 /* if this is remateriazable */
7332 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7335 /* so hx now contains the address */
7336 aopOp (result, ic, FALSE);
7338 /* if bit then unpack */
7339 if (IS_BITVAR (retype))
7340 genUnpackBits (result, ifx);
7343 size = AOP_SIZE (result);
7348 accopWithMisc ("lda", ",x");
7351 emitcode ("aix", "#1");
7352 hc08_dirtyReg (hc08_reg_hx, FALSE);
7355 storeRegToAop (hc08_reg_a, AOP (result), offset);
7357 hc08_freeReg (hc08_reg_a);
7361 freeAsmop (left, NULL, ic, TRUE);
7362 freeAsmop (result, NULL, ic, TRUE);
7365 aopOp (IC_RESULT (pi), pi, FALSE);
7366 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7367 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7371 if (ifx && !ifx->generated)
7373 genIfxJump (ifx, "a");
7376 hc08_freeReg (hc08_reg_hx);
7380 /*-----------------------------------------------------------------*/
7381 /* genPackBits - generates code for packed bit storage */
7382 /*-----------------------------------------------------------------*/
7384 genPackBits (sym_link * etype,
7387 int offset = 0; /* source byte offset */
7388 int rlen = 0; /* remaining bitfield length */
7389 int blen; /* bitfield length */
7390 int bstr; /* bitfield starting bit within byte */
7391 int litval; /* source literal value (if AOP_LIT) */
7392 unsigned char mask; /* bitmask within current byte */
7395 D(emitcode ("; genPackBits",""));
7397 blen = SPEC_BLEN (etype);
7398 bstr = SPEC_BSTR (etype);
7400 /* If the bitfield length is less than a byte */
7403 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7404 (unsigned char) (0xFF >> (8 - bstr)));
7406 if (AOP_TYPE (right) == AOP_LIT)
7408 /* Case with a bitfield length <8 and literal source
7410 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7412 litval &= (~mask) & 0xff;
7414 emitcode ("lda", ",x");
7415 if ((mask|litval)!=0xff)
7416 emitcode ("and","#0x%02x", mask);
7418 emitcode ("ora","#0x%02x", litval);
7419 hc08_dirtyReg (hc08_reg_a, FALSE);
7420 emitcode ("sta", ",x");
7422 hc08_freeReg (hc08_reg_a);
7426 /* Case with a bitfield length < 8 and arbitrary source
7428 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7429 /* shift and mask source value */
7431 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7432 hc08_dirtyReg (hc08_reg_a, FALSE);
7433 pushReg (hc08_reg_a, TRUE);
7435 emitcode ("lda", ",x");
7436 emitcode ("and", "#0x%02x", mask);
7437 emitcode ("ora", "1,s");
7438 emitcode ("sta", ",x");
7439 pullReg (hc08_reg_a);
7441 hc08_freeReg (hc08_reg_a);
7445 /* Bit length is greater than 7 bits. In this case, copy */
7446 /* all except the partial byte at the end */
7447 for (rlen=blen;rlen>=8;rlen-=8)
7449 if (AOP (right)->type == AOP_DIR)
7451 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7456 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7457 emitcode ("sta", "%d,x", offset);
7462 /* If there was a partial byte at the end */
7465 mask = (((unsigned char) -1 << rlen) & 0xff);
7467 if (AOP_TYPE (right) == AOP_LIT)
7469 /* Case with partial byte and literal source
7471 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7472 litval >>= (blen-rlen);
7473 litval &= (~mask) & 0xff;
7474 emitcode ("lda", "%d,x", offset - xoffset);
7475 hc08_dirtyReg (hc08_reg_a, FALSE);
7476 if ((mask|litval)!=0xff)
7477 emitcode ("and","#0x%02x", mask);
7479 emitcode ("ora","#0x%02x", litval);
7480 emitcode ("sta", "%d,x", offset - xoffset);
7481 hc08_dirtyReg (hc08_reg_a, FALSE);
7482 hc08_freeReg (hc08_reg_a);
7486 /* Case with partial byte and arbitrary source
7488 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7489 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7490 hc08_dirtyReg (hc08_reg_a, FALSE);
7491 pushReg (hc08_reg_a, TRUE);
7493 emitcode ("lda", "%d,x", offset - xoffset);
7494 emitcode ("and", "#0x%02x", mask);
7495 emitcode ("ora", "1,s");
7496 emitcode ("sta", "%d,x", offset - xoffset);
7497 pullReg (hc08_reg_a);
7500 hc08_freeReg (hc08_reg_a);
7503 /*-----------------------------------------------------------------*/
7504 /* genPackBitsImmed - generates code for packed bit storage */
7505 /*-----------------------------------------------------------------*/
7507 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7511 int offset = 0; /* source byte offset */
7512 int rlen = 0; /* remaining bitfield length */
7513 int blen; /* bitfield length */
7514 int bstr; /* bitfield starting bit within byte */
7515 int litval; /* source literal value (if AOP_LIT) */
7516 unsigned char mask; /* bitmask within current byte */
7518 D(emitcode ("; genPackBitsImmed",""));
7520 blen = SPEC_BLEN (etype);
7521 bstr = SPEC_BSTR (etype);
7523 aopOp (right, ic, FALSE);
7524 size = AOP_SIZE (right);
7526 derefaop = aopDerefAop (AOP (result));
7527 freeAsmop (result, NULL, ic, TRUE);
7528 derefaop->size = size;
7530 /* if the bitfield is a single bit in the direct page */
7531 if (blen == 1 && derefaop->type == AOP_DIR)
7533 if (AOP_TYPE (right) == AOP_LIT)
7535 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7537 emitcode ((litval & 1) ? "bset" : "bclr",
7538 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7542 symbol *tlbl1 = newiTempLabel (NULL);
7543 symbol *tlbl2 = newiTempLabel (NULL);
7545 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7546 emitcode ("bit", "#1");
7547 emitBranch ("bne", tlbl1);
7548 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7549 emitBranch ("bra", tlbl2);
7551 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7553 hc08_freeReg (hc08_reg_a);
7558 /* If the bitfield length is less than a byte */
7561 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7562 (unsigned char) (0xFF >> (8 - bstr)));
7564 if (AOP_TYPE (right) == AOP_LIT)
7566 /* Case with a bitfield length <8 and literal source
7568 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7570 litval &= (~mask) & 0xff;
7572 loadRegFromAop (hc08_reg_a, derefaop, 0);
7573 if ((mask|litval)!=0xff)
7574 emitcode ("and","#0x%02x", mask);
7576 emitcode ("ora","#0x%02x", litval);
7577 hc08_dirtyReg (hc08_reg_a, FALSE);
7578 storeRegToAop (hc08_reg_a, derefaop, 0);
7580 hc08_freeReg (hc08_reg_a);
7584 /* Case with a bitfield length < 8 and arbitrary source
7586 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7587 /* shift and mask source value */
7589 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7590 hc08_dirtyReg (hc08_reg_a, FALSE);
7591 pushReg (hc08_reg_a, TRUE);
7593 loadRegFromAop (hc08_reg_a, derefaop, 0);
7594 emitcode ("and", "#0x%02x", mask);
7595 emitcode ("ora", "1,s");
7596 storeRegToAop (hc08_reg_a, derefaop, 0);
7597 pullReg (hc08_reg_a);
7599 hc08_freeReg (hc08_reg_a);
7603 /* Bit length is greater than 7 bits. In this case, copy */
7604 /* all except the partial byte at the end */
7605 for (rlen=blen;rlen>=8;rlen-=8)
7607 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7611 /* If there was a partial byte at the end */
7614 mask = (((unsigned char) -1 << rlen) & 0xff);
7616 if (AOP_TYPE (right) == AOP_LIT)
7618 /* Case with partial byte and literal source
7620 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7621 litval >>= (blen-rlen);
7622 litval &= (~mask) & 0xff;
7623 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7624 if ((mask|litval)!=0xff)
7625 emitcode ("and","#0x%02x", mask);
7627 emitcode ("ora","#0x%02x", litval);
7628 hc08_dirtyReg (hc08_reg_a, FALSE);
7629 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7630 hc08_dirtyReg (hc08_reg_a, FALSE);
7631 hc08_freeReg (hc08_reg_a);
7635 /* Case with partial byte and arbitrary source
7637 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7638 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7639 hc08_dirtyReg (hc08_reg_a, FALSE);
7640 pushReg (hc08_reg_a, TRUE);
7642 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7643 emitcode ("and", "#0x%02x", mask);
7644 emitcode ("ora", "1,s");
7645 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7646 pullReg (hc08_reg_a);
7649 hc08_freeReg (hc08_reg_a);
7652 freeAsmop (right, NULL, ic, TRUE);
7653 freeAsmop (NULL, derefaop, ic, TRUE);
7656 /*-----------------------------------------------------------------*/
7657 /* genDataPointerSet - remat pointer to data space */
7658 /*-----------------------------------------------------------------*/
7660 genDataPointerSet (operand * right,
7667 D(emitcode ("; genDataPointerSet",""));
7669 aopOp (right, ic, FALSE);
7670 size = AOP_SIZE (right);
7672 derefaop = aopDerefAop (AOP (result));
7673 freeAsmop (result, NULL, ic, TRUE);
7674 derefaop->size = size;
7678 transferAopAop (AOP (right), size, derefaop, size);
7681 freeAsmop (right, NULL, ic, TRUE);
7682 freeAsmop (NULL, derefaop, ic, TRUE);
7686 /*-----------------------------------------------------------------*/
7687 /* genPointerSet - stores the value into a pointer location */
7688 /*-----------------------------------------------------------------*/
7690 genPointerSet (iCode * ic, iCode *pi)
7692 operand *right = IC_RIGHT (ic);
7693 operand *result = IC_RESULT (ic);
7694 sym_link *type, *etype;
7696 sym_link *retype = getSpec (operandType (right));
7697 sym_link *letype = getSpec (operandType (result));
7699 D(emitcode ("; genPointerSet",""));
7701 type = operandType (result);
7702 etype = getSpec (type);
7704 aopOp (result, ic, FALSE);
7706 /* if the result is rematerializable */
7707 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7709 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7711 genDataPointerSet (right, result, ic);
7716 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7721 /* if the operand is already in hx
7722 then we do nothing else we move the value to hx */
7723 if (AOP_TYPE (result) != AOP_STR)
7725 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7727 /* so hx now contains the address */
7728 aopOp (right, ic, FALSE);
7730 /* if bit then unpack */
7731 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7732 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7735 size = AOP_SIZE (right);
7740 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7741 accopWithMisc ("sta", ",x");
7744 emitcode ("aix", "#1");
7746 hc08_freeReg (hc08_reg_a);
7750 freeAsmop (result, NULL, ic, TRUE);
7751 freeAsmop (right, NULL, ic, TRUE);
7754 aopOp (IC_RESULT (pi), pi, FALSE);
7755 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7756 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7760 hc08_freeReg (hc08_reg_hx);
7764 /*-----------------------------------------------------------------*/
7765 /* genIfx - generate code for Ifx statement */
7766 /*-----------------------------------------------------------------*/
7768 genIfx (iCode * ic, iCode * popIc)
7770 operand *cond = IC_COND (ic);
7773 D(emitcode ("; genIfx",""));
7775 aopOp (cond, ic, FALSE);
7777 /* If the condition is a literal, we can just do an unconditional */
7778 /* branch or no branch */
7779 if (AOP_TYPE (cond) == AOP_LIT)
7781 unsigned long lit = (unsigned long) floatFromVal (AOP (cond)->aopu.aop_lit);
7782 freeAsmop (cond, NULL, ic, TRUE);
7784 /* if there was something to be popped then do it */
7790 emitBranch ("jmp", IC_TRUE (ic));
7795 emitBranch ("jmp", IC_FALSE (ic));
7801 /* get the value into acc */
7802 if (AOP_TYPE (cond) != AOP_CRY)
7803 asmopToBool (AOP (cond), FALSE);
7806 /* the result is now in the accumulator */
7807 freeAsmop (cond, NULL, ic, TRUE);
7809 /* if there was something to be popped then do it */
7813 /* if the condition is a bit variable */
7814 if (isbit && IS_ITEMP (cond) &&
7816 genIfxJump (ic, SPIL_LOC (cond)->rname);
7817 else if (isbit && !IS_ITEMP (cond))
7818 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7820 genIfxJump (ic, "a");
7825 /*-----------------------------------------------------------------*/
7826 /* genAddrOf - generates code for address of */
7827 /*-----------------------------------------------------------------*/
7829 genAddrOf (iCode * ic)
7831 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7834 D(emitcode ("; genAddrOf",""));
7836 aopOp (IC_RESULT (ic), ic, FALSE);
7838 /* if the operand is on the stack then we
7839 need to get the stack offset of this
7843 /* if it has an offset then we need to compute it */
7844 offset = _G.stackOfs + _G.stackPushes + sym->stack;
7845 hc08_useReg (hc08_reg_hx);
7846 emitcode ("tsx", "");
7847 while (offset > 127)
7849 emitcode ("aix", "#127");
7852 while (offset < -128)
7854 emitcode ("aix", "#-128");
7857 emitcode ("aix", "#%d", offset);
7858 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7859 hc08_freeReg (hc08_reg_hx);
7864 /* object not on stack then we need the name */
7865 size = AOP_SIZE (IC_RESULT (ic));
7870 char s[SDCC_NAME_MAX+10];
7873 sprintf (s, "#%s", sym->rname);
7876 sprintf (s, "#>%s", sym->rname);
7879 sprintf (s, "#(%s >> %d)",
7883 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7887 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7891 /*-----------------------------------------------------------------*/
7892 /* genAssign - generate code for assignment */
7893 /*-----------------------------------------------------------------*/
7895 genAssign (iCode * ic)
7897 operand *result, *right;
7899 // unsigned long lit = 0L;
7901 D(emitcode("; genAssign",""));
7903 result = IC_RESULT (ic);
7904 right = IC_RIGHT (ic);
7906 /* if they are the same */
7907 if (operandsEqu (result, right)) {
7911 aopOp (right, ic, FALSE);
7912 aopOp (result, ic, TRUE);
7914 /* if they are the same registers */
7915 if (sameRegs (AOP (right), AOP (result)))
7918 if ((AOP_TYPE (right) == AOP_LIT)
7919 && (IS_AOP_HX(AOP(result))))
7921 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7926 size = AOP_SIZE (result);
7929 transferAopAop (AOP (right), size, AOP (result), size);
7933 freeAsmop (right, NULL, ic, TRUE);
7934 freeAsmop (result, NULL, ic, TRUE);
7937 /*-----------------------------------------------------------------*/
7938 /* genJumpTab - generates code for jump table */
7939 /*-----------------------------------------------------------------*/
7941 genJumpTab (iCode * ic)
7944 symbol *jtablo = newiTempLabel (NULL);
7945 symbol *jtabhi = newiTempLabel (NULL);
7947 D(emitcode ("; genJumpTab",""));
7949 aopOp (IC_JTCOND (ic), ic, FALSE);
7951 if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7953 /* get the condition into x */
7954 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7955 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7956 loadRegFromConst (hc08_reg_h, zero);
7958 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7959 emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7960 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7961 emitcode ("jmp", ",x");
7963 hc08_dirtyReg (hc08_reg_a, TRUE);
7964 hc08_dirtyReg (hc08_reg_hx, TRUE);
7969 pushReg(hc08_reg_hx, TRUE);
7971 /* get the condition into x */
7972 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7973 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7974 loadRegFromConst (hc08_reg_h, zero);
7976 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7977 emitcode ("sta", "3,s");
7978 emitcode ("lda", "%05d$,x", jtablo->key + 100);
7979 emitcode ("sta", "4,s");
7981 pullReg(hc08_reg_hx);
7982 emitcode ("rts", "");
7983 _G.stackPushes += 2;
7987 /* now generate the jump labels */
7989 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7990 jtab = setNextItem (IC_JTLABELS (ic)))
7991 emitcode (".db", "%05d$", jtab->key + 100);
7993 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7994 jtab = setNextItem (IC_JTLABELS (ic)))
7995 emitcode (".db", ">%05d$", jtab->key + 100);
7999 /*-----------------------------------------------------------------*/
8000 /* genCast - gen code for casting */
8001 /*-----------------------------------------------------------------*/
8003 genCast (iCode * ic)
8005 operand *result = IC_RESULT (ic);
8006 sym_link *ctype = operandType (IC_LEFT (ic));
8007 sym_link *rtype = operandType (IC_RIGHT (ic));
8008 operand *right = IC_RIGHT (ic);
8011 D(emitcode("; genCast",""));
8013 /* if they are equivalent then do nothing */
8014 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8017 aopOp (right, ic, FALSE);
8018 aopOp (result, ic, FALSE);
8021 /* if they are the same size : or less */
8022 if (AOP_SIZE (result) <= AOP_SIZE (right))
8025 /* if they are in the same place */
8027 if (sameRegs (AOP (right), AOP (result)))
8031 /* if they in different places then copy */
8032 size = AOP_SIZE (result);
8036 transferAopAop(AOP (right), offset, AOP (result), offset);
8043 /* if the result is of type pointer */
8048 sym_link *type = operandType (right);
8049 sym_link *etype = getSpec (type);
8051 /* pointer to generic pointer */
8052 if (IS_GENPTR (ctype))
8055 p_type = DCL_TYPE (type);
8058 if (SPEC_SCLS(etype)==S_REGISTER) {
8059 // let's assume it is a generic pointer
8062 /* we have to go by the storage class */
8063 p_type = PTR_TYPE (SPEC_OCLS (etype));
8067 /* the first two bytes are known */
8068 size = GPTRSIZE - 1;
8072 transferAopAop(AOP (right), offset, AOP (result), offset);
8075 /* the last byte depending on type */
8078 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8083 // pointerTypeToGPByte will have bitched.
8087 sprintf(gpValStr, "#0x%x", gpVal);
8088 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8094 /* just copy the pointers */
8095 size = AOP_SIZE (result);
8099 transferAopAop(AOP (right), offset, AOP (result), offset);
8105 /* so we now know that the size of destination is greater
8106 than the size of the source */
8107 /* we move to result for the size of source */
8108 size = AOP_SIZE (right);
8112 transferAopAop(AOP (right), offset, AOP (result), offset);
8116 /* now depending on the sign of the source && destination */
8117 size = AOP_SIZE (result) - AOP_SIZE (right);
8118 /* if unsigned or not an integral type */
8119 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8122 storeConstToAop (zero, AOP (result), offset++);
8126 /* we need to extend the sign :{ */
8127 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
8128 accopWithMisc ("rola", "");
8129 accopWithMisc ("clra", "");
8130 accopWithMisc ("sbc", zero);
8132 storeRegToAop (hc08_reg_a, AOP (result), offset++);
8135 /* we are done hurray !!!! */
8138 freeAsmop (right, NULL, ic, TRUE);
8139 freeAsmop (result, NULL, ic, TRUE);
8143 /*-----------------------------------------------------------------*/
8144 /* genDjnz - generate decrement & jump if not zero instrucion */
8145 /*-----------------------------------------------------------------*/
8147 genDjnz (iCode * ic, iCode * ifx)
8153 D(emitcode ("; genDjnz",""));
8155 /* if the if condition has a false label
8156 then we cannot save */
8160 /* if the minus is not of the form
8162 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8163 !IS_OP_LITERAL (IC_RIGHT (ic)))
8166 if (operandLitValue (IC_RIGHT (ic)) != 1)
8169 /* dbnz doesn't support extended mode */
8170 if (isOperandInFarSpace (IC_RESULT (ic)))
8173 /* if the size of this greater than one then no
8175 // if (getSize (operandType (IC_RESULT (ic))) > 1)
8177 aopOp (IC_RESULT (ic), ic, FALSE);
8178 if (AOP_SIZE (IC_RESULT (ic))>1)
8180 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8184 /* otherwise we can save BIG */
8185 lbl = newiTempLabel (NULL);
8186 lbl1 = newiTempLabel (NULL);
8189 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
8192 emitBranch ("bra", lbl1);
8194 emitBranch ("jmp", IC_TRUE (ifx));
8197 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8202 /*-----------------------------------------------------------------*/
8203 /* genReceive - generate code for a receive iCode */
8204 /*-----------------------------------------------------------------*/
8206 genReceive (iCode * ic)
8210 D(emitcode ("; genReceive",""));
8212 aopOp (IC_RESULT (ic), ic, FALSE);
8213 size = AOP_SIZE (IC_RESULT (ic));
8218 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
8219 AOP (IC_RESULT (ic)), offset);
8220 if (hc08_aop_pass[offset]->type == AOP_REG)
8221 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
8226 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8229 /*-----------------------------------------------------------------*/
8230 /* genDummyRead - generate code for dummy read of volatiles */
8231 /*-----------------------------------------------------------------*/
8233 genDummyRead (iCode * ic)
8238 D(emitcode("; genDummyRead",""));
8241 if (op && IS_SYMOP (op))
8244 aopOp (op, ic, FALSE);
8246 size = AOP_SIZE (op);
8251 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8252 hc08_freeReg (hc08_reg_a);
8256 freeAsmop (op, NULL, ic, TRUE);
8259 if (op && IS_SYMOP (op))
8262 aopOp (op, ic, FALSE);
8264 size = AOP_SIZE (op);
8269 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8270 hc08_freeReg (hc08_reg_a);
8274 freeAsmop (op, NULL, ic, TRUE);
8278 /*-----------------------------------------------------------------*/
8279 /* genCritical - generate code for start of a critical sequence */
8280 /*-----------------------------------------------------------------*/
8282 genCritical (iCode *ic)
8284 D(emitcode("; genCritical",""));
8287 aopOp (IC_RESULT (ic), ic, TRUE);
8289 emitcode ("tpa", "");
8290 hc08_dirtyReg (hc08_reg_a, FALSE);
8291 emitcode ("sei", "");
8294 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8296 pushReg (hc08_reg_a, FALSE);
8298 hc08_freeReg (hc08_reg_a);
8300 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8303 /*-----------------------------------------------------------------*/
8304 /* genEndCritical - generate code for end of a critical sequence */
8305 /*-----------------------------------------------------------------*/
8307 genEndCritical (iCode *ic)
8309 D(emitcode("; genEndCritical",""));
8313 aopOp (IC_RIGHT (ic), ic, FALSE);
8314 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8315 emitcode ("tap", "");
8316 hc08_freeReg (hc08_reg_a);
8317 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8321 pullReg (hc08_reg_a);
8322 emitcode ("tap", "");
8328 /*-----------------------------------------------------------------*/
8329 /* genhc08Code - generate code for HC08 based controllers */
8330 /*-----------------------------------------------------------------*/
8332 genhc08Code (iCode * lic)
8339 lineHead = lineCurr = NULL;
8341 /* print the allocation information */
8342 if (allocInfo && currFunc)
8343 printAllocInfo (currFunc, codeOutBuf);
8344 /* if debug information required */
8345 if (options.debug && currFunc)
8347 debugFile->writeFunction (currFunc, lic);
8350 if (IS_STATIC (currFunc->etype))
8351 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8353 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8357 /* stack pointer name */
8358 if (options.useXstack)
8363 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8365 hc08_aop_pass[0] = newAsmop (AOP_REG);
8366 hc08_aop_pass[0]->size=1;
8367 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8368 hc08_aop_pass[1] = newAsmop (AOP_REG);
8369 hc08_aop_pass[1]->size=1;
8370 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8371 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8372 hc08_aop_pass[2]->size=1;
8373 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8374 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8375 hc08_aop_pass[3]->size=1;
8376 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8378 for (ic = lic; ic; ic = ic->next)
8381 _G.current_iCode = ic;
8383 if (ic->level != clevel || ic->block != cblock)
8387 debugFile->writeScope(ic);
8393 if (ic->lineno && cln != ic->lineno)
8397 debugFile->writeCLine(ic);
8400 emitcode ("", "C$%s$%d$%d$%d ==.",
8401 FileBaseName (ic->filename), ic->lineno,
8402 ic->level, ic->block);
8406 if (!options.noCcodeInAsm) {
8407 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8408 printCLine(ic->filename, ic->lineno));
8412 if (options.iCodeInAsm) {
8417 for (i=0; i<6; i++) {
8418 sprintf (®sInUse[i],
8419 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8422 iLine = printILine(ic);
8423 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8426 /* if the result is marked as
8427 spilt and rematerializable or code for
8428 this has already been generated then
8430 if (resultRemat (ic) || ic->generated)
8438 for (i=A_IDX;i<=XA_IDX;i++)
8440 reg = hc08_regWithIdx(i);
8442 emitcode("","; %s = %s offset %d", reg->name,
8443 aopName(reg->aop), reg->aopofs);
8446 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8448 sym = OP_SYMBOL (IC_LEFT (ic));
8449 if (sym->accuse == ACCUSE_HX)
8451 hc08_reg_h->isFree = FALSE;
8452 hc08_reg_x->isFree = FALSE;
8454 else if (sym->accuse == ACCUSE_XA)
8456 hc08_reg_a->isFree = FALSE;
8458 hc08_reg_x->isFree = FALSE;
8461 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8463 sym = OP_SYMBOL (IC_RIGHT (ic));
8464 if (sym->accuse == ACCUSE_HX)
8466 hc08_reg_h->isFree = FALSE;
8467 hc08_reg_x->isFree = FALSE;
8469 else if (sym->accuse == ACCUSE_XA)
8471 hc08_reg_a->isFree = FALSE;
8473 hc08_reg_x->isFree = FALSE;
8478 /* depending on the operation */
8498 /* IPOP happens only when trying to restore a
8499 spilt live range, if there is an ifx statement
8500 following this pop then the if statement might
8501 be using some of the registers being popped which
8502 would destory the contents of the register so
8503 we need to check for this condition and handle it */
8505 ic->next->op == IFX &&
8506 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8507 genIfx (ic->next, ic);
8525 genEndFunction (ic);
8541 if (!genPointerGetSetOfs (ic))
8546 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8566 genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
8571 genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
8583 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8587 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8591 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8618 case GET_VALUE_AT_ADDRESS:
8620 hasInc (IC_LEFT (ic), ic,
8621 getSize (operandType (IC_RESULT (ic)))),
8622 ifxForOp (IC_RESULT (ic), ic) );
8626 if (POINTER_SET (ic))
8627 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8653 addSet (&_G.sendSet, ic);
8656 case DUMMY_READ_VOLATILE:
8665 genEndCritical (ic);
8676 if (!hc08_reg_a->isFree)
8677 DD(emitcode("","; forgot to free a"));
8678 if (!hc08_reg_x->isFree)
8679 DD(emitcode("","; forgot to free x"));
8680 if (!hc08_reg_h->isFree)
8681 DD(emitcode("","; forgot to free h"));
8682 if (!hc08_reg_hx->isFree)
8683 DD(emitcode("","; forgot to free hx"));
8684 if (!hc08_reg_xa->isFree)
8685 DD(emitcode("","; forgot to free xa"));
8688 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8691 /* now we are ready to call the
8692 peep hole optimizer */
8693 if (!options.nopeep)
8694 peepHole (&lineHead);
8696 /* now do the actual printing */
8697 printLine (lineHead, codeOutBuf);