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 they have the same rname */
1625 if (sym1->rname[0] && sym2->rname[0]
1626 && strcmp (sym1->rname, sym2->rname) == 0)
1629 /* if left is a tmp & right is not */
1630 if (IS_ITEMP (op1) &&
1633 (sym1->usl.spillLoc == sym2))
1636 if (IS_ITEMP (op2) &&
1640 (sym2->usl.spillLoc == sym1))
1646 /*-----------------------------------------------------------------*/
1647 /* sameRegs - two asmops have the same registers */
1648 /*-----------------------------------------------------------------*/
1650 sameRegs (asmop * aop1, asmop * aop2)
1657 // if (aop1->size != aop2->size)
1660 if (aop1->type == aop2->type)
1665 for (i = 0; i < aop1->size; i++)
1666 if (aop1->aopu.aop_reg[i] !=
1667 aop2->aopu.aop_reg[i])
1671 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1674 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1681 /*-----------------------------------------------------------------*/
1682 /* aopOp - allocates an asmop for an operand : */
1683 /*-----------------------------------------------------------------*/
1685 aopOp (operand * op, iCode * ic, bool result)
1694 // Is this a pointer set result?
1696 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1700 // printf("checking literal\n");
1701 /* if this a literal */
1702 if (IS_OP_LITERAL (op))
1704 op->aop = aop = newAsmop (AOP_LIT);
1705 aop->aopu.aop_lit = op->operand.valOperand;
1706 aop->size = getSize (operandType (op));
1708 aop->isaddr = op->isaddr;
1712 // printf("checking pre-existing\n");
1713 /* if already has a asmop then continue */
1717 op->aop->isaddr = op->isaddr;
1721 // printf("checking underlying sym\n");
1722 /* if the underlying symbol has a aop */
1723 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1725 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1726 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1727 //op->aop = aop = OP_SYMBOL (op)->aop;
1728 aop->size = getSize( operandType (op));
1729 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1730 //printf (" with size = %d\n", aop->size);
1733 aop->isaddr = op->isaddr;
1734 /* if (aop->isaddr & IS_ITEMP (op))
1736 aop->psize=aop->size;
1737 aop->size = getSize( operandType (op)->next);
1742 // printf("checking true sym\n");
1743 /* if this is a true symbol */
1744 if (IS_TRUE_SYMOP (op))
1746 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1748 aop->isaddr = op->isaddr;
1749 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1750 //printf (" with size = %d\n", aop->size);
1754 /* this is a temporary : this has
1760 e) can be a return use only */
1762 sym = OP_SYMBOL (op);
1764 // printf("checking conditional\n");
1765 /* if the type is a conditional */
1766 if (sym->regType == REG_CND)
1768 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1771 aop->isaddr = op->isaddr;
1775 // printf("checking spilt\n");
1776 /* if it is spilt then two situations
1778 b) has a spill location */
1779 if (sym->isspilt || sym->nRegs == 0)
1782 // printf("checking remat\n");
1783 /* rematerialize it NOW */
1786 sym->aop = op->aop = aop =
1788 aop->size = getSize (sym->type);
1790 aop->isaddr = op->isaddr;
1791 /* if (aop->isaddr & IS_ITEMP (op))
1793 aop->psize=aop->size;
1794 aop->size = getSize( operandType (op)->next);
1799 // printf("checking accuse\n");
1802 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1803 aop->size = getSize (sym->type);
1804 switch (sym->accuse)
1807 aop->aopu.aop_reg[0] = hc08_reg_a;
1808 aop->aopu.aop_reg[1] = hc08_reg_x;
1811 aop->aopu.aop_reg[0] = hc08_reg_x;
1812 aop->aopu.aop_reg[1] = hc08_reg_h;
1816 aop->isaddr = op->isaddr;
1820 // printf("checking ruonly\n");
1826 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1827 aop->size = getSize (sym->type);
1828 for (i = 0; i < fReturnSizeHC08; i++)
1829 aop->aopu.aop_str[i] = fReturn2[i];
1831 aop->isaddr = op->isaddr;
1835 /* else spill location */
1836 if (sym->usl.spillLoc)
1838 asmop *oldAsmOp = NULL;
1840 if (sym->usl.spillLoc->aop
1841 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1843 /* force a new aop if sizes differ */
1844 oldAsmOp = sym->usl.spillLoc->aop;
1845 sym->usl.spillLoc->aop = NULL;
1846 //printf ("forcing new aop\n");
1848 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1849 if (sym->usl.spillLoc->aop->size != getSize (sym->type))
1851 /* Don't reuse the new aop, go with the last one */
1852 sym->usl.spillLoc->aop = oldAsmOp;
1854 aop->size = getSize (sym->type);
1856 aop->isaddr = op->isaddr;
1857 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1858 //printf (" with size = %d\n", aop->size);
1862 /* else must be a dummy iTemp */
1863 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1864 aop->size = getSize (sym->type);
1868 // printf("assuming register\n");
1869 /* must be in a register */
1870 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1871 aop->size = sym->nRegs;
1872 for (i = 0; i < sym->nRegs; i++)
1873 aop->aopu.aop_reg[i] = sym->regs[i];
1875 aop->isaddr = op->isaddr;
1879 /*-----------------------------------------------------------------*/
1880 /* freeAsmop - free up the asmop given to an operand */
1881 /*----------------------------------------------------------------*/
1883 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1905 DD(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1908 for (loffset=0; loffset<aop->size; loffset++)
1909 if (aop->stk_aop[loffset])
1911 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1914 pullNull (stackAdjust);
1918 /* all other cases just dealloc */
1924 OP_SYMBOL (op)->aop = NULL;
1925 /* if the symbol has a spill */
1927 SPIL_LOC (op)->aop = NULL;
1933 /*-----------------------------------------------------------------*/
1934 /* aopDerefAop - treating the aop parameter as a pointer, return */
1935 /* an asmop for the object it references */
1936 /*-----------------------------------------------------------------*/
1938 aopDerefAop (asmop *aop)
1943 asmop *newaop = NULL;
1944 sym_link *type, *etype;
1947 DD(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1951 type = operandType (aop->op);
1952 etype = getSpec (type);
1953 /* if op is of type of pointer then it is simple */
1954 if (IS_PTR (type) && !IS_FUNC (type->next))
1955 p_type = DCL_TYPE (type);
1958 /* we have to go by the storage class */
1959 p_type = PTR_TYPE (SPEC_OCLS (etype));
1968 if (p_type == POINTER)
1969 newaop = newAsmop (AOP_DIR);
1971 newaop = newAsmop (AOP_EXT);
1972 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1975 adr = (int) floatFromVal (aop->aopu.aop_lit);
1976 if (p_type == POINTER)
1981 newaop = newAsmop (AOP_DIR);
1982 sprintf (s, "0x%02x",adr);
1986 newaop = newAsmop (AOP_EXT);
1987 sprintf (s, "0x%04x",adr);
1989 rs = Safe_calloc (1, strlen (s) + 1);
1991 newaop->aopu.aop_dir = rs;
1994 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1995 "unsupported asmop");
2005 /*-----------------------------------------------------------------*/
2006 /* aopAdrStr - for referencing the address of the aop */
2007 /*-----------------------------------------------------------------*/
2009 aopAdrStr (asmop * aop, int loffset, bool bit16)
2013 int offset = aop->size - 1 - loffset;
2016 /* offset is greater than
2018 if (loffset > (aop->size - 1) &&
2019 aop->type != AOP_LIT)
2022 /* depending on type */
2030 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
2031 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
2033 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
2037 sprintf (s, "#(%s >> %d)",
2038 aop->aopu.aop_immd.aop_immd1,
2042 aop->aopu.aop_immd.aop_immd1);
2046 aop->aopu.aop_immd.aop_immd1);
2047 rs = Safe_calloc (1, strlen (s) + 1);
2053 sprintf (s, "*(%s + %d)",
2057 sprintf (s, "*%s", aop->aopu.aop_dir);
2058 rs = Safe_calloc (1, strlen (s) + 1);
2064 sprintf (s, "(%s + %d)",
2068 sprintf (s, "%s", aop->aopu.aop_dir);
2069 rs = Safe_calloc (1, strlen (s) + 1);
2074 return aop->aopu.aop_reg[loffset]->name;
2078 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
2080 return aopLiteral (aop->aopu.aop_lit, loffset);
2084 return aop->aopu.aop_str[loffset];
2087 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2089 rs = Safe_calloc (1, strlen (s) + 1);
2095 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2096 "aopAdrStr got unsupported aop->type");
2105 /*-----------------------------------------------------------------*/
2106 /* opIsGptr: returns non-zero if the passed operand is */
2107 /* a generic pointer type. */
2108 /*-----------------------------------------------------------------*/
2110 opIsGptr (operand * op)
2112 sym_link *type = operandType (op);
2114 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2122 /*-----------------------------------------------------------------*/
2123 /* getDataSize - get the operand data size */
2124 /*-----------------------------------------------------------------*/
2126 getDataSize (operand * op)
2129 size = AOP_SIZE (op);
2134 /*-----------------------------------------------------------------*/
2135 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2136 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2137 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2138 /*-----------------------------------------------------------------*/
2140 asmopToBool (asmop *aop, bool resultInA)
2142 symbol *tlbl, *tlbl1;
2143 int size = aop->size;
2144 bool needpula = FALSE;
2145 bool flagsonly = TRUE;
2150 hc08_freeReg(hc08_reg_a);
2157 emitcode ("tsta", "");
2160 else if (IS_AOP_X(aop))
2161 emitcode ("tstx", "");
2162 else if (IS_AOP_H(aop))
2164 if (hc08_reg_a->isFree)
2166 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2167 emitcode ("tsta", "");
2169 hc08_freeReg(hc08_reg_a);
2171 else if (hc08_reg_x->isFree)
2173 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2174 emitcode ("tstx", "");
2175 hc08_freeReg(hc08_reg_x);
2179 emitcode ("pshh", "");
2180 emitcode ("tst", "1,s");
2181 emitcode ("ais", "#1");
2184 else if (IS_AOP_HX(aop))
2185 emitcode ("cphx", zero);
2186 else if (IS_AOP_XA(aop))
2188 symbol *tlbl = newiTempLabel (NULL);
2189 emitcode ("tsta", "");
2190 emitcode ("bne", "%05d$", (tlbl->key + 100));
2191 emitcode ("tstx", "");
2196 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2197 "Bad rIdx in asmToBool");
2205 needpula = pushRegIfUsed (hc08_reg_a);
2206 loadRegFromAop (hc08_reg_a, aop, 0);
2207 for (offset=1; offset<size; offset++)
2208 accopWithAop ("ora", aop, offset);
2210 pullReg (hc08_reg_a);
2213 hc08_freeReg (hc08_reg_a);
2218 /* Higher levels should optimize this case away but let's be safe */
2219 if ((unsigned long) floatFromVal (aop->aopu.aop_lit))
2220 loadRegFromConst (hc08_reg_a, one);
2222 loadRegFromConst (hc08_reg_a, zero);
2223 hc08_freeReg(hc08_reg_a);
2230 loadRegFromAop (hc08_reg_a, aop, 0);
2231 hc08_freeReg (hc08_reg_a);
2235 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2240 if (hc08_reg_a->isFree)
2242 loadRegFromAop (hc08_reg_a, aop, 0);
2243 accopWithAop ("ora", aop, 1);
2244 hc08_freeReg (hc08_reg_a);
2249 tlbl = newiTempLabel (NULL);
2250 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2251 emitcode ("bne", "%05d$", (tlbl->key + 100));
2252 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2259 needpula = pushRegIfUsed (hc08_reg_a);
2260 loadRegFromAop (hc08_reg_a, aop, 0);
2261 for (offset=1; offset<size; offset++)
2262 accopWithAop ("ora", aop, offset);
2264 pullReg (hc08_reg_a);
2267 hc08_freeReg (hc08_reg_a);
2275 tlbl = newiTempLabel (NULL);
2279 tlbl1 = newiTempLabel (NULL);
2280 emitBranch ("bne", tlbl1);
2281 loadRegFromConst (hc08_reg_a, zero);
2282 emitBranch ("bra", tlbl);
2284 loadRegFromConst (hc08_reg_a, one);
2288 emitBranch ("beq", tlbl);
2289 loadRegFromConst (hc08_reg_a, one);
2292 hc08_useReg (hc08_reg_a);
2298 /*-----------------------------------------------------------------*/
2299 /* genNot - generate code for ! operation */
2300 /*-----------------------------------------------------------------*/
2304 D(emitcode ("; genNot",""));
2306 /* assign asmOps to operand & result */
2307 aopOp (IC_LEFT (ic), ic, FALSE);
2308 aopOp (IC_RESULT (ic), ic, TRUE);
2310 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2311 emitcode ("eor", one);
2312 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2314 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2315 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2319 /*-----------------------------------------------------------------*/
2320 /* genCpl - generate code for complement */
2321 /*-----------------------------------------------------------------*/
2327 regs* reg = hc08_reg_a;
2331 D(emitcode ("; genCpl",""));
2333 /* assign asmOps to operand & result */
2334 aopOp (IC_LEFT (ic), ic, FALSE);
2335 aopOp (IC_RESULT (ic), ic, TRUE);
2337 size = AOP_SIZE (IC_RESULT (ic));
2340 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2341 rmwWithReg ("com", reg);
2343 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2348 /* release the aops */
2349 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2350 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2353 /*-----------------------------------------------------------------*/
2354 /* genUminusFloat - unary minus for floating points */
2355 /*-----------------------------------------------------------------*/
2357 genUminusFloat (operand * op, operand * result)
2359 int size, offset = 0;
2362 D(emitcode ("; genUminusFloat",""));
2364 /* for this we just copy and then flip the bit */
2366 size = AOP_SIZE (op) - 1;
2370 transferAopAop (AOP (op), offset, AOP (result), offset);
2374 needpula = pushRegIfUsed (hc08_reg_a);
2375 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2376 emitcode ("eor", "#0x80");
2377 hc08_useReg (hc08_reg_a);
2378 storeRegToAop (hc08_reg_a, AOP (result), offset);
2379 pullOrFreeReg (hc08_reg_a, needpula);
2382 /*-----------------------------------------------------------------*/
2383 /* genUminus - unary minus code generation */
2384 /*-----------------------------------------------------------------*/
2386 genUminus (iCode * ic)
2389 sym_link *optype, *rtype;
2394 D(emitcode ("; genUminus",""));
2397 aopOp (IC_LEFT (ic), ic, FALSE);
2398 aopOp (IC_RESULT (ic), ic, TRUE);
2400 optype = operandType (IC_LEFT (ic));
2401 rtype = operandType (IC_RESULT (ic));
2403 /* if float then do float stuff */
2404 if (IS_FLOAT (optype))
2406 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2410 /* otherwise subtract from zero */
2411 size = AOP_SIZE (IC_LEFT (ic));
2416 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2417 needpula = pushRegIfUsed (hc08_reg_a);
2420 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2421 emitcode ("nega", "");
2422 hc08_freeReg (hc08_reg_a);
2423 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2424 SPEC_USIGN (operandType (IC_LEFT (ic))));
2425 pullOrFreeReg (hc08_reg_a, needpula);
2429 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2430 result = forceStackedAop (AOP (IC_RESULT (ic)), FALSE);
2432 result = AOP (IC_RESULT (ic));
2434 needpula = pushRegIfUsed (hc08_reg_a);
2438 loadRegFromConst (hc08_reg_a, zero);
2439 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2440 storeRegToAop (hc08_reg_a, result, offset++);
2443 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2444 SPEC_USIGN (operandType (IC_LEFT (ic))));
2445 pullOrFreeReg (hc08_reg_a, needpula);
2447 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2448 freeAsmop (NULL, result, ic, TRUE);
2454 /* release the aops */
2455 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2456 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2459 /*-----------------------------------------------------------------*/
2460 /* saveRegisters - will look for a call and save the registers */
2461 /*-----------------------------------------------------------------*/
2463 saveRegisters (iCode * lic)
2470 for (ic = lic; ic; ic = ic->next)
2471 if (ic->op == CALL || ic->op == PCALL)
2476 fprintf (stderr, "found parameter push with no function call\n");
2480 /* if the registers have been saved already or don't need to be then
2484 if (IS_SYMOP(IC_LEFT(ic)) &&
2485 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2486 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2489 /* safe the registers in use at this time but skip the
2490 ones for the result */
2491 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2492 hc08_rUmaskForOp (IC_RESULT(ic)));
2495 for (i = 0; i < hc08_nRegs; i++)
2497 if (bitVectBitValue (rsave, i))
2498 pushReg ( hc08_regWithIdx (i), FALSE);
2502 /*-----------------------------------------------------------------*/
2503 /* unsaveRegisters - pop the pushed registers */
2504 /*-----------------------------------------------------------------*/
2506 unsaveRegisters (iCode * ic)
2511 /* restore the registers in use at this time but skip the
2512 ones for the result */
2513 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2514 hc08_rUmaskForOp (IC_RESULT(ic)));
2516 for (i = hc08_nRegs; i >= 0; i--)
2518 if (bitVectBitValue (rsave, i))
2519 pullReg ( hc08_regWithIdx (i));
2525 /*-----------------------------------------------------------------*/
2527 /*-----------------------------------------------------------------*/
2529 pushSide (operand * oper, int size)
2534 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2535 pushReg ( hc08_reg_a, TRUE);
2539 /*-----------------------------------------------------------------*/
2540 /* assignResultValue - */
2541 /*-----------------------------------------------------------------*/
2543 assignResultValue (operand * oper)
2545 int size = AOP_SIZE (oper);
2549 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2550 if (hc08_aop_pass[offset]->type == AOP_REG)
2551 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2558 /*-----------------------------------------------------------------*/
2559 /* genIpush - genrate code for pushing this gets a little complex */
2560 /*-----------------------------------------------------------------*/
2562 genIpush (iCode * ic)
2564 int size, offset = 0;
2567 D(emitcode ("; genIpush",""));
2569 /* if this is not a parm push : ie. it is spill push
2570 and spill push is always done on the local stack */
2574 /* and the item is spilt then do nothing */
2575 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2578 aopOp (IC_LEFT (ic), ic, FALSE);
2579 size = AOP_SIZE (IC_LEFT (ic));
2581 /* push it on the stack */
2584 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2585 pushReg ( hc08_reg_a, TRUE);
2591 /* this is a paramter push: in this case we call
2592 the routine to find the call and save those
2593 registers that need to be saved */
2596 /* then do the push */
2597 aopOp (IC_LEFT (ic), ic, FALSE);
2600 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2601 size = AOP_SIZE (IC_LEFT (ic));
2604 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2605 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2607 if ((size==2) && hc08_reg_hx->isFree)
2609 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2610 pushReg (hc08_reg_hx, TRUE);
2617 // printf("loading %d\n", offset);
2618 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2619 // printf("pushing \n");
2620 pushReg (hc08_reg_a, TRUE);
2624 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2627 /*-----------------------------------------------------------------*/
2628 /* genIpop - recover the registers: can happen only for spilling */
2629 /*-----------------------------------------------------------------*/
2631 genIpop (iCode * ic)
2635 D(emitcode ("; genIpop",""));
2637 /* if the temp was not pushed then */
2638 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2641 aopOp (IC_LEFT (ic), ic, FALSE);
2642 size = AOP_SIZE (IC_LEFT (ic));
2646 pullReg (hc08_reg_a);
2647 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2649 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2653 /*-----------------------------------------------------------------*/
2654 /* genSend - gen code for SEND */
2655 /*-----------------------------------------------------------------*/
2656 static void genSend(set *sendSet)
2660 for (sic = setFirstItem (sendSet); sic;
2661 sic = setNextItem (sendSet)) {
2662 int size, offset = 0;
2663 aopOp (IC_LEFT (sic), sic, FALSE);
2664 size = AOP_SIZE (IC_LEFT (sic));
2669 transferAopAop( AOP (IC_LEFT (sic)), offset,
2670 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2674 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2678 /*-----------------------------------------------------------------*/
2679 /* genCall - generates a call statement */
2680 /*-----------------------------------------------------------------*/
2682 genCall (iCode * ic)
2685 // bool restoreBank = FALSE;
2686 // bool swapBanks = FALSE;
2688 D(emitcode("; genCall",""));
2690 dtype = operandType (IC_LEFT (ic));
2691 /* if send set is not empty then assign */
2694 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2695 genSend(reverseSet(_G.sendSet));
2697 genSend(_G.sendSet);
2703 /* if caller saves & we have not saved then */
2709 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2710 OP_SYMBOL (IC_LEFT (ic))->rname :
2711 OP_SYMBOL (IC_LEFT (ic))->name));
2714 /* if we need assign a result value */
2715 if ((IS_ITEMP (IC_RESULT (ic)) &&
2716 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2717 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2718 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2719 IS_TRUE_SYMOP (IC_RESULT (ic)))
2723 aopOp (IC_RESULT (ic), ic, FALSE);
2726 assignResultValue (IC_RESULT (ic));
2728 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2731 /* adjust the stack for parameters if
2735 pullNull (ic->parmBytes);
2738 /* if we had saved some registers then unsave them */
2739 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2740 unsaveRegisters (ic);
2744 /*-----------------------------------------------------------------*/
2745 /* -10l - generates a call by pointer statement */
2746 /*-----------------------------------------------------------------*/
2748 genPcall (iCode * ic)
2751 symbol *rlbl = newiTempLabel (NULL);
2752 symbol *tlbl = newiTempLabel (NULL);
2753 // bool restoreBank=FALSE;
2754 // bool swapBanks = FALSE;
2756 D(emitcode("; genPCall",""));
2758 /* if caller saves & we have not saved then */
2762 /* if we are calling a not _naked function that is not using
2763 the same register bank then we need to save the
2764 destination registers on the stack */
2765 dtype = operandType (IC_LEFT (ic))->next;
2767 /* now push the calling address */
2768 emitBranch ("bsr", tlbl);
2769 emitBranch ("bra", rlbl);
2771 _G.stackPushes += 2; /* account for the bsr return address now on stack */
2774 /* Push the function's address */
2775 aopOp (IC_LEFT (ic), ic, FALSE);
2776 pushSide (IC_LEFT (ic), FPTRSIZE);
2777 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2779 /* if send set is not empty the assign */
2782 genSend(reverseSet(_G.sendSet));
2788 emitcode ("rts", "");
2791 _G.stackPushes -= 4; /* account for rts here & in called function */
2795 /* if we need assign a result value */
2796 if ((IS_ITEMP (IC_RESULT (ic)) &&
2797 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2798 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2799 IS_TRUE_SYMOP (IC_RESULT (ic)))
2803 aopOp (IC_RESULT (ic), ic, FALSE);
2806 assignResultValue (IC_RESULT (ic));
2808 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2811 /* adjust the stack for parameters if
2815 pullNull (ic->parmBytes);
2818 /* if we hade saved some registers then
2820 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2821 unsaveRegisters (ic);
2824 /*-----------------------------------------------------------------*/
2825 /* resultRemat - result is rematerializable */
2826 /*-----------------------------------------------------------------*/
2828 resultRemat (iCode * ic)
2830 if (SKIP_IC (ic) || ic->op == IFX)
2833 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2835 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2836 if (sym->remat && !POINTER_SET (ic))
2843 /*-----------------------------------------------------------------*/
2844 /* inExcludeList - return 1 if the string is in exclude Reg list */
2845 /*-----------------------------------------------------------------*/
2847 regsCmp(void *p1, void *p2)
2849 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2853 inExcludeList (char *s)
2855 const char *p = setFirstItem(options.excludeRegsSet);
2857 if (p == NULL || STRCASECMP(p, "none") == 0)
2861 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2864 /*-----------------------------------------------------------------*/
2865 /* genFunction - generated code for function entry */
2866 /*-----------------------------------------------------------------*/
2868 genFunction (iCode * ic)
2870 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2872 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2873 int stackAdjust = sym->stack;
2874 int accIsFree = sym->recvSize == 0;
2878 /* create the function header */
2879 emitcode (";", "-----------------------------------------");
2880 emitcode (";", " function %s", sym->name);
2881 emitcode (";", "-----------------------------------------");
2883 emitcode ("", "%s:", sym->rname);
2884 lineCurr->isLabel = 1;
2885 ftype = operandType (IC_LEFT (ic));
2889 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2891 if (IFFUNC_ISNAKED(ftype))
2893 emitcode(";", "naked function: no prologue.");
2897 /* if this is an interrupt service routine then
2899 if (IFFUNC_ISISR (sym->type))
2902 if (!inExcludeList ("h"))
2903 pushReg (hc08_reg_h, FALSE);
2906 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2907 /* before setting up the stack frame completely. */
2908 while (ric && ric->next && ric->next->op == RECEIVE)
2910 while (ric && IC_RESULT (ric))
2912 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2913 int rsymSize = rsym ? getSize(rsym->type) : 0;
2917 if (rsym && rsym->regType == REG_CND)
2919 if (rsym && (rsym->accuse || rsym->ruonly))
2921 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2922 rsym = rsym->usl.spillLoc;
2925 /* If the RECEIVE operand immediately spills to the first entry on the */
2926 /* stack, we can push it directly rather than use an sp relative store. */
2927 if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize)
2931 _G.current_iCode = ric;
2932 D(emitcode ("; genReceive",""));
2933 for (ofs=0; ofs < rsymSize; ofs++)
2935 regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
2936 pushReg (reg, TRUE);
2937 if (reg->rIdx == A_IDX)
2941 _G.current_iCode = ic;
2944 ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
2947 /* adjust the stack for the function */
2950 adjustStack (-stackAdjust);
2952 _G.stackOfs = sym->stack;
2955 /* if critical function then turn interrupts off */
2956 if (IFFUNC_ISCRITICAL (ftype))
2960 /* Function was passed parameters, so make sure A is preserved */
2961 pushReg (hc08_reg_a, FALSE);
2962 pushReg (hc08_reg_a, FALSE);
2963 emitcode ("tpa", "");
2964 emitcode ("sta", "2,s");
2965 emitcode ("sei", "");
2966 pullReg (hc08_reg_a);
2970 /* No passed parameters, so A can be freely modified */
2971 emitcode ("tpa", "");
2972 pushReg (hc08_reg_a, TRUE);
2973 emitcode ("sei", "");
2979 /*-----------------------------------------------------------------*/
2980 /* genEndFunction - generates epilogue for functions */
2981 /*-----------------------------------------------------------------*/
2983 genEndFunction (iCode * ic)
2985 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2987 if (IFFUNC_ISNAKED(sym->type))
2989 emitcode(";", "naked function: no epilogue.");
2990 if (options.debug && currFunc)
2991 debugFile->writeEndFunction (currFunc, ic, 0);
2995 if (IFFUNC_ISCRITICAL (sym->type))
2997 if (!IS_VOID(sym->type->next))
2999 /* Function has return value, so make sure A is preserved */
3000 pushReg (hc08_reg_a, FALSE);
3001 emitcode ("lda", "2,s");
3002 emitcode ("tap", "");
3003 pullReg (hc08_reg_a);
3008 /* Function returns void, so A can be freely modified */
3009 pullReg (hc08_reg_a);
3010 emitcode ("tap", "");
3014 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
3020 _G.stackPushes += sym->stack;
3021 adjustStack (sym->stack);
3025 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3029 if (IFFUNC_ISISR (sym->type))
3032 if (!inExcludeList ("h"))
3033 pullReg (hc08_reg_h);
3036 /* if debug then send end of function */
3037 if (options.debug && currFunc)
3039 debugFile->writeEndFunction (currFunc, ic, 1);
3042 emitcode ("rti", "");
3046 if (IFFUNC_CALLEESAVES(sym->type))
3050 /* if any registers used */
3053 /* save the registers used */
3054 for (i = sym->regsUsed->size; i >= 0; i--)
3056 if (bitVectBitValue (sym->regsUsed, i) ||
3057 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3058 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3064 /* if debug then send end of function */
3065 if (options.debug && currFunc)
3067 debugFile->writeEndFunction (currFunc, ic, 1);
3070 emitcode ("rts", "");
3075 /*-----------------------------------------------------------------*/
3076 /* genRet - generate code for return statement */
3077 /*-----------------------------------------------------------------*/
3081 int size, offset = 0;
3084 D(emitcode ("; genRet",""));
3086 /* if we have no return value then
3087 just generate the "ret" */
3091 /* we have something to return then
3092 move the return value into place */
3093 aopOp (IC_LEFT (ic), ic, FALSE);
3094 size = AOP_SIZE (IC_LEFT (ic));
3100 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3107 /* 4 byte return: store value in the global return variable */
3111 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3112 STA (fReturn2[offset--], FALSE);
3113 hc08_freeReg (hc08_reg_a);
3117 /* 2 byte return: store value in x:a */
3118 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3119 hc08_freeReg (hc08_reg_xa);
3122 /* 1 byte return: store value in a */
3123 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3124 hc08_freeReg (hc08_reg_a);
3129 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3132 /* generate a jump to the return label
3133 if the next is not the return statement */
3134 if (!(ic->next && ic->next->op == LABEL &&
3135 IC_LABEL (ic->next) == returnLabel))
3137 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3141 /*-----------------------------------------------------------------*/
3142 /* genLabel - generates a label */
3143 /*-----------------------------------------------------------------*/
3145 genLabel (iCode * ic)
3150 /* For the high level labels we cannot depend on any */
3151 /* register's contents. Amnesia time. */
3152 for (i=A_IDX;i<=XA_IDX;i++)
3154 reg = hc08_regWithIdx(i);
3159 /* special case never generate */
3160 if (IC_LABEL (ic) == entryLabel)
3163 debugFile->writeLabel(IC_LABEL (ic), ic);
3165 emitLabel (IC_LABEL (ic));
3169 /*-----------------------------------------------------------------*/
3170 /* genGoto - generates a jmp */
3171 /*-----------------------------------------------------------------*/
3173 genGoto (iCode * ic)
3175 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3179 /*-----------------------------------------------------------------*/
3180 /* findLabelBackwards: walks back through the iCode chain looking */
3181 /* for the given label. Returns number of iCode instructions */
3182 /* between that label and given ic. */
3183 /* Returns zero if label not found. */
3184 /*-----------------------------------------------------------------*/
3186 findLabelBackwards (iCode * ic, int key)
3195 /* If we have any pushes or pops, we cannot predict the distance.
3196 I don't like this at all, this should be dealt with in the
3198 if (ic->op == IPUSH || ic->op == IPOP) {
3202 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3212 /*-----------------------------------------------------------------*/
3213 /* genPlusIncr :- does addition with increment if possible */
3214 /*-----------------------------------------------------------------*/
3216 genPlusIncr (iCode * ic)
3224 unsigned int size = getDataSize (IC_RESULT (ic));
3225 unsigned int offset;
3226 symbol *tlbl = NULL;
3228 left = IC_LEFT (ic);
3229 result = IC_RESULT (ic);
3231 /* will try to generate an increment */
3232 /* if the right side is not a literal
3234 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3237 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3239 DD(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3241 if ((IS_AOP_HX (AOP (left)) ||
3242 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3244 && (icount>=-128) && (icount<=127) && (size==2))
3246 if (!IS_AOP_HX (AOP (left)))
3248 needpulx = pushRegIfUsed (hc08_reg_x);
3249 needpulh = pushRegIfUsed (hc08_reg_h);
3256 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3257 emitcode ("aix","#%d", icount);
3258 hc08_dirtyReg (hc08_reg_hx, FALSE);
3259 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3260 pullOrFreeReg (hc08_reg_h, needpulh);
3261 pullOrFreeReg (hc08_reg_x, needpulx);
3265 DD(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3266 sameRegs (AOP (left), AOP (result))));
3268 if ((icount > 255) || (icount<0))
3271 if (!sameRegs (AOP (left), AOP (result)))
3274 D(emitcode ("; genPlusIncr",""));
3277 tlbl = newiTempLabel (NULL);
3282 rmwWithAop ("inc", AOP (result), 0);
3284 emitBranch ("bne", tlbl);
3288 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3289 needpula = pushRegIfUsed (hc08_reg_a);
3292 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3293 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3294 hc08_useReg (hc08_reg_a);
3295 storeRegToAop (hc08_reg_a, AOP (result), 0);
3296 hc08_freeReg (hc08_reg_a);
3298 emitBranch ("bcc", tlbl);
3300 for (offset=1; offset<size; offset++)
3302 rmwWithAop ("inc", AOP (result), offset);
3303 if ((offset+1)<size)
3304 emitBranch ("bne", tlbl);
3310 pullOrFreeReg (hc08_reg_a, needpula);
3317 /*-----------------------------------------------------------------*/
3318 /* genPlus - generates code for addition */
3319 /*-----------------------------------------------------------------*/
3321 genPlus (iCode * ic)
3323 int size, offset = 0;
3325 asmop *leftOp, *rightOp;
3327 /* special cases :- */
3329 D(emitcode ("; genPlus",""));
3331 aopOp (IC_LEFT (ic), ic, FALSE);
3332 aopOp (IC_RIGHT (ic), ic, FALSE);
3333 aopOp (IC_RESULT (ic), ic, TRUE);
3335 /* we want registers on the left and literals on the right */
3336 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3337 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3339 operand *t = IC_RIGHT (ic);
3340 IC_RIGHT (ic) = IC_LEFT (ic);
3345 /* if I can do an increment instead
3346 of add then GOOD for ME */
3347 if (genPlusIncr (ic) == TRUE)
3350 DD(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3351 DD(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3352 DD(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3354 size = getDataSize (IC_RESULT (ic));
3356 leftOp = AOP(IC_LEFT(ic));
3357 rightOp = AOP(IC_RIGHT(ic));
3363 loadRegFromAop (hc08_reg_a, leftOp, offset);
3364 accopWithAop(add, rightOp, offset);
3365 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3366 hc08_freeReg (hc08_reg_a);
3367 add = "adc"; /* further adds must propagate carry */
3371 // adjustArithmeticResult (ic);
3374 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3375 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3376 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3379 /*-----------------------------------------------------------------*/
3380 /* genMinusDec :- does subtraction with decrement if possible */
3381 /*-----------------------------------------------------------------*/
3383 genMinusDec (iCode * ic)
3385 unsigned int icount;
3390 unsigned int size = getDataSize (IC_RESULT (ic));
3394 left = IC_LEFT (ic);
3395 result = IC_RESULT (ic);
3397 /* will try to generate an increment */
3398 /* if the right side is not a literal
3400 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3403 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3405 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3406 && (icount>=-127) && (icount<=128) && (size==2))
3408 if (!IS_AOP_HX (AOP (left)))
3410 needpulx = pushRegIfUsed (hc08_reg_x);
3411 needpulh = pushRegIfUsed (hc08_reg_h);
3418 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3419 emitcode ("aix","#%d", -icount);
3420 hc08_dirtyReg (hc08_reg_hx, FALSE);
3421 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3422 pullOrFreeReg (hc08_reg_h, needpulh);
3423 pullOrFreeReg (hc08_reg_x, needpulx);
3427 if ((icount > 1) || (icount<0))
3430 if (!sameRegs (AOP (left), AOP (result)))
3436 D(emitcode ("; genMinusDec",""));
3438 rmwWithAop ("dec", AOP (result), 0);
3443 /*-----------------------------------------------------------------*/
3444 /* addSign - complete with sign */
3445 /*-----------------------------------------------------------------*/
3447 addSign (operand * result, int offset, int sign)
3449 int size = (getDataSize (result) - offset);
3454 emitcode ("rola", "");
3455 emitcode ("clra", "");
3456 emitcode ("sbc", zero);
3458 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3462 storeConstToAop (zero, AOP (result), offset++);
3467 /*-----------------------------------------------------------------*/
3468 /* genMinus - generates code for subtraction */
3469 /*-----------------------------------------------------------------*/
3471 genMinus (iCode * ic)
3474 int size, offset = 0;
3476 asmop *leftOp, *rightOp;
3478 D(emitcode ("; genMinus",""));
3480 aopOp (IC_LEFT (ic), ic, FALSE);
3481 aopOp (IC_RIGHT (ic), ic, FALSE);
3482 aopOp (IC_RESULT (ic), ic, TRUE);
3484 /* special cases :- */
3485 /* if I can do an decrement instead
3486 of subtract then GOOD for ME */
3487 if (genMinusDec (ic) == TRUE)
3490 size = getDataSize (IC_RESULT (ic));
3493 leftOp = AOP(IC_LEFT(ic));
3494 rightOp = AOP(IC_RIGHT(ic));
3498 if (IS_AOP_A (rightOp))
3500 loadRegFromAop ( hc08_reg_a, rightOp, offset);
3501 accopWithAop (sub, leftOp, offset);
3502 accopWithMisc ("nega", "");
3503 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3509 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3510 accopWithAop (sub, rightOp, offset);
3511 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3516 // adjustArithmeticResult (ic);
3519 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3520 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3521 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3526 /*-----------------------------------------------------------------*/
3527 /* genMultOneByte : 8*8=8/16 bit multiplication */
3528 /*-----------------------------------------------------------------*/
3530 genMultOneByte (operand * left,
3534 /* sym_link *opetype = operandType (result); */
3535 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3536 int size=AOP_SIZE(result);
3537 bool negLiteral = FALSE;
3538 bool lUnsigned, rUnsigned;
3540 D(emitcode ("; genMultOneByte",""));
3542 if (size<1 || size>2) {
3543 // this should never happen
3544 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3545 AOP_SIZE(result), __FILE__, lineno);
3549 /* (if two literals: the value is computed before) */
3550 /* if one literal, literal on the right */
3551 if (AOP_TYPE (left) == AOP_LIT)
3557 /* if an operand is in A, make sure it is on the left */
3558 if (IS_AOP_A (AOP (right)))
3565 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3566 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3568 /* lUnsigned rUnsigned negLiteral negate case */
3569 /* false false false odd 3 */
3570 /* false false true even 3 */
3571 /* false true false odd 3 */
3572 /* false true true impossible */
3573 /* true false false odd 3 */
3574 /* true false true always 2 */
3575 /* true true false never 1 */
3576 /* true true true impossible */
3580 || (lUnsigned && rUnsigned))
3582 // just an unsigned 8*8=8/16 multiply
3583 //DD(emitcode (";","unsigned"));
3585 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3586 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3587 emitcode ("mul", "");
3588 hc08_dirtyReg (hc08_reg_xa, FALSE);
3589 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3590 hc08_freeReg (hc08_reg_xa);
3595 // we have to do a signed multiply
3598 /* left unsigned, right signed literal -- literal determines sign handling */
3599 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3601 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3603 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3605 emitcode ("ldx", "#0x%02x", -val);
3607 emitcode ("ldx", "#0x%02x", val);
3609 emitcode ("mul", "");
3613 rmwWithReg ("neg", hc08_reg_a);
3614 tlbl4 = newiTempLabel (NULL);
3615 emitBranch ("bcc", tlbl4);
3616 rmwWithReg ("inc", hc08_reg_x);
3618 rmwWithReg ("neg", hc08_reg_x);
3621 hc08_dirtyReg (hc08_reg_xa, FALSE);
3622 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3623 hc08_freeReg (hc08_reg_xa);
3630 emitcode ("clr", "1,s");
3632 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3635 tlbl1 = newiTempLabel (NULL);
3636 emitcode ("tsta","");
3637 emitBranch ("bpl", tlbl1);
3638 emitcode ("inc", "1,s");
3639 rmwWithReg ("neg", hc08_reg_a);
3643 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3645 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3646 /* AND literal negative */
3648 emitcode ("ldx", "#0x%02x", -val);
3651 emitcode ("ldx", "#0x%02x", val);
3653 hc08_useReg (hc08_reg_x);
3657 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3660 tlbl2 = newiTempLabel (NULL);
3661 emitcode ("tstx", "");
3662 emitBranch ("bpl", tlbl2);
3663 emitcode ("inc", "1,s");
3664 rmwWithReg ("neg", hc08_reg_x);
3669 emitcode ("mul", "");
3670 hc08_dirtyReg (hc08_reg_xa, FALSE);
3672 tlbl3 = newiTempLabel (NULL);
3673 emitcode ("dec", "1,s");
3674 if (!lUnsigned && !rUnsigned && negLiteral)
3675 emitBranch ("beq", tlbl3);
3677 emitBranch ("bne", tlbl3);
3679 rmwWithReg ("neg", hc08_reg_a);
3680 tlbl4 = newiTempLabel (NULL);
3681 emitBranch ("bcc", tlbl4);
3682 rmwWithReg ("inc", hc08_reg_x);
3684 rmwWithReg ("neg", hc08_reg_x);
3688 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3689 hc08_freeReg (hc08_reg_xa);
3693 /*-----------------------------------------------------------------*/
3694 /* genMult - generates code for multiplication */
3695 /*-----------------------------------------------------------------*/
3697 genMult (iCode * ic)
3699 operand *left = IC_LEFT (ic);
3700 operand *right = IC_RIGHT (ic);
3701 operand *result = IC_RESULT (ic);
3703 D(emitcode ("; genMult",""));
3705 /* assign the amsops */
3706 aopOp (left, ic, FALSE);
3707 aopOp (right, ic, FALSE);
3708 aopOp (result, ic, TRUE);
3710 /* special cases first */
3711 /* if both are of size == 1 */
3712 // if (getSize(operandType(left)) == 1 &&
3713 // getSize(operandType(right)) == 1)
3714 if (AOP_SIZE (left) == 1 &&
3715 AOP_SIZE (right) == 1)
3717 genMultOneByte (left, right, result);
3721 /* should have been converted to function call */
3722 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3723 getSize(OP_SYMBOL(right)->type));
3724 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3729 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3730 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3731 freeAsmop (result, NULL, ic, TRUE);
3734 /*-----------------------------------------------------------------*/
3735 /* genDivOneByte : 8 bit division */
3736 /*-----------------------------------------------------------------*/
3738 genDivOneByte (operand * left,
3742 symbol *tlbl1, *tlbl2, *tlbl3;
3745 bool lUnsigned, rUnsigned;
3746 bool runtimeSign, compiletimeSign;
3748 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3749 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3751 D(emitcode ("; genDivOneByte",""));
3753 size = AOP_SIZE (result);
3754 /* signed or unsigned */
3755 if (lUnsigned && rUnsigned)
3757 /* unsigned is easy */
3758 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3759 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3760 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3761 emitcode ("div", "");
3762 hc08_dirtyReg (hc08_reg_a, FALSE);
3763 hc08_dirtyReg (hc08_reg_h, FALSE);
3764 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3765 hc08_freeReg (hc08_reg_a);
3766 hc08_freeReg (hc08_reg_x);
3767 hc08_freeReg (hc08_reg_h);
3771 /* signed is a little bit more difficult */
3773 /* now sign adjust for both left & right */
3775 /* let's see what's needed: */
3776 /* apply negative sign during runtime */
3777 runtimeSign = FALSE;
3778 /* negative sign from literals */
3779 compiletimeSign = FALSE;
3783 if (AOP_TYPE(left) == AOP_LIT)
3785 /* signed literal */
3786 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3788 compiletimeSign = TRUE;
3791 /* signed but not literal */
3797 if (AOP_TYPE(right) == AOP_LIT)
3799 /* signed literal */
3800 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3802 compiletimeSign ^= TRUE;
3805 /* signed but not literal */
3809 /* initialize the runtime sign */
3812 if (compiletimeSign)
3813 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3815 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3816 pushReg (hc08_reg_x, TRUE);
3819 /* save the signs of the operands */
3820 if (AOP_TYPE(right) == AOP_LIT)
3822 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3824 if (!rUnsigned && val < 0)
3825 emitcode ("ldx", "#0x%02x", -val);
3827 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3829 else /* ! literal */
3831 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3834 tlbl1 = newiTempLabel (NULL);
3835 emitcode ("tstx", "");
3836 emitBranch ("bpl", tlbl1);
3837 emitcode ("inc", "1,s");
3838 rmwWithReg ("neg", hc08_reg_x);
3843 if (AOP_TYPE(left) == AOP_LIT)
3845 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3847 if (!lUnsigned && val < 0)
3848 emitcode ("lda", "#0x%02x", -val);
3850 emitcode ("lda", "#0x%02x", (unsigned char) val);
3852 else /* ! literal */
3854 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3857 tlbl2 = newiTempLabel (NULL);
3858 emitcode ("tsta", "");
3859 emitBranch ("bpl", tlbl2);
3860 emitcode ("inc", "1,s");
3861 rmwWithReg ("neg", hc08_reg_a);
3866 loadRegFromConst (hc08_reg_h, zero);
3867 emitcode ("div", "");
3868 hc08_dirtyReg (hc08_reg_x, FALSE);
3869 hc08_dirtyReg (hc08_reg_a, FALSE);
3870 hc08_dirtyReg (hc08_reg_h, FALSE);
3872 if (runtimeSign || compiletimeSign)
3874 tlbl3 = newiTempLabel (NULL);
3877 pullReg (hc08_reg_x);
3878 rmwWithReg ("lsr", hc08_reg_x);
3879 rmwWithReg ("ror", hc08_reg_x);
3880 emitBranch ("bpl", tlbl3);
3883 rmwWithReg ("neg", hc08_reg_a);
3887 storeRegToAop (hc08_reg_a, AOP (result), 0);
3891 /* msb is 0x00 or 0xff depending on the sign */
3894 rmwWithReg ("lsl", hc08_reg_x);
3895 emitcode ("clra", "");
3896 emitcode ("sbc", "#0");
3898 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3900 else /* compiletimeSign */
3902 storeConstToAop ("#0xff", AOP (result), ++offset);
3907 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3910 hc08_freeReg (hc08_reg_a);
3911 hc08_freeReg (hc08_reg_x);
3912 hc08_freeReg (hc08_reg_h);
3915 /*-----------------------------------------------------------------*/
3916 /* genDiv - generates code for division */
3917 /*-----------------------------------------------------------------*/
3921 operand *left = IC_LEFT (ic);
3922 operand *right = IC_RIGHT (ic);
3923 operand *result = IC_RESULT (ic);
3925 D(emitcode ("; genDiv",""));
3927 /* assign the amsops */
3928 aopOp (left, ic, FALSE);
3929 aopOp (right, ic, FALSE);
3930 aopOp (result, ic, TRUE);
3932 /* special cases first */
3933 /* if both are of size == 1 */
3934 if (AOP_SIZE (left) <= 2 &&
3935 AOP_SIZE (right) == 1)
3937 genDivOneByte (left, right, result);
3941 /* should have been converted to function call */
3944 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3945 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3946 freeAsmop (result, NULL, ic, TRUE);
3949 /*-----------------------------------------------------------------*/
3950 /* genModOneByte : 8 bit modulus */
3951 /*-----------------------------------------------------------------*/
3953 genModOneByte (operand * left,
3957 symbol *tlbl1, *tlbl2, *tlbl3;
3960 bool lUnsigned, rUnsigned;
3961 bool runtimeSign, compiletimeSign;
3963 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3964 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3966 D(emitcode ("; genModOneByte",""));
3968 size = AOP_SIZE (result);
3970 if (lUnsigned && rUnsigned)
3972 /* unsigned is easy */
3973 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3974 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3975 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3976 emitcode ("div", "");
3977 hc08_freeReg (hc08_reg_a);
3978 hc08_freeReg (hc08_reg_x);
3979 hc08_dirtyReg (hc08_reg_h, FALSE);
3980 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3981 hc08_freeReg (hc08_reg_h);
3985 /* signed is a little bit more difficult */
3987 if (AOP_TYPE(right) == AOP_LIT)
3989 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3991 if (!rUnsigned && val < 0)
3992 emitcode ("ldx", "#0x%02x", -val);
3994 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3996 else /* ! literal */
3998 loadRegFromAop (hc08_reg_x, AOP (right), 0);
4001 tlbl1 = newiTempLabel (NULL);
4002 emitcode ("tstx", "");
4003 emitBranch ("bpl", tlbl1);
4004 rmwWithReg ("neg", hc08_reg_x);
4009 /* let's see what's needed: */
4010 /* apply negative sign during runtime */
4011 runtimeSign = FALSE;
4012 /* negative sign from literals */
4013 compiletimeSign = FALSE;
4015 /* sign adjust left side */
4016 if (AOP_TYPE(left) == AOP_LIT)
4018 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4020 if (!lUnsigned && val < 0)
4022 compiletimeSign = TRUE; /* set sign flag */
4023 emitcode ("lda", "#0x%02x", -val);
4026 emitcode ("lda", "#0x%02x", (unsigned char) val);
4028 else /* ! literal */
4031 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4036 emitcode ("clr", "1,s");
4038 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4039 tlbl2 = newiTempLabel (NULL);
4040 emitcode ("tsta", "");
4041 emitBranch ("bpl", tlbl2);
4042 emitcode ("inc", "1,s");
4043 rmwWithReg ("neg", hc08_reg_a);
4048 loadRegFromConst (hc08_reg_h, zero);
4049 emitcode ("div", "");
4050 hc08_freeReg (hc08_reg_a);
4051 hc08_freeReg (hc08_reg_x);
4052 hc08_dirtyReg (hc08_reg_h, FALSE);
4054 if (runtimeSign || compiletimeSign)
4056 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4057 tlbl3 = newiTempLabel (NULL);
4060 pullReg (hc08_reg_x);
4061 rmwWithReg ("lsr", hc08_reg_x);
4062 rmwWithReg ("ror", hc08_reg_x);
4063 emitBranch ("bpl", tlbl3);
4066 rmwWithReg ("neg", hc08_reg_a);
4070 storeRegToAop (hc08_reg_a, AOP (result), 0);
4074 /* msb is 0x00 or 0xff depending on the sign */
4077 rmwWithReg ("lsl", hc08_reg_x);
4078 emitcode ("clra", "");
4079 emitcode ("sbc", "#0");
4081 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4083 else /* compiletimeSign */
4085 storeConstToAop ("#0xff", AOP (result), ++offset);
4090 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4093 hc08_freeReg (hc08_reg_a);
4094 hc08_freeReg (hc08_reg_x);
4095 hc08_freeReg (hc08_reg_h);
4098 /*-----------------------------------------------------------------*/
4099 /* genMod - generates code for division */
4100 /*-----------------------------------------------------------------*/
4104 operand *left = IC_LEFT (ic);
4105 operand *right = IC_RIGHT (ic);
4106 operand *result = IC_RESULT (ic);
4108 D(emitcode ("; genMod",""));
4110 /* assign the amsops */
4111 aopOp (left, ic, FALSE);
4112 aopOp (right, ic, FALSE);
4113 aopOp (result, ic, TRUE);
4115 /* special cases first */
4116 /* if both are of size == 1 */
4117 if (AOP_SIZE (left) <= 2 &&
4118 AOP_SIZE (right) == 1)
4120 genModOneByte (left, right, result);
4124 /* should have been converted to function call */
4128 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4129 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4130 freeAsmop (result, NULL, ic, TRUE);
4133 /*-----------------------------------------------------------------*/
4134 /* genIfxJump :- will create a jump depending on the ifx */
4135 /*-----------------------------------------------------------------*/
4137 genIfxJump (iCode * ic, char *jval)
4140 symbol *tlbl = newiTempLabel (NULL);
4143 D(emitcode ("; genIfxJump",""));
4145 /* if true label then we jump if condition
4149 jlbl = IC_TRUE (ic);
4150 if (!strcmp (jval, "a"))
4152 else if (!strcmp (jval, "c"))
4159 /* false label is present */
4160 jlbl = IC_FALSE (ic);
4161 if (!strcmp (jval, "a"))
4163 else if (!strcmp (jval, "c"))
4168 emitBranch (inst, tlbl);
4169 emitBranch ("jmp", jlbl);
4172 /* mark the icode as generated */
4177 /*-----------------------------------------------------------------*/
4178 /* exchangedCmp : returns the opcode need if the two operands are */
4179 /* exchanged in a comparison */
4180 /*-----------------------------------------------------------------*/
4182 exchangedCmp (int opcode)
4199 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4200 "opcode not a comparison");
4202 return EQ_OP; /* shouldn't happen, but need to return something */
4205 /*------------------------------------------------------------------*/
4206 /* negatedCmp : returns the equivalent opcode for when a comparison */
4208 /*------------------------------------------------------------------*/
4210 negatedCmp (int opcode)
4227 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4228 "opcode not a comparison");
4230 return EQ_OP; /* shouldn't happen, but need to return something */
4233 /* compile only if the debugging macro D is enabled */
4236 nameCmp (int opcode)
4258 /*------------------------------------------------------------------*/
4259 /* branchInstCmp : returns the conditional branch instruction that */
4260 /* will branch if the comparison is true */
4261 /*------------------------------------------------------------------*/
4263 branchInstCmp (int opcode, int sign)
4271 return "bcs"; /* same as blo */
4286 return "bcc"; /* same as bhs */
4292 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4293 "opcode not a comparison");
4299 /*------------------------------------------------------------------*/
4300 /* genCmp :- greater or less than (and maybe with equal) comparison */
4301 /*------------------------------------------------------------------*/
4303 genCmp (iCode * ic, iCode * ifx)
4305 operand *left, *right, *result;
4306 sym_link *letype, *retype;
4308 int size, offset = 0;
4309 unsigned long lit = 0L;
4311 symbol *jlbl = NULL;
4315 D(emitcode ("; genCmp", "(%s)",nameCmp (opcode)));
4317 result = IC_RESULT (ic);
4318 left = IC_LEFT (ic);
4319 right = IC_RIGHT (ic);
4321 letype = getSpec (operandType (left));
4322 retype = getSpec (operandType (right));
4323 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4324 /* assign the amsops */
4325 aopOp (left, ic, FALSE);
4326 aopOp (right, ic, FALSE);
4327 aopOp (result, ic, TRUE);
4329 /* need register operand on left, prefer literal operand on right */
4330 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4332 operand *temp = left;
4335 opcode = exchangedCmp (opcode);
4342 jlbl = IC_TRUE (ifx);
4343 opcode = negatedCmp (opcode);
4347 /* false label is present */
4348 jlbl = IC_FALSE (ifx);
4352 size = max (AOP_SIZE (left), AOP_SIZE (right));
4355 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4356 && ((AOP_TYPE (right) == AOP_LIT) ||
4357 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4358 && hc08_reg_hx->isFree)
4360 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4361 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4362 hc08_freeReg (hc08_reg_hx);
4373 /* These conditions depend on the Z flag bit, but Z is */
4374 /* only valid for the last byte of the comparison, not */
4375 /* the whole value. So exchange the operands to get a */
4376 /* comparison that doesn't depend on Z. (This is safe */
4377 /* to do here since ralloc won't assign multi-byte */
4378 /* operands to registers for comparisons) */
4379 if ((opcode == '>') || (opcode == LE_OP))
4381 operand *temp = left;
4384 opcode = exchangedCmp (opcode);
4387 if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
4389 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4390 while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
4399 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4400 accopWithAop (sub, AOP (right), offset);
4401 hc08_freeReg (hc08_reg_a);
4406 freeAsmop (right, NULL, ic, FALSE);
4407 freeAsmop (left, NULL, ic, FALSE);
4411 symbol *tlbl = newiTempLabel (NULL);
4414 freeAsmop (result, NULL, ic, TRUE);
4416 inst = branchInstCmp (opcode, sign);
4417 emitBranch (inst, tlbl);
4418 emitBranch ("jmp", jlbl);
4421 /* mark the icode as generated */
4426 symbol *tlbl1 = newiTempLabel (NULL);
4427 symbol *tlbl2 = newiTempLabel (NULL);
4429 emitBranch (branchInstCmp (opcode, sign), tlbl1);
4430 loadRegFromConst (hc08_reg_a, zero);
4431 emitBranch ("bra", tlbl2);
4433 loadRegFromConst (hc08_reg_a, one);
4435 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4436 freeAsmop (result, NULL, ic, TRUE);
4441 /*-----------------------------------------------------------------*/
4442 /* genCmpEQorNE - equal or not equal comparison */
4443 /*-----------------------------------------------------------------*/
4445 genCmpEQorNE (iCode * ic, iCode * ifx)
4447 operand *left, *right, *result;
4448 sym_link *letype, *retype;
4450 int size, offset = 0;
4452 symbol *jlbl = NULL;
4453 symbol *tlbl_NE = NULL;
4454 symbol *tlbl_EQ = NULL;
4458 D(emitcode ("; genCmpEQorNE", "(%s)",nameCmp (opcode)));
4460 result = IC_RESULT (ic);
4461 left = IC_LEFT (ic);
4462 right = IC_RIGHT (ic);
4464 letype = getSpec (operandType (left));
4465 retype = getSpec (operandType (right));
4466 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4467 /* assign the amsops */
4468 aopOp (left, ic, FALSE);
4469 aopOp (right, ic, FALSE);
4470 aopOp (result, ic, TRUE);
4472 /* need register operand on left, prefer literal operand on right */
4473 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4475 operand *temp = left;
4478 opcode = exchangedCmp (opcode);
4485 jlbl = IC_TRUE (ifx);
4486 opcode = negatedCmp (opcode);
4490 /* false label is present */
4491 jlbl = IC_FALSE (ifx);
4495 size = max (AOP_SIZE (left), AOP_SIZE (right));
4498 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4499 && ((AOP_TYPE (right) == AOP_LIT) ||
4500 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4501 && hc08_reg_hx->isFree)
4503 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4504 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4505 hc08_freeReg (hc08_reg_hx);
4513 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4514 accopWithAop (sub, AOP (right), offset);
4518 tlbl_NE = newiTempLabel (NULL);
4519 emitBranch ("bne", tlbl_NE);
4521 hc08_freeReg (hc08_reg_a);
4525 freeAsmop (right, NULL, ic, FALSE);
4526 freeAsmop (left, NULL, ic, FALSE);
4530 freeAsmop (result, NULL, ic, TRUE);
4532 if (opcode == EQ_OP)
4535 tlbl_EQ = newiTempLabel (NULL);
4536 emitBranch ("beq", tlbl_EQ);
4538 emitLabel (tlbl_NE);
4539 emitBranch ("jmp", jlbl);
4540 emitLabel (tlbl_EQ);
4545 tlbl_NE = newiTempLabel (NULL);
4546 emitBranch ("bne", tlbl_NE);
4547 emitBranch ("jmp", jlbl);
4548 emitLabel (tlbl_NE);
4551 /* mark the icode as generated */
4556 symbol *tlbl = newiTempLabel (NULL);
4558 if (opcode == EQ_OP)
4561 tlbl_EQ = newiTempLabel (NULL);
4562 emitBranch ("beq", tlbl_EQ);
4564 emitLabel (tlbl_NE);
4565 loadRegFromConst (hc08_reg_a, zero);
4566 emitBranch ("bra", tlbl);
4567 emitLabel (tlbl_EQ);
4568 loadRegFromConst (hc08_reg_a, one);
4573 tlbl_NE = newiTempLabel (NULL);
4574 emitBranch ("bne", tlbl_NE);
4575 loadRegFromConst (hc08_reg_a, zero);
4576 emitBranch ("bra", tlbl);
4577 emitLabel (tlbl_NE);
4578 loadRegFromConst (hc08_reg_a, one);
4582 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4583 freeAsmop (result, NULL, ic, TRUE);
4589 /*-----------------------------------------------------------------*/
4590 /* ifxForOp - returns the icode containing the ifx for operand */
4591 /*-----------------------------------------------------------------*/
4593 ifxForOp (operand * op, iCode * ic)
4595 /* if true symbol then needs to be assigned */
4596 if (IS_TRUE_SYMOP (op))
4599 /* if this has register type condition and
4600 the next instruction is ifx with the same operand
4601 and live to of the operand is upto the ifx only then */
4603 ic->next->op == IFX &&
4604 IC_COND (ic->next)->key == op->key &&
4605 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4612 genPointerGetSetOfs (iCode *ic)
4614 iCode *lic = ic->next;
4620 /* Make sure we have a next iCode */
4621 DD(emitcode("","; checking lic"));
4625 /* Make sure the result of the addition is an iCode */
4626 DD(emitcode("","; checking IS_ITEMP"));
4627 if (!IS_ITEMP (IC_RESULT (ic)))
4630 /* Make sure the next iCode is a pointer set or get */
4631 pset = POINTER_SET(lic);
4632 pget = POINTER_GET(lic);
4633 DD(emitcode("","; pset=%d, pget=%d",pset,pget));
4637 /* Make sure this is the only use of the pointer */
4638 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4641 DD(emitcode("", "; checking pset operandsEqu"));
4642 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4645 DD(emitcode("", "; checking pget operandsEqu"));
4646 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4649 DD(emitcode("", "; checking IS_SYMOP"));
4650 if (!IS_SYMOP (IC_LEFT (ic)))
4653 DD(emitcode("", "; checking !IS_TRUE_SYMOP"));
4654 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4657 sym = OP_SYMBOL (IC_LEFT (ic));
4659 DD(emitcode("", "; checking remat"));
4666 D(emitcode ("; genPointerGetOfs",""));
4667 aopOp (IC_LEFT(ic), ic, FALSE);
4668 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4669 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4671 aopOp (IC_RIGHT(ic), ic, FALSE);
4672 aopOp (IC_RESULT(lic), lic, FALSE);
4674 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4676 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4678 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4679 loadRegFromConst (hc08_reg_h, zero);
4683 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4684 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4685 emitcode ("rola","");
4686 emitcode ("clra","");
4687 emitcode ("sbc", "#0");
4688 hc08_useReg (hc08_reg_a);
4689 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4693 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4694 size = AOP_SIZE (IC_RESULT(lic));
4695 derefaop->size = size;
4699 emitcode ("lda", "%s,x",
4700 aopAdrStr (derefaop, size, TRUE));
4701 hc08_useReg (hc08_reg_a);
4702 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
4703 hc08_freeReg (hc08_reg_a);
4707 hc08_freeReg (hc08_reg_hx);
4709 freeAsmop (NULL, derefaop, ic, TRUE);
4710 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4711 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4718 D(emitcode ("; genPointerSetOfs",""));
4719 aopOp (IC_LEFT(ic), ic, FALSE);
4720 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4721 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4723 aopOp (IC_RIGHT(ic), ic, FALSE);
4724 aopOp (IC_RIGHT(lic), lic, FALSE);
4726 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4728 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4730 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4731 loadRegFromConst (hc08_reg_h, zero);
4735 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4736 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4737 emitcode ("rola","");
4738 emitcode ("clra","");
4739 emitcode ("sbc", "#0");
4740 hc08_useReg (hc08_reg_a);
4741 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4745 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4746 size = AOP_SIZE (IC_RIGHT(lic));
4747 derefaop->size = size;
4751 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
4752 emitcode ("sta", "%s,x",
4753 aopAdrStr (derefaop, size, TRUE));
4754 hc08_freeReg (hc08_reg_a);
4758 hc08_freeReg (hc08_reg_hx);
4760 freeAsmop (NULL, derefaop, ic, TRUE);
4761 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4762 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4771 /*-----------------------------------------------------------------*/
4772 /* hasInc - operand is incremented before any other use */
4773 /*-----------------------------------------------------------------*/
4775 hasInc (operand *op, iCode *ic,int osize)
4777 sym_link *type = operandType(op);
4778 sym_link *retype = getSpec (type);
4779 iCode *lic = ic->next;
4782 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4783 if (!IS_SYMOP(op)) return NULL;
4785 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4786 if (IS_AGGREGATE(type->next)) return NULL;
4787 if (osize != (isize = getSize(type->next))) return NULL;
4790 /* if operand of the form op = op + <sizeof *op> */
4791 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4792 isOperandEqual(IC_RESULT(lic),op) &&
4793 isOperandLiteral(IC_RIGHT(lic)) &&
4794 operandLitValue(IC_RIGHT(lic)) == isize) {
4797 /* if the operand used or deffed */
4798 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
4801 /* if GOTO or IFX */
4802 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4808 /*-----------------------------------------------------------------*/
4809 /* genAndOp - for && operation */
4810 /*-----------------------------------------------------------------*/
4812 genAndOp (iCode * ic)
4814 operand *left, *right, *result;
4815 symbol *tlbl, *tlbl0;
4817 D(emitcode ("; genAndOp",""));
4819 /* note here that && operations that are in an
4820 if statement are taken away by backPatchLabels
4821 only those used in arthmetic operations remain */
4822 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4823 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4824 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4826 tlbl = newiTempLabel (NULL);
4827 tlbl0 = newiTempLabel (NULL);
4829 asmopToBool (AOP (left), FALSE);
4830 emitBranch ("beq", tlbl0);
4831 asmopToBool (AOP (right), FALSE);
4832 emitBranch ("beq", tlbl0);
4833 loadRegFromConst (hc08_reg_a,one);
4834 emitBranch ("bra", tlbl);
4836 loadRegFromConst (hc08_reg_a,zero);
4839 hc08_useReg (hc08_reg_a);
4840 hc08_freeReg (hc08_reg_a);
4842 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4844 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4845 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4846 freeAsmop (result, NULL, ic, TRUE);
4850 /*-----------------------------------------------------------------*/
4851 /* genOrOp - for || operation */
4852 /*-----------------------------------------------------------------*/
4854 genOrOp (iCode * ic)
4856 operand *left, *right, *result;
4857 symbol *tlbl, *tlbl0;
4859 D(emitcode ("; genOrOp",""));
4861 /* note here that || operations that are in an
4862 if statement are taken away by backPatchLabels
4863 only those used in arthmetic operations remain */
4864 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4865 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4866 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4868 tlbl = newiTempLabel (NULL);
4869 tlbl0 = newiTempLabel (NULL);
4871 asmopToBool (AOP (left), FALSE);
4872 emitBranch ("bne", tlbl0);
4873 asmopToBool (AOP (right), FALSE);
4874 emitBranch ("bne", tlbl0);
4875 loadRegFromConst (hc08_reg_a,zero);
4876 emitBranch ("bra", tlbl);
4878 loadRegFromConst (hc08_reg_a,one);
4881 hc08_useReg (hc08_reg_a);
4882 hc08_freeReg (hc08_reg_a);
4884 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4887 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4888 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4889 freeAsmop (result, NULL, ic, TRUE);
4892 /*-----------------------------------------------------------------*/
4893 /* isLiteralBit - test if lit == 2^n */
4894 /*-----------------------------------------------------------------*/
4896 isLiteralBit (unsigned long lit)
4898 unsigned long pw[32] =
4899 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4900 0x100L, 0x200L, 0x400L, 0x800L,
4901 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4902 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4903 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4904 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4905 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4908 for (idx = 0; idx < 32; idx++)
4915 /*-----------------------------------------------------------------*/
4916 /* continueIfTrue - */
4917 /*-----------------------------------------------------------------*/
4919 continueIfTrue (iCode * ic)
4922 emitBranch ("jmp", IC_TRUE (ic));
4926 /*-----------------------------------------------------------------*/
4928 /*-----------------------------------------------------------------*/
4930 jumpIfTrue (iCode * ic)
4933 emitBranch ("jmp", IC_FALSE (ic));
4937 /*-----------------------------------------------------------------*/
4938 /* jmpTrueOrFalse - */
4939 /*-----------------------------------------------------------------*/
4941 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4943 // ugly but optimized by peephole
4946 symbol *nlbl = newiTempLabel (NULL);
4947 emitBranch ("bra", nlbl);
4949 emitBranch ("jmp", IC_TRUE (ic));
4954 emitBranch ("jmp", IC_FALSE (ic));
4961 /*-----------------------------------------------------------------*/
4962 /* genAnd - code for and */
4963 /*-----------------------------------------------------------------*/
4965 genAnd (iCode * ic, iCode * ifx)
4967 operand *left, *right, *result;
4968 int size, offset = 0;
4969 unsigned long lit = 0L;
4970 unsigned long litinv;
4971 unsigned char bytemask;
4977 D(emitcode ("; genAnd",""));
4979 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4980 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4981 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4984 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4986 AOP_TYPE (left), AOP_TYPE (right)));
4987 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4989 AOP_SIZE (left), AOP_SIZE (right)));
4992 /* if left is a literal & right is not then exchange them */
4993 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4995 operand *tmp = right;
5000 /* if right is accumulator & left is not then exchange them */
5001 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5003 operand *tmp = right;
5008 if (AOP_TYPE (right) == AOP_LIT)
5009 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5011 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5013 if (AOP_TYPE (result) == AOP_CRY
5015 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5017 /* this generates ugly code, but meets volatility requirements */
5018 loadRegFromConst (hc08_reg_a, zero);
5019 pushReg (hc08_reg_a, TRUE);
5024 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5025 accopWithAop ("and", AOP (right), offset);
5026 emitcode ("ora", "1,s");
5027 emitcode ("sta", "1,s");
5031 pullReg (hc08_reg_a);
5032 emitcode ("tsta", "");
5033 genIfxJump (ifx, "a");
5037 if (AOP_TYPE (result) == AOP_CRY)
5039 symbol *tlbl = NULL;
5040 wassertl (ifx, "AOP_CRY result without ifx");
5045 bytemask = (lit >> (offset*8)) & 0xff;
5047 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5051 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5053 rmwWithAop ("tst", AOP (left), offset);
5057 tlbl = newiTempLabel (NULL);
5058 emitBranch ("bne", tlbl);
5063 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5064 accopWithAop ("and", AOP (right), offset);
5065 hc08_freeReg( hc08_reg_a);
5069 tlbl = newiTempLabel (NULL);
5070 emitBranch ("bne", tlbl);
5077 genIfxJump (ifx, "a");
5081 size = AOP_SIZE (result);
5083 if (AOP_TYPE (right) == AOP_LIT)
5085 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
5086 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5087 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
5089 int bitpos = isLiteralBit(litinv)-1;
5090 emitcode ("bclr","#%d,%s",bitpos & 7,
5091 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5099 bytemask = (lit >> (offset*8)) & 0xff;
5101 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5103 if (isOperandVolatile (left, FALSE))
5105 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5106 hc08_freeReg( hc08_reg_a);
5108 storeConstToAop (zero, AOP (result), offset);
5110 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5112 transferAopAop (AOP (left), offset, AOP (result), offset);
5116 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5117 accopWithAop ("and", AOP (right), offset);
5118 storeRegToAop (hc08_reg_a, AOP (result), offset);
5119 hc08_freeReg (hc08_reg_a);
5125 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5126 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5127 freeAsmop (result, NULL, ic, TRUE);
5130 /*-----------------------------------------------------------------*/
5131 /* genOr - code for or */
5132 /*-----------------------------------------------------------------*/
5134 genOr (iCode * ic, iCode * ifx)
5136 operand *left, *right, *result;
5137 int size, offset = 0;
5138 unsigned long lit = 0L;
5139 unsigned char bytemask;
5141 D(emitcode ("; genOr",""));
5143 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5144 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5145 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5148 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5150 AOP_TYPE (left), AOP_TYPE (right)));
5151 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5153 AOP_SIZE (left), AOP_SIZE (right)));
5156 /* if left is a literal & right is not then exchange them */
5157 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5159 operand *tmp = right;
5164 /* if left is accumulator & right is not then exchange them */
5165 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5167 operand *tmp = right;
5172 if (AOP_TYPE (right) == AOP_LIT)
5173 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5175 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5177 if (AOP_TYPE (result) == AOP_CRY
5179 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5181 /* this generates ugly code, but meets volatility requirements */
5182 loadRegFromConst (hc08_reg_a, zero);
5183 pushReg (hc08_reg_a, TRUE);
5188 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5189 accopWithAop ("ora", AOP (right), offset);
5190 emitcode ("ora", "1,s");
5191 emitcode ("sta", "1,s");
5195 pullReg (hc08_reg_a);
5196 emitcode ("tsta", "");
5197 genIfxJump (ifx, "a");
5201 if (AOP_TYPE (result) == AOP_CRY)
5203 symbol *tlbl = NULL;
5204 wassertl (ifx, "AOP_CRY result without ifx");
5209 bytemask = (lit >> (offset*8)) & 0xff;
5211 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5213 rmwWithAop ("tst", AOP (left), offset);
5217 tlbl = newiTempLabel (NULL);
5218 emitBranch ("bne", tlbl);
5223 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5224 accopWithAop ("ora", AOP (right), offset);
5225 hc08_freeReg( hc08_reg_a);
5229 tlbl = newiTempLabel (NULL);
5230 emitBranch ("bne", tlbl);
5237 genIfxJump (ifx, "a");
5240 if (AOP_TYPE (right) == AOP_LIT)
5241 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5243 size = AOP_SIZE (result);
5245 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5246 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5247 (AOP_TYPE (left) == AOP_DIR))
5249 int bitpos = isLiteralBit(lit)-1;
5250 emitcode ("bset","#%d,%s",bitpos & 7,
5251 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5258 bytemask = (lit >> (offset*8)) & 0xff;
5260 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5262 if (isOperandVolatile (left, FALSE))
5264 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5265 hc08_freeReg( hc08_reg_a);
5267 transferAopAop (AOP (right), offset, AOP (result), offset);
5269 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5271 transferAopAop (AOP (left), offset, AOP (result), offset);
5275 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5276 accopWithAop ("ora", AOP (right), offset);
5277 storeRegToAop (hc08_reg_a, AOP (result), offset);
5278 hc08_freeReg (hc08_reg_a);
5285 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5286 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5287 freeAsmop (result, NULL, ic, TRUE);
5290 /*-----------------------------------------------------------------*/
5291 /* genXor - code for xclusive or */
5292 /*-----------------------------------------------------------------*/
5294 genXor (iCode * ic, iCode * ifx)
5296 operand *left, *right, *result;
5297 int size, offset = 0;
5298 unsigned long lit = 0L;
5300 D(emitcode ("; genXor",""));
5302 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5303 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5304 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5307 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5309 AOP_TYPE (left), AOP_TYPE (right)));
5310 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5312 AOP_SIZE (left), AOP_SIZE (right)));
5315 /* if left is a literal & right is not ||
5316 if left needs acc & right does not */
5317 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5319 operand *tmp = right;
5324 /* if left is accumulator & right is not then exchange them */
5325 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5327 operand *tmp = right;
5332 if (AOP_TYPE (result) == AOP_CRY)
5335 wassertl (ifx, "AOP_CPY result without ifx");
5337 tlbl = newiTempLabel (NULL);
5338 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5342 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5343 if ((AOP_TYPE (right) == AOP_LIT)
5344 && (((lit >> (offset*8)) & 0xff) == 0))
5345 emitcode ("tsta","");
5347 accopWithAop ("eor", AOP (right), offset);
5348 hc08_freeReg( hc08_reg_a);
5350 emitBranch ("bne", tlbl);
5354 genIfxJump (ifx, "a");
5360 if (AOP_TYPE (right) == AOP_LIT)
5361 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5363 size = AOP_SIZE (result);
5367 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5368 accopWithAop ("eor", AOP (right), offset);
5369 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5370 hc08_freeReg( hc08_reg_a);
5374 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5375 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5376 freeAsmop (result, NULL, ic, TRUE);
5380 emitinline (iCode * ic, char *inlin)
5386 symbol *sym, *tempsym;
5395 while (isalnum((unsigned char)*inlin) || (*inlin == '_'))
5399 //printf("Found possible symbol '%s'\n",symname);
5400 tempsym = newSymbol (symname, ic->level);
5401 tempsym->block = ic->block;
5402 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5411 aop = aopForSym (ic, sym, FALSE);
5412 l = aopAdrStr (aop, aop->size - 1, TRUE);
5416 if (sym->level && !sym->allocreq && !sym->ismyparm)
5418 werror (E_ID_UNDEF, sym->name);
5420 " Add 'volatile' to the variable declaration so that it\n"
5421 " can be referenced within inline assembly");
5423 //printf("Replacing with '%s'\n",l);
5427 if ((2+bp-buffer)>sizeof(buffer))
5436 if ((2+bp-buffer)>sizeof(buffer))
5443 if ((2+bp-buffer)>sizeof(buffer))
5444 fprintf(stderr, "Inline assembly buffer overflow\n");
5446 //printf("%s\n",buffer);
5447 emitcode (buffer,"");
5451 /*-----------------------------------------------------------------*/
5452 /* genInline - write the inline code out */
5453 /*-----------------------------------------------------------------*/
5455 genInline (iCode * ic)
5457 char *buffer, *bp, *bp1;
5459 D(emitcode ("; genInline",""));
5461 _G.inLine += (!options.asmpeep);
5463 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5464 strcpy (buffer, IC_INLINE (ic));
5466 /* emit each line as a code */
5472 /* emitcode (bp1, ""); */
5473 emitinline (ic, bp1);
5492 /* emitcode (bp1, ""); */
5493 emitinline (ic, bp1);
5495 /* emitcode("",buffer); */
5496 _G.inLine -= (!options.asmpeep);
5499 /*-----------------------------------------------------------------*/
5500 /* genRRC - rotate right with carry */
5501 /*-----------------------------------------------------------------*/
5505 operand *left, *result;
5506 int size, offset = 0;
5507 bool needpula = FALSE;
5508 bool resultInA = FALSE;
5511 D(emitcode ("; genRRC",""));
5513 /* rotate right with carry */
5514 left = IC_LEFT (ic);
5515 result = IC_RESULT (ic);
5516 aopOp (left, ic, FALSE);
5517 aopOp (result, ic, FALSE);
5519 if ((AOP_TYPE (result) == AOP_REG)
5520 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5523 size = AOP_SIZE (result);
5527 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5531 rmwWithAop (shift, AOP (result), offset--);
5539 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5540 rmwWithReg (shift, hc08_reg_a);
5541 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5542 hc08_freeReg (hc08_reg_a);
5547 if ((!hc08_reg_a->isFree) || resultInA)
5549 pushReg (hc08_reg_a, TRUE);
5553 /* now we need to put the carry into the
5554 highest order byte of the result */
5555 offset = AOP_SIZE (result) - 1;
5556 emitcode ("clra","");
5557 emitcode ("rora","");
5558 hc08_dirtyReg (hc08_reg_a, FALSE);
5561 emitcode ("ora", "1,s");
5562 emitcode ("ais", "#1");
5563 hc08_dirtyReg (hc08_reg_a, FALSE);
5567 accopWithAop ("ora", AOP (result), offset);
5568 storeRegToAop (hc08_reg_a, AOP (result), offset);
5570 pullOrFreeReg (hc08_reg_a, needpula);
5572 freeAsmop (left, NULL, ic, TRUE);
5573 freeAsmop (result, NULL, ic, TRUE);
5576 /*-----------------------------------------------------------------*/
5577 /* genRLC - generate code for rotate left with carry */
5578 /*-----------------------------------------------------------------*/
5582 operand *left, *result;
5583 int size, offset = 0;
5585 bool resultInA = FALSE;
5586 bool needpula = FALSE;
5588 D(emitcode ("; genRLC",""));
5590 /* rotate right with carry */
5591 left = IC_LEFT (ic);
5592 result = IC_RESULT (ic);
5593 aopOp (left, ic, FALSE);
5594 aopOp (result, ic, FALSE);
5596 if ((AOP_TYPE (result) == AOP_REG)
5597 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5600 size = AOP_SIZE (result);
5604 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5608 rmwWithAop (shift, AOP (result), offset--);
5616 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5617 rmwWithReg (shift, hc08_reg_a);
5618 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5619 hc08_freeReg (hc08_reg_a);
5624 if ((!hc08_reg_a->isFree) || resultInA)
5626 pushReg (hc08_reg_a, TRUE);
5630 /* now we need to put the carry into the
5631 lowest order byte of the result */
5633 emitcode ("clra","");
5634 emitcode ("rola","");
5635 hc08_dirtyReg (hc08_reg_a, FALSE);
5638 emitcode ("ora", "1,s");
5639 emitcode ("ais", "#1");
5640 hc08_dirtyReg (hc08_reg_a, FALSE);
5644 accopWithAop ("ora", AOP (result), offset);
5645 storeRegToAop (hc08_reg_a, AOP (result), offset);
5647 pullOrFreeReg (hc08_reg_a, needpula);
5649 freeAsmop (left, NULL, ic, TRUE);
5650 freeAsmop (result, NULL, ic, TRUE);
5653 /*-----------------------------------------------------------------*/
5654 /* genGetHbit - generates code get highest order bit */
5655 /*-----------------------------------------------------------------*/
5657 genGetHbit (iCode * ic)
5659 operand *left, *result;
5661 D(emitcode ("; genGetHbit",""));
5663 left = IC_LEFT (ic);
5664 result = IC_RESULT (ic);
5665 aopOp (left, ic, FALSE);
5666 aopOp (result, ic, FALSE);
5668 /* get the highest order byte into a */
5669 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5670 emitcode ("rola", "");
5671 emitcode ("clra", "");
5672 emitcode ("rola", "");
5673 hc08_dirtyReg (hc08_reg_a, FALSE);
5674 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5675 hc08_freeReg (hc08_reg_a);
5677 freeAsmop (left, NULL, ic, TRUE);
5678 freeAsmop (result, NULL, ic, TRUE);
5681 /*-----------------------------------------------------------------*/
5682 /* genSwap - generates code to swap nibbles or bytes */
5683 /*-----------------------------------------------------------------*/
5685 genSwap (iCode * ic)
5687 operand *left, *result;
5689 D(emitcode ("; genSwap",""));
5691 left = IC_LEFT (ic);
5692 result = IC_RESULT (ic);
5693 aopOp (left, ic, FALSE);
5694 aopOp (result, ic, FALSE);
5696 switch (AOP_SIZE (left))
5698 case 1: /* swap nibbles in byte */
5699 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5700 emitcode ("nsa", "");
5701 hc08_dirtyReg (hc08_reg_a, FALSE);
5702 storeRegToAop (hc08_reg_a, AOP (result), 0);
5703 hc08_freeReg (hc08_reg_a);
5705 case 2: /* swap bytes in a word */
5706 if (operandsEqu (left, result) || sameRegs (AOP (left), AOP (result)))
5708 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5709 hc08_useReg (hc08_reg_a);
5710 transferAopAop (AOP (left), 1, AOP (result), 0);
5711 storeRegToAop (hc08_reg_a, AOP (result), 1);
5712 hc08_freeReg (hc08_reg_a);
5716 transferAopAop (AOP (left), 0, AOP (result), 1);
5717 transferAopAop (AOP (left), 1, AOP (result), 0);
5721 wassertl(FALSE, "unsupported SWAP operand size");
5724 freeAsmop (left, NULL, ic, TRUE);
5725 freeAsmop (result, NULL, ic, TRUE);
5729 /*-----------------------------------------------------------------*/
5730 /* AccRol - rotate left accumulator by known count */
5731 /*-----------------------------------------------------------------*/
5733 AccRol (int shCount)
5735 shCount &= 0x0007; // shCount : 0..7
5742 emitcode ("rola", ""); /* 1 cycle */
5745 emitcode ("rola", ""); /* 1 cycle */
5746 emitcode ("rola", ""); /* 1 cycle */
5749 emitcode ("nsa", "");
5750 emitcode ("rora", "");
5753 emitcode ("nsa", ""); /* 3 cycles */
5756 emitcode ("nsa", ""); /* 3 cycles */
5757 emitcode ("rola", ""); /* 1 cycle */
5760 emitcode ("nsa", ""); /* 3 cycles */
5761 emitcode ("rola", ""); /* 1 cycle */
5762 emitcode ("rola", ""); /* 1 cycle */
5765 emitcode ("nsa", ""); /* 3 cycles */
5766 emitcode ("rola", ""); /* 1 cycle */
5767 emitcode ("rola", ""); /* 1 cycle */
5768 emitcode ("rola", ""); /* 1 cycle */
5775 /*-----------------------------------------------------------------*/
5776 /* AccLsh - left shift accumulator by known count */
5777 /*-----------------------------------------------------------------*/
5779 AccLsh (int shCount)
5783 shCount &= 0x0007; // shCount : 0..7
5785 /* Shift counts of 4 and 5 are currently optimized for code size. */
5786 /* Falling through to the unrolled loop would be optimal for code speed. */
5787 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5791 if (optimize.codeSpeed)
5793 accopWithMisc ("nsa", "");
5794 accopWithMisc ("and", "#0xf0");
5795 /* total: 5 cycles, 3 bytes */
5798 if (optimize.codeSpeed)
5800 accopWithMisc ("nsa", "");
5801 accopWithMisc ("and", "#0xf0");
5802 accopWithMisc ("lsla", "");
5803 /* total: 6 cycles, 4 bytes */
5806 accopWithMisc ("rora", "");
5807 accopWithMisc ("rora", "");
5808 accopWithMisc ("rora", "");
5809 accopWithMisc ("and", "#0xc0");
5810 /* total: 5 cycles, 5 bytes */
5813 accopWithMisc ("rora", "");
5814 accopWithMisc ("clra", "");
5815 accopWithMisc ("rora", "");
5816 /* total: 3 cycles, 3 bytes */
5820 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5821 /* the fastest (shCount<6) and shortest (shCount<4). */
5822 for (i=0;i<shCount;i++)
5823 accopWithMisc ("lsla", "");
5827 /*-----------------------------------------------------------------*/
5828 /* AccSRsh - signed right shift accumulator by known count */
5829 /*-----------------------------------------------------------------*/
5831 AccSRsh (int shCount)
5835 shCount &= 0x0007; // shCount : 0..7
5839 accopWithMisc ("rola", "");
5840 accopWithMisc ("clra", "");
5841 accopWithMisc ("sbc", zero);
5842 /* total: 4 cycles, 4 bytes */
5846 for (i=0;i<shCount;i++)
5847 accopWithMisc ("asra", "");
5850 /*-----------------------------------------------------------------*/
5851 /* AccRsh - right shift accumulator by known count */
5852 /*-----------------------------------------------------------------*/
5854 AccRsh (int shCount, bool sign)
5864 shCount &= 0x0007; // shCount : 0..7
5866 /* Shift counts of 4 and 5 are currently optimized for code size. */
5867 /* Falling through to the unrolled loop would be optimal for code speed. */
5868 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5872 if (optimize.codeSpeed)
5874 accopWithMisc ("nsa", "");
5875 accopWithMisc ("and", "#0x0f");
5876 /* total: 5 cycles, 3 bytes */
5879 if (optimize.codeSpeed)
5881 accopWithMisc ("nsa", "");
5882 accopWithMisc ("and", "#0x0f");
5883 accopWithMisc ("lsra", "");
5884 /* total: 6 cycles, 4 bytes */
5887 accopWithMisc ("rola", "");
5888 accopWithMisc ("rola", "");
5889 accopWithMisc ("rola", "");
5890 accopWithMisc ("and", "#0x03");
5891 /* total: 5 cycles, 5 bytes */
5894 accopWithMisc ("rola", "");
5895 accopWithMisc ("clra", "");
5896 accopWithMisc ("rola", "");
5897 /* total: 3 cycles, 3 bytes */
5901 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5902 /* the fastest (shCount<6) and shortest (shCount<4). */
5903 for (i=0;i<shCount;i++)
5904 accopWithMisc ("lsra", "");
5908 /*-----------------------------------------------------------------*/
5909 /* XAccLsh - left shift register pair XA by known count */
5910 /*-----------------------------------------------------------------*/
5912 XAccLsh (int shCount)
5916 shCount &= 0x000f; // shCount : 0..15
5921 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5922 loadRegFromConst (hc08_reg_a, zero);
5926 /* if we can beat 2n cycles or bytes for some special case, do it here */
5930 /* bytes cycles reg x reg a carry
5931 ** abcd efgh ijkl mnop ?
5932 ** lsrx 1 1 0abc defg ijkl mnop h
5933 ** rora 1 1 0abc defg hijk lmno p
5934 ** tax 1 1 hijk lmno hijk lmno p
5935 ** clra 1 1 hijk lmno 0000 0000 p
5936 ** rora 1 1 hijk lmno p000 0000 0
5937 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5939 rmwWithReg ("lsr", hc08_reg_x);
5940 rmwWithReg ("ror", hc08_reg_a);
5941 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5942 loadRegFromConst (hc08_reg_a, zero);
5943 rmwWithReg ("ror", hc08_reg_a);
5950 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5951 /* the fastest and shortest. */
5952 for (i=0;i<shCount;i++)
5954 rmwWithReg ("lsl", hc08_reg_a);
5955 rmwWithReg ("rol", hc08_reg_x);
5959 /*-----------------------------------------------------------------*/
5960 /* XAccSRsh - signed right shift register pair XA by known count */
5961 /*-----------------------------------------------------------------*/
5963 XAccSRsh (int shCount)
5967 shCount &= 0x000f; // shCount : 0..7
5969 /* if we can beat 2n cycles or bytes for some special case, do it here */
5973 /* bytes cycles reg x reg a carry
5974 ** abcd efgh ijkl mnop ?
5975 ** lslx 1 1 bcde fgh0 ijkl mnop a
5976 ** clra 1 1 bcde fgh0 0000 0000 a
5977 ** rola 1 1 bcde fgh0 0000 000a 0
5978 ** nega 1 1 bcde fgh0 aaaa aaaa a
5979 ** tax 1 1 aaaa aaaa aaaa aaaa a
5980 ** total: 5 cycles, 5 bytes
5982 rmwWithReg ("lsl", hc08_reg_x);
5983 loadRegFromConst (hc08_reg_a, zero);
5984 rmwWithReg ("rol", hc08_reg_a);
5985 rmwWithReg ("neg", hc08_reg_a);
5986 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5996 /* bytes cycles reg x reg a carry
5997 ** abcd efgh ijkl mnop ?
5998 ** txa 1 1 abcd efgh abcd efgh ?
5999 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
6000 ** lsla 1 1 abcd efgh ???? ???? a
6001 ** clrx 1 1 0000 0000 ???? ???? a
6002 ** rolx 1 1 0000 000a ???? ???? 0
6003 ** negx 1 1 aaaa aaaa ???? ???? a
6004 ** rora 1 1 aaaa aaaa LSBresult 0
6005 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
6007 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6008 AccSRsh (shCount-8);
6009 rmwWithReg ("lsl", hc08_reg_a);
6010 loadRegFromConst (hc08_reg_x, zero);
6011 rmwWithReg ("rol", hc08_reg_x);
6012 rmwWithReg ("neg", hc08_reg_x);
6013 rmwWithReg ("ror", hc08_reg_a);
6020 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6021 /* the fastest and shortest. */
6022 for (i=0;i<shCount;i++)
6024 rmwWithReg ("asr", hc08_reg_x);
6025 rmwWithReg ("ror", hc08_reg_a);
6029 /*-----------------------------------------------------------------*/
6030 /* XAccRsh - right shift register pair XA by known count */
6031 /*-----------------------------------------------------------------*/
6033 XAccRsh (int shCount, bool sign)
6043 shCount &= 0x000f; // shCount : 0..f
6045 /* if we can beat 2n cycles or bytes for some special case, do it here */
6049 /* bytes cycles reg x reg a carry
6050 ** abcd efgh ijkl mnop ?
6051 ** clra 1 1 abcd efgh 0000 0000 a
6052 ** lslx 1 1 bcde fgh0 0000 0000 a
6053 ** rola 1 1 bcde fgh0 0000 000a 0
6054 ** clrx 1 1 0000 0000 0000 000a 0
6055 ** total: 4 cycles, 4 bytes
6057 loadRegFromConst (hc08_reg_x, zero);
6058 rmwWithReg ("lsl", hc08_reg_x);
6059 rmwWithReg ("rol", hc08_reg_a);
6060 loadRegFromConst (hc08_reg_a, zero);
6064 /* bytes cycles reg x reg a carry
6065 ** abcd efgh ijkl mnop ?
6066 ** clra 1 1 abcd efgh 0000 0000 a
6067 ** lslx 1 1 bcde fgh0 0000 0000 a
6068 ** rola 1 1 bcde fgh0 0000 000a 0
6069 ** lslx 1 1 cdef gh00 0000 000a b
6070 ** rola 1 1 cdef gh00 0000 00ab 0
6071 ** clrx 1 1 0000 0000 0000 00ab 0
6072 ** total: 6 cycles, 6 bytes
6074 loadRegFromConst (hc08_reg_x, zero);
6075 rmwWithReg ("lsl", hc08_reg_x);
6076 rmwWithReg ("rol", hc08_reg_a);
6077 rmwWithReg ("lsl", hc08_reg_x);
6078 rmwWithReg ("rol", hc08_reg_a);
6079 loadRegFromConst (hc08_reg_a, zero);
6088 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6089 AccRsh (shCount-8, FALSE);
6090 loadRegFromConst (hc08_reg_x, zero);
6094 /* bytes cycles reg x reg a carry
6095 ** abcd efgh ijkl mnop ?
6096 ** lsla 1 1 abcd efgh jklm nop0 i
6097 ** txa 1 1 abcd efgh abcd efgh i
6098 ** rola 1 1 abcd efgh bcde fghi a
6099 ** clrx 1 1 0000 0000 bcde fghi a
6100 ** rolx 1 1 0000 000a bcde fghi 0
6101 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
6103 rmwWithReg ("lsl", hc08_reg_a);
6104 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6105 rmwWithReg ("rol", hc08_reg_a);
6106 loadRegFromConst (hc08_reg_x, zero);
6107 rmwWithReg ("rol", hc08_reg_x);
6110 /* bytes cycles reg x reg a carry
6111 ** abcd efgh ijkl mnop ?
6112 ** lsla 1 1 abcd efgh jklm nop0 i
6113 ** rolx 1 1 bcde fghi jklm nop0 a
6114 ** rola 1 1 bcde fghi klmn op0a j
6115 ** rolx 1 1 cdef ghij klmn op0a b
6116 ** rola 1 1 cdef ghij lmno p0ab k
6117 ** and #3 2 2 cdef ghij 0000 00ab k
6118 ** psha 1 2 cdef ghij 0000 00ab k
6119 ** txa 1 1 cdef ghij cdef ghij k
6120 ** pula 1 2 0000 00ab cdef ghij k
6121 ** total: 12 cycles, 10 bytes (beats 12 bytes)
6127 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6128 /* the fastest and shortest. */
6129 for (i=0;i<shCount;i++)
6131 rmwWithReg ("lsr", hc08_reg_x);
6132 rmwWithReg ("ror", hc08_reg_a);
6139 /*-----------------------------------------------------------------*/
6140 /* shiftR1Left2Result - shift right one byte from left to result */
6141 /*-----------------------------------------------------------------*/
6143 shiftR1Left2Result (operand * left, int offl,
6144 operand * result, int offr,
6145 int shCount, int sign)
6147 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6148 /* shift right accumulator */
6149 AccRsh (shCount, sign);
6150 storeRegToAop (hc08_reg_a, AOP (result), offr);
6154 /*-----------------------------------------------------------------*/
6155 /* shiftL1Left2Result - shift left one byte from left to result */
6156 /*-----------------------------------------------------------------*/
6158 shiftL1Left2Result (operand * left, int offl,
6159 operand * result, int offr, int shCount)
6161 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6162 /* shift left accumulator */
6164 storeRegToAop (hc08_reg_a, AOP (result), offr);
6167 /*-----------------------------------------------------------------*/
6168 /* movLeft2Result - move byte from left to result */
6169 /*-----------------------------------------------------------------*/
6171 movLeft2Result (operand * left, int offl,
6172 operand * result, int offr, int sign)
6174 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6176 transferAopAop (AOP (left), offl, AOP (result), offr);
6181 /*-----------------------------------------------------------------*/
6182 /* shiftL2Left2Result - shift left two bytes from left to result */
6183 /*-----------------------------------------------------------------*/
6185 shiftL2Left2Result (operand * left, int offl,
6186 operand * result, int offr, int shCount)
6189 bool needpula = FALSE;
6190 bool needpulx = FALSE;
6192 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6193 needpula = pushRegIfUsed (hc08_reg_a);
6196 if (!IS_AOP_XA (AOP (left)))
6197 needpulx = pushRegIfUsed (hc08_reg_x);
6201 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6206 rmwWithReg ("lsr", hc08_reg_x);
6207 rmwWithReg ("ror", hc08_reg_a);
6208 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6209 rmwWithReg ("clr", hc08_reg_a);
6210 rmwWithReg ("ror", hc08_reg_a);
6213 for (i=0; i<shCount; i++)
6215 rmwWithReg ("lsl", hc08_reg_a);
6216 rmwWithReg ("rol", hc08_reg_x);
6219 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6221 pullOrFreeReg (hc08_reg_x, needpulx);
6222 pullOrFreeReg (hc08_reg_a, needpula);
6228 /*-----------------------------------------------------------------*/
6229 /* shiftR2Left2Result - shift right two bytes from left to result */
6230 /*-----------------------------------------------------------------*/
6232 shiftR2Left2Result (operand * left, int offl,
6233 operand * result, int offr,
6234 int shCount, int sign)
6237 bool needpula = FALSE;
6238 bool needpulx = FALSE;
6240 needpula = pushRegIfUsed (hc08_reg_a);
6241 needpulx = pushRegIfUsed (hc08_reg_x);
6243 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6244 for (i=0; i<shCount; i++)
6247 rmwWithReg ("asr", hc08_reg_x);
6249 rmwWithReg ("lsr", hc08_reg_x);
6250 rmwWithReg ("ror", hc08_reg_a);
6252 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6254 pullOrFreeReg (hc08_reg_x, needpulx);
6255 pullOrFreeReg (hc08_reg_a, needpula);
6260 /*-----------------------------------------------------------------*/
6261 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6262 /*-----------------------------------------------------------------*/
6264 shiftLLeftOrResult (operand * left, int offl,
6265 operand * result, int offr, int shCount)
6267 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6268 /* shift left accumulator */
6270 /* or with result */
6271 accopWithAop ("ora", AOP (result), offr);
6272 /* back to result */
6273 storeRegToAop (hc08_reg_a, AOP (result), offr);
6274 hc08_freeReg (hc08_reg_a);
6278 /*-----------------------------------------------------------------*/
6279 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6280 /*-----------------------------------------------------------------*/
6282 shiftRLeftOrResult (operand * left, int offl,
6283 operand * result, int offr, int shCount)
6285 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6286 /* shift left accumulator */
6287 AccRsh (shCount, FALSE);
6288 /* or with result */
6289 accopWithAop ("ora", AOP (result), offr);
6290 /* back to result */
6291 storeRegToAop (hc08_reg_a, AOP (result), offr);
6292 hc08_freeReg (hc08_reg_a);
6295 /*-----------------------------------------------------------------*/
6296 /* genlshOne - left shift a one byte quantity by known count */
6297 /*-----------------------------------------------------------------*/
6299 genlshOne (operand * result, operand * left, int shCount)
6301 D(emitcode ("; genlshOne",""));
6303 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6306 /*-----------------------------------------------------------------*/
6307 /* genlshTwo - left shift two bytes by known amount != 0 */
6308 /*-----------------------------------------------------------------*/
6310 genlshTwo (operand * result, operand * left, int shCount)
6314 D(emitcode ("; genlshTwo",""));
6317 size = getDataSize (result);
6319 /* if shCount >= 8 */
6326 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6328 storeRegToAop (hc08_reg_a, AOP (result), 1);
6330 storeConstToAop(zero, AOP (result), LSB);
6333 /* 1 <= shCount <= 7 */
6336 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6338 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6342 /*-----------------------------------------------------------------*/
6343 /* shiftLLong - shift left one long from left to result */
6344 /* offr = LSB or MSB16 */
6345 /*-----------------------------------------------------------------*/
6347 shiftLLong (operand * left, operand * result, int offr)
6350 // int size = AOP_SIZE (result);
6352 bool needpula = FALSE;
6353 bool needpulx = FALSE;
6355 needpula = pushRegIfUsed (hc08_reg_a);
6356 needpulx = pushRegIfUsed (hc08_reg_x);
6358 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6359 rmwWithReg ("lsl", hc08_reg_a);
6360 rmwWithReg ("rol", hc08_reg_x);
6364 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6365 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6366 rmwWithReg ("rol", hc08_reg_a);
6367 rmwWithReg ("rol", hc08_reg_x);
6368 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6370 else if (offr==MSB16)
6372 storeRegToAop (hc08_reg_a, AOP (result), offr);
6373 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6374 storeRegToAop (hc08_reg_x, AOP (result), offr+1);
6375 rmwWithReg ("rol", hc08_reg_a);
6376 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6377 storeConstToAop (zero, AOP (result), 0);
6380 pullOrFreeReg (hc08_reg_x, needpulx);
6381 pullOrFreeReg (hc08_reg_a, needpula);
6384 /*-----------------------------------------------------------------*/
6385 /* genlshFour - shift four byte by a known amount != 0 */
6386 /*-----------------------------------------------------------------*/
6388 genlshFour (operand * result, operand * left, int shCount)
6392 D(emitcode ("; genlshFour",""));
6394 size = AOP_SIZE (result);
6396 /* TODO: deal with the &result == &left case */
6398 /* if shifting more that 3 bytes */
6403 /* lowest order of left goes to the highest
6404 order of the destination */
6405 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6407 movLeft2Result (left, LSB, result, MSB32, 0);
6408 storeConstToAop (zero, AOP (result), LSB);
6409 storeConstToAop (zero, AOP (result), MSB16);
6410 storeConstToAop (zero, AOP (result), MSB24);
6414 /* more than two bytes */
6415 else if (shCount >= 16)
6417 /* lower order two bytes goes to higher order two bytes */
6419 /* if some more remaining */
6421 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6424 movLeft2Result (left, MSB16, result, MSB32, 0);
6425 movLeft2Result (left, LSB, result, MSB24, 0);
6427 storeConstToAop (zero, AOP (result), LSB);
6428 storeConstToAop (zero, AOP (result), MSB16);
6432 /* if more than 1 byte */
6433 else if (shCount >= 8)
6435 /* lower order three bytes goes to higher order three bytes */
6440 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6442 movLeft2Result (left, LSB, result, MSB16, 0);
6448 movLeft2Result (left, MSB24, result, MSB32, 0);
6449 movLeft2Result (left, MSB16, result, MSB24, 0);
6450 movLeft2Result (left, LSB, result, MSB16, 0);
6451 storeConstToAop (zero, AOP (result), LSB);
6453 else if (shCount == 1)
6454 shiftLLong (left, result, MSB16);
6457 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6458 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6459 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6460 storeConstToAop (zero, AOP (result), LSB);
6465 /* 1 <= shCount <= 7 */
6466 else if (shCount <= 2)
6468 shiftLLong (left, result, LSB);
6470 shiftLLong (result, result, LSB);
6472 /* 3 <= shCount <= 7, optimize */
6475 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6476 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6477 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6481 /*-----------------------------------------------------------------*/
6482 /* genLeftShiftLiteral - left shifting by known count */
6483 /*-----------------------------------------------------------------*/
6485 genLeftShiftLiteral (operand * left,
6490 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6493 D(emitcode ("; genLeftShiftLiteral",""));
6495 freeAsmop (right, NULL, ic, TRUE);
6497 aopOp (left, ic, FALSE);
6498 aopOp (result, ic, FALSE);
6500 // size = getSize (operandType (result));
6501 size = AOP_SIZE (result);
6504 DD(emitcode ("; shift left ", "result %d, left %d", size,
6511 transferAopAop( AOP(left), size, AOP(result), size);
6513 else if (shCount >= (size * 8))
6516 storeConstToAop (zero, AOP (result), size);
6523 genlshOne (result, left, shCount);
6527 genlshTwo (result, left, shCount);
6531 genlshFour (result, left, shCount);
6534 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6535 "*** ack! mystery literal shift!\n");
6539 freeAsmop (left, NULL, ic, TRUE);
6540 freeAsmop (result, NULL, ic, TRUE);
6543 /*-----------------------------------------------------------------*/
6544 /* genLeftShift - generates code for left shifting */
6545 /*-----------------------------------------------------------------*/
6547 genLeftShift (iCode * ic)
6549 operand *left, *right, *result;
6551 symbol *tlbl, *tlbl1;
6555 D(emitcode ("; genLeftShift",""));
6557 right = IC_RIGHT (ic);
6558 left = IC_LEFT (ic);
6559 result = IC_RESULT (ic);
6561 aopOp (right, ic, FALSE);
6563 /* if the shift count is known then do it
6564 as efficiently as possible */
6565 if (AOP_TYPE (right) == AOP_LIT)
6567 genLeftShiftLiteral (left, right, result, ic);
6571 /* shift count is unknown then we have to form
6572 a loop get the loop count in X : Note: we take
6573 only the lower order byte since shifting
6574 more that 32 bits make no sense anyway, ( the
6575 largest size of an object can be only 32 bits ) */
6577 aopOp (result, ic, FALSE);
6578 aopOp (left, ic, FALSE);
6579 aopResult = AOP (result);
6581 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result))
6582 || isOperandVolatile (result, FALSE))
6583 aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result)));
6585 /* now move the left to the result if they are not the
6587 if (!sameRegs (AOP (left), aopResult))
6589 size = AOP_SIZE (result);
6593 transferAopAop (AOP (left), offset, aopResult, offset);
6597 freeAsmop (left, NULL, ic, TRUE);
6598 AOP (result) = aopResult;
6600 tlbl = newiTempLabel (NULL);
6601 size = AOP_SIZE (result);
6603 tlbl1 = newiTempLabel (NULL);
6605 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6606 emitcode ("tstx", "");
6607 emitBranch ("beq", tlbl1);
6611 for (offset=0;offset<size;offset++)
6613 rmwWithAop (shift, AOP (result), offset);
6616 rmwWithReg ("dec", hc08_reg_x);
6617 emitBranch ("bne", tlbl);
6619 hc08_freeReg (hc08_reg_x);
6621 freeAsmop (result, NULL, ic, TRUE);
6622 freeAsmop (right, NULL, ic, TRUE);
6625 /*-----------------------------------------------------------------*/
6626 /* genrshOne - right shift a one byte quantity by known count */
6627 /*-----------------------------------------------------------------*/
6629 genrshOne (operand * result, operand * left,
6630 int shCount, int sign)
6632 D(emitcode ("; genrshOne",""));
6634 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6635 AccRsh (shCount, sign);
6636 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6639 /*-----------------------------------------------------------------*/
6640 /* genrshTwo - right shift two bytes by known amount != 0 */
6641 /*-----------------------------------------------------------------*/
6643 genrshTwo (operand * result, operand * left,
6644 int shCount, int sign)
6646 D(emitcode ("; genrshTwo",""));
6648 /* if shCount >= 8 */
6651 if (shCount || sign)
6653 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6654 AccRsh (shCount-8, sign);
6655 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6659 transferAopAop (AOP (left), 1, AOP (result), 0);
6660 storeConstToAop (zero, AOP (result), 1);
6664 /* 1 <= shCount <= 7 */
6667 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6668 XAccRsh (shCount, sign);
6669 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6673 /*-----------------------------------------------------------------*/
6674 /* shiftRLong - shift right one long from left to result */
6675 /* offl = LSB or MSB16 */
6676 /*-----------------------------------------------------------------*/
6678 shiftRLong (operand * left, int offl,
6679 operand * result, int sign)
6682 // int size = AOP_SIZE (result);
6684 bool needpula = FALSE;
6685 bool needpulx = FALSE;
6687 needpula = pushRegIfUsed (hc08_reg_a);
6688 needpulx = pushRegIfUsed (hc08_reg_x);
6692 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6694 rmwWithReg ("asr", hc08_reg_x);
6696 rmwWithReg ("lsr", hc08_reg_x);
6697 rmwWithReg ("ror", hc08_reg_a);
6698 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6699 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6701 else if (offl==MSB16)
6703 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6705 rmwWithReg ("asr", hc08_reg_a);
6707 rmwWithReg ("lsr", hc08_reg_a);
6708 loadRegFromAop (hc08_reg_x, AOP (left), MSB24);
6709 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6710 loadRegFromAop (hc08_reg_a, AOP (left), MSB16);
6713 rmwWithReg ("ror", hc08_reg_x);
6714 rmwWithReg ("ror", hc08_reg_a);
6715 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6721 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6722 storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
6726 storeConstToAop (zero, AOP (result), MSB32);
6730 pullOrFreeReg (hc08_reg_x, needpulx);
6731 pullOrFreeReg (hc08_reg_a, needpula);
6734 /*-----------------------------------------------------------------*/
6735 /* genrshFour - shift four byte by a known amount != 0 */
6736 /*-----------------------------------------------------------------*/
6738 genrshFour (operand * result, operand * left,
6739 int shCount, int sign)
6741 /* TODO: handle cases where left == result */
6743 D(emitcode ("; genrshFour",""));
6745 /* if shifting more that 3 bytes */
6748 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6749 AccRsh (shCount-24, sign);
6750 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6753 else if (shCount >= 16)
6755 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6756 XAccRsh (shCount-16, sign);
6757 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6760 else if (shCount >= 8)
6763 shiftRLong (left, MSB16, result, sign);
6764 else if (shCount == 8)
6766 transferAopAop (AOP (left), 1, AOP (result), 0);
6767 transferAopAop (AOP (left), 2, AOP (result), 1);
6768 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6769 storeRegToAop (hc08_reg_a, AOP (result), 2);
6770 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6772 else if (shCount == 9)
6774 shiftRLong (left, MSB16, result, sign);
6778 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6779 XAccRsh (shCount-8, FALSE);
6780 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6781 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6782 loadRegFromConst (hc08_reg_a, zero);
6783 XAccRsh (shCount-8, sign);
6784 accopWithAop ("ora", AOP (result), 1);
6785 storeRegToAop (hc08_reg_xa, AOP (result), 1);
6786 storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
6790 { /* 1 <= shCount <= 7 */
6793 shiftRLong (left, LSB, result, sign);
6797 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6798 XAccRsh (shCount, FALSE);
6799 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6800 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6802 accopWithAop ("ora", AOP (result), 1);
6803 storeRegToAop (hc08_reg_a, AOP (result), 1);
6804 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6805 XAccRsh (shCount, sign);
6806 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6811 /*-----------------------------------------------------------------*/
6812 /* genRightShiftLiteral - right shifting by known count */
6813 /*-----------------------------------------------------------------*/
6815 genRightShiftLiteral (operand * left,
6821 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6824 D(emitcode ("; genRightShiftLiteral",""));
6826 freeAsmop (right, NULL, ic, TRUE);
6828 aopOp (left, ic, FALSE);
6829 aopOp (result, ic, FALSE);
6832 DD(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6836 size = getDataSize (left);
6837 /* test the LEFT size !!! */
6839 /* I suppose that the left size >= result size */
6842 size = getDataSize (result);
6844 transferAopAop (AOP (left), size, AOP(result), size);
6846 else if (shCount >= (size * 8))
6849 /* get sign in acc.7 */
6850 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6852 addSign (result, LSB, sign);
6859 genrshOne (result, left, shCount, sign);
6863 genrshTwo (result, left, shCount, sign);
6867 genrshFour (result, left, shCount, sign);
6873 freeAsmop (left, NULL, ic, TRUE);
6874 freeAsmop (result, NULL, ic, TRUE);
6878 /*-----------------------------------------------------------------*/
6879 /* genRightShift - generate code for right shifting */
6880 /*-----------------------------------------------------------------*/
6882 genRightShift (iCode * ic)
6884 operand *right, *left, *result;
6887 symbol *tlbl, *tlbl1;
6892 D(emitcode ("; genRightShift",""));
6894 /* if signed then we do it the hard way preserve the
6895 sign bit moving it inwards */
6896 retype = getSpec (operandType (IC_RESULT (ic)));
6897 sign = !SPEC_USIGN (retype);
6899 /* signed & unsigned types are treated the same : i.e. the
6900 signed is NOT propagated inwards : quoting from the
6901 ANSI - standard : "for E1 >> E2, is equivalent to division
6902 by 2**E2 if unsigned or if it has a non-negative value,
6903 otherwise the result is implementation defined ", MY definition
6904 is that the sign does not get propagated */
6906 right = IC_RIGHT (ic);
6907 left = IC_LEFT (ic);
6908 result = IC_RESULT (ic);
6910 aopOp (right, ic, FALSE);
6912 /* if the shift count is known then do it
6913 as efficiently as possible */
6914 if (AOP_TYPE (right) == AOP_LIT)
6916 genRightShiftLiteral (left, right, result, ic, sign);
6920 /* shift count is unknown then we have to form
6921 a loop get the loop count in X : Note: we take
6922 only the lower order byte since shifting
6923 more that 32 bits make no sense anyway, ( the
6924 largest size of an object can be only 32 bits ) */
6926 aopOp (result, ic, FALSE);
6927 aopOp (left, ic, FALSE);
6928 aopResult = AOP (result);
6930 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result))
6931 || isOperandVolatile (result, FALSE))
6932 aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result)));
6934 /* now move the left to the result if they are not the
6936 if (!sameRegs (AOP (left), aopResult))
6938 size = AOP_SIZE (result);
6942 transferAopAop (AOP (left), offset, aopResult, offset);
6946 freeAsmop (left, NULL, ic, TRUE);
6947 AOP (result) = aopResult;
6949 tlbl = newiTempLabel (NULL);
6950 size = AOP_SIZE (result);
6952 tlbl1 = newiTempLabel (NULL);
6954 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6955 emitcode ("tstx", "");
6956 emitBranch ("beq", tlbl1);
6959 shift= sign ? "asr" : "lsr";
6960 for (offset=size-1;offset>=0;offset--)
6962 rmwWithAop (shift, AOP (result), offset);
6965 rmwWithReg ("dec", hc08_reg_x);
6966 emitBranch ("bne", tlbl);
6968 hc08_freeReg (hc08_reg_x);
6970 freeAsmop (result, NULL, ic, TRUE);
6971 freeAsmop (right, NULL, ic, TRUE);
6975 /*-----------------------------------------------------------------*/
6976 /* genUnpackBits - generates code for unpacking bits */
6977 /*-----------------------------------------------------------------*/
6979 genUnpackBits (operand * result, iCode *ifx)
6981 int offset = 0; /* result byte offset */
6982 int rsize; /* result size */
6983 int rlen = 0; /* remaining bitfield length */
6984 sym_link *etype; /* bitfield type information */
6985 int blen; /* bitfield length */
6986 int bstr; /* bitfield starting bit within byte */
6988 D(emitcode ("; genUnpackBits",""));
6990 etype = getSpec (operandType (result));
6991 rsize = getSize (operandType (result));
6992 blen = SPEC_BLEN (etype);
6993 bstr = SPEC_BSTR (etype);
6995 if (ifx && blen <= 8)
6997 emitcode ("lda", ",x");
6998 hc08_dirtyReg (hc08_reg_a, FALSE);
7001 emitcode ("and", "#0x%02x",
7002 (((unsigned char) -1) >> (8 - blen)) << bstr);
7004 genIfxJump (ifx, "a");
7009 /* If the bitfield length is less than a byte */
7012 emitcode ("lda", ",x");
7013 hc08_dirtyReg (hc08_reg_a, FALSE);
7014 AccRsh (bstr, FALSE);
7015 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7016 if (!SPEC_USIGN (etype))
7018 /* signed bitfield */
7019 symbol *tlbl = newiTempLabel (NULL);
7021 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7022 emitcode ("beq", "%05d$", tlbl->key + 100);
7023 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7026 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7030 /* Bit field did not fit in a byte. Copy all
7031 but the partial byte at the end. */
7032 for (rlen=blen;rlen>=8;rlen-=8)
7034 emitcode ("lda", ",x");
7035 hc08_dirtyReg (hc08_reg_a, FALSE);
7036 storeRegToAop (hc08_reg_a, AOP (result), offset);
7039 emitcode ("aix", "#1");
7042 /* Handle the partial byte at the end */
7045 emitcode ("lda", ",x");
7046 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7047 if (!SPEC_USIGN (etype))
7049 /* signed bitfield */
7050 symbol *tlbl = newiTempLabel (NULL);
7052 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7053 emitcode ("beq", "%05d$", tlbl->key + 100);
7054 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7057 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7064 if (SPEC_USIGN (etype))
7067 storeConstToAop (zero, AOP (result), offset++);
7071 /* signed bitfield: sign extension with 0x00 or 0xff */
7072 emitcode ("rola", "");
7073 emitcode ("clra", "");
7074 emitcode ("sbc", zero);
7077 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7083 /*-----------------------------------------------------------------*/
7084 /* genUnpackBitsImmed - generates code for unpacking bits */
7085 /*-----------------------------------------------------------------*/
7087 genUnpackBitsImmed (operand * left,
7093 int offset = 0; /* result byte offset */
7094 int rsize; /* result size */
7095 int rlen = 0; /* remaining bitfield length */
7096 sym_link *etype; /* bitfield type information */
7097 int blen; /* bitfield length */
7098 int bstr; /* bitfield starting bit within byte */
7101 D(emitcode ("; genUnpackBitsImmed",""));
7103 aopOp (result, ic, TRUE);
7104 size = AOP_SIZE (result);
7106 derefaop = aopDerefAop (AOP (left));
7107 freeAsmop (left, NULL, ic, TRUE);
7108 derefaop->size = size;
7110 etype = getSpec (operandType (result));
7111 rsize = getSize (operandType (result));
7112 blen = SPEC_BLEN (etype);
7113 bstr = SPEC_BSTR (etype);
7115 /* if the bitfield is a single bit in the direct page */
7116 if (blen == 1 && derefaop->type == AOP_DIR)
7120 symbol *tlbl = newiTempLabel (NULL);
7122 loadRegFromConst (hc08_reg_a, zero);
7123 emitcode ("brclr", "#%d,%s,%05d$",
7124 bstr, aopAdrStr (derefaop, 0, FALSE),
7126 if (SPEC_USIGN (etype))
7127 rmwWithReg ("inc", hc08_reg_a);
7129 rmwWithReg ("dec", hc08_reg_a);
7131 storeRegToAop (hc08_reg_a, AOP (result), offset);
7132 hc08_freeReg (hc08_reg_a);
7138 symbol *tlbl = newiTempLabel (NULL);
7144 jlbl = IC_TRUE (ifx);
7149 jlbl = IC_FALSE (ifx);
7152 emitcode (inst, "#%d,%s,%05d$",
7153 bstr, aopAdrStr (derefaop, 0, FALSE),
7155 emitBranch ("jmp", jlbl);
7163 /* If the bitfield length is less than a byte */
7166 loadRegFromAop (hc08_reg_a, derefaop, 0);
7169 AccRsh (bstr, FALSE);
7170 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7171 hc08_dirtyReg (hc08_reg_a, FALSE);
7172 if (!SPEC_USIGN (etype))
7174 /* signed bitfield */
7175 symbol *tlbl = newiTempLabel (NULL);
7177 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7178 emitcode ("beq", "%05d$", tlbl->key + 100);
7179 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7182 storeRegToAop (hc08_reg_a, AOP (result), offset);
7186 emitcode ("and", "#0x%02x",
7187 (((unsigned char) -1) >> (8 - blen)) << bstr);
7188 hc08_dirtyReg (hc08_reg_a, FALSE);
7194 /* Bit field did not fit in a byte. Copy all
7195 but the partial byte at the end. */
7196 for (rlen=blen;rlen>=8;rlen-=8)
7198 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7200 storeRegToAop (hc08_reg_a, AOP (result), offset);
7202 emitcode ("tsta", "");
7206 /* Handle the partial byte at the end */
7209 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7210 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7211 if (!SPEC_USIGN (etype))
7213 /* signed bitfield */
7214 symbol *tlbl = newiTempLabel (NULL);
7216 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7217 emitcode ("beq", "%05d$", tlbl->key + 100);
7218 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7221 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7228 if (SPEC_USIGN (etype))
7231 storeConstToAop (zero, AOP (result), offset++);
7235 /* signed bitfield: sign extension with 0x00 or 0xff */
7236 emitcode ("rola", "");
7237 emitcode ("clra", "");
7238 emitcode ("sbc", zero);
7241 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7245 freeAsmop (NULL, derefaop, ic, TRUE);
7246 freeAsmop (result, NULL, ic, TRUE);
7248 if (ifx && !ifx->generated)
7250 genIfxJump (ifx, "a");
7255 /*-----------------------------------------------------------------*/
7256 /* genDataPointerGet - generates code when ptr offset is known */
7257 /*-----------------------------------------------------------------*/
7259 genDataPointerGet (operand * left,
7267 D(emitcode ("; genDataPointerGet",""));
7269 aopOp (result, ic, TRUE);
7270 size = AOP_SIZE (result);
7272 derefaop = aopDerefAop (AOP (left));
7273 freeAsmop (left, NULL, ic, TRUE);
7274 derefaop->size = size;
7279 transferAopAop (derefaop, size, AOP (result), size);
7281 loadRegFromAop (hc08_reg_a, derefaop, size);
7284 freeAsmop (NULL, derefaop, ic, TRUE);
7285 freeAsmop (result, NULL, ic, TRUE);
7287 if (ifx && !ifx->generated)
7289 genIfxJump (ifx, "a");
7294 /*-----------------------------------------------------------------*/
7295 /* genPointerGet - generate code for pointer get */
7296 /*-----------------------------------------------------------------*/
7298 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7300 operand *left = IC_LEFT (ic);
7301 operand *result = IC_RESULT (ic);
7303 sym_link *retype = getSpec (operandType (result));
7305 D(emitcode ("; genPointerGet",""));
7307 if (getSize (operandType (result))>1)
7310 aopOp (left, ic, FALSE);
7312 /* if left is rematerialisable and
7313 result is not bit variable type */
7314 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7316 if (!IS_BITVAR (retype))
7318 genDataPointerGet (left, result, ic, ifx);
7323 genUnpackBitsImmed (left, result, ic, ifx);
7328 /* if the operand is already in hx
7329 then we do nothing else we move the value to hx */
7330 if (AOP_TYPE (left) != AOP_STR)
7332 /* if this is remateriazable */
7333 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7336 /* so hx now contains the address */
7337 aopOp (result, ic, FALSE);
7339 /* if bit then unpack */
7340 if (IS_BITVAR (retype))
7341 genUnpackBits (result, ifx);
7344 size = AOP_SIZE (result);
7349 accopWithMisc ("lda", ",x");
7352 emitcode ("aix", "#1");
7353 hc08_dirtyReg (hc08_reg_hx, FALSE);
7356 storeRegToAop (hc08_reg_a, AOP (result), offset);
7358 hc08_freeReg (hc08_reg_a);
7362 freeAsmop (left, NULL, ic, TRUE);
7363 freeAsmop (result, NULL, ic, TRUE);
7366 aopOp (IC_RESULT (pi), pi, FALSE);
7367 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7368 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7372 if (ifx && !ifx->generated)
7374 genIfxJump (ifx, "a");
7377 hc08_freeReg (hc08_reg_hx);
7381 /*-----------------------------------------------------------------*/
7382 /* genPackBits - generates code for packed bit storage */
7383 /*-----------------------------------------------------------------*/
7385 genPackBits (sym_link * etype,
7388 int offset = 0; /* source byte offset */
7389 int rlen = 0; /* remaining bitfield length */
7390 int blen; /* bitfield length */
7391 int bstr; /* bitfield starting bit within byte */
7392 int litval; /* source literal value (if AOP_LIT) */
7393 unsigned char mask; /* bitmask within current byte */
7396 D(emitcode ("; genPackBits",""));
7398 blen = SPEC_BLEN (etype);
7399 bstr = SPEC_BSTR (etype);
7401 /* If the bitfield length is less than a byte */
7404 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7405 (unsigned char) (0xFF >> (8 - bstr)));
7407 if (AOP_TYPE (right) == AOP_LIT)
7409 /* Case with a bitfield length <8 and literal source
7411 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7413 litval &= (~mask) & 0xff;
7415 emitcode ("lda", ",x");
7416 if ((mask|litval)!=0xff)
7417 emitcode ("and","#0x%02x", mask);
7419 emitcode ("ora","#0x%02x", litval);
7420 hc08_dirtyReg (hc08_reg_a, FALSE);
7421 emitcode ("sta", ",x");
7423 hc08_freeReg (hc08_reg_a);
7427 /* Case with a bitfield length < 8 and arbitrary source
7429 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7430 /* shift and mask source value */
7432 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7433 hc08_dirtyReg (hc08_reg_a, FALSE);
7434 pushReg (hc08_reg_a, TRUE);
7436 emitcode ("lda", ",x");
7437 emitcode ("and", "#0x%02x", mask);
7438 emitcode ("ora", "1,s");
7439 emitcode ("sta", ",x");
7440 pullReg (hc08_reg_a);
7442 hc08_freeReg (hc08_reg_a);
7446 /* Bit length is greater than 7 bits. In this case, copy */
7447 /* all except the partial byte at the end */
7448 for (rlen=blen;rlen>=8;rlen-=8)
7450 if (AOP (right)->type == AOP_DIR)
7452 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7457 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7458 emitcode ("sta", "%d,x", offset);
7463 /* If there was a partial byte at the end */
7466 mask = (((unsigned char) -1 << rlen) & 0xff);
7468 if (AOP_TYPE (right) == AOP_LIT)
7470 /* Case with partial byte and literal source
7472 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7473 litval >>= (blen-rlen);
7474 litval &= (~mask) & 0xff;
7475 emitcode ("lda", "%d,x", offset - xoffset);
7476 hc08_dirtyReg (hc08_reg_a, FALSE);
7477 if ((mask|litval)!=0xff)
7478 emitcode ("and","#0x%02x", mask);
7480 emitcode ("ora","#0x%02x", litval);
7481 emitcode ("sta", "%d,x", offset - xoffset);
7482 hc08_dirtyReg (hc08_reg_a, FALSE);
7483 hc08_freeReg (hc08_reg_a);
7487 /* Case with partial byte and arbitrary source
7489 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7490 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7491 hc08_dirtyReg (hc08_reg_a, FALSE);
7492 pushReg (hc08_reg_a, TRUE);
7494 emitcode ("lda", "%d,x", offset - xoffset);
7495 emitcode ("and", "#0x%02x", mask);
7496 emitcode ("ora", "1,s");
7497 emitcode ("sta", "%d,x", offset - xoffset);
7498 pullReg (hc08_reg_a);
7501 hc08_freeReg (hc08_reg_a);
7504 /*-----------------------------------------------------------------*/
7505 /* genPackBitsImmed - generates code for packed bit storage */
7506 /*-----------------------------------------------------------------*/
7508 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7512 int offset = 0; /* source byte offset */
7513 int rlen = 0; /* remaining bitfield length */
7514 int blen; /* bitfield length */
7515 int bstr; /* bitfield starting bit within byte */
7516 int litval; /* source literal value (if AOP_LIT) */
7517 unsigned char mask; /* bitmask within current byte */
7519 D(emitcode ("; genPackBitsImmed",""));
7521 blen = SPEC_BLEN (etype);
7522 bstr = SPEC_BSTR (etype);
7524 aopOp (right, ic, FALSE);
7525 size = AOP_SIZE (right);
7527 derefaop = aopDerefAop (AOP (result));
7528 freeAsmop (result, NULL, ic, TRUE);
7529 derefaop->size = size;
7531 /* if the bitfield is a single bit in the direct page */
7532 if (blen == 1 && derefaop->type == AOP_DIR)
7534 if (AOP_TYPE (right) == AOP_LIT)
7536 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7538 emitcode ((litval & 1) ? "bset" : "bclr",
7539 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7543 symbol *tlbl1 = newiTempLabel (NULL);
7544 symbol *tlbl2 = newiTempLabel (NULL);
7546 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7547 emitcode ("bit", "#1");
7548 emitBranch ("bne", tlbl1);
7549 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7550 emitBranch ("bra", tlbl2);
7552 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7554 hc08_freeReg (hc08_reg_a);
7559 /* If the bitfield length is less than a byte */
7562 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7563 (unsigned char) (0xFF >> (8 - bstr)));
7565 if (AOP_TYPE (right) == AOP_LIT)
7567 /* Case with a bitfield length <8 and literal source
7569 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7571 litval &= (~mask) & 0xff;
7573 loadRegFromAop (hc08_reg_a, derefaop, 0);
7574 if ((mask|litval)!=0xff)
7575 emitcode ("and","#0x%02x", mask);
7577 emitcode ("ora","#0x%02x", litval);
7578 hc08_dirtyReg (hc08_reg_a, FALSE);
7579 storeRegToAop (hc08_reg_a, derefaop, 0);
7581 hc08_freeReg (hc08_reg_a);
7585 /* Case with a bitfield length < 8 and arbitrary source
7587 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7588 /* shift and mask source value */
7590 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7591 hc08_dirtyReg (hc08_reg_a, FALSE);
7592 pushReg (hc08_reg_a, TRUE);
7594 loadRegFromAop (hc08_reg_a, derefaop, 0);
7595 emitcode ("and", "#0x%02x", mask);
7596 emitcode ("ora", "1,s");
7597 storeRegToAop (hc08_reg_a, derefaop, 0);
7598 pullReg (hc08_reg_a);
7600 hc08_freeReg (hc08_reg_a);
7604 /* Bit length is greater than 7 bits. In this case, copy */
7605 /* all except the partial byte at the end */
7606 for (rlen=blen;rlen>=8;rlen-=8)
7608 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7612 /* If there was a partial byte at the end */
7615 mask = (((unsigned char) -1 << rlen) & 0xff);
7617 if (AOP_TYPE (right) == AOP_LIT)
7619 /* Case with partial byte and literal source
7621 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7622 litval >>= (blen-rlen);
7623 litval &= (~mask) & 0xff;
7624 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7625 if ((mask|litval)!=0xff)
7626 emitcode ("and","#0x%02x", mask);
7628 emitcode ("ora","#0x%02x", litval);
7629 hc08_dirtyReg (hc08_reg_a, FALSE);
7630 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7631 hc08_dirtyReg (hc08_reg_a, FALSE);
7632 hc08_freeReg (hc08_reg_a);
7636 /* Case with partial byte and arbitrary source
7638 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7639 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7640 hc08_dirtyReg (hc08_reg_a, FALSE);
7641 pushReg (hc08_reg_a, TRUE);
7643 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7644 emitcode ("and", "#0x%02x", mask);
7645 emitcode ("ora", "1,s");
7646 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7647 pullReg (hc08_reg_a);
7650 hc08_freeReg (hc08_reg_a);
7653 freeAsmop (right, NULL, ic, TRUE);
7654 freeAsmop (NULL, derefaop, ic, TRUE);
7657 /*-----------------------------------------------------------------*/
7658 /* genDataPointerSet - remat pointer to data space */
7659 /*-----------------------------------------------------------------*/
7661 genDataPointerSet (operand * right,
7668 D(emitcode ("; genDataPointerSet",""));
7670 aopOp (right, ic, FALSE);
7671 size = AOP_SIZE (right);
7673 derefaop = aopDerefAop (AOP (result));
7674 freeAsmop (result, NULL, ic, TRUE);
7675 derefaop->size = size;
7679 transferAopAop (AOP (right), size, derefaop, size);
7682 freeAsmop (right, NULL, ic, TRUE);
7683 freeAsmop (NULL, derefaop, ic, TRUE);
7687 /*-----------------------------------------------------------------*/
7688 /* genPointerSet - stores the value into a pointer location */
7689 /*-----------------------------------------------------------------*/
7691 genPointerSet (iCode * ic, iCode *pi)
7693 operand *right = IC_RIGHT (ic);
7694 operand *result = IC_RESULT (ic);
7695 sym_link *type, *etype;
7697 sym_link *retype = getSpec (operandType (right));
7698 sym_link *letype = getSpec (operandType (result));
7700 D(emitcode ("; genPointerSet",""));
7702 type = operandType (result);
7703 etype = getSpec (type);
7705 aopOp (result, ic, FALSE);
7707 /* if the result is rematerializable */
7708 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7710 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7712 genDataPointerSet (right, result, ic);
7717 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7722 /* if the operand is already in hx
7723 then we do nothing else we move the value to hx */
7724 if (AOP_TYPE (result) != AOP_STR)
7726 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7728 /* so hx now contains the address */
7729 aopOp (right, ic, FALSE);
7731 /* if bit then unpack */
7732 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7733 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7736 size = AOP_SIZE (right);
7741 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7742 accopWithMisc ("sta", ",x");
7745 emitcode ("aix", "#1");
7747 hc08_freeReg (hc08_reg_a);
7751 freeAsmop (result, NULL, ic, TRUE);
7752 freeAsmop (right, NULL, ic, TRUE);
7755 aopOp (IC_RESULT (pi), pi, FALSE);
7756 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7757 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7761 hc08_freeReg (hc08_reg_hx);
7765 /*-----------------------------------------------------------------*/
7766 /* genIfx - generate code for Ifx statement */
7767 /*-----------------------------------------------------------------*/
7769 genIfx (iCode * ic, iCode * popIc)
7771 operand *cond = IC_COND (ic);
7774 D(emitcode ("; genIfx",""));
7776 aopOp (cond, ic, FALSE);
7778 /* If the condition is a literal, we can just do an unconditional */
7779 /* branch or no branch */
7780 if (AOP_TYPE (cond) == AOP_LIT)
7782 unsigned long lit = (unsigned long) floatFromVal (AOP (cond)->aopu.aop_lit);
7783 freeAsmop (cond, NULL, ic, TRUE);
7785 /* if there was something to be popped then do it */
7791 emitBranch ("jmp", IC_TRUE (ic));
7796 emitBranch ("jmp", IC_FALSE (ic));
7802 /* get the value into acc */
7803 if (AOP_TYPE (cond) != AOP_CRY)
7804 asmopToBool (AOP (cond), FALSE);
7807 /* the result is now in the accumulator */
7808 freeAsmop (cond, NULL, ic, TRUE);
7810 /* if there was something to be popped then do it */
7814 /* if the condition is a bit variable */
7815 if (isbit && IS_ITEMP (cond) &&
7817 genIfxJump (ic, SPIL_LOC (cond)->rname);
7818 else if (isbit && !IS_ITEMP (cond))
7819 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7821 genIfxJump (ic, "a");
7826 /*-----------------------------------------------------------------*/
7827 /* genAddrOf - generates code for address of */
7828 /*-----------------------------------------------------------------*/
7830 genAddrOf (iCode * ic)
7832 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7835 D(emitcode ("; genAddrOf",""));
7837 aopOp (IC_RESULT (ic), ic, FALSE);
7839 /* if the operand is on the stack then we
7840 need to get the stack offset of this
7844 /* if it has an offset then we need to compute it */
7845 offset = _G.stackOfs + _G.stackPushes + sym->stack;
7846 hc08_useReg (hc08_reg_hx);
7847 emitcode ("tsx", "");
7848 while (offset > 127)
7850 emitcode ("aix", "#127");
7853 while (offset < -128)
7855 emitcode ("aix", "#-128");
7858 emitcode ("aix", "#%d", offset);
7859 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7860 hc08_freeReg (hc08_reg_hx);
7865 /* object not on stack then we need the name */
7866 size = AOP_SIZE (IC_RESULT (ic));
7871 char s[SDCC_NAME_MAX+10];
7874 sprintf (s, "#%s", sym->rname);
7877 sprintf (s, "#>%s", sym->rname);
7880 sprintf (s, "#(%s >> %d)",
7884 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7888 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7892 /*-----------------------------------------------------------------*/
7893 /* genAssign - generate code for assignment */
7894 /*-----------------------------------------------------------------*/
7896 genAssign (iCode * ic)
7898 operand *result, *right;
7900 // unsigned long lit = 0L;
7902 D(emitcode("; genAssign",""));
7904 result = IC_RESULT (ic);
7905 right = IC_RIGHT (ic);
7907 /* if they are the same */
7908 if (operandsEqu (result, right)) {
7912 aopOp (right, ic, FALSE);
7913 aopOp (result, ic, TRUE);
7915 /* if they are the same registers */
7916 if (sameRegs (AOP (right), AOP (result)))
7919 if ((AOP_TYPE (right) == AOP_LIT)
7920 && (IS_AOP_HX(AOP(result))))
7922 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7927 size = AOP_SIZE (result);
7930 transferAopAop (AOP (right), size, AOP (result), size);
7934 freeAsmop (right, NULL, ic, TRUE);
7935 freeAsmop (result, NULL, ic, TRUE);
7938 /*-----------------------------------------------------------------*/
7939 /* genJumpTab - generates code for jump table */
7940 /*-----------------------------------------------------------------*/
7942 genJumpTab (iCode * ic)
7945 symbol *jtablo = newiTempLabel (NULL);
7946 symbol *jtabhi = newiTempLabel (NULL);
7948 D(emitcode ("; genJumpTab",""));
7950 aopOp (IC_JTCOND (ic), ic, FALSE);
7952 if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7954 /* get the condition into x */
7955 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7956 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7957 loadRegFromConst (hc08_reg_h, zero);
7959 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7960 emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7961 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7962 emitcode ("jmp", ",x");
7964 hc08_dirtyReg (hc08_reg_a, TRUE);
7965 hc08_dirtyReg (hc08_reg_hx, TRUE);
7970 pushReg(hc08_reg_hx, TRUE);
7972 /* get the condition into x */
7973 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7974 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7975 loadRegFromConst (hc08_reg_h, zero);
7977 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7978 emitcode ("sta", "3,s");
7979 emitcode ("lda", "%05d$,x", jtablo->key + 100);
7980 emitcode ("sta", "4,s");
7982 pullReg(hc08_reg_hx);
7983 emitcode ("rts", "");
7984 _G.stackPushes += 2;
7988 /* now generate the jump labels */
7990 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7991 jtab = setNextItem (IC_JTLABELS (ic)))
7992 emitcode (".db", "%05d$", jtab->key + 100);
7994 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7995 jtab = setNextItem (IC_JTLABELS (ic)))
7996 emitcode (".db", ">%05d$", jtab->key + 100);
8000 /*-----------------------------------------------------------------*/
8001 /* genCast - gen code for casting */
8002 /*-----------------------------------------------------------------*/
8004 genCast (iCode * ic)
8006 operand *result = IC_RESULT (ic);
8007 sym_link *ctype = operandType (IC_LEFT (ic));
8008 sym_link *rtype = operandType (IC_RIGHT (ic));
8009 operand *right = IC_RIGHT (ic);
8012 D(emitcode("; genCast",""));
8014 /* if they are equivalent then do nothing */
8015 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8018 aopOp (right, ic, FALSE);
8019 aopOp (result, ic, FALSE);
8022 /* if they are the same size : or less */
8023 if (AOP_SIZE (result) <= AOP_SIZE (right))
8026 /* if they are in the same place */
8028 if (sameRegs (AOP (right), AOP (result)))
8032 /* if they in different places then copy */
8033 size = AOP_SIZE (result);
8037 transferAopAop(AOP (right), offset, AOP (result), offset);
8044 /* if the result is of type pointer */
8049 sym_link *type = operandType (right);
8050 sym_link *etype = getSpec (type);
8052 /* pointer to generic pointer */
8053 if (IS_GENPTR (ctype))
8056 p_type = DCL_TYPE (type);
8059 if (SPEC_SCLS(etype)==S_REGISTER) {
8060 // let's assume it is a generic pointer
8063 /* we have to go by the storage class */
8064 p_type = PTR_TYPE (SPEC_OCLS (etype));
8068 /* the first two bytes are known */
8069 size = GPTRSIZE - 1;
8073 transferAopAop(AOP (right), offset, AOP (result), offset);
8076 /* the last byte depending on type */
8079 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8084 // pointerTypeToGPByte will have bitched.
8088 sprintf(gpValStr, "#0x%x", gpVal);
8089 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8095 /* just copy the pointers */
8096 size = AOP_SIZE (result);
8100 transferAopAop(AOP (right), offset, AOP (result), offset);
8106 /* so we now know that the size of destination is greater
8107 than the size of the source */
8108 /* we move to result for the size of source */
8109 size = AOP_SIZE (right);
8113 transferAopAop(AOP (right), offset, AOP (result), offset);
8117 /* now depending on the sign of the source && destination */
8118 size = AOP_SIZE (result) - AOP_SIZE (right);
8119 /* if unsigned or not an integral type */
8120 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8123 storeConstToAop (zero, AOP (result), offset++);
8127 /* we need to extend the sign :{ */
8128 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
8129 accopWithMisc ("rola", "");
8130 accopWithMisc ("clra", "");
8131 accopWithMisc ("sbc", zero);
8133 storeRegToAop (hc08_reg_a, AOP (result), offset++);
8136 /* we are done hurray !!!! */
8139 freeAsmop (right, NULL, ic, TRUE);
8140 freeAsmop (result, NULL, ic, TRUE);
8144 /*-----------------------------------------------------------------*/
8145 /* genDjnz - generate decrement & jump if not zero instrucion */
8146 /*-----------------------------------------------------------------*/
8148 genDjnz (iCode * ic, iCode * ifx)
8154 D(emitcode ("; genDjnz",""));
8156 /* if the if condition has a false label
8157 then we cannot save */
8161 /* if the minus is not of the form
8163 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8164 !IS_OP_LITERAL (IC_RIGHT (ic)))
8167 if (operandLitValue (IC_RIGHT (ic)) != 1)
8170 /* dbnz doesn't support extended mode */
8171 if (isOperandInFarSpace (IC_RESULT (ic)))
8174 /* if the size of this greater than one then no
8176 // if (getSize (operandType (IC_RESULT (ic))) > 1)
8178 aopOp (IC_RESULT (ic), ic, FALSE);
8179 if (AOP_SIZE (IC_RESULT (ic))>1)
8181 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8185 /* otherwise we can save BIG */
8186 lbl = newiTempLabel (NULL);
8187 lbl1 = newiTempLabel (NULL);
8190 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
8193 emitBranch ("bra", lbl1);
8195 emitBranch ("jmp", IC_TRUE (ifx));
8198 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8203 /*-----------------------------------------------------------------*/
8204 /* genReceive - generate code for a receive iCode */
8205 /*-----------------------------------------------------------------*/
8207 genReceive (iCode * ic)
8211 D(emitcode ("; genReceive",""));
8213 aopOp (IC_RESULT (ic), ic, FALSE);
8214 size = AOP_SIZE (IC_RESULT (ic));
8219 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
8220 AOP (IC_RESULT (ic)), offset);
8221 if (hc08_aop_pass[offset]->type == AOP_REG)
8222 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
8227 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8230 /*-----------------------------------------------------------------*/
8231 /* genDummyRead - generate code for dummy read of volatiles */
8232 /*-----------------------------------------------------------------*/
8234 genDummyRead (iCode * ic)
8239 D(emitcode("; genDummyRead",""));
8242 if (op && IS_SYMOP (op))
8245 aopOp (op, ic, FALSE);
8247 size = AOP_SIZE (op);
8252 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8253 hc08_freeReg (hc08_reg_a);
8257 freeAsmop (op, NULL, ic, TRUE);
8260 if (op && IS_SYMOP (op))
8263 aopOp (op, ic, FALSE);
8265 size = AOP_SIZE (op);
8270 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8271 hc08_freeReg (hc08_reg_a);
8275 freeAsmop (op, NULL, ic, TRUE);
8279 /*-----------------------------------------------------------------*/
8280 /* genCritical - generate code for start of a critical sequence */
8281 /*-----------------------------------------------------------------*/
8283 genCritical (iCode *ic)
8285 D(emitcode("; genCritical",""));
8288 aopOp (IC_RESULT (ic), ic, TRUE);
8290 emitcode ("tpa", "");
8291 hc08_dirtyReg (hc08_reg_a, FALSE);
8292 emitcode ("sei", "");
8295 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8297 pushReg (hc08_reg_a, FALSE);
8299 hc08_freeReg (hc08_reg_a);
8301 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8304 /*-----------------------------------------------------------------*/
8305 /* genEndCritical - generate code for end of a critical sequence */
8306 /*-----------------------------------------------------------------*/
8308 genEndCritical (iCode *ic)
8310 D(emitcode("; genEndCritical",""));
8314 aopOp (IC_RIGHT (ic), ic, FALSE);
8315 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8316 emitcode ("tap", "");
8317 hc08_freeReg (hc08_reg_a);
8318 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8322 pullReg (hc08_reg_a);
8323 emitcode ("tap", "");
8329 /*-----------------------------------------------------------------*/
8330 /* genhc08Code - generate code for HC08 based controllers */
8331 /*-----------------------------------------------------------------*/
8333 genhc08Code (iCode * lic)
8340 lineHead = lineCurr = NULL;
8342 /* print the allocation information */
8343 if (allocInfo && currFunc)
8344 printAllocInfo (currFunc, codeOutBuf);
8345 /* if debug information required */
8346 if (options.debug && currFunc)
8348 debugFile->writeFunction (currFunc, lic);
8351 if (IS_STATIC (currFunc->etype))
8352 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8354 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8358 /* stack pointer name */
8359 if (options.useXstack)
8364 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8366 hc08_aop_pass[0] = newAsmop (AOP_REG);
8367 hc08_aop_pass[0]->size=1;
8368 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8369 hc08_aop_pass[1] = newAsmop (AOP_REG);
8370 hc08_aop_pass[1]->size=1;
8371 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8372 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8373 hc08_aop_pass[2]->size=1;
8374 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8375 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8376 hc08_aop_pass[3]->size=1;
8377 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8379 for (ic = lic; ic; ic = ic->next)
8382 _G.current_iCode = ic;
8384 if (ic->level != clevel || ic->block != cblock)
8388 debugFile->writeScope(ic);
8394 if (ic->lineno && cln != ic->lineno)
8398 debugFile->writeCLine(ic);
8401 emitcode ("", "C$%s$%d$%d$%d ==.",
8402 FileBaseName (ic->filename), ic->lineno,
8403 ic->level, ic->block);
8407 if (!options.noCcodeInAsm) {
8408 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8409 printCLine(ic->filename, ic->lineno));
8413 if (options.iCodeInAsm) {
8418 for (i=0; i<6; i++) {
8419 sprintf (®sInUse[i],
8420 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8423 iLine = printILine(ic);
8424 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8427 /* if the result is marked as
8428 spilt and rematerializable or code for
8429 this has already been generated then
8431 if (resultRemat (ic) || ic->generated)
8439 for (i=A_IDX;i<=XA_IDX;i++)
8441 reg = hc08_regWithIdx(i);
8443 emitcode("","; %s = %s offset %d", reg->name,
8444 aopName(reg->aop), reg->aopofs);
8447 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8449 sym = OP_SYMBOL (IC_LEFT (ic));
8450 if (sym->accuse == ACCUSE_HX)
8452 hc08_reg_h->isFree = FALSE;
8453 hc08_reg_x->isFree = FALSE;
8455 else if (sym->accuse == ACCUSE_XA)
8457 hc08_reg_a->isFree = FALSE;
8459 hc08_reg_x->isFree = FALSE;
8462 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8464 sym = OP_SYMBOL (IC_RIGHT (ic));
8465 if (sym->accuse == ACCUSE_HX)
8467 hc08_reg_h->isFree = FALSE;
8468 hc08_reg_x->isFree = FALSE;
8470 else if (sym->accuse == ACCUSE_XA)
8472 hc08_reg_a->isFree = FALSE;
8474 hc08_reg_x->isFree = FALSE;
8479 /* depending on the operation */
8499 /* IPOP happens only when trying to restore a
8500 spilt live range, if there is an ifx statement
8501 following this pop then the if statement might
8502 be using some of the registers being popped which
8503 would destory the contents of the register so
8504 we need to check for this condition and handle it */
8506 ic->next->op == IFX &&
8507 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8508 genIfx (ic->next, ic);
8526 genEndFunction (ic);
8542 if (!genPointerGetSetOfs (ic))
8547 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8567 genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
8572 genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
8584 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8588 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8592 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8619 case GET_VALUE_AT_ADDRESS:
8621 hasInc (IC_LEFT (ic), ic,
8622 getSize (operandType (IC_RESULT (ic)))),
8623 ifxForOp (IC_RESULT (ic), ic) );
8627 if (POINTER_SET (ic))
8628 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8654 addSet (&_G.sendSet, ic);
8657 case DUMMY_READ_VOLATILE:
8666 genEndCritical (ic);
8677 if (!hc08_reg_a->isFree)
8678 DD(emitcode("","; forgot to free a"));
8679 if (!hc08_reg_x->isFree)
8680 DD(emitcode("","; forgot to free x"));
8681 if (!hc08_reg_h->isFree)
8682 DD(emitcode("","; forgot to free h"));
8683 if (!hc08_reg_hx->isFree)
8684 DD(emitcode("","; forgot to free hx"));
8685 if (!hc08_reg_xa->isFree)
8686 DD(emitcode("","; forgot to free xa"));
8689 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8692 /* now we are ready to call the
8693 peep hole optimizer */
8694 if (!options.nopeep)
8695 peepHole (&lineHead);
8697 /* now do the actual printing */
8698 printLine (lineHead, codeOutBuf);