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 FILE *codeOutFile;
87 //static void saveRBank (int, iCode *, bool);
88 static bool operandsEqu (operand * op1, operand * op2);
89 static void loadRegFromConst (regs *reg, char *c);
90 static char *aopName (asmop *aop);
91 static asmop * newAsmop (short type);
92 static char * aopAdrStr (asmop * aop, int loffset, bool bit16);
93 #define RESULTONSTACK(x) \
94 (IC_RESULT(x) && IC_RESULT(x)->aop && \
95 IC_RESULT(x)->aop->type == AOP_STK )
97 #define IS_AOP_HX(x) \
98 (((x)->type == AOP_REG) \
99 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
100 && ((x)->aopu.aop_reg[1] == hc08_reg_h) )
102 #define IS_AOP_XA(x) \
103 (((x)->type == AOP_REG) \
104 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
105 && ((x)->aopu.aop_reg[1] == hc08_reg_x) )
107 #define IS_AOP_A(x) \
108 (((x)->type == AOP_REG) \
109 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
110 && ((x)->size == 1) )
112 #define IS_AOP_X(x) \
113 (((x)->type == AOP_REG) \
114 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
115 && ((x)->size == 1) )
117 #define IS_AOP_H(x) \
118 (((x)->type == AOP_REG) \
119 && ((x)->aopu.aop_reg[0] == hc08_reg_h) \
120 && ((x)->size == 1) )
122 #define CLRC emitcode("clc","")
124 static lineNode *lineHead = NULL;
125 static lineNode *lineCurr = NULL;
128 static unsigned char SLMask[] =
129 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
130 0xE0, 0xC0, 0x80, 0x00};
131 static unsigned char SRMask[] =
132 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
133 0x07, 0x03, 0x01, 0x00};
141 #define AOP(op) op->aop
142 #define AOP_TYPE(op) AOP(op)->type
143 #define AOP_SIZE(op) AOP(op)->size
144 #define AOP_OP(aop) aop->op
147 /*-----------------------------------------------------------------*/
148 /* emitcode - writes the code into a file : for now it is simple */
149 /*-----------------------------------------------------------------*/
151 emitcode (char *inst, char *fmt,...)
154 char lb[INITIAL_INLINEASM];
162 sprintf (lb, "%s\t", inst);
164 sprintf (lb, "%s", inst);
165 vsprintf (lb + (strlen (lb)), fmt, ap);
168 vsprintf (lb, fmt, ap);
170 while (isspace ((unsigned char)*lbp))
174 lineCurr = (lineCurr ?
175 connectLine (lineCurr, newLineNode (lb)) :
176 (lineHead = newLineNode (lb)));
177 lineCurr->isInline = _G.inLine;
178 lineCurr->isDebug = _G.debugLine;
179 lineCurr->ic = _G.current_iCode;
180 lineCurr->isComment = (*lbp==';');
182 //printf("%s\n", lb);
187 emitBranch (char *branchop, symbol *tlbl)
189 emitcode (branchop, "%05d$", (tlbl->key + 100));
193 emitLabel (symbol *tlbl)
195 emitcode ("", "%05d$:", (tlbl->key +100));
196 lineCurr->isLabel = 1;
199 /*-----------------------------------------------------------------*/
200 /* hc08_emitDebuggerSymbol - associate the current code location */
201 /* with a debugger symbol */
202 /*-----------------------------------------------------------------*/
204 hc08_emitDebuggerSymbol (char * debugSym)
207 emitcode ("", "%s ==.", debugSym);
212 /*--------------------------------------------------------------------------*/
213 /* transferRegReg - Transfer from register(s) sreg to register(s) dreg. If */
214 /* freesrc is true, sreg is marked free and available for */
215 /* reuse. sreg and dreg must be of equal size */
216 /*--------------------------------------------------------------------------*/
218 transferRegReg (regs *sreg, regs *dreg, bool freesrc)
224 /* Nothing to do if no destination. */
228 /* But it's definately an error if there's no source. */
231 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
232 "NULL sreg in transferRegReg");
236 DD(emitcode ("", "; transferRegReg(%s,%s)",
237 sreg->name, dreg->name));
250 case H_IDX: /* H to A */
251 pushReg (hc08_reg_h, FALSE);
252 pullReg (hc08_reg_a);
254 case X_IDX: /* X to A */
255 emitcode ("txa", "");
264 case A_IDX: /* A to H */
265 pushReg (hc08_reg_a, FALSE);
266 pullReg (hc08_reg_h);
268 case X_IDX: /* X to H */
269 pushReg (hc08_reg_x, FALSE);
270 pullReg (hc08_reg_h);
279 case A_IDX: /* A to X */
280 emitcode ("tax", "");
282 case H_IDX: /* H to X */
283 pushReg (hc08_reg_h, FALSE);
284 pullReg (hc08_reg_x);
293 case XA_IDX: /* XA to HX */
294 pushReg (hc08_reg_x, FALSE);
295 pullReg (hc08_reg_h);
296 emitcode ("tax", "");
305 case HX_IDX: /* HX to XA */
306 emitcode ("txa", "");
307 pushReg (hc08_reg_h, FALSE);
308 pullReg (hc08_reg_x);
318 wassertl (!error, "bad combo in transferRegReg");
323 dreg->aop = sreg->aop;
324 dreg->aopofs = sreg->aopofs;
325 dreg->isFree = FALSE;
329 /*--------------------------------------------------------------------------*/
330 /* updateCFA - update the debugger information to reflect the current */
331 /* connonical frame address relative to the stack pointer */
332 /*--------------------------------------------------------------------------*/
336 /* there is no frame unless there is a function */
340 debugFile->writeFrameAddress (NULL, hc08_reg_sp,
341 1 + _G.stackOfs + _G.stackPushes);
344 /*--------------------------------------------------------------------------*/
345 /* pushReg - Push register reg onto the stack. If freereg is true, reg is */
346 /* marked free and available for reuse. */
347 /*--------------------------------------------------------------------------*/
349 pushReg (regs *reg, bool freereg)
351 int regidx = reg->rIdx;
356 emitcode ("psha", "");
361 emitcode ("pshx", "");
366 emitcode ("pshh", "");
371 emitcode ("pshx", "");
374 emitcode ("pshh", "");
379 emitcode ("psha", "");
382 emitcode ("pshx", "");
391 return -_G.stackOfs-_G.stackPushes;
394 /*--------------------------------------------------------------------------*/
395 /* pullReg - Pull register reg off the stack. */
396 /*--------------------------------------------------------------------------*/
400 int regidx = reg->rIdx;
405 emitcode ("pula", "");
410 emitcode ("pulx", "");
415 emitcode ("pulh", "");
420 emitcode ("pulh", "");
423 emitcode ("pulx", "");
428 emitcode ("pulx", "");
431 emitcode ("pula", "");
439 hc08_dirtyReg(reg, FALSE);
442 /*--------------------------------------------------------------------------*/
443 /* pullNull - Discard n bytes off the top of the stack */
444 /*--------------------------------------------------------------------------*/
450 emitcode("ais","#%d",n);
456 /*--------------------------------------------------------------------------*/
457 /* pushRegIfUsed - Push register reg if marked in use. Returns true if the */
458 /* push was performed, false otherwise. */
459 /*--------------------------------------------------------------------------*/
461 pushRegIfUsed (regs *reg)
472 /*--------------------------------------------------------------------------*/
473 /* pullOrFreeReg - If needpull is true, register reg is pulled from the */
474 /* stack. Otherwise register reg is marked as free. */
475 /*--------------------------------------------------------------------------*/
477 pullOrFreeReg (regs *reg, bool needpull)
485 /*--------------------------------------------------------------------------*/
486 /* adjustStack - Adjust the stack pointer by n bytes. */
487 /*--------------------------------------------------------------------------*/
495 emitcode ("ais","#127");
497 _G.stackPushes -= 127;
502 emitcode ("ais","#-128");
504 _G.stackPushes += 128;
509 emitcode ("ais", "#%d", n);
518 /*--------------------------------------------------------------------------*/
519 /* aopName - Return a string with debugging information about an asmop. */
520 /*--------------------------------------------------------------------------*/
524 static char buffer[256];
528 return "(asmop*)NULL";
533 sprintf (buf,"IMMD(%s)", aop->aopu.aop_immd.aop_immd1);
536 sprintf (buf,"LIT(%s)", aopLiteral (aop->aopu.aop_lit, 0));
539 sprintf (buf,"DIR(%s)", aop->aopu.aop_dir);
542 sprintf (buf,"EXT(%s)", aop->aopu.aop_dir);
545 sprintf (buf,"SOF(%s)", OP_SYMBOL (aop->op)->name);
548 sprintf (buf, "REG(%s,%s,%s,%s)",
549 aop->aopu.aop_reg[3] ? aop->aopu.aop_reg[3]->name : "-",
550 aop->aopu.aop_reg[2] ? aop->aopu.aop_reg[2]->name : "-",
551 aop->aopu.aop_reg[1] ? aop->aopu.aop_reg[1]->name : "-",
552 aop->aopu.aop_reg[0] ? aop->aopu.aop_reg[0]->name : "-");
559 sprintf (buf,"?%d", aop->type);
567 /*--------------------------------------------------------------------------*/
568 /* loadRegFromAop - Load register reg from logical offset loffset of aop. */
569 /*--------------------------------------------------------------------------*/
571 loadRegFromAop (regs *reg, asmop *aop, int loffset)
573 int regidx = reg->rIdx;
575 if (aop->stacked && aop->stk_aop[loffset])
577 loadRegFromAop (reg, aop->stk_aop[loffset], 0);
582 printf("loadRegFromAop called\n");
585 printf(" reg = NULL\n");
588 printf(" reg = %s\n", reg->name);
591 printf(" aop = NULL\n");
594 printf(" aop->type = %d\n", aop->type);
595 printf(" loffset = %d\n", loffset);
598 printf(" aop has operand link\n");
600 printf(" aop missing operand link\n");
602 printf(" reg has operand link\n");
604 printf(" reg missing operand link\n");
607 DD(emitcode ("", "; loadRegFromAop (%s, %s, %d)",
608 reg->name, aopName (aop), loffset));
610 /* If operand is volatile, we cannot optimize. */
611 if (!aop->op || isOperandVolatile (aop->op, FALSE))
615 /* If this register already has this offset of the operand
616 then we need only mark it as in use. */
617 if (reg->aop && reg->aop->op && aop->op
618 && operandsEqu(reg->aop->op,aop->op)
619 && (reg->aopofs == loffset))
622 DD(emitcode ("","; already had correct value for %s", reg->name));
626 /* TODO: check to see if we can transfer from another register */
628 if (hc08_reg_h->aop && hc08_reg_h->aop->op && aop->op
629 && operandsEqu(hc08_reg_h->aop->op,aop->op)
630 && (hc08_reg_h->aopofs == loffset))
632 DD(emitcode ("","; found correct value for %s in h", reg->name));
633 transferRegReg (hc08_reg_h, reg, FALSE);
639 if (hc08_reg_x->aop && hc08_reg_x->aop->op && aop->op
640 && operandsEqu(hc08_reg_x->aop->op,aop->op)
641 && (hc08_reg_x->aopofs == loffset))
643 DD(emitcode ("","; found correct value for %s in x", reg->name));
644 transferRegReg (hc08_reg_x, reg, FALSE);
649 if (hc08_reg_a->aop && hc08_reg_a->aop->op && aop->op
650 && operandsEqu(hc08_reg_a->aop->op,aop->op)
651 && (hc08_reg_a->aopofs == loffset))
653 DD(emitcode ("","; found correct value for %s in a", reg->name));
654 transferRegReg (hc08_reg_a, reg, FALSE);
664 if (aop->type == AOP_REG)
666 if (loffset < aop->size)
667 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
669 emitcode ("clra", ""); /* TODO: handle sign extension */
673 char * l = aopAdrStr (aop, loffset, FALSE);
674 if (!strcmp (l, zero))
675 emitcode ("clra", "");
677 emitcode ("lda", "%s", l);
681 if (aop->type == AOP_REG)
683 if (loffset < aop->size)
684 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
686 emitcode ("clrx", ""); /* TODO: handle sign extension */
690 char * l = aopAdrStr (aop, loffset, FALSE);
691 if (!strcmp (l, zero))
692 emitcode ("clrx", "");
694 emitcode ("ldx", "%s", l);
699 char * l = aopAdrStr (aop, loffset, FALSE);
700 if (!strcmp (l, zero))
702 emitcode ("clrh", "");
706 if (hc08_reg_a->isFree)
708 loadRegFromAop (hc08_reg_a, aop, loffset);
709 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
711 else if (hc08_reg_x->isFree)
713 loadRegFromAop (hc08_reg_x, aop, loffset);
714 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
718 pushReg (hc08_reg_a, TRUE);
719 loadRegFromAop (hc08_reg_a, aop, loffset);
720 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
721 pullReg (hc08_reg_a);
727 else if (IS_AOP_XA(aop))
728 transferRegReg (hc08_reg_xa, hc08_reg_hx, FALSE);
729 else if ((aop->type == AOP_DIR))
731 if (aop->size>(loffset+1))
732 emitcode ("ldhx","%s", aopAdrStr (aop, loffset+1, TRUE));
735 loadRegFromAop (hc08_reg_x, aop, loffset);
736 loadRegFromConst (hc08_reg_h, zero);
739 else if ((aop->type == AOP_LIT) || (aop->type == AOP_IMMD))
741 emitcode ("ldhx","%s", aopAdrStr (aop, loffset, TRUE));
746 needpula = pushRegIfUsed (hc08_reg_a);
747 loadRegFromAop (hc08_reg_a, aop, loffset+1);
748 loadRegFromAop (hc08_reg_x, aop, loffset);
749 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
750 pullOrFreeReg (hc08_reg_a, needpula);
756 else if (IS_AOP_HX(aop))
757 transferRegReg (hc08_reg_hx, hc08_reg_xa, FALSE);
760 loadRegFromAop (hc08_reg_a, aop, loffset);
761 loadRegFromAop (hc08_reg_x, aop, loffset+1);
766 // ignore caching for now
769 reg->aopofs = loffset;
774 /*--------------------------------------------------------------------------*/
775 /* forceStackedAop - Reserve space on the stack for asmop aop; when */
776 /* freeAsmop is called with aop, the stacked data will */
777 /* be copied to the original aop location. */
778 /*--------------------------------------------------------------------------*/
780 forceStackedAop (asmop *aop, bool copyOrig)
784 asmop *newaop = newAsmop (aop->type);
785 memcpy (newaop, aop, sizeof(*newaop));
787 DD(emitcode("", "; forcedStackAop %s", aopName(aop)));
789 if (copyOrig && hc08_reg_a->isFree)
791 else if (copyOrig && hc08_reg_x->isFree)
796 for (loffset=0; loffset < newaop->size; loffset++)
798 asmop *aopsof = newAsmop (AOP_SOF);
802 loadRegFromAop (reg, aop, loffset);
803 aopsof->aopu.aop_stk = pushReg (reg, FALSE);
807 aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE);
809 aopsof->op = aop->op;
810 newaop->stk_aop[loffset] = aopsof;
814 if (!reg && copyOrig)
816 for (loffset=0; loffset < newaop->size; loffset++)
818 transferAopAop (aop, loffset, newaop, loffset);
826 /*--------------------------------------------------------------------------*/
827 /* storeRegToAop - Store register reg to logical offset loffset of aop. */
828 /*--------------------------------------------------------------------------*/
830 storeRegToAop (regs *reg, asmop *aop, int loffset)
832 int regidx = reg->rIdx;
838 DD(emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
839 reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr));
841 if ((reg->rIdx == HX_IDX) && aop->stacked
842 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
844 storeRegToAop (hc08_reg_h, aop, loffset+1);
845 storeRegToAop (hc08_reg_x, aop, loffset);
849 if ((reg->rIdx == XA_IDX) && aop->stacked
850 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
852 storeRegToAop (hc08_reg_x, aop, loffset+1);
853 storeRegToAop (hc08_reg_a, aop, loffset);
857 if (aop->stacked && aop->stk_aop[loffset])
859 storeRegToAop (reg, aop->stk_aop[loffset], 0);
863 if (aop->type == AOP_STR)
866 transferRegReg (reg, hc08_reg_x, FALSE);
868 transferRegReg (reg, hc08_reg_h, FALSE);
872 if (aop->type == AOP_DUMMY)
875 if (aop->type == AOP_CRY) /* This can only happen if IFX was optimized */
876 return; /* away, so just toss the result */
881 if ((aop->type == AOP_REG) && (loffset < aop->size))
882 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
884 emitcode ("sta","%s", aopAdrStr (aop, loffset, FALSE));
887 if ((aop->type == AOP_REG) && (loffset < aop->size))
888 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
890 emitcode ("stx","%s", aopAdrStr (aop, loffset, FALSE));
893 if (hc08_reg_a->isFree)
895 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
896 storeRegToAop (hc08_reg_a, aop, loffset);
897 hc08_freeReg (hc08_reg_a);
899 else if (hc08_reg_x->isFree)
901 transferRegReg (hc08_reg_h, hc08_reg_x, FALSE);
902 storeRegToAop (hc08_reg_x, aop, loffset);
903 hc08_freeReg (hc08_reg_x);
907 pushReg (hc08_reg_a, TRUE);
908 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
909 storeRegToAop (hc08_reg_a, aop, loffset);
910 pullReg (hc08_reg_a);
914 if ((aop->type == AOP_DIR) )
916 emitcode("sthx","%s", aopAdrStr (aop, loffset+1, TRUE));
918 else if (IS_AOP_XA(aop))
919 transferRegReg(reg, hc08_reg_xa, FALSE);
920 else if (IS_AOP_HX(aop))
925 needpula = pushRegIfUsed (hc08_reg_a);
926 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
927 storeRegToAop (hc08_reg_a, aop, loffset+1);
928 storeRegToAop (hc08_reg_x, aop, loffset);
929 pullOrFreeReg (hc08_reg_a, needpula);
934 transferRegReg(reg, hc08_reg_hx, FALSE);
935 else if (IS_AOP_XA(aop))
939 storeRegToAop (hc08_reg_a, aop, loffset);
940 storeRegToAop (hc08_reg_x, aop, loffset+1);
945 /* Disable the register tracking for now */
947 //if (!reg->aop || (reg->aop && (reg->aop != aop)))
950 for (otheridx=0;otheridx<hc08_nRegs;otheridx++)
952 otherreg=hc08_regWithIdx(otheridx);
953 if (otherreg && otherreg->aop
954 && otherreg->aop->op && aop->op
955 && operandsEqu(otherreg->aop->op,aop->op)
956 && (otherreg->aopofs == loffset))
958 DD(emitcode("","; marking %s stale", otherreg->name));
962 if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
964 hc08_reg_hx->aop = NULL;
965 DD(emitcode("","; marking hx stale"));
967 if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
969 hc08_reg_xa->aop = NULL;
970 DD(emitcode("","; marking xa stale"));
974 reg->aopofs = loffset;
979 /*--------------------------------------------------------------------------*/
980 /* loadRegFromConst - Load register reg from constant c. */
981 /*--------------------------------------------------------------------------*/
983 loadRegFromConst (regs *reg, char *c)
989 emitcode ("clra", "");
991 emitcode ("lda", "%s", c);
995 emitcode ("clrx", "");
997 emitcode ("ldx", "%s", c);
1000 if (!strcmp(c,zero))
1001 emitcode ("clrh", "");
1002 else if (hc08_reg_a->isFree)
1004 loadRegFromConst (hc08_reg_a, c);
1005 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
1007 else if (hc08_reg_x->isFree)
1009 loadRegFromConst (hc08_reg_x, c);
1010 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
1014 pushReg (hc08_reg_a, TRUE);
1015 loadRegFromConst (hc08_reg_a, c);
1016 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
1017 pullReg (hc08_reg_a);
1021 emitcode ("ldhx", "%s", c);
1024 emitcode ("lda", "%s", c);
1025 emitcode ("ldx", "%s >> 8", c);
1028 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1029 "Bad rIdx in loadRegFromConst");
1036 /*--------------------------------------------------------------------------*/
1037 /* storeConstToAop- Store constant c to logical offset loffset of asmop aop.*/
1038 /*--------------------------------------------------------------------------*/
1040 storeConstToAop (char *c, asmop *aop, int loffset)
1042 if (aop->stacked && aop->stk_aop[loffset])
1044 storeConstToAop (c, aop->stk_aop[loffset], 0);
1051 if (!strcmp(c,zero))
1052 emitcode ("clr", "%s", aopAdrStr (aop, loffset, FALSE));
1054 emitcode ("mov", "%s,%s", c, aopAdrStr (aop, loffset, FALSE));
1057 if (loffset>(aop->size-1))
1059 loadRegFromConst (aop->aopu.aop_reg[loffset], c);
1064 if (hc08_reg_a->isFree)
1066 loadRegFromConst (hc08_reg_a, c);
1067 storeRegToAop( hc08_reg_a, aop, loffset);
1068 hc08_freeReg (hc08_reg_a);
1070 else if (hc08_reg_x->isFree)
1072 loadRegFromConst (hc08_reg_x, c);
1073 storeRegToAop( hc08_reg_x, aop, loffset);
1074 hc08_freeReg (hc08_reg_x);
1078 pushReg (hc08_reg_a, TRUE);
1079 loadRegFromConst (hc08_reg_a, c);
1080 storeRegToAop( hc08_reg_a, aop, loffset);
1081 pullReg (hc08_reg_a);
1087 /*--------------------------------------------------------------------------*/
1088 /* storeRegSignToUpperAop - If isSigned is true, the sign bit of register */
1089 /* reg is extended to fill logical offsets loffset */
1090 /* and above of asmop aop. Otherwise, logical */
1091 /* offsets loffset and above of asmop aop are */
1092 /* zeroed. reg must be an 8-bit register. */
1093 /*--------------------------------------------------------------------------*/
1095 storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned)
1097 // int regidx = reg->rIdx;
1098 int size = aop->size;
1106 while (loffset<size)
1107 storeConstToAop(zero, aop, loffset++);
1112 transferRegReg (reg, hc08_reg_a, FALSE);
1113 emitcode ("rola","");
1114 emitcode ("clra","");
1115 emitcode ("sbc", "#0");
1116 hc08_useReg (hc08_reg_a);
1117 while (loffset<size)
1118 storeRegToAop (hc08_reg_a, aop, loffset++);
1119 hc08_freeReg (hc08_reg_a);
1123 /*--------------------------------------------------------------------------*/
1124 /* storeRegToFullAop - Store register reg to asmop aop with appropriate */
1125 /* padding and/or truncation as needed. If isSigned is */
1126 /* true, sign extension will take place in the padding. */
1127 /*--------------------------------------------------------------------------*/
1129 storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
1131 int regidx = reg->rIdx;
1132 int size = aop->size;
1139 storeRegToAop (reg, aop, 0);
1140 storeRegSignToUpperAop (reg, aop, 1, isSigned);
1145 storeRegToAop (hc08_reg_x, aop, 0);
1149 storeRegToAop (reg, aop, 0);
1150 storeRegSignToUpperAop (hc08_reg_h, aop, 2, isSigned);
1156 storeRegToAop (hc08_reg_a, aop, 0);
1160 storeRegToAop (reg, aop, 0);
1161 storeRegSignToUpperAop (hc08_reg_x, aop, 2, isSigned);
1167 /*--------------------------------------------------------------------------*/
1168 /* transferAopAop - Transfer the value at logical offset srcofs of asmop */
1169 /* srcaop to logical offset dstofs of asmop dstaop. */
1170 /*--------------------------------------------------------------------------*/
1172 transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
1174 bool needpula = FALSE;
1177 bool keepreg = FALSE;
1179 /* ignore transfers at the same byte, unless its volatile */
1180 if (srcaop->op && !isOperandVolatile (srcaop->op, FALSE)
1181 && dstaop->op && !isOperandVolatile (dstaop->op, FALSE)
1182 && operandsEqu(srcaop->op, dstaop->op) && srcofs == dstofs
1183 && dstaop->type == srcaop->type)
1186 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1188 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1192 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1194 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1198 // DD(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1199 // aopName (srcaop), srcofs, aopName (dstaop), dstofs));
1200 // DD(emitcode ("", "; srcaop->type = %d", srcaop->type));
1201 // DD(emitcode ("", "; dstaop->type = %d", dstaop->type));
1203 if (dstofs >= dstaop->size)
1206 if ((dstaop->type == AOP_DIR)
1207 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1209 if (srcaop->type == AOP_LIT)
1212 unsigned long bytemask;
1214 lit = (unsigned long) floatFromVal (srcaop->aopu.aop_lit);
1215 bytemask = (lit >> (srcofs*8)) & 0xff;
1219 emitcode ("clr", "%s", aopAdrStr(dstaop, dstofs, FALSE));
1224 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1225 aopAdrStr(dstaop, dstofs, FALSE));
1229 if (dstaop->type == AOP_REG)
1231 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1232 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1234 reg = dstaop->aopu.aop_reg[dstofs];
1239 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1241 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1242 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1244 reg = srcaop->aopu.aop_reg[srcofs];
1251 if (hc08_reg_a->isFree)
1253 else if (hc08_reg_x->isFree)
1257 pushReg (hc08_reg_a, TRUE);
1263 loadRegFromAop (reg, srcaop, srcofs);
1264 storeRegToAop (reg, dstaop, dstofs);
1267 pullOrFreeReg (hc08_reg_a, needpula);
1271 /*--------------------------------------------------------------------------*/
1272 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1273 /* parameter param. */
1274 /*--------------------------------------------------------------------------*/
1276 accopWithMisc (char *accop, char *param)
1278 emitcode (accop, "%s", param);
1279 hc08_dirtyReg (hc08_reg_a, FALSE);
1282 /*--------------------------------------------------------------------------*/
1283 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1284 /* byte at logical offset loffset of asmop aop. */
1285 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1286 /*--------------------------------------------------------------------------*/
1288 accopWithAop (char *accop, asmop *aop, int loffset)
1290 if (aop->stacked && aop->stk_aop[loffset])
1292 accopWithAop (accop, aop->stk_aop[loffset], 0);
1296 if (aop->type == AOP_DUMMY)
1299 if (aop->type == AOP_REG)
1301 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1302 emitcode (accop, "1,s");
1306 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1308 hc08_dirtyReg (hc08_reg_a, FALSE);
1312 /*--------------------------------------------------------------------------*/
1313 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1314 /* byte at logical offset loffset of asmop aop. Register reg */
1315 /* must be 8-bit. */
1316 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1317 /*--------------------------------------------------------------------------*/
1319 rmwWithReg (char *rmwop, regs *reg)
1322 char *rmwaop = rmwbuf;
1324 if (reg->rIdx == A_IDX)
1326 sprintf(rmwaop,"%sa", rmwop);
1327 emitcode (rmwaop, "");
1328 hc08_dirtyReg (hc08_reg_a, FALSE);
1330 else if (reg->rIdx == X_IDX)
1332 sprintf(rmwaop,"%sx", rmwop);
1333 emitcode (rmwaop, "");
1334 hc08_dirtyReg (hc08_reg_a, FALSE);
1336 else if (hc08_reg_a->isFree)
1338 transferRegReg(reg, hc08_reg_a, FALSE);
1339 sprintf(rmwaop,"%sa", rmwop);
1340 emitcode (rmwaop, "");
1341 hc08_dirtyReg (hc08_reg_a, FALSE);
1342 transferRegReg(hc08_reg_a, reg, TRUE);
1346 pushReg (reg, FALSE);
1347 emitcode (rmwop, "1,s");
1349 hc08_dirtyReg (reg, FALSE);
1353 /*--------------------------------------------------------------------------*/
1354 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1355 /* logical offset loffset of asmop aop. */
1356 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror, tst */
1357 /*--------------------------------------------------------------------------*/
1359 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1361 bool needpula = FALSE;
1363 if (aop->stacked && aop->stk_aop[loffset])
1365 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1372 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1375 needpula = pushRegIfUsed (hc08_reg_a);
1376 loadRegFromAop (hc08_reg_a, aop, loffset);
1377 rmwWithReg (rmwop, hc08_reg_a);
1378 if (strcmp ("tst", rmwop))
1379 storeRegToAop (hc08_reg_a, aop, loffset);
1380 pullOrFreeReg (hc08_reg_a, needpula);
1385 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1391 /*-----------------------------------------------------------------*/
1392 /* newAsmop - creates a new asmOp */
1393 /*-----------------------------------------------------------------*/
1395 newAsmop (short type)
1399 aop = Safe_calloc (1, sizeof (asmop));
1406 /*-----------------------------------------------------------------*/
1407 /* pointerCode - returns the code for a pointer type */
1408 /*-----------------------------------------------------------------*/
1410 pointerCode (sym_link * etype)
1413 return PTR_TYPE (SPEC_OCLS (etype));
1418 /*-----------------------------------------------------------------*/
1419 /* aopForSym - for a true symbol */
1420 /*-----------------------------------------------------------------*/
1422 aopForSym (iCode * ic, symbol * sym, bool result)
1427 wassertl (ic != NULL, "Got a null iCode");
1428 wassertl (sym != NULL, "Got a null symbol");
1430 // printf("in aopForSym for symbol %s\n", sym->name);
1432 space = SPEC_OCLS (sym->etype);
1434 /* if already has one */
1440 /* special case for a function */
1441 if (IS_FUNC (sym->type))
1443 sym->aop = aop = newAsmop (AOP_IMMD);
1444 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1445 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1446 aop->size = FPTRSIZE;
1450 /* if it is in direct space */
1451 if (IN_DIRSPACE (space))
1453 sym->aop = aop = newAsmop (AOP_DIR);
1454 aop->aopu.aop_dir = sym->rname;
1455 aop->size = getSize (sym->type);
1459 /* if it is in far space */
1460 if (IN_FARSPACE (space))
1462 sym->aop = aop = newAsmop (AOP_EXT);
1463 aop->aopu.aop_dir = sym->rname;
1464 aop->size = getSize (sym->type);
1468 if (IN_STACK (sym->etype))
1470 sym->aop = aop = newAsmop (AOP_SOF);
1471 aop->aopu.aop_dir = sym->rname;
1472 aop->size = getSize (sym->type);
1473 aop->aopu.aop_stk = sym->stack;
1479 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1480 "aopForSym should never reach here");
1484 /* if it is in code space */
1485 if (IN_CODESPACE (space))
1491 /*-----------------------------------------------------------------*/
1492 /* aopForRemat - rematerialzes an object */
1493 /*-----------------------------------------------------------------*/
1495 aopForRemat (symbol * sym)
1497 iCode *ic = sym->rematiCode;
1505 val += (int) operandLitValue (IC_RIGHT (ic));
1506 else if (ic->op == '-')
1507 val -= (int) operandLitValue (IC_RIGHT (ic));
1508 else if (IS_CAST_ICODE(ic)) {
1509 sym_link *from_type = operandType(IC_RIGHT(ic));
1510 aop->aopu.aop_immd.from_cast_remat = 1;
1511 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1512 ptr_type = DCL_TYPE(from_type);
1513 if (ptr_type == IPOINTER) {
1520 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1523 if (ic->op == ADDRESS_OF)
1526 sprintf (buffer, "(%s %c 0x%04x)",
1527 OP_SYMBOL (IC_LEFT (ic))->rname,
1528 val >= 0 ? '+' : '-',
1529 abs (val) & 0xffff);
1531 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1533 aop = newAsmop (AOP_IMMD);
1534 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1535 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1536 /* set immd2 field if required */
1537 if (aop->aopu.aop_immd.from_cast_remat)
1539 sprintf(buffer,"#0x%02x",ptr_type);
1540 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1541 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1544 else if (ic->op == '=')
1546 val += (int) operandLitValue (IC_RIGHT (ic));
1548 sprintf (buffer, "0x%04x", val);
1549 aop = newAsmop (AOP_LIT);
1550 aop->aopu.aop_lit = constVal (buffer);
1553 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1554 "unexpected rematerialization");
1561 /*-----------------------------------------------------------------*/
1562 /* regsInCommon - two operands have some registers in common */
1563 /*-----------------------------------------------------------------*/
1565 regsInCommon (operand * op1, operand * op2)
1567 symbol *sym1, *sym2;
1570 /* if they have registers in common */
1571 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1574 sym1 = OP_SYMBOL (op1);
1575 sym2 = OP_SYMBOL (op2);
1577 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1580 for (i = 0; i < sym1->nRegs; i++)
1586 for (j = 0; j < sym2->nRegs; j++)
1591 if (sym2->regs[j] == sym1->regs[i])
1599 /*-----------------------------------------------------------------*/
1600 /* operandsEqu - equivalent */
1601 /*-----------------------------------------------------------------*/
1603 operandsEqu (operand * op1, operand * op2)
1605 symbol *sym1, *sym2;
1607 /* if they not symbols */
1608 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1611 sym1 = OP_SYMBOL (op1);
1612 sym2 = OP_SYMBOL (op2);
1614 /* if both are itemps & one is spilt
1615 and the other is not then false */
1616 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1617 sym1->isspilt != sym2->isspilt)
1620 /* if they are the same */
1624 if (sym1->rname[0] && sym2->rname[0]
1625 && strcmp (sym1->rname, sym2->rname) == 0)
1628 /* if left is a tmp & right is not */
1629 if (IS_ITEMP (op1) &&
1632 (sym1->usl.spillLoc == sym2))
1635 if (IS_ITEMP (op2) &&
1639 (sym2->usl.spillLoc == sym1))
1645 /*-----------------------------------------------------------------*/
1646 /* sameRegs - two asmops have the same registers */
1647 /*-----------------------------------------------------------------*/
1649 sameRegs (asmop * aop1, asmop * aop2)
1656 // if (aop1->size != aop2->size)
1659 if (aop1->type == aop2->type)
1664 for (i = 0; i < aop1->size; i++)
1665 if (aop1->aopu.aop_reg[i] !=
1666 aop2->aopu.aop_reg[i])
1670 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1673 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1680 /*-----------------------------------------------------------------*/
1681 /* aopOp - allocates an asmop for an operand : */
1682 /*-----------------------------------------------------------------*/
1684 aopOp (operand * op, iCode * ic, bool result)
1693 // Is this a pointer set result?
1695 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1699 // printf("checking literal\n");
1700 /* if this a literal */
1701 if (IS_OP_LITERAL (op))
1703 op->aop = aop = newAsmop (AOP_LIT);
1704 aop->aopu.aop_lit = op->operand.valOperand;
1705 aop->size = getSize (operandType (op));
1707 aop->isaddr = op->isaddr;
1711 // printf("checking pre-existing\n");
1712 /* if already has a asmop then continue */
1716 op->aop->isaddr = op->isaddr;
1720 // printf("checking underlying sym\n");
1721 /* if the underlying symbol has a aop */
1722 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1724 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1725 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1726 //op->aop = aop = OP_SYMBOL (op)->aop;
1727 aop->size = getSize( operandType (op));
1728 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1729 //printf (" with size = %d\n", aop->size);
1732 aop->isaddr = op->isaddr;
1733 /* if (aop->isaddr & IS_ITEMP (op))
1735 aop->psize=aop->size;
1736 aop->size = getSize( operandType (op)->next);
1741 // printf("checking true sym\n");
1742 /* if this is a true symbol */
1743 if (IS_TRUE_SYMOP (op))
1745 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1747 aop->isaddr = op->isaddr;
1748 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1749 //printf (" with size = %d\n", aop->size);
1753 /* this is a temporary : this has
1759 e) can be a return use only */
1761 sym = OP_SYMBOL (op);
1763 // printf("checking conditional\n");
1764 /* if the type is a conditional */
1765 if (sym->regType == REG_CND)
1767 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1770 aop->isaddr = op->isaddr;
1774 // printf("checking spilt\n");
1775 /* if it is spilt then two situations
1777 b) has a spill location */
1778 if (sym->isspilt || sym->nRegs == 0)
1781 // printf("checking remat\n");
1782 /* rematerialize it NOW */
1785 sym->aop = op->aop = aop =
1787 aop->size = getSize (sym->type);
1789 aop->isaddr = op->isaddr;
1790 /* if (aop->isaddr & IS_ITEMP (op))
1792 aop->psize=aop->size;
1793 aop->size = getSize( operandType (op)->next);
1798 // printf("checking accuse\n");
1801 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1802 aop->size = getSize (sym->type);
1803 switch (sym->accuse)
1806 aop->aopu.aop_reg[0] = hc08_reg_a;
1807 aop->aopu.aop_reg[1] = hc08_reg_x;
1810 aop->aopu.aop_reg[0] = hc08_reg_x;
1811 aop->aopu.aop_reg[1] = hc08_reg_h;
1815 aop->isaddr = op->isaddr;
1819 // printf("checking ruonly\n");
1825 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1826 aop->size = getSize (sym->type);
1827 for (i = 0; i < fReturnSizeHC08; i++)
1828 aop->aopu.aop_str[i] = fReturn2[i];
1830 aop->isaddr = op->isaddr;
1834 /* else spill location */
1835 if (sym->usl.spillLoc)
1837 asmop *oldAsmOp = NULL;
1839 if (sym->usl.spillLoc->aop
1840 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1842 /* force a new aop if sizes differ */
1843 oldAsmOp = sym->usl.spillLoc->aop;
1844 sym->usl.spillLoc->aop = NULL;
1845 //printf ("forcing new aop\n");
1847 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1848 if (sym->usl.spillLoc->aop->size != getSize (sym->type))
1850 /* Don't reuse the new aop, go with the last one */
1851 sym->usl.spillLoc->aop = oldAsmOp;
1853 aop->size = getSize (sym->type);
1855 aop->isaddr = op->isaddr;
1856 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1857 //printf (" with size = %d\n", aop->size);
1861 /* else must be a dummy iTemp */
1862 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1863 aop->size = getSize (sym->type);
1867 // printf("assuming register\n");
1868 /* must be in a register */
1869 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1870 aop->size = sym->nRegs;
1871 for (i = 0; i < sym->nRegs; i++)
1872 aop->aopu.aop_reg[i] = sym->regs[i];
1874 aop->isaddr = op->isaddr;
1878 /*-----------------------------------------------------------------*/
1879 /* freeAsmop - free up the asmop given to an operand */
1880 /*----------------------------------------------------------------*/
1882 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1904 DD(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1907 for (loffset=0; loffset<aop->size; loffset++)
1908 if (aop->stk_aop[loffset])
1910 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1913 pullNull (stackAdjust);
1917 /* all other cases just dealloc */
1923 OP_SYMBOL (op)->aop = NULL;
1924 /* if the symbol has a spill */
1926 SPIL_LOC (op)->aop = NULL;
1932 /*-----------------------------------------------------------------*/
1933 /* aopDerefAop - treating the aop parameter as a pointer, return */
1934 /* an asmop for the object it references */
1935 /*-----------------------------------------------------------------*/
1937 aopDerefAop (asmop *aop)
1942 asmop *newaop = NULL;
1943 sym_link *type, *etype;
1946 DD(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1950 type = operandType (aop->op);
1951 etype = getSpec (type);
1952 /* if op is of type of pointer then it is simple */
1953 if (IS_PTR (type) && !IS_FUNC (type->next))
1954 p_type = DCL_TYPE (type);
1957 /* we have to go by the storage class */
1958 p_type = PTR_TYPE (SPEC_OCLS (etype));
1967 if (p_type == POINTER)
1968 newaop = newAsmop (AOP_DIR);
1970 newaop = newAsmop (AOP_EXT);
1971 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1974 adr = (int) floatFromVal (aop->aopu.aop_lit);
1975 if (p_type == POINTER)
1980 newaop = newAsmop (AOP_DIR);
1981 sprintf (s, "0x%02x",adr);
1985 newaop = newAsmop (AOP_EXT);
1986 sprintf (s, "0x%04x",adr);
1988 rs = Safe_calloc (1, strlen (s) + 1);
1990 newaop->aopu.aop_dir = rs;
1993 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1994 "unsupported asmop");
2004 /*-----------------------------------------------------------------*/
2005 /* aopAdrStr - for referencing the address of the aop */
2006 /*-----------------------------------------------------------------*/
2008 aopAdrStr (asmop * aop, int loffset, bool bit16)
2012 int offset = aop->size - 1 - loffset;
2015 /* offset is greater than
2017 if (loffset > (aop->size - 1) &&
2018 aop->type != AOP_LIT)
2021 /* depending on type */
2029 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
2030 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
2032 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
2036 sprintf (s, "#(%s >> %d)",
2037 aop->aopu.aop_immd.aop_immd1,
2041 aop->aopu.aop_immd.aop_immd1);
2045 aop->aopu.aop_immd.aop_immd1);
2046 rs = Safe_calloc (1, strlen (s) + 1);
2052 sprintf (s, "*(%s + %d)",
2056 sprintf (s, "*%s", aop->aopu.aop_dir);
2057 rs = Safe_calloc (1, strlen (s) + 1);
2063 sprintf (s, "(%s + %d)",
2067 sprintf (s, "%s", aop->aopu.aop_dir);
2068 rs = Safe_calloc (1, strlen (s) + 1);
2073 return aop->aopu.aop_reg[loffset]->name;
2077 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
2079 return aopLiteral (aop->aopu.aop_lit, loffset);
2083 return aop->aopu.aop_str[loffset];
2086 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2088 rs = Safe_calloc (1, strlen (s) + 1);
2094 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2095 "aopAdrStr got unsupported aop->type");
2104 /*-----------------------------------------------------------------*/
2105 /* opIsGptr: returns non-zero if the passed operand is */
2106 /* a generic pointer type. */
2107 /*-----------------------------------------------------------------*/
2109 opIsGptr (operand * op)
2111 sym_link *type = operandType (op);
2113 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2121 /*-----------------------------------------------------------------*/
2122 /* getDataSize - get the operand data size */
2123 /*-----------------------------------------------------------------*/
2125 getDataSize (operand * op)
2128 size = AOP_SIZE (op);
2133 /*-----------------------------------------------------------------*/
2134 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2135 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2136 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2137 /*-----------------------------------------------------------------*/
2139 asmopToBool (asmop *aop, bool resultInA)
2141 symbol *tlbl, *tlbl1;
2142 int size = aop->size;
2143 bool needpula = FALSE;
2144 bool flagsonly = TRUE;
2149 hc08_freeReg(hc08_reg_a);
2156 emitcode ("tsta", "");
2159 else if (IS_AOP_X(aop))
2160 emitcode ("tstx", "");
2161 else if (IS_AOP_H(aop))
2163 if (hc08_reg_a->isFree)
2165 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2166 emitcode ("tsta", "");
2168 hc08_freeReg(hc08_reg_a);
2170 else if (hc08_reg_x->isFree)
2172 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2173 emitcode ("tstx", "");
2174 hc08_freeReg(hc08_reg_x);
2178 emitcode ("pshh", "");
2179 emitcode ("tst", "1,s");
2180 emitcode ("ais", "#1");
2183 else if (IS_AOP_HX(aop))
2184 emitcode ("cphx", zero);
2185 else if (IS_AOP_XA(aop))
2187 symbol *tlbl = newiTempLabel (NULL);
2188 emitcode ("tsta", "");
2189 emitcode ("bne", "%05d$", (tlbl->key + 100));
2190 emitcode ("tstx", "");
2195 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2196 "Bad rIdx in asmToBool");
2204 needpula = pushRegIfUsed (hc08_reg_a);
2205 loadRegFromAop (hc08_reg_a, aop, 0);
2206 for (offset=1; offset<size; offset++)
2207 accopWithAop ("ora", aop, offset);
2209 pullReg (hc08_reg_a);
2212 hc08_freeReg (hc08_reg_a);
2217 /* Higher levels should optimize this case away but let's be safe */
2218 if ((unsigned long) floatFromVal (aop->aopu.aop_lit))
2219 loadRegFromConst (hc08_reg_a, one);
2221 loadRegFromConst (hc08_reg_a, zero);
2222 hc08_freeReg(hc08_reg_a);
2229 loadRegFromAop (hc08_reg_a, aop, 0);
2230 hc08_freeReg (hc08_reg_a);
2234 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2239 if (hc08_reg_a->isFree)
2241 loadRegFromAop (hc08_reg_a, aop, 0);
2242 accopWithAop ("ora", aop, 1);
2243 hc08_freeReg (hc08_reg_a);
2248 tlbl = newiTempLabel (NULL);
2249 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2250 emitcode ("bne", "%05d$", (tlbl->key + 100));
2251 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2258 needpula = pushRegIfUsed (hc08_reg_a);
2259 loadRegFromAop (hc08_reg_a, aop, 0);
2260 for (offset=1; offset<size; offset++)
2261 accopWithAop ("ora", aop, offset);
2263 pullReg (hc08_reg_a);
2266 hc08_freeReg (hc08_reg_a);
2274 tlbl = newiTempLabel (NULL);
2278 tlbl1 = newiTempLabel (NULL);
2279 emitBranch ("bne", tlbl1);
2280 loadRegFromConst (hc08_reg_a, zero);
2281 emitBranch ("bra", tlbl);
2283 loadRegFromConst (hc08_reg_a, one);
2287 emitBranch ("beq", tlbl);
2288 loadRegFromConst (hc08_reg_a, one);
2291 hc08_useReg (hc08_reg_a);
2297 /*-----------------------------------------------------------------*/
2298 /* genNot - generate code for ! operation */
2299 /*-----------------------------------------------------------------*/
2303 D(emitcode ("; genNot",""));
2305 /* assign asmOps to operand & result */
2306 aopOp (IC_LEFT (ic), ic, FALSE);
2307 aopOp (IC_RESULT (ic), ic, TRUE);
2309 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2310 emitcode ("eor", one);
2311 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2313 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2314 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2318 /*-----------------------------------------------------------------*/
2319 /* genCpl - generate code for complement */
2320 /*-----------------------------------------------------------------*/
2326 regs* reg = hc08_reg_a;
2330 D(emitcode ("; genCpl",""));
2332 /* assign asmOps to operand & result */
2333 aopOp (IC_LEFT (ic), ic, FALSE);
2334 aopOp (IC_RESULT (ic), ic, TRUE);
2336 size = AOP_SIZE (IC_RESULT (ic));
2339 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2340 rmwWithReg ("com", reg);
2342 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2347 /* release the aops */
2348 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2349 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2352 /*-----------------------------------------------------------------*/
2353 /* genUminusFloat - unary minus for floating points */
2354 /*-----------------------------------------------------------------*/
2356 genUminusFloat (operand * op, operand * result)
2358 int size, offset = 0;
2361 D(emitcode ("; genUminusFloat",""));
2363 /* for this we just copy and then flip the bit */
2365 size = AOP_SIZE (op) - 1;
2369 transferAopAop (AOP (op), offset, AOP (result), offset);
2373 needpula = pushRegIfUsed (hc08_reg_a);
2374 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2375 emitcode ("eor", "#0x80");
2376 hc08_useReg (hc08_reg_a);
2377 storeRegToAop (hc08_reg_a, AOP (result), offset);
2378 pullOrFreeReg (hc08_reg_a, needpula);
2381 /*-----------------------------------------------------------------*/
2382 /* genUminus - unary minus code generation */
2383 /*-----------------------------------------------------------------*/
2385 genUminus (iCode * ic)
2388 sym_link *optype, *rtype;
2393 D(emitcode ("; genUminus",""));
2396 aopOp (IC_LEFT (ic), ic, FALSE);
2397 aopOp (IC_RESULT (ic), ic, TRUE);
2399 optype = operandType (IC_LEFT (ic));
2400 rtype = operandType (IC_RESULT (ic));
2402 /* if float then do float stuff */
2403 if (IS_FLOAT (optype))
2405 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2409 /* otherwise subtract from zero */
2410 size = AOP_SIZE (IC_LEFT (ic));
2415 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2416 needpula = pushRegIfUsed (hc08_reg_a);
2419 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2420 emitcode ("nega", "");
2421 hc08_freeReg (hc08_reg_a);
2422 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2423 SPEC_USIGN (operandType (IC_LEFT (ic))));
2424 pullOrFreeReg (hc08_reg_a, needpula);
2428 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2429 result = forceStackedAop (AOP (IC_RESULT (ic)), FALSE);
2431 result = AOP (IC_RESULT (ic));
2433 needpula = pushRegIfUsed (hc08_reg_a);
2437 loadRegFromConst (hc08_reg_a, zero);
2438 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2439 storeRegToAop (hc08_reg_a, result, offset++);
2442 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2443 SPEC_USIGN (operandType (IC_LEFT (ic))));
2444 pullOrFreeReg (hc08_reg_a, needpula);
2446 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2447 freeAsmop (NULL, result, ic, TRUE);
2453 /* release the aops */
2454 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2455 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2458 /*-----------------------------------------------------------------*/
2459 /* saveRegisters - will look for a call and save the registers */
2460 /*-----------------------------------------------------------------*/
2462 saveRegisters (iCode * lic)
2469 for (ic = lic; ic; ic = ic->next)
2470 if (ic->op == CALL || ic->op == PCALL)
2475 fprintf (stderr, "found parameter push with no function call\n");
2479 /* if the registers have been saved already or don't need to be then
2483 if (IS_SYMOP(IC_LEFT(ic)) &&
2484 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2485 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2488 /* safe the registers in use at this time but skip the
2489 ones for the result */
2490 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2491 hc08_rUmaskForOp (IC_RESULT(ic)));
2494 for (i = 0; i < hc08_nRegs; i++)
2496 if (bitVectBitValue (rsave, i))
2497 pushReg ( hc08_regWithIdx (i), FALSE);
2501 /*-----------------------------------------------------------------*/
2502 /* unsaveRegisters - pop the pushed registers */
2503 /*-----------------------------------------------------------------*/
2505 unsaveRegisters (iCode * ic)
2510 /* restore the registers in use at this time but skip the
2511 ones for the result */
2512 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2513 hc08_rUmaskForOp (IC_RESULT(ic)));
2515 for (i = hc08_nRegs; i >= 0; i--)
2517 if (bitVectBitValue (rsave, i))
2518 pullReg ( hc08_regWithIdx (i));
2524 /*-----------------------------------------------------------------*/
2526 /*-----------------------------------------------------------------*/
2528 pushSide (operand * oper, int size)
2533 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2534 pushReg ( hc08_reg_a, TRUE);
2538 /*-----------------------------------------------------------------*/
2539 /* assignResultValue - */
2540 /*-----------------------------------------------------------------*/
2542 assignResultValue (operand * oper)
2544 int size = AOP_SIZE (oper);
2548 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2549 if (hc08_aop_pass[offset]->type == AOP_REG)
2550 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2557 /*-----------------------------------------------------------------*/
2558 /* genIpush - genrate code for pushing this gets a little complex */
2559 /*-----------------------------------------------------------------*/
2561 genIpush (iCode * ic)
2563 int size, offset = 0;
2566 D(emitcode ("; genIpush",""));
2568 /* if this is not a parm push : ie. it is spill push
2569 and spill push is always done on the local stack */
2573 /* and the item is spilt then do nothing */
2574 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2577 aopOp (IC_LEFT (ic), ic, FALSE);
2578 size = AOP_SIZE (IC_LEFT (ic));
2580 /* push it on the stack */
2583 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2584 pushReg ( hc08_reg_a, TRUE);
2590 /* this is a paramter push: in this case we call
2591 the routine to find the call and save those
2592 registers that need to be saved */
2595 /* then do the push */
2596 aopOp (IC_LEFT (ic), ic, FALSE);
2599 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2600 size = AOP_SIZE (IC_LEFT (ic));
2603 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2604 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2606 if ((size==2) && hc08_reg_hx->isFree)
2608 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2609 pushReg (hc08_reg_hx, TRUE);
2616 // printf("loading %d\n", offset);
2617 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2618 // printf("pushing \n");
2619 pushReg (hc08_reg_a, TRUE);
2623 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2626 /*-----------------------------------------------------------------*/
2627 /* genIpop - recover the registers: can happen only for spilling */
2628 /*-----------------------------------------------------------------*/
2630 genIpop (iCode * ic)
2634 D(emitcode ("; genIpop",""));
2636 /* if the temp was not pushed then */
2637 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2640 aopOp (IC_LEFT (ic), ic, FALSE);
2641 size = AOP_SIZE (IC_LEFT (ic));
2645 pullReg (hc08_reg_a);
2646 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2648 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2652 /*-----------------------------------------------------------------*/
2653 /* genSend - gen code for SEND */
2654 /*-----------------------------------------------------------------*/
2655 static void genSend(set *sendSet)
2659 for (sic = setFirstItem (sendSet); sic;
2660 sic = setNextItem (sendSet)) {
2661 int size, offset = 0;
2662 aopOp (IC_LEFT (sic), sic, FALSE);
2663 size = AOP_SIZE (IC_LEFT (sic));
2668 transferAopAop( AOP (IC_LEFT (sic)), offset,
2669 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2673 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2677 /*-----------------------------------------------------------------*/
2678 /* genCall - generates a call statement */
2679 /*-----------------------------------------------------------------*/
2681 genCall (iCode * ic)
2684 // bool restoreBank = FALSE;
2685 // bool swapBanks = FALSE;
2687 D(emitcode("; genCall",""));
2689 dtype = operandType (IC_LEFT (ic));
2690 /* if send set is not empty then assign */
2693 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2694 genSend(reverseSet(_G.sendSet));
2696 genSend(_G.sendSet);
2702 /* if caller saves & we have not saved then */
2708 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2709 OP_SYMBOL (IC_LEFT (ic))->rname :
2710 OP_SYMBOL (IC_LEFT (ic))->name));
2713 /* if we need assign a result value */
2714 if ((IS_ITEMP (IC_RESULT (ic)) &&
2715 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2716 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2717 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2718 IS_TRUE_SYMOP (IC_RESULT (ic)))
2722 aopOp (IC_RESULT (ic), ic, FALSE);
2725 assignResultValue (IC_RESULT (ic));
2727 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2730 /* adjust the stack for parameters if
2734 pullNull (ic->parmBytes);
2737 /* if we had saved some registers then unsave them */
2738 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2739 unsaveRegisters (ic);
2743 /*-----------------------------------------------------------------*/
2744 /* -10l - generates a call by pointer statement */
2745 /*-----------------------------------------------------------------*/
2747 genPcall (iCode * ic)
2750 symbol *rlbl = newiTempLabel (NULL);
2751 symbol *tlbl = newiTempLabel (NULL);
2752 // bool restoreBank=FALSE;
2753 // bool swapBanks = FALSE;
2755 D(emitcode("; genPCall",""));
2757 /* if caller saves & we have not saved then */
2761 /* if we are calling a not _naked function that is not using
2762 the same register bank then we need to save the
2763 destination registers on the stack */
2764 dtype = operandType (IC_LEFT (ic))->next;
2766 /* now push the calling address */
2767 emitBranch ("bsr", tlbl);
2768 emitBranch ("bra", rlbl);
2770 _G.stackPushes += 2; /* account for the bsr return address now on stack */
2773 /* Push the function's address */
2774 aopOp (IC_LEFT (ic), ic, FALSE);
2775 pushSide (IC_LEFT (ic), FPTRSIZE);
2776 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2778 /* if send set is not empty the assign */
2781 genSend(reverseSet(_G.sendSet));
2787 emitcode ("rts", "");
2790 _G.stackPushes -= 4; /* account for rts here & in called function */
2794 /* if we need assign a result value */
2795 if ((IS_ITEMP (IC_RESULT (ic)) &&
2796 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2797 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2798 IS_TRUE_SYMOP (IC_RESULT (ic)))
2802 aopOp (IC_RESULT (ic), ic, FALSE);
2805 assignResultValue (IC_RESULT (ic));
2807 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2810 /* adjust the stack for parameters if
2814 pullNull (ic->parmBytes);
2817 /* if we hade saved some registers then
2819 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2820 unsaveRegisters (ic);
2823 /*-----------------------------------------------------------------*/
2824 /* resultRemat - result is rematerializable */
2825 /*-----------------------------------------------------------------*/
2827 resultRemat (iCode * ic)
2829 if (SKIP_IC (ic) || ic->op == IFX)
2832 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2834 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2835 if (sym->remat && !POINTER_SET (ic))
2842 #if defined(__BORLANDC__) || defined(_MSC_VER)
2843 #define STRCASECMP stricmp
2845 #define STRCASECMP strcasecmp
2848 /*-----------------------------------------------------------------*/
2849 /* inExcludeList - return 1 if the string is in exclude Reg list */
2850 /*-----------------------------------------------------------------*/
2852 regsCmp(void *p1, void *p2)
2854 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2858 inExcludeList (char *s)
2860 const char *p = setFirstItem(options.excludeRegsSet);
2862 if (p == NULL || STRCASECMP(p, "none") == 0)
2866 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2869 /*-----------------------------------------------------------------*/
2870 /* genFunction - generated code for function entry */
2871 /*-----------------------------------------------------------------*/
2873 genFunction (iCode * ic)
2875 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2877 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2878 int stackAdjust = sym->stack;
2879 int accIsFree = sym->recvSize == 0;
2883 /* create the function header */
2884 emitcode (";", "-----------------------------------------");
2885 emitcode (";", " function %s", sym->name);
2886 emitcode (";", "-----------------------------------------");
2888 emitcode ("", "%s:", sym->rname);
2889 lineCurr->isLabel = 1;
2890 ftype = operandType (IC_LEFT (ic));
2894 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2896 if (IFFUNC_ISNAKED(ftype))
2898 emitcode(";", "naked function: no prologue.");
2902 /* if this is an interrupt service routine then
2904 if (IFFUNC_ISISR (sym->type))
2907 if (!inExcludeList ("h"))
2908 pushReg (hc08_reg_h, FALSE);
2911 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2912 /* before setting up the stack frame completely. */
2913 while (ric && ric->next && ric->next->op == RECEIVE)
2915 while (ric && IC_RESULT (ric))
2917 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2918 int rsymSize = rsym ? getSize(rsym->type) : 0;
2922 if (rsym && rsym->regType == REG_CND)
2924 if (rsym && (rsym->accuse || rsym->ruonly))
2926 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2927 rsym = rsym->usl.spillLoc;
2930 /* If the RECEIVE operand immediately spills to the first entry on the */
2931 /* stack, we can push it directly rather than use an sp relative store. */
2932 if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize)
2936 _G.current_iCode = ric;
2937 D(emitcode ("; genReceive",""));
2938 for (ofs=0; ofs < rsymSize; ofs++)
2940 regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
2941 pushReg (reg, TRUE);
2942 if (reg->rIdx == A_IDX)
2946 _G.current_iCode = ic;
2949 ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
2952 /* adjust the stack for the function */
2955 adjustStack (-stackAdjust);
2957 _G.stackOfs = sym->stack;
2960 /* if critical function then turn interrupts off */
2961 if (IFFUNC_ISCRITICAL (ftype))
2965 /* Function was passed parameters, so make sure A is preserved */
2966 pushReg (hc08_reg_a, FALSE);
2967 pushReg (hc08_reg_a, FALSE);
2968 emitcode ("tpa", "");
2969 emitcode ("sta", "2,s");
2970 emitcode ("sei", "");
2971 pullReg (hc08_reg_a);
2975 /* No passed parameters, so A can be freely modified */
2976 emitcode ("tpa", "");
2977 pushReg (hc08_reg_a, TRUE);
2978 emitcode ("sei", "");
2984 /*-----------------------------------------------------------------*/
2985 /* genEndFunction - generates epilogue for functions */
2986 /*-----------------------------------------------------------------*/
2988 genEndFunction (iCode * ic)
2990 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2992 if (IFFUNC_ISNAKED(sym->type))
2994 emitcode(";", "naked function: no epilogue.");
2995 if (options.debug && currFunc)
2996 debugFile->writeEndFunction (currFunc, ic, 0);
3000 if (IFFUNC_ISCRITICAL (sym->type))
3002 if (!IS_VOID(sym->type->next))
3004 /* Function has return value, so make sure A is preserved */
3005 pushReg (hc08_reg_a, FALSE);
3006 emitcode ("lda", "2,s");
3007 emitcode ("tap", "");
3008 pullReg (hc08_reg_a);
3013 /* Function returns void, so A can be freely modified */
3014 pullReg (hc08_reg_a);
3015 emitcode ("tap", "");
3019 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
3025 _G.stackPushes += sym->stack;
3026 adjustStack (sym->stack);
3030 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3034 if (IFFUNC_ISISR (sym->type))
3037 if (!inExcludeList ("h"))
3038 pullReg (hc08_reg_h);
3041 /* if debug then send end of function */
3042 if (options.debug && currFunc)
3044 debugFile->writeEndFunction (currFunc, ic, 1);
3047 emitcode ("rti", "");
3051 if (IFFUNC_CALLEESAVES(sym->type))
3055 /* if any registers used */
3058 /* save the registers used */
3059 for (i = sym->regsUsed->size; i >= 0; i--)
3061 if (bitVectBitValue (sym->regsUsed, i) ||
3062 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3063 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3069 /* if debug then send end of function */
3070 if (options.debug && currFunc)
3072 debugFile->writeEndFunction (currFunc, ic, 1);
3075 emitcode ("rts", "");
3080 /*-----------------------------------------------------------------*/
3081 /* genRet - generate code for return statement */
3082 /*-----------------------------------------------------------------*/
3086 int size, offset = 0;
3089 D(emitcode ("; genRet",""));
3091 /* if we have no return value then
3092 just generate the "ret" */
3096 /* we have something to return then
3097 move the return value into place */
3098 aopOp (IC_LEFT (ic), ic, FALSE);
3099 size = AOP_SIZE (IC_LEFT (ic));
3105 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3112 /* 4 byte return: store value in the global return variable */
3116 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3117 STA (fReturn2[offset--], FALSE);
3118 hc08_freeReg (hc08_reg_a);
3122 /* 2 byte return: store value in x:a */
3123 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3124 hc08_freeReg (hc08_reg_xa);
3127 /* 1 byte return: store value in a */
3128 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3129 hc08_freeReg (hc08_reg_a);
3134 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3137 /* generate a jump to the return label
3138 if the next is not the return statement */
3139 if (!(ic->next && ic->next->op == LABEL &&
3140 IC_LABEL (ic->next) == returnLabel))
3142 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3146 /*-----------------------------------------------------------------*/
3147 /* genLabel - generates a label */
3148 /*-----------------------------------------------------------------*/
3150 genLabel (iCode * ic)
3155 /* For the high level labels we cannot depend on any */
3156 /* register's contents. Amnesia time. */
3157 for (i=A_IDX;i<=XA_IDX;i++)
3159 reg = hc08_regWithIdx(i);
3164 /* special case never generate */
3165 if (IC_LABEL (ic) == entryLabel)
3168 debugFile->writeLabel(IC_LABEL (ic), ic);
3170 emitLabel (IC_LABEL (ic));
3174 /*-----------------------------------------------------------------*/
3175 /* genGoto - generates a jmp */
3176 /*-----------------------------------------------------------------*/
3178 genGoto (iCode * ic)
3180 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3184 /*-----------------------------------------------------------------*/
3185 /* findLabelBackwards: walks back through the iCode chain looking */
3186 /* for the given label. Returns number of iCode instructions */
3187 /* between that label and given ic. */
3188 /* Returns zero if label not found. */
3189 /*-----------------------------------------------------------------*/
3191 findLabelBackwards (iCode * ic, int key)
3200 /* If we have any pushes or pops, we cannot predict the distance.
3201 I don't like this at all, this should be dealt with in the
3203 if (ic->op == IPUSH || ic->op == IPOP) {
3207 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3217 /*-----------------------------------------------------------------*/
3218 /* genPlusIncr :- does addition with increment if possible */
3219 /*-----------------------------------------------------------------*/
3221 genPlusIncr (iCode * ic)
3229 unsigned int size = getDataSize (IC_RESULT (ic));
3230 unsigned int offset;
3231 symbol *tlbl = NULL;
3233 left = IC_LEFT (ic);
3234 result = IC_RESULT (ic);
3236 /* will try to generate an increment */
3237 /* if the right side is not a literal
3239 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3242 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3244 DD(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3246 if ((IS_AOP_HX (AOP (left)) ||
3247 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3249 && (icount>=-128) && (icount<=127) && (size==2))
3251 if (!IS_AOP_HX (AOP (left)))
3253 needpulx = pushRegIfUsed (hc08_reg_x);
3254 needpulh = pushRegIfUsed (hc08_reg_h);
3261 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3262 emitcode ("aix","#%d", icount);
3263 hc08_dirtyReg (hc08_reg_hx, FALSE);
3264 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3265 pullOrFreeReg (hc08_reg_h, needpulh);
3266 pullOrFreeReg (hc08_reg_x, needpulx);
3270 DD(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3271 sameRegs (AOP (left), AOP (result))));
3273 if ((icount > 255) || (icount<0))
3276 if (!sameRegs (AOP (left), AOP (result)))
3279 D(emitcode ("; genPlusIncr",""));
3282 tlbl = newiTempLabel (NULL);
3287 rmwWithAop ("inc", AOP (result), 0);
3289 emitBranch ("bne", tlbl);
3293 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3294 needpula = pushRegIfUsed (hc08_reg_a);
3297 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3298 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3299 hc08_useReg (hc08_reg_a);
3300 storeRegToAop (hc08_reg_a, AOP (result), 0);
3301 hc08_freeReg (hc08_reg_a);
3303 emitBranch ("bcc", tlbl);
3305 for (offset=1; offset<size; offset++)
3307 rmwWithAop ("inc", AOP (result), offset);
3308 if ((offset+1)<size)
3309 emitBranch ("bne", tlbl);
3315 pullOrFreeReg (hc08_reg_a, needpula);
3322 /*-----------------------------------------------------------------*/
3323 /* genPlus - generates code for addition */
3324 /*-----------------------------------------------------------------*/
3326 genPlus (iCode * ic)
3328 int size, offset = 0;
3330 asmop *leftOp, *rightOp;
3332 /* special cases :- */
3334 D(emitcode ("; genPlus",""));
3336 aopOp (IC_LEFT (ic), ic, FALSE);
3337 aopOp (IC_RIGHT (ic), ic, FALSE);
3338 aopOp (IC_RESULT (ic), ic, TRUE);
3340 /* we want registers on the left and literals on the right */
3341 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3342 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3344 operand *t = IC_RIGHT (ic);
3345 IC_RIGHT (ic) = IC_LEFT (ic);
3350 /* if I can do an increment instead
3351 of add then GOOD for ME */
3352 if (genPlusIncr (ic) == TRUE)
3355 DD(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3356 DD(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3357 DD(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3359 size = getDataSize (IC_RESULT (ic));
3361 leftOp = AOP(IC_LEFT(ic));
3362 rightOp = AOP(IC_RIGHT(ic));
3368 loadRegFromAop (hc08_reg_a, leftOp, offset);
3369 accopWithAop(add, rightOp, offset);
3370 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3371 hc08_freeReg (hc08_reg_a);
3372 add = "adc"; /* further adds must propagate carry */
3376 // adjustArithmeticResult (ic);
3379 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3380 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3381 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3384 /*-----------------------------------------------------------------*/
3385 /* genMinusDec :- does subtraction with decrement if possible */
3386 /*-----------------------------------------------------------------*/
3388 genMinusDec (iCode * ic)
3390 unsigned int icount;
3395 unsigned int size = getDataSize (IC_RESULT (ic));
3399 left = IC_LEFT (ic);
3400 result = IC_RESULT (ic);
3402 /* will try to generate an increment */
3403 /* if the right side is not a literal
3405 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3408 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3410 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3411 && (icount>=-127) && (icount<=128) && (size==2))
3413 if (!IS_AOP_HX (AOP (left)))
3415 needpulx = pushRegIfUsed (hc08_reg_x);
3416 needpulh = pushRegIfUsed (hc08_reg_h);
3423 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3424 emitcode ("aix","#%d", -icount);
3425 hc08_dirtyReg (hc08_reg_hx, FALSE);
3426 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3427 pullOrFreeReg (hc08_reg_h, needpulh);
3428 pullOrFreeReg (hc08_reg_x, needpulx);
3432 if ((icount > 1) || (icount<0))
3435 if (!sameRegs (AOP (left), AOP (result)))
3441 D(emitcode ("; genMinusDec",""));
3443 rmwWithAop ("dec", AOP (result), 0);
3448 /*-----------------------------------------------------------------*/
3449 /* addSign - complete with sign */
3450 /*-----------------------------------------------------------------*/
3452 addSign (operand * result, int offset, int sign)
3454 int size = (getDataSize (result) - offset);
3459 emitcode ("rola", "");
3460 emitcode ("clra", "");
3461 emitcode ("sbc", zero);
3463 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3467 storeConstToAop (zero, AOP (result), offset++);
3472 /*-----------------------------------------------------------------*/
3473 /* genMinus - generates code for subtraction */
3474 /*-----------------------------------------------------------------*/
3476 genMinus (iCode * ic)
3479 int size, offset = 0;
3481 asmop *leftOp, *rightOp;
3483 D(emitcode ("; genMinus",""));
3485 aopOp (IC_LEFT (ic), ic, FALSE);
3486 aopOp (IC_RIGHT (ic), ic, FALSE);
3487 aopOp (IC_RESULT (ic), ic, TRUE);
3489 /* special cases :- */
3490 /* if I can do an decrement instead
3491 of subtract then GOOD for ME */
3492 if (genMinusDec (ic) == TRUE)
3495 size = getDataSize (IC_RESULT (ic));
3498 leftOp = AOP(IC_LEFT(ic));
3499 rightOp = AOP(IC_RIGHT(ic));
3503 if (IS_AOP_A (rightOp))
3505 loadRegFromAop ( hc08_reg_a, rightOp, offset);
3506 accopWithAop (sub, leftOp, offset);
3507 accopWithMisc ("nega", "");
3508 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3514 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3515 accopWithAop (sub, rightOp, offset);
3516 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3521 // adjustArithmeticResult (ic);
3524 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3525 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3526 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3531 /*-----------------------------------------------------------------*/
3532 /* genMultOneByte : 8*8=8/16 bit multiplication */
3533 /*-----------------------------------------------------------------*/
3535 genMultOneByte (operand * left,
3539 /* sym_link *opetype = operandType (result); */
3540 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3541 int size=AOP_SIZE(result);
3542 bool negLiteral = FALSE;
3543 bool lUnsigned, rUnsigned;
3545 D(emitcode ("; genMultOneByte",""));
3547 if (size<1 || size>2) {
3548 // this should never happen
3549 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3550 AOP_SIZE(result), __FILE__, lineno);
3554 /* (if two literals: the value is computed before) */
3555 /* if one literal, literal on the right */
3556 if (AOP_TYPE (left) == AOP_LIT)
3562 /* if an operand is in A, make sure it is on the left */
3563 if (IS_AOP_A (AOP (right)))
3570 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3571 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3573 /* lUnsigned rUnsigned negLiteral negate case */
3574 /* false false false odd 3 */
3575 /* false false true even 3 */
3576 /* false true false odd 3 */
3577 /* false true true impossible */
3578 /* true false false odd 3 */
3579 /* true false true always 2 */
3580 /* true true false never 1 */
3581 /* true true true impossible */
3585 || (lUnsigned && rUnsigned))
3587 // just an unsigned 8*8=8/16 multiply
3588 //DD(emitcode (";","unsigned"));
3590 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3591 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3592 emitcode ("mul", "");
3593 hc08_dirtyReg (hc08_reg_xa, FALSE);
3594 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3595 hc08_freeReg (hc08_reg_xa);
3600 // we have to do a signed multiply
3603 /* left unsigned, right signed literal -- literal determines sign handling */
3604 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3606 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3608 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3610 emitcode ("ldx", "#0x%02x", -val);
3612 emitcode ("ldx", "#0x%02x", val);
3614 emitcode ("mul", "");
3618 rmwWithReg ("neg", hc08_reg_a);
3619 tlbl4 = newiTempLabel (NULL);
3620 emitBranch ("bcc", tlbl4);
3621 rmwWithReg ("inc", hc08_reg_x);
3623 rmwWithReg ("neg", hc08_reg_x);
3626 hc08_dirtyReg (hc08_reg_xa, FALSE);
3627 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3628 hc08_freeReg (hc08_reg_xa);
3635 emitcode ("clr", "1,s");
3637 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3640 tlbl1 = newiTempLabel (NULL);
3641 emitcode ("tsta","");
3642 emitBranch ("bpl", tlbl1);
3643 emitcode ("inc", "1,s");
3644 rmwWithReg ("neg", hc08_reg_a);
3648 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3650 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3651 /* AND literal negative */
3653 emitcode ("ldx", "#0x%02x", -val);
3656 emitcode ("ldx", "#0x%02x", val);
3658 hc08_useReg (hc08_reg_x);
3662 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3665 tlbl2 = newiTempLabel (NULL);
3666 emitcode ("tstx", "");
3667 emitBranch ("bpl", tlbl2);
3668 emitcode ("inc", "1,s");
3669 rmwWithReg ("neg", hc08_reg_x);
3674 emitcode ("mul", "");
3675 hc08_dirtyReg (hc08_reg_xa, FALSE);
3677 tlbl3 = newiTempLabel (NULL);
3678 emitcode ("dec", "1,s");
3679 if (!lUnsigned && !rUnsigned && negLiteral)
3680 emitBranch ("beq", tlbl3);
3682 emitBranch ("bne", tlbl3);
3684 rmwWithReg ("neg", hc08_reg_a);
3685 tlbl4 = newiTempLabel (NULL);
3686 emitBranch ("bcc", tlbl4);
3687 rmwWithReg ("inc", hc08_reg_x);
3689 rmwWithReg ("neg", hc08_reg_x);
3693 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3694 hc08_freeReg (hc08_reg_xa);
3698 /*-----------------------------------------------------------------*/
3699 /* genMult - generates code for multiplication */
3700 /*-----------------------------------------------------------------*/
3702 genMult (iCode * ic)
3704 operand *left = IC_LEFT (ic);
3705 operand *right = IC_RIGHT (ic);
3706 operand *result = IC_RESULT (ic);
3708 D(emitcode ("; genMult",""));
3710 /* assign the amsops */
3711 aopOp (left, ic, FALSE);
3712 aopOp (right, ic, FALSE);
3713 aopOp (result, ic, TRUE);
3715 /* special cases first */
3716 /* if both are of size == 1 */
3717 // if (getSize(operandType(left)) == 1 &&
3718 // getSize(operandType(right)) == 1)
3719 if (AOP_SIZE (left) == 1 &&
3720 AOP_SIZE (right) == 1)
3722 genMultOneByte (left, right, result);
3726 /* should have been converted to function call */
3727 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3728 getSize(OP_SYMBOL(right)->type));
3729 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3734 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3735 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3736 freeAsmop (result, NULL, ic, TRUE);
3739 /*-----------------------------------------------------------------*/
3740 /* genDivOneByte : 8 bit division */
3741 /*-----------------------------------------------------------------*/
3743 genDivOneByte (operand * left,
3747 symbol *tlbl1, *tlbl2, *tlbl3;
3750 bool lUnsigned, rUnsigned;
3751 bool runtimeSign, compiletimeSign;
3753 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3754 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3756 D(emitcode ("; genDivOneByte",""));
3758 size = AOP_SIZE (result);
3759 /* signed or unsigned */
3760 if (lUnsigned && rUnsigned)
3762 /* unsigned is easy */
3763 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3764 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3765 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3766 emitcode ("div", "");
3767 hc08_dirtyReg (hc08_reg_a, FALSE);
3768 hc08_dirtyReg (hc08_reg_h, FALSE);
3769 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3770 hc08_freeReg (hc08_reg_a);
3771 hc08_freeReg (hc08_reg_x);
3772 hc08_freeReg (hc08_reg_h);
3776 /* signed is a little bit more difficult */
3778 /* now sign adjust for both left & right */
3780 /* let's see what's needed: */
3781 /* apply negative sign during runtime */
3782 runtimeSign = FALSE;
3783 /* negative sign from literals */
3784 compiletimeSign = FALSE;
3788 if (AOP_TYPE(left) == AOP_LIT)
3790 /* signed literal */
3791 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3793 compiletimeSign = TRUE;
3796 /* signed but not literal */
3802 if (AOP_TYPE(right) == AOP_LIT)
3804 /* signed literal */
3805 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3807 compiletimeSign ^= TRUE;
3810 /* signed but not literal */
3814 /* initialize the runtime sign */
3817 if (compiletimeSign)
3818 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3820 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3821 pushReg (hc08_reg_x, TRUE);
3824 /* save the signs of the operands */
3825 if (AOP_TYPE(right) == AOP_LIT)
3827 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3829 if (!rUnsigned && val < 0)
3830 emitcode ("ldx", "#0x%02x", -val);
3832 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3834 else /* ! literal */
3836 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3839 tlbl1 = newiTempLabel (NULL);
3840 emitcode ("tstx", "");
3841 emitBranch ("bpl", tlbl1);
3842 emitcode ("inc", "1,s");
3843 rmwWithReg ("neg", hc08_reg_x);
3848 if (AOP_TYPE(left) == AOP_LIT)
3850 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3852 if (!lUnsigned && val < 0)
3853 emitcode ("lda", "#0x%02x", -val);
3855 emitcode ("lda", "#0x%02x", (unsigned char) val);
3857 else /* ! literal */
3859 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3862 tlbl2 = newiTempLabel (NULL);
3863 emitcode ("tsta", "");
3864 emitBranch ("bpl", tlbl2);
3865 emitcode ("inc", "1,s");
3866 rmwWithReg ("neg", hc08_reg_a);
3871 loadRegFromConst (hc08_reg_h, zero);
3872 emitcode ("div", "");
3873 hc08_dirtyReg (hc08_reg_x, FALSE);
3874 hc08_dirtyReg (hc08_reg_a, FALSE);
3875 hc08_dirtyReg (hc08_reg_h, FALSE);
3877 if (runtimeSign || compiletimeSign)
3879 tlbl3 = newiTempLabel (NULL);
3882 pullReg (hc08_reg_x);
3883 rmwWithReg ("lsr", hc08_reg_x);
3884 rmwWithReg ("ror", hc08_reg_x);
3885 emitBranch ("bpl", tlbl3);
3888 rmwWithReg ("neg", hc08_reg_a);
3892 storeRegToAop (hc08_reg_a, AOP (result), 0);
3896 /* msb is 0x00 or 0xff depending on the sign */
3899 rmwWithReg ("lsl", hc08_reg_x);
3900 emitcode ("clra", "");
3901 emitcode ("sbc", "#0");
3903 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3905 else /* compiletimeSign */
3907 storeConstToAop ("#0xff", AOP (result), ++offset);
3912 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3915 hc08_freeReg (hc08_reg_a);
3916 hc08_freeReg (hc08_reg_x);
3917 hc08_freeReg (hc08_reg_h);
3920 /*-----------------------------------------------------------------*/
3921 /* genDiv - generates code for division */
3922 /*-----------------------------------------------------------------*/
3926 operand *left = IC_LEFT (ic);
3927 operand *right = IC_RIGHT (ic);
3928 operand *result = IC_RESULT (ic);
3930 D(emitcode ("; genDiv",""));
3932 /* assign the amsops */
3933 aopOp (left, ic, FALSE);
3934 aopOp (right, ic, FALSE);
3935 aopOp (result, ic, TRUE);
3937 /* special cases first */
3938 /* if both are of size == 1 */
3939 if (AOP_SIZE (left) <= 2 &&
3940 AOP_SIZE (right) == 1)
3942 genDivOneByte (left, right, result);
3946 /* should have been converted to function call */
3949 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3950 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3951 freeAsmop (result, NULL, ic, TRUE);
3954 /*-----------------------------------------------------------------*/
3955 /* genModOneByte : 8 bit modulus */
3956 /*-----------------------------------------------------------------*/
3958 genModOneByte (operand * left,
3962 symbol *tlbl1, *tlbl2, *tlbl3;
3965 bool lUnsigned, rUnsigned;
3966 bool runtimeSign, compiletimeSign;
3968 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3969 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3971 D(emitcode ("; genModOneByte",""));
3973 size = AOP_SIZE (result);
3975 if (lUnsigned && rUnsigned)
3977 /* unsigned is easy */
3978 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3979 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3980 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3981 emitcode ("div", "");
3982 hc08_freeReg (hc08_reg_a);
3983 hc08_freeReg (hc08_reg_x);
3984 hc08_dirtyReg (hc08_reg_h, FALSE);
3985 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3986 hc08_freeReg (hc08_reg_h);
3990 /* signed is a little bit more difficult */
3992 if (AOP_TYPE(right) == AOP_LIT)
3994 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3996 if (!rUnsigned && val < 0)
3997 emitcode ("ldx", "#0x%02x", -val);
3999 emitcode ("ldx", "#0x%02x", (unsigned char) val);
4001 else /* ! literal */
4003 loadRegFromAop (hc08_reg_x, AOP (right), 0);
4006 tlbl1 = newiTempLabel (NULL);
4007 emitcode ("tstx", "");
4008 emitBranch ("bpl", tlbl1);
4009 rmwWithReg ("neg", hc08_reg_x);
4014 /* let's see what's needed: */
4015 /* apply negative sign during runtime */
4016 runtimeSign = FALSE;
4017 /* negative sign from literals */
4018 compiletimeSign = FALSE;
4020 /* sign adjust left side */
4021 if (AOP_TYPE(left) == AOP_LIT)
4023 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4025 if (!lUnsigned && val < 0)
4027 compiletimeSign = TRUE; /* set sign flag */
4028 emitcode ("lda", "#0x%02x", -val);
4031 emitcode ("lda", "#0x%02x", (unsigned char) val);
4033 else /* ! literal */
4036 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4041 emitcode ("clr", "1,s");
4043 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4044 tlbl2 = newiTempLabel (NULL);
4045 emitcode ("tsta", "");
4046 emitBranch ("bpl", tlbl2);
4047 emitcode ("inc", "1,s");
4048 rmwWithReg ("neg", hc08_reg_a);
4053 loadRegFromConst (hc08_reg_h, zero);
4054 emitcode ("div", "");
4055 hc08_freeReg (hc08_reg_a);
4056 hc08_freeReg (hc08_reg_x);
4057 hc08_dirtyReg (hc08_reg_h, FALSE);
4059 if (runtimeSign || compiletimeSign)
4061 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4062 tlbl3 = newiTempLabel (NULL);
4065 pullReg (hc08_reg_x);
4066 rmwWithReg ("lsr", hc08_reg_x);
4067 rmwWithReg ("ror", hc08_reg_x);
4068 emitBranch ("bpl", tlbl3);
4071 rmwWithReg ("neg", hc08_reg_a);
4075 storeRegToAop (hc08_reg_a, AOP (result), 0);
4079 /* msb is 0x00 or 0xff depending on the sign */
4082 rmwWithReg ("lsl", hc08_reg_x);
4083 emitcode ("clra", "");
4084 emitcode ("sbc", "#0");
4086 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4088 else /* compiletimeSign */
4090 storeConstToAop ("#0xff", AOP (result), ++offset);
4095 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4098 hc08_freeReg (hc08_reg_a);
4099 hc08_freeReg (hc08_reg_x);
4100 hc08_freeReg (hc08_reg_h);
4103 /*-----------------------------------------------------------------*/
4104 /* genMod - generates code for division */
4105 /*-----------------------------------------------------------------*/
4109 operand *left = IC_LEFT (ic);
4110 operand *right = IC_RIGHT (ic);
4111 operand *result = IC_RESULT (ic);
4113 D(emitcode ("; genMod",""));
4115 /* assign the amsops */
4116 aopOp (left, ic, FALSE);
4117 aopOp (right, ic, FALSE);
4118 aopOp (result, ic, TRUE);
4120 /* special cases first */
4121 /* if both are of size == 1 */
4122 if (AOP_SIZE (left) <= 2 &&
4123 AOP_SIZE (right) == 1)
4125 genModOneByte (left, right, result);
4129 /* should have been converted to function call */
4133 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4134 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4135 freeAsmop (result, NULL, ic, TRUE);
4138 /*-----------------------------------------------------------------*/
4139 /* genIfxJump :- will create a jump depending on the ifx */
4140 /*-----------------------------------------------------------------*/
4142 genIfxJump (iCode * ic, char *jval)
4145 symbol *tlbl = newiTempLabel (NULL);
4148 D(emitcode ("; genIfxJump",""));
4150 /* if true label then we jump if condition
4154 jlbl = IC_TRUE (ic);
4155 if (!strcmp (jval, "a"))
4157 else if (!strcmp (jval, "c"))
4164 /* false label is present */
4165 jlbl = IC_FALSE (ic);
4166 if (!strcmp (jval, "a"))
4168 else if (!strcmp (jval, "c"))
4173 emitBranch (inst, tlbl);
4174 emitBranch ("jmp", jlbl);
4177 /* mark the icode as generated */
4182 /*-----------------------------------------------------------------*/
4183 /* exchangedCmp : returns the opcode need if the two operands are */
4184 /* exchanged in a comparison */
4185 /*-----------------------------------------------------------------*/
4187 exchangedCmp (int opcode)
4204 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4205 "opcode not a comparison");
4207 return EQ_OP; /* shouldn't happen, but need to return something */
4210 /*------------------------------------------------------------------*/
4211 /* negatedCmp : returns the equivalent opcode for when a comparison */
4213 /*------------------------------------------------------------------*/
4215 negatedCmp (int opcode)
4232 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4233 "opcode not a comparison");
4235 return EQ_OP; /* shouldn't happen, but need to return something */
4238 /* compile only if the debugging macro D is enabled */
4241 nameCmp (int opcode)
4263 /*------------------------------------------------------------------*/
4264 /* branchInstCmp : returns the conditional branch instruction that */
4265 /* will branch if the comparison is true */
4266 /*------------------------------------------------------------------*/
4268 branchInstCmp (int opcode, int sign)
4276 return "bcs"; /* same as blo */
4291 return "bcc"; /* same as bhs */
4297 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4298 "opcode not a comparison");
4304 /*------------------------------------------------------------------*/
4305 /* genCmp :- greater or less than (and maybe with equal) comparison */
4306 /*------------------------------------------------------------------*/
4308 genCmp (iCode * ic, iCode * ifx)
4310 operand *left, *right, *result;
4311 sym_link *letype, *retype;
4313 int size, offset = 0;
4314 unsigned long lit = 0L;
4316 symbol *jlbl = NULL;
4320 D(emitcode ("; genCmp", "(%s)",nameCmp (opcode)));
4322 result = IC_RESULT (ic);
4323 left = IC_LEFT (ic);
4324 right = IC_RIGHT (ic);
4326 letype = getSpec (operandType (left));
4327 retype = getSpec (operandType (right));
4328 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4329 /* assign the amsops */
4330 aopOp (left, ic, FALSE);
4331 aopOp (right, ic, FALSE);
4332 aopOp (result, ic, TRUE);
4334 /* need register operand on left, prefer literal operand on right */
4335 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4337 operand *temp = left;
4340 opcode = exchangedCmp (opcode);
4347 jlbl = IC_TRUE (ifx);
4348 opcode = negatedCmp (opcode);
4352 /* false label is present */
4353 jlbl = IC_FALSE (ifx);
4357 size = max (AOP_SIZE (left), AOP_SIZE (right));
4360 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4361 && ((AOP_TYPE (right) == AOP_LIT) ||
4362 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4363 && hc08_reg_hx->isFree)
4365 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4366 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4367 hc08_freeReg (hc08_reg_hx);
4378 /* These conditions depend on the Z flag bit, but Z is */
4379 /* only valid for the last byte of the comparison, not */
4380 /* the whole value. So exchange the operands to get a */
4381 /* comparison that doesn't depend on Z. (This is safe */
4382 /* to do here since ralloc won't assign multi-byte */
4383 /* operands to registers for comparisons) */
4384 if ((opcode == '>') || (opcode == LE_OP))
4386 operand *temp = left;
4389 opcode = exchangedCmp (opcode);
4392 if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
4394 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4395 while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
4404 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4405 accopWithAop (sub, AOP (right), offset);
4406 hc08_freeReg (hc08_reg_a);
4411 freeAsmop (right, NULL, ic, FALSE);
4412 freeAsmop (left, NULL, ic, FALSE);
4416 symbol *tlbl = newiTempLabel (NULL);
4419 freeAsmop (result, NULL, ic, TRUE);
4421 inst = branchInstCmp (opcode, sign);
4422 emitBranch (inst, tlbl);
4423 emitBranch ("jmp", jlbl);
4426 /* mark the icode as generated */
4431 symbol *tlbl1 = newiTempLabel (NULL);
4432 symbol *tlbl2 = newiTempLabel (NULL);
4434 emitBranch (branchInstCmp (opcode, sign), tlbl1);
4435 loadRegFromConst (hc08_reg_a, zero);
4436 emitBranch ("bra", tlbl2);
4438 loadRegFromConst (hc08_reg_a, one);
4440 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4441 freeAsmop (result, NULL, ic, TRUE);
4446 /*-----------------------------------------------------------------*/
4447 /* genCmpEQorNE - equal or not equal comparison */
4448 /*-----------------------------------------------------------------*/
4450 genCmpEQorNE (iCode * ic, iCode * ifx)
4452 operand *left, *right, *result;
4453 sym_link *letype, *retype;
4455 int size, offset = 0;
4457 symbol *jlbl = NULL;
4458 symbol *tlbl_NE = NULL;
4459 symbol *tlbl_EQ = NULL;
4463 D(emitcode ("; genCmpEQorNE", "(%s)",nameCmp (opcode)));
4465 result = IC_RESULT (ic);
4466 left = IC_LEFT (ic);
4467 right = IC_RIGHT (ic);
4469 letype = getSpec (operandType (left));
4470 retype = getSpec (operandType (right));
4471 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4472 /* assign the amsops */
4473 aopOp (left, ic, FALSE);
4474 aopOp (right, ic, FALSE);
4475 aopOp (result, ic, TRUE);
4477 /* need register operand on left, prefer literal operand on right */
4478 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4480 operand *temp = left;
4483 opcode = exchangedCmp (opcode);
4490 jlbl = IC_TRUE (ifx);
4491 opcode = negatedCmp (opcode);
4495 /* false label is present */
4496 jlbl = IC_FALSE (ifx);
4500 size = max (AOP_SIZE (left), AOP_SIZE (right));
4503 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4504 && ((AOP_TYPE (right) == AOP_LIT) ||
4505 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4506 && hc08_reg_hx->isFree)
4508 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4509 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4510 hc08_freeReg (hc08_reg_hx);
4518 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4519 accopWithAop (sub, AOP (right), offset);
4523 tlbl_NE = newiTempLabel (NULL);
4524 emitBranch ("bne", tlbl_NE);
4526 hc08_freeReg (hc08_reg_a);
4530 freeAsmop (right, NULL, ic, FALSE);
4531 freeAsmop (left, NULL, ic, FALSE);
4535 freeAsmop (result, NULL, ic, TRUE);
4537 if (opcode == EQ_OP)
4540 tlbl_EQ = newiTempLabel (NULL);
4541 emitBranch ("beq", tlbl_EQ);
4543 emitLabel (tlbl_NE);
4544 emitBranch ("jmp", jlbl);
4545 emitLabel (tlbl_EQ);
4550 tlbl_NE = newiTempLabel (NULL);
4551 emitBranch ("bne", tlbl_NE);
4552 emitBranch ("jmp", jlbl);
4553 emitLabel (tlbl_NE);
4556 /* mark the icode as generated */
4561 symbol *tlbl = newiTempLabel (NULL);
4563 if (opcode == EQ_OP)
4566 tlbl_EQ = newiTempLabel (NULL);
4567 emitBranch ("beq", tlbl_EQ);
4569 emitLabel (tlbl_NE);
4570 loadRegFromConst (hc08_reg_a, zero);
4571 emitBranch ("bra", tlbl);
4572 emitLabel (tlbl_EQ);
4573 loadRegFromConst (hc08_reg_a, one);
4578 tlbl_NE = newiTempLabel (NULL);
4579 emitBranch ("bne", tlbl_NE);
4580 loadRegFromConst (hc08_reg_a, zero);
4581 emitBranch ("bra", tlbl);
4582 emitLabel (tlbl_NE);
4583 loadRegFromConst (hc08_reg_a, one);
4587 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4588 freeAsmop (result, NULL, ic, TRUE);
4594 /*-----------------------------------------------------------------*/
4595 /* ifxForOp - returns the icode containing the ifx for operand */
4596 /*-----------------------------------------------------------------*/
4598 ifxForOp (operand * op, iCode * ic)
4600 /* if true symbol then needs to be assigned */
4601 if (IS_TRUE_SYMOP (op))
4604 /* if this has register type condition and
4605 the next instruction is ifx with the same operand
4606 and live to of the operand is upto the ifx only then */
4608 ic->next->op == IFX &&
4609 IC_COND (ic->next)->key == op->key &&
4610 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4617 genPointerGetSetOfs (iCode *ic)
4619 iCode *lic = ic->next;
4625 /* Make sure we have a next iCode */
4626 DD(emitcode("","; checking lic"));
4630 /* Make sure the result of the addition is an iCode */
4631 DD(emitcode("","; checking IS_ITEMP"));
4632 if (!IS_ITEMP (IC_RESULT (ic)))
4635 /* Make sure the next iCode is a pointer set or get */
4636 pset = POINTER_SET(lic);
4637 pget = POINTER_GET(lic);
4638 DD(emitcode("","; pset=%d, pget=%d",pset,pget));
4642 /* Make sure this is the only use of the pointer */
4643 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4646 DD(emitcode("", "; checking pset operandsEqu"));
4647 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4650 DD(emitcode("", "; checking pget operandsEqu"));
4651 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4654 DD(emitcode("", "; checking IS_SYMOP"));
4655 if (!IS_SYMOP (IC_LEFT (ic)))
4658 DD(emitcode("", "; checking !IS_TRUE_SYMOP"));
4659 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4662 sym = OP_SYMBOL (IC_LEFT (ic));
4664 DD(emitcode("", "; checking remat"));
4671 D(emitcode ("; genPointerGetOfs",""));
4672 aopOp (IC_LEFT(ic), ic, FALSE);
4673 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4674 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4676 aopOp (IC_RIGHT(ic), ic, FALSE);
4677 aopOp (IC_RESULT(lic), lic, FALSE);
4679 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4681 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4683 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4684 loadRegFromConst (hc08_reg_h, zero);
4688 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4689 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4690 emitcode ("rola","");
4691 emitcode ("clra","");
4692 emitcode ("sbc", "#0");
4693 hc08_useReg (hc08_reg_a);
4694 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4698 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4699 size = AOP_SIZE (IC_RESULT(lic));
4700 derefaop->size = size;
4704 emitcode ("lda", "%s,x",
4705 aopAdrStr (derefaop, size, TRUE));
4706 hc08_useReg (hc08_reg_a);
4707 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
4708 hc08_freeReg (hc08_reg_a);
4712 hc08_freeReg (hc08_reg_hx);
4714 freeAsmop (NULL, derefaop, ic, TRUE);
4715 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4716 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4723 D(emitcode ("; genPointerSetOfs",""));
4724 aopOp (IC_LEFT(ic), ic, FALSE);
4725 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4726 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4728 aopOp (IC_RIGHT(ic), ic, FALSE);
4729 aopOp (IC_RIGHT(lic), lic, FALSE);
4731 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4733 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4735 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4736 loadRegFromConst (hc08_reg_h, zero);
4740 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4741 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4742 emitcode ("rola","");
4743 emitcode ("clra","");
4744 emitcode ("sbc", "#0");
4745 hc08_useReg (hc08_reg_a);
4746 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4750 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4751 size = AOP_SIZE (IC_RIGHT(lic));
4752 derefaop->size = size;
4756 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
4757 emitcode ("sta", "%s,x",
4758 aopAdrStr (derefaop, size, TRUE));
4759 hc08_freeReg (hc08_reg_a);
4763 hc08_freeReg (hc08_reg_hx);
4765 freeAsmop (NULL, derefaop, ic, TRUE);
4766 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4767 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4776 /*-----------------------------------------------------------------*/
4777 /* hasInc - operand is incremented before any other use */
4778 /*-----------------------------------------------------------------*/
4780 hasInc (operand *op, iCode *ic,int osize)
4782 sym_link *type = operandType(op);
4783 sym_link *retype = getSpec (type);
4784 iCode *lic = ic->next;
4787 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4788 if (!IS_SYMOP(op)) return NULL;
4790 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4791 if (IS_AGGREGATE(type->next)) return NULL;
4792 if (osize != (isize = getSize(type->next))) return NULL;
4795 /* if operand of the form op = op + <sizeof *op> */
4796 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4797 isOperandEqual(IC_RESULT(lic),op) &&
4798 isOperandLiteral(IC_RIGHT(lic)) &&
4799 operandLitValue(IC_RIGHT(lic)) == isize) {
4802 /* if the operand used or deffed */
4803 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
4806 /* if GOTO or IFX */
4807 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4813 /*-----------------------------------------------------------------*/
4814 /* genAndOp - for && operation */
4815 /*-----------------------------------------------------------------*/
4817 genAndOp (iCode * ic)
4819 operand *left, *right, *result;
4820 symbol *tlbl, *tlbl0;
4822 D(emitcode ("; genAndOp",""));
4824 /* note here that && operations that are in an
4825 if statement are taken away by backPatchLabels
4826 only those used in arthmetic operations remain */
4827 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4828 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4829 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4831 tlbl = newiTempLabel (NULL);
4832 tlbl0 = newiTempLabel (NULL);
4834 asmopToBool (AOP (left), FALSE);
4835 emitBranch ("beq", tlbl0);
4836 asmopToBool (AOP (right), FALSE);
4837 emitBranch ("beq", tlbl0);
4838 loadRegFromConst (hc08_reg_a,one);
4839 emitBranch ("bra", tlbl);
4841 loadRegFromConst (hc08_reg_a,zero);
4844 hc08_useReg (hc08_reg_a);
4845 hc08_freeReg (hc08_reg_a);
4847 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4849 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4850 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4851 freeAsmop (result, NULL, ic, TRUE);
4855 /*-----------------------------------------------------------------*/
4856 /* genOrOp - for || operation */
4857 /*-----------------------------------------------------------------*/
4859 genOrOp (iCode * ic)
4861 operand *left, *right, *result;
4862 symbol *tlbl, *tlbl0;
4864 D(emitcode ("; genOrOp",""));
4866 /* note here that || operations that are in an
4867 if statement are taken away by backPatchLabels
4868 only those used in arthmetic operations remain */
4869 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4870 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4871 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4873 tlbl = newiTempLabel (NULL);
4874 tlbl0 = newiTempLabel (NULL);
4876 asmopToBool (AOP (left), FALSE);
4877 emitBranch ("bne", tlbl0);
4878 asmopToBool (AOP (right), FALSE);
4879 emitBranch ("bne", tlbl0);
4880 loadRegFromConst (hc08_reg_a,zero);
4881 emitBranch ("bra", tlbl);
4883 loadRegFromConst (hc08_reg_a,one);
4886 hc08_useReg (hc08_reg_a);
4887 hc08_freeReg (hc08_reg_a);
4889 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4892 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4893 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4894 freeAsmop (result, NULL, ic, TRUE);
4897 /*-----------------------------------------------------------------*/
4898 /* isLiteralBit - test if lit == 2^n */
4899 /*-----------------------------------------------------------------*/
4901 isLiteralBit (unsigned long lit)
4903 unsigned long pw[32] =
4904 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4905 0x100L, 0x200L, 0x400L, 0x800L,
4906 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4907 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4908 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4909 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4910 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4913 for (idx = 0; idx < 32; idx++)
4920 /*-----------------------------------------------------------------*/
4921 /* continueIfTrue - */
4922 /*-----------------------------------------------------------------*/
4924 continueIfTrue (iCode * ic)
4927 emitBranch ("jmp", IC_TRUE (ic));
4931 /*-----------------------------------------------------------------*/
4933 /*-----------------------------------------------------------------*/
4935 jumpIfTrue (iCode * ic)
4938 emitBranch ("jmp", IC_FALSE (ic));
4942 /*-----------------------------------------------------------------*/
4943 /* jmpTrueOrFalse - */
4944 /*-----------------------------------------------------------------*/
4946 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4948 // ugly but optimized by peephole
4951 symbol *nlbl = newiTempLabel (NULL);
4952 emitBranch ("bra", nlbl);
4954 emitBranch ("jmp", IC_TRUE (ic));
4959 emitBranch ("jmp", IC_FALSE (ic));
4966 /*-----------------------------------------------------------------*/
4967 /* genAnd - code for and */
4968 /*-----------------------------------------------------------------*/
4970 genAnd (iCode * ic, iCode * ifx)
4972 operand *left, *right, *result;
4973 int size, offset = 0;
4974 unsigned long lit = 0L;
4975 unsigned long litinv;
4976 unsigned char bytemask;
4982 D(emitcode ("; genAnd",""));
4984 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4985 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4986 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4989 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4991 AOP_TYPE (left), AOP_TYPE (right)));
4992 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4994 AOP_SIZE (left), AOP_SIZE (right)));
4997 /* if left is a literal & right is not then exchange them */
4998 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5000 operand *tmp = right;
5005 /* if right is accumulator & left is not then exchange them */
5006 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5008 operand *tmp = right;
5013 if (AOP_TYPE (right) == AOP_LIT)
5014 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5016 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5018 if (AOP_TYPE (result) == AOP_CRY
5020 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5022 /* this generates ugly code, but meets volatility requirements */
5023 loadRegFromConst (hc08_reg_a, zero);
5024 pushReg (hc08_reg_a, TRUE);
5029 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5030 accopWithAop ("and", AOP (right), offset);
5031 emitcode ("ora", "1,s");
5032 emitcode ("sta", "1,s");
5036 pullReg (hc08_reg_a);
5037 emitcode ("tsta", "");
5038 genIfxJump (ifx, "a");
5042 if (AOP_TYPE (result) == AOP_CRY)
5044 symbol *tlbl = NULL;
5045 wassertl (ifx, "AOP_CRY result without ifx");
5050 bytemask = (lit >> (offset*8)) & 0xff;
5052 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5056 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5058 rmwWithAop ("tst", AOP (left), offset);
5062 tlbl = newiTempLabel (NULL);
5063 emitBranch ("bne", tlbl);
5068 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5069 accopWithAop ("and", AOP (right), offset);
5070 hc08_freeReg( hc08_reg_a);
5074 tlbl = newiTempLabel (NULL);
5075 emitBranch ("bne", tlbl);
5082 genIfxJump (ifx, "a");
5086 size = AOP_SIZE (result);
5088 if (AOP_TYPE (right) == AOP_LIT)
5090 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
5091 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5092 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
5094 int bitpos = isLiteralBit(litinv)-1;
5095 emitcode ("bclr","#%d,%s",bitpos & 7,
5096 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5104 bytemask = (lit >> (offset*8)) & 0xff;
5106 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5108 if (isOperandVolatile (left, FALSE))
5110 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5111 hc08_freeReg( hc08_reg_a);
5113 storeConstToAop (zero, AOP (result), offset);
5115 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5117 transferAopAop (AOP (left), offset, AOP (result), offset);
5121 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5122 accopWithAop ("and", AOP (right), offset);
5123 storeRegToAop (hc08_reg_a, AOP (result), offset);
5124 hc08_freeReg (hc08_reg_a);
5130 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5131 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5132 freeAsmop (result, NULL, ic, TRUE);
5135 /*-----------------------------------------------------------------*/
5136 /* genOr - code for or */
5137 /*-----------------------------------------------------------------*/
5139 genOr (iCode * ic, iCode * ifx)
5141 operand *left, *right, *result;
5142 int size, offset = 0;
5143 unsigned long lit = 0L;
5144 unsigned char bytemask;
5146 D(emitcode ("; genOr",""));
5148 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5149 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5150 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5153 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5155 AOP_TYPE (left), AOP_TYPE (right)));
5156 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5158 AOP_SIZE (left), AOP_SIZE (right)));
5161 /* if left is a literal & right is not then exchange them */
5162 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5164 operand *tmp = right;
5169 /* if left is accumulator & right is not then exchange them */
5170 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5172 operand *tmp = right;
5177 if (AOP_TYPE (right) == AOP_LIT)
5178 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5180 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5182 if (AOP_TYPE (result) == AOP_CRY
5184 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5186 /* this generates ugly code, but meets volatility requirements */
5187 loadRegFromConst (hc08_reg_a, zero);
5188 pushReg (hc08_reg_a, TRUE);
5193 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5194 accopWithAop ("ora", AOP (right), offset);
5195 emitcode ("ora", "1,s");
5196 emitcode ("sta", "1,s");
5200 pullReg (hc08_reg_a);
5201 emitcode ("tsta", "");
5202 genIfxJump (ifx, "a");
5206 if (AOP_TYPE (result) == AOP_CRY)
5208 symbol *tlbl = NULL;
5209 wassertl (ifx, "AOP_CRY result without ifx");
5214 bytemask = (lit >> (offset*8)) & 0xff;
5216 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5218 rmwWithAop ("tst", AOP (left), offset);
5222 tlbl = newiTempLabel (NULL);
5223 emitBranch ("bne", tlbl);
5228 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5229 accopWithAop ("ora", AOP (right), offset);
5230 hc08_freeReg( hc08_reg_a);
5234 tlbl = newiTempLabel (NULL);
5235 emitBranch ("bne", tlbl);
5242 genIfxJump (ifx, "a");
5245 if (AOP_TYPE (right) == AOP_LIT)
5246 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5248 size = AOP_SIZE (result);
5250 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5251 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5252 (AOP_TYPE (left) == AOP_DIR))
5254 int bitpos = isLiteralBit(lit)-1;
5255 emitcode ("bset","#%d,%s",bitpos & 7,
5256 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5263 bytemask = (lit >> (offset*8)) & 0xff;
5265 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5267 if (isOperandVolatile (left, FALSE))
5269 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5270 hc08_freeReg( hc08_reg_a);
5272 transferAopAop (AOP (right), offset, AOP (result), offset);
5274 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5276 transferAopAop (AOP (left), offset, AOP (result), offset);
5280 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5281 accopWithAop ("ora", AOP (right), offset);
5282 storeRegToAop (hc08_reg_a, AOP (result), offset);
5283 hc08_freeReg (hc08_reg_a);
5290 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5291 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5292 freeAsmop (result, NULL, ic, TRUE);
5295 /*-----------------------------------------------------------------*/
5296 /* genXor - code for xclusive or */
5297 /*-----------------------------------------------------------------*/
5299 genXor (iCode * ic, iCode * ifx)
5301 operand *left, *right, *result;
5302 int size, offset = 0;
5303 unsigned long lit = 0L;
5305 D(emitcode ("; genXor",""));
5307 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5308 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5309 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5312 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5314 AOP_TYPE (left), AOP_TYPE (right)));
5315 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5317 AOP_SIZE (left), AOP_SIZE (right)));
5320 /* if left is a literal & right is not ||
5321 if left needs acc & right does not */
5322 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5324 operand *tmp = right;
5329 /* if left is accumulator & right is not then exchange them */
5330 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5332 operand *tmp = right;
5337 if (AOP_TYPE (result) == AOP_CRY)
5340 wassertl (ifx, "AOP_CPY result without ifx");
5342 tlbl = newiTempLabel (NULL);
5343 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5347 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5348 if ((AOP_TYPE (right) == AOP_LIT)
5349 && (((lit >> (offset*8)) & 0xff) == 0))
5350 emitcode ("tsta","");
5352 accopWithAop ("eor", AOP (right), offset);
5353 hc08_freeReg( hc08_reg_a);
5355 emitBranch ("bne", tlbl);
5359 genIfxJump (ifx, "a");
5365 if (AOP_TYPE (right) == AOP_LIT)
5366 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5368 size = AOP_SIZE (result);
5372 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5373 accopWithAop ("eor", AOP (right), offset);
5374 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5375 hc08_freeReg( hc08_reg_a);
5379 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5380 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5381 freeAsmop (result, NULL, ic, TRUE);
5385 emitinline (iCode * ic, char *inlin)
5391 symbol *sym, *tempsym;
5400 while (isalnum((unsigned char)*inlin) || (*inlin == '_'))
5404 //printf("Found possible symbol '%s'\n",symname);
5405 tempsym = newSymbol (symname, ic->level);
5406 tempsym->block = ic->block;
5407 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5416 aop = aopForSym (ic, sym, FALSE);
5417 l = aopAdrStr (aop, aop->size - 1, TRUE);
5421 if (sym->level && !sym->allocreq && !sym->ismyparm)
5423 werror (E_ID_UNDEF, sym->name);
5425 " Add 'volatile' to the variable declaration so that it\n"
5426 " can be referenced within inline assembly");
5428 //printf("Replacing with '%s'\n",l);
5432 if ((2+bp-buffer)>sizeof(buffer))
5441 if ((2+bp-buffer)>sizeof(buffer))
5448 if ((2+bp-buffer)>sizeof(buffer))
5449 fprintf(stderr, "Inline assembly buffer overflow\n");
5451 //printf("%s\n",buffer);
5452 emitcode (buffer,"");
5456 /*-----------------------------------------------------------------*/
5457 /* genInline - write the inline code out */
5458 /*-----------------------------------------------------------------*/
5460 genInline (iCode * ic)
5462 char *buffer, *bp, *bp1;
5464 D(emitcode ("; genInline",""));
5466 _G.inLine += (!options.asmpeep);
5468 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5469 strcpy (buffer, IC_INLINE (ic));
5471 /* emit each line as a code */
5477 /* emitcode (bp1, ""); */
5478 emitinline (ic, bp1);
5497 /* emitcode (bp1, ""); */
5498 emitinline (ic, bp1);
5500 /* emitcode("",buffer); */
5501 _G.inLine -= (!options.asmpeep);
5504 /*-----------------------------------------------------------------*/
5505 /* genRRC - rotate right with carry */
5506 /*-----------------------------------------------------------------*/
5510 operand *left, *result;
5511 int size, offset = 0;
5512 bool needpula = FALSE;
5513 bool resultInA = FALSE;
5516 D(emitcode ("; genRRC",""));
5518 /* rotate right with carry */
5519 left = IC_LEFT (ic);
5520 result = IC_RESULT (ic);
5521 aopOp (left, ic, FALSE);
5522 aopOp (result, ic, FALSE);
5524 if ((AOP_TYPE (result) == AOP_REG)
5525 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5528 size = AOP_SIZE (result);
5532 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5536 rmwWithAop (shift, AOP (result), offset--);
5544 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5545 rmwWithReg (shift, hc08_reg_a);
5546 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5547 hc08_freeReg (hc08_reg_a);
5552 if ((!hc08_reg_a->isFree) || resultInA)
5554 pushReg (hc08_reg_a, TRUE);
5558 /* now we need to put the carry into the
5559 highest order byte of the result */
5560 offset = AOP_SIZE (result) - 1;
5561 emitcode ("clra","");
5562 emitcode ("rora","");
5563 hc08_dirtyReg (hc08_reg_a, FALSE);
5566 emitcode ("ora", "1,s");
5567 emitcode ("ais", "#1");
5568 hc08_dirtyReg (hc08_reg_a, FALSE);
5572 accopWithAop ("ora", AOP (result), offset);
5573 storeRegToAop (hc08_reg_a, AOP (result), offset);
5575 pullOrFreeReg (hc08_reg_a, needpula);
5577 freeAsmop (left, NULL, ic, TRUE);
5578 freeAsmop (result, NULL, ic, TRUE);
5581 /*-----------------------------------------------------------------*/
5582 /* genRLC - generate code for rotate left with carry */
5583 /*-----------------------------------------------------------------*/
5587 operand *left, *result;
5588 int size, offset = 0;
5590 bool resultInA = FALSE;
5591 bool needpula = FALSE;
5593 D(emitcode ("; genRLC",""));
5595 /* rotate right with carry */
5596 left = IC_LEFT (ic);
5597 result = IC_RESULT (ic);
5598 aopOp (left, ic, FALSE);
5599 aopOp (result, ic, FALSE);
5601 if ((AOP_TYPE (result) == AOP_REG)
5602 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5605 size = AOP_SIZE (result);
5609 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5613 rmwWithAop (shift, AOP (result), offset--);
5621 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5622 rmwWithReg (shift, hc08_reg_a);
5623 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5624 hc08_freeReg (hc08_reg_a);
5629 if ((!hc08_reg_a->isFree) || resultInA)
5631 pushReg (hc08_reg_a, TRUE);
5635 /* now we need to put the carry into the
5636 lowest order byte of the result */
5638 emitcode ("clra","");
5639 emitcode ("rola","");
5640 hc08_dirtyReg (hc08_reg_a, FALSE);
5643 emitcode ("ora", "1,s");
5644 emitcode ("ais", "#1");
5645 hc08_dirtyReg (hc08_reg_a, FALSE);
5649 accopWithAop ("ora", AOP (result), offset);
5650 storeRegToAop (hc08_reg_a, AOP (result), offset);
5652 pullOrFreeReg (hc08_reg_a, needpula);
5654 freeAsmop (left, NULL, ic, TRUE);
5655 freeAsmop (result, NULL, ic, TRUE);
5658 /*-----------------------------------------------------------------*/
5659 /* genGetHbit - generates code get highest order bit */
5660 /*-----------------------------------------------------------------*/
5662 genGetHbit (iCode * ic)
5664 operand *left, *result;
5666 D(emitcode ("; genGetHbit",""));
5668 left = IC_LEFT (ic);
5669 result = IC_RESULT (ic);
5670 aopOp (left, ic, FALSE);
5671 aopOp (result, ic, FALSE);
5673 /* get the highest order byte into a */
5674 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5675 emitcode ("rola", "");
5676 emitcode ("clra", "");
5677 emitcode ("rola", "");
5678 hc08_dirtyReg (hc08_reg_a, FALSE);
5679 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5680 hc08_freeReg (hc08_reg_a);
5682 freeAsmop (left, NULL, ic, TRUE);
5683 freeAsmop (result, NULL, ic, TRUE);
5686 /*-----------------------------------------------------------------*/
5687 /* genSwap - generates code to swap nibbles or bytes */
5688 /*-----------------------------------------------------------------*/
5690 genSwap (iCode * ic)
5692 operand *left, *result;
5694 D(emitcode ("; genSwap",""));
5696 left = IC_LEFT (ic);
5697 result = IC_RESULT (ic);
5698 aopOp (left, ic, FALSE);
5699 aopOp (result, ic, FALSE);
5701 switch (AOP_SIZE (left))
5703 case 1: /* swap nibbles in byte */
5704 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5705 emitcode ("nsa", "");
5706 hc08_dirtyReg (hc08_reg_a, FALSE);
5707 storeRegToAop (hc08_reg_a, AOP (result), 0);
5708 hc08_freeReg (hc08_reg_a);
5710 case 2: /* swap bytes in a word */
5711 if (operandsEqu (left, result))
5713 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5714 hc08_useReg (hc08_reg_a);
5715 transferAopAop (AOP (left), 1, AOP (result), 0);
5716 storeRegToAop (hc08_reg_a, AOP (result), 1);
5717 hc08_freeReg (hc08_reg_a);
5721 transferAopAop (AOP (left), 0, AOP (result), 1);
5722 transferAopAop (AOP (left), 1, AOP (result), 0);
5726 wassertl(FALSE, "unsupported SWAP operand size");
5729 freeAsmop (left, NULL, ic, TRUE);
5730 freeAsmop (result, NULL, ic, TRUE);
5734 /*-----------------------------------------------------------------*/
5735 /* AccRol - rotate left accumulator by known count */
5736 /*-----------------------------------------------------------------*/
5738 AccRol (int shCount)
5740 shCount &= 0x0007; // shCount : 0..7
5747 emitcode ("rola", ""); /* 1 cycle */
5750 emitcode ("rola", ""); /* 1 cycle */
5751 emitcode ("rola", ""); /* 1 cycle */
5754 emitcode ("nsa", "");
5755 emitcode ("rora", "");
5758 emitcode ("nsa", ""); /* 3 cycles */
5761 emitcode ("nsa", ""); /* 3 cycles */
5762 emitcode ("rola", ""); /* 1 cycle */
5765 emitcode ("nsa", ""); /* 3 cycles */
5766 emitcode ("rola", ""); /* 1 cycle */
5767 emitcode ("rola", ""); /* 1 cycle */
5770 emitcode ("nsa", ""); /* 3 cycles */
5771 emitcode ("rola", ""); /* 1 cycle */
5772 emitcode ("rola", ""); /* 1 cycle */
5773 emitcode ("rola", ""); /* 1 cycle */
5780 /*-----------------------------------------------------------------*/
5781 /* AccLsh - left shift accumulator by known count */
5782 /*-----------------------------------------------------------------*/
5784 AccLsh (int shCount)
5788 shCount &= 0x0007; // shCount : 0..7
5790 /* Shift counts of 4 and 5 are currently optimized for code size. */
5791 /* Falling through to the unrolled loop would be optimal for code speed. */
5792 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5796 if (optimize.codeSpeed)
5798 accopWithMisc ("nsa", "");
5799 accopWithMisc ("and", "#0xf0");
5800 /* total: 5 cycles, 3 bytes */
5803 if (optimize.codeSpeed)
5805 accopWithMisc ("nsa", "");
5806 accopWithMisc ("and", "#0xf0");
5807 accopWithMisc ("lsla", "");
5808 /* total: 6 cycles, 4 bytes */
5811 accopWithMisc ("rora", "");
5812 accopWithMisc ("rora", "");
5813 accopWithMisc ("rora", "");
5814 accopWithMisc ("and", "#0xc0");
5815 /* total: 5 cycles, 5 bytes */
5818 accopWithMisc ("rora", "");
5819 accopWithMisc ("clra", "");
5820 accopWithMisc ("rora", "");
5821 /* total: 3 cycles, 3 bytes */
5825 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5826 /* the fastest (shCount<6) and shortest (shCount<4). */
5827 for (i=0;i<shCount;i++)
5828 accopWithMisc ("lsla", "");
5832 /*-----------------------------------------------------------------*/
5833 /* AccSRsh - signed right shift accumulator by known count */
5834 /*-----------------------------------------------------------------*/
5836 AccSRsh (int shCount)
5840 shCount &= 0x0007; // shCount : 0..7
5844 accopWithMisc ("rola", "");
5845 accopWithMisc ("clra", "");
5846 accopWithMisc ("sbc", zero);
5847 /* total: 4 cycles, 4 bytes */
5851 for (i=0;i<shCount;i++)
5852 accopWithMisc ("asra", "");
5855 /*-----------------------------------------------------------------*/
5856 /* AccRsh - right shift accumulator by known count */
5857 /*-----------------------------------------------------------------*/
5859 AccRsh (int shCount, bool sign)
5869 shCount &= 0x0007; // shCount : 0..7
5871 /* Shift counts of 4 and 5 are currently optimized for code size. */
5872 /* Falling through to the unrolled loop would be optimal for code speed. */
5873 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5877 if (optimize.codeSpeed)
5879 accopWithMisc ("nsa", "");
5880 accopWithMisc ("and", "#0x0f");
5881 /* total: 5 cycles, 3 bytes */
5884 if (optimize.codeSpeed)
5886 accopWithMisc ("nsa", "");
5887 accopWithMisc ("and", "#0x0f");
5888 accopWithMisc ("lsra", "");
5889 /* total: 6 cycles, 4 bytes */
5892 accopWithMisc ("rola", "");
5893 accopWithMisc ("rola", "");
5894 accopWithMisc ("rola", "");
5895 accopWithMisc ("and", "#0x03");
5896 /* total: 5 cycles, 5 bytes */
5899 accopWithMisc ("rola", "");
5900 accopWithMisc ("clra", "");
5901 accopWithMisc ("rola", "");
5902 /* total: 3 cycles, 3 bytes */
5906 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5907 /* the fastest (shCount<6) and shortest (shCount<4). */
5908 for (i=0;i<shCount;i++)
5909 accopWithMisc ("lsra", "");
5913 /*-----------------------------------------------------------------*/
5914 /* XAccLsh - left shift register pair XA by known count */
5915 /*-----------------------------------------------------------------*/
5917 XAccLsh (int shCount)
5921 shCount &= 0x000f; // shCount : 0..15
5926 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5927 loadRegFromConst (hc08_reg_a, zero);
5931 /* if we can beat 2n cycles or bytes for some special case, do it here */
5935 /* bytes cycles reg x reg a carry
5936 ** abcd efgh ijkl mnop ?
5937 ** lsrx 1 1 0abc defg ijkl mnop h
5938 ** rora 1 1 0abc defg hijk lmno p
5939 ** tax 1 1 hijk lmno hijk lmno p
5940 ** clra 1 1 hijk lmno 0000 0000 p
5941 ** rora 1 1 hijk lmno p000 0000 0
5942 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5944 rmwWithReg ("lsr", hc08_reg_x);
5945 rmwWithReg ("ror", hc08_reg_a);
5946 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5947 loadRegFromConst (hc08_reg_a, zero);
5948 rmwWithReg ("ror", hc08_reg_a);
5955 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5956 /* the fastest and shortest. */
5957 for (i=0;i<shCount;i++)
5959 rmwWithReg ("lsl", hc08_reg_a);
5960 rmwWithReg ("rol", hc08_reg_x);
5964 /*-----------------------------------------------------------------*/
5965 /* XAccSRsh - signed right shift register pair XA by known count */
5966 /*-----------------------------------------------------------------*/
5968 XAccSRsh (int shCount)
5972 shCount &= 0x000f; // shCount : 0..7
5974 /* if we can beat 2n cycles or bytes for some special case, do it here */
5978 /* bytes cycles reg x reg a carry
5979 ** abcd efgh ijkl mnop ?
5980 ** lslx 1 1 bcde fgh0 ijkl mnop a
5981 ** clra 1 1 bcde fgh0 0000 0000 a
5982 ** rola 1 1 bcde fgh0 0000 000a 0
5983 ** nega 1 1 bcde fgh0 aaaa aaaa a
5984 ** tax 1 1 aaaa aaaa aaaa aaaa a
5985 ** total: 5 cycles, 5 bytes
5987 rmwWithReg ("lsl", hc08_reg_x);
5988 loadRegFromConst (hc08_reg_a, zero);
5989 rmwWithReg ("rol", hc08_reg_a);
5990 rmwWithReg ("neg", hc08_reg_a);
5991 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6001 /* bytes cycles reg x reg a carry
6002 ** abcd efgh ijkl mnop ?
6003 ** txa 1 1 abcd efgh abcd efgh ?
6004 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
6005 ** lsla 1 1 abcd efgh ???? ???? a
6006 ** clrx 1 1 0000 0000 ???? ???? a
6007 ** rolx 1 1 0000 000a ???? ???? 0
6008 ** negx 1 1 aaaa aaaa ???? ???? a
6009 ** rora 1 1 aaaa aaaa LSBresult 0
6010 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
6012 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6013 AccSRsh (shCount-8);
6014 rmwWithReg ("lsl", hc08_reg_a);
6015 loadRegFromConst (hc08_reg_x, zero);
6016 rmwWithReg ("rol", hc08_reg_x);
6017 rmwWithReg ("neg", hc08_reg_x);
6018 rmwWithReg ("ror", hc08_reg_a);
6025 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6026 /* the fastest and shortest. */
6027 for (i=0;i<shCount;i++)
6029 rmwWithReg ("asr", hc08_reg_x);
6030 rmwWithReg ("ror", hc08_reg_a);
6034 /*-----------------------------------------------------------------*/
6035 /* XAccRsh - right shift register pair XA by known count */
6036 /*-----------------------------------------------------------------*/
6038 XAccRsh (int shCount, bool sign)
6048 shCount &= 0x000f; // shCount : 0..f
6050 /* if we can beat 2n cycles or bytes for some special case, do it here */
6054 /* bytes cycles reg x reg a carry
6055 ** abcd efgh ijkl mnop ?
6056 ** clra 1 1 abcd efgh 0000 0000 a
6057 ** lslx 1 1 bcde fgh0 0000 0000 a
6058 ** rola 1 1 bcde fgh0 0000 000a 0
6059 ** clrx 1 1 0000 0000 0000 000a 0
6060 ** total: 4 cycles, 4 bytes
6062 loadRegFromConst (hc08_reg_x, zero);
6063 rmwWithReg ("lsl", hc08_reg_x);
6064 rmwWithReg ("rol", hc08_reg_a);
6065 loadRegFromConst (hc08_reg_a, zero);
6069 /* bytes cycles reg x reg a carry
6070 ** abcd efgh ijkl mnop ?
6071 ** clra 1 1 abcd efgh 0000 0000 a
6072 ** lslx 1 1 bcde fgh0 0000 0000 a
6073 ** rola 1 1 bcde fgh0 0000 000a 0
6074 ** lslx 1 1 cdef gh00 0000 000a b
6075 ** rola 1 1 cdef gh00 0000 00ab 0
6076 ** clrx 1 1 0000 0000 0000 00ab 0
6077 ** total: 6 cycles, 6 bytes
6079 loadRegFromConst (hc08_reg_x, zero);
6080 rmwWithReg ("lsl", hc08_reg_x);
6081 rmwWithReg ("rol", hc08_reg_a);
6082 rmwWithReg ("lsl", hc08_reg_x);
6083 rmwWithReg ("rol", hc08_reg_a);
6084 loadRegFromConst (hc08_reg_a, zero);
6093 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6094 AccRsh (shCount-8, FALSE);
6095 loadRegFromConst (hc08_reg_x, zero);
6099 /* bytes cycles reg x reg a carry
6100 ** abcd efgh ijkl mnop ?
6101 ** lsla 1 1 abcd efgh jklm nop0 i
6102 ** txa 1 1 abcd efgh abcd efgh i
6103 ** rola 1 1 abcd efgh bcde fghi a
6104 ** clrx 1 1 0000 0000 bcde fghi a
6105 ** rolx 1 1 0000 000a bcde fghi 0
6106 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
6108 rmwWithReg ("lsl", hc08_reg_a);
6109 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6110 rmwWithReg ("rol", hc08_reg_a);
6111 loadRegFromConst (hc08_reg_x, zero);
6112 rmwWithReg ("rol", hc08_reg_x);
6115 /* bytes cycles reg x reg a carry
6116 ** abcd efgh ijkl mnop ?
6117 ** lsla 1 1 abcd efgh jklm nop0 i
6118 ** rolx 1 1 bcde fghi jklm nop0 a
6119 ** rola 1 1 bcde fghi klmn op0a j
6120 ** rolx 1 1 cdef ghij klmn op0a b
6121 ** rola 1 1 cdef ghij lmno p0ab k
6122 ** and #3 2 2 cdef ghij 0000 00ab k
6123 ** psha 1 2 cdef ghij 0000 00ab k
6124 ** txa 1 1 cdef ghij cdef ghij k
6125 ** pula 1 2 0000 00ab cdef ghij k
6126 ** total: 12 cycles, 10 bytes (beats 12 bytes)
6132 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6133 /* the fastest and shortest. */
6134 for (i=0;i<shCount;i++)
6136 rmwWithReg ("lsr", hc08_reg_x);
6137 rmwWithReg ("ror", hc08_reg_a);
6144 /*-----------------------------------------------------------------*/
6145 /* shiftR1Left2Result - shift right one byte from left to result */
6146 /*-----------------------------------------------------------------*/
6148 shiftR1Left2Result (operand * left, int offl,
6149 operand * result, int offr,
6150 int shCount, int sign)
6152 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6153 /* shift right accumulator */
6154 AccRsh (shCount, sign);
6155 storeRegToAop (hc08_reg_a, AOP (result), offr);
6159 /*-----------------------------------------------------------------*/
6160 /* shiftL1Left2Result - shift left one byte from left to result */
6161 /*-----------------------------------------------------------------*/
6163 shiftL1Left2Result (operand * left, int offl,
6164 operand * result, int offr, int shCount)
6166 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6167 /* shift left accumulator */
6169 storeRegToAop (hc08_reg_a, AOP (result), offr);
6172 /*-----------------------------------------------------------------*/
6173 /* movLeft2Result - move byte from left to result */
6174 /*-----------------------------------------------------------------*/
6176 movLeft2Result (operand * left, int offl,
6177 operand * result, int offr, int sign)
6179 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6181 transferAopAop (AOP (left), offl, AOP (result), offr);
6186 /*-----------------------------------------------------------------*/
6187 /* shiftL2Left2Result - shift left two bytes from left to result */
6188 /*-----------------------------------------------------------------*/
6190 shiftL2Left2Result (operand * left, int offl,
6191 operand * result, int offr, int shCount)
6194 bool needpula = FALSE;
6195 bool needpulx = FALSE;
6197 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6198 needpula = pushRegIfUsed (hc08_reg_a);
6201 if (!IS_AOP_XA (AOP (left)))
6202 needpulx = pushRegIfUsed (hc08_reg_x);
6206 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6211 rmwWithReg ("lsr", hc08_reg_x);
6212 rmwWithReg ("ror", hc08_reg_a);
6213 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6214 rmwWithReg ("clr", hc08_reg_a);
6215 rmwWithReg ("ror", hc08_reg_a);
6218 for (i=0; i<shCount; i++)
6220 rmwWithReg ("lsl", hc08_reg_a);
6221 rmwWithReg ("rol", hc08_reg_x);
6224 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6226 pullOrFreeReg (hc08_reg_x, needpulx);
6227 pullOrFreeReg (hc08_reg_a, needpula);
6233 /*-----------------------------------------------------------------*/
6234 /* shiftR2Left2Result - shift right two bytes from left to result */
6235 /*-----------------------------------------------------------------*/
6237 shiftR2Left2Result (operand * left, int offl,
6238 operand * result, int offr,
6239 int shCount, int sign)
6242 bool needpula = FALSE;
6243 bool needpulx = FALSE;
6245 needpula = pushRegIfUsed (hc08_reg_a);
6246 needpulx = pushRegIfUsed (hc08_reg_x);
6248 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6249 for (i=0; i<shCount; i++)
6252 rmwWithReg ("asr", hc08_reg_x);
6254 rmwWithReg ("lsr", hc08_reg_x);
6255 rmwWithReg ("ror", hc08_reg_a);
6257 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6259 pullOrFreeReg (hc08_reg_x, needpulx);
6260 pullOrFreeReg (hc08_reg_a, needpula);
6265 /*-----------------------------------------------------------------*/
6266 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6267 /*-----------------------------------------------------------------*/
6269 shiftLLeftOrResult (operand * left, int offl,
6270 operand * result, int offr, int shCount)
6272 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6273 /* shift left accumulator */
6275 /* or with result */
6276 accopWithAop ("ora", AOP (result), offr);
6277 /* back to result */
6278 storeRegToAop (hc08_reg_a, AOP (result), offr);
6279 hc08_freeReg (hc08_reg_a);
6283 /*-----------------------------------------------------------------*/
6284 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6285 /*-----------------------------------------------------------------*/
6287 shiftRLeftOrResult (operand * left, int offl,
6288 operand * result, int offr, int shCount)
6290 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6291 /* shift left accumulator */
6292 AccRsh (shCount, FALSE);
6293 /* or with result */
6294 accopWithAop ("ora", AOP (result), offr);
6295 /* back to result */
6296 storeRegToAop (hc08_reg_a, AOP (result), offr);
6297 hc08_freeReg (hc08_reg_a);
6300 /*-----------------------------------------------------------------*/
6301 /* genlshOne - left shift a one byte quantity by known count */
6302 /*-----------------------------------------------------------------*/
6304 genlshOne (operand * result, operand * left, int shCount)
6306 D(emitcode ("; genlshOne",""));
6308 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6311 /*-----------------------------------------------------------------*/
6312 /* genlshTwo - left shift two bytes by known amount != 0 */
6313 /*-----------------------------------------------------------------*/
6315 genlshTwo (operand * result, operand * left, int shCount)
6319 D(emitcode ("; genlshTwo",""));
6322 size = getDataSize (result);
6324 /* if shCount >= 8 */
6331 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6333 storeRegToAop (hc08_reg_a, AOP (result), 1);
6335 storeConstToAop(zero, AOP (result), LSB);
6338 /* 1 <= shCount <= 7 */
6341 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6343 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6347 /*-----------------------------------------------------------------*/
6348 /* shiftLLong - shift left one long from left to result */
6349 /* offr = LSB or MSB16 */
6350 /*-----------------------------------------------------------------*/
6352 shiftLLong (operand * left, operand * result, int offr)
6355 // int size = AOP_SIZE (result);
6357 bool needpula = FALSE;
6358 bool needpulx = FALSE;
6360 needpula = pushRegIfUsed (hc08_reg_a);
6361 needpulx = pushRegIfUsed (hc08_reg_x);
6363 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6364 rmwWithReg ("lsl", hc08_reg_a);
6365 rmwWithReg ("rol", hc08_reg_x);
6369 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6370 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6371 rmwWithReg ("rol", hc08_reg_a);
6372 rmwWithReg ("rol", hc08_reg_x);
6373 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6375 else if (offr==MSB16)
6377 storeRegToAop (hc08_reg_a, AOP (result), offr);
6378 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6379 storeRegToAop (hc08_reg_x, AOP (result), offr+1);
6380 rmwWithReg ("rol", hc08_reg_a);
6381 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6382 storeConstToAop (zero, AOP (result), 0);
6385 pullOrFreeReg (hc08_reg_x, needpulx);
6386 pullOrFreeReg (hc08_reg_a, needpula);
6389 /*-----------------------------------------------------------------*/
6390 /* genlshFour - shift four byte by a known amount != 0 */
6391 /*-----------------------------------------------------------------*/
6393 genlshFour (operand * result, operand * left, int shCount)
6397 D(emitcode ("; genlshFour",""));
6399 size = AOP_SIZE (result);
6401 /* TODO: deal with the &result == &left case */
6403 /* if shifting more that 3 bytes */
6408 /* lowest order of left goes to the highest
6409 order of the destination */
6410 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6412 movLeft2Result (left, LSB, result, MSB32, 0);
6413 storeConstToAop (zero, AOP (result), LSB);
6414 storeConstToAop (zero, AOP (result), MSB16);
6415 storeConstToAop (zero, AOP (result), MSB24);
6419 /* more than two bytes */
6420 else if (shCount >= 16)
6422 /* lower order two bytes goes to higher order two bytes */
6424 /* if some more remaining */
6426 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6429 movLeft2Result (left, MSB16, result, MSB32, 0);
6430 movLeft2Result (left, LSB, result, MSB24, 0);
6432 storeConstToAop (zero, AOP (result), LSB);
6433 storeConstToAop (zero, AOP (result), MSB16);
6437 /* if more than 1 byte */
6438 else if (shCount >= 8)
6440 /* lower order three bytes goes to higher order three bytes */
6445 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6447 movLeft2Result (left, LSB, result, MSB16, 0);
6453 movLeft2Result (left, MSB24, result, MSB32, 0);
6454 movLeft2Result (left, MSB16, result, MSB24, 0);
6455 movLeft2Result (left, LSB, result, MSB16, 0);
6456 storeConstToAop (zero, AOP (result), LSB);
6458 else if (shCount == 1)
6459 shiftLLong (left, result, MSB16);
6462 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6463 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6464 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6465 storeConstToAop (zero, AOP (result), LSB);
6470 /* 1 <= shCount <= 7 */
6471 else if (shCount <= 2)
6473 shiftLLong (left, result, LSB);
6475 shiftLLong (result, result, LSB);
6477 /* 3 <= shCount <= 7, optimize */
6480 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6481 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6482 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6486 /*-----------------------------------------------------------------*/
6487 /* genLeftShiftLiteral - left shifting by known count */
6488 /*-----------------------------------------------------------------*/
6490 genLeftShiftLiteral (operand * left,
6495 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6498 D(emitcode ("; genLeftShiftLiteral",""));
6500 freeAsmop (right, NULL, ic, TRUE);
6502 aopOp (left, ic, FALSE);
6503 aopOp (result, ic, FALSE);
6505 // size = getSize (operandType (result));
6506 size = AOP_SIZE (result);
6509 DD(emitcode ("; shift left ", "result %d, left %d", size,
6516 transferAopAop( AOP(left), size, AOP(result), size);
6518 else if (shCount >= (size * 8))
6521 storeConstToAop (zero, AOP (result), size);
6528 genlshOne (result, left, shCount);
6532 genlshTwo (result, left, shCount);
6536 genlshFour (result, left, shCount);
6539 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6540 "*** ack! mystery literal shift!\n");
6544 freeAsmop (left, NULL, ic, TRUE);
6545 freeAsmop (result, NULL, ic, TRUE);
6548 /*-----------------------------------------------------------------*/
6549 /* genLeftShift - generates code for left shifting */
6550 /*-----------------------------------------------------------------*/
6552 genLeftShift (iCode * ic)
6554 operand *left, *right, *result;
6556 symbol *tlbl, *tlbl1;
6560 D(emitcode ("; genLeftShift",""));
6562 right = IC_RIGHT (ic);
6563 left = IC_LEFT (ic);
6564 result = IC_RESULT (ic);
6566 aopOp (right, ic, FALSE);
6568 /* if the shift count is known then do it
6569 as efficiently as possible */
6570 if (AOP_TYPE (right) == AOP_LIT)
6572 genLeftShiftLiteral (left, right, result, ic);
6576 /* shift count is unknown then we have to form
6577 a loop get the loop count in X : Note: we take
6578 only the lower order byte since shifting
6579 more that 32 bits make no sense anyway, ( the
6580 largest size of an object can be only 32 bits ) */
6582 aopOp (result, ic, FALSE);
6583 aopOp (left, ic, FALSE);
6584 aopResult = AOP (result);
6586 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result))
6587 || isOperandVolatile (result, FALSE))
6588 aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result)));
6590 /* now move the left to the result if they are not the
6592 if (!sameRegs (AOP (left), aopResult))
6594 size = AOP_SIZE (result);
6598 transferAopAop (AOP (left), offset, aopResult, offset);
6602 freeAsmop (left, NULL, ic, TRUE);
6603 AOP (result) = aopResult;
6605 tlbl = newiTempLabel (NULL);
6606 size = AOP_SIZE (result);
6608 tlbl1 = newiTempLabel (NULL);
6610 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6611 emitcode ("tstx", "");
6612 emitBranch ("beq", tlbl1);
6616 for (offset=0;offset<size;offset++)
6618 rmwWithAop (shift, AOP (result), offset);
6621 rmwWithReg ("dec", hc08_reg_x);
6622 emitBranch ("bne", tlbl);
6624 hc08_freeReg (hc08_reg_x);
6626 freeAsmop (result, NULL, ic, TRUE);
6627 freeAsmop (right, NULL, ic, TRUE);
6630 /*-----------------------------------------------------------------*/
6631 /* genrshOne - right shift a one byte quantity by known count */
6632 /*-----------------------------------------------------------------*/
6634 genrshOne (operand * result, operand * left,
6635 int shCount, int sign)
6637 D(emitcode ("; genrshOne",""));
6639 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6640 AccRsh (shCount, sign);
6641 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6644 /*-----------------------------------------------------------------*/
6645 /* genrshTwo - right shift two bytes by known amount != 0 */
6646 /*-----------------------------------------------------------------*/
6648 genrshTwo (operand * result, operand * left,
6649 int shCount, int sign)
6651 D(emitcode ("; genrshTwo",""));
6653 /* if shCount >= 8 */
6656 if (shCount || sign)
6658 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6659 AccRsh (shCount-8, sign);
6660 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6664 transferAopAop (AOP (left), 1, AOP (result), 0);
6665 storeConstToAop (zero, AOP (result), 1);
6669 /* 1 <= shCount <= 7 */
6672 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6673 XAccRsh (shCount, sign);
6674 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6678 /*-----------------------------------------------------------------*/
6679 /* shiftRLong - shift right one long from left to result */
6680 /* offl = LSB or MSB16 */
6681 /*-----------------------------------------------------------------*/
6683 shiftRLong (operand * left, int offl,
6684 operand * result, int sign)
6687 // int size = AOP_SIZE (result);
6689 bool needpula = FALSE;
6690 bool needpulx = FALSE;
6692 needpula = pushRegIfUsed (hc08_reg_a);
6693 needpulx = pushRegIfUsed (hc08_reg_x);
6697 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6699 rmwWithReg ("asr", hc08_reg_x);
6701 rmwWithReg ("lsr", hc08_reg_x);
6702 rmwWithReg ("ror", hc08_reg_a);
6703 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6704 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6706 else if (offl==MSB16)
6708 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6710 rmwWithReg ("asr", hc08_reg_a);
6712 rmwWithReg ("lsr", hc08_reg_a);
6713 loadRegFromAop (hc08_reg_x, AOP (left), MSB24);
6714 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6715 loadRegFromAop (hc08_reg_a, AOP (left), MSB16);
6718 rmwWithReg ("ror", hc08_reg_x);
6719 rmwWithReg ("ror", hc08_reg_a);
6720 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6726 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6727 storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
6731 storeConstToAop (zero, AOP (result), MSB32);
6735 pullOrFreeReg (hc08_reg_x, needpulx);
6736 pullOrFreeReg (hc08_reg_a, needpula);
6739 /*-----------------------------------------------------------------*/
6740 /* genrshFour - shift four byte by a known amount != 0 */
6741 /*-----------------------------------------------------------------*/
6743 genrshFour (operand * result, operand * left,
6744 int shCount, int sign)
6746 /* TODO: handle cases where left == result */
6748 D(emitcode ("; genrshFour",""));
6750 /* if shifting more that 3 bytes */
6753 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6754 AccRsh (shCount-24, sign);
6755 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6758 else if (shCount >= 16)
6760 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6761 XAccRsh (shCount-16, sign);
6762 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6765 else if (shCount >= 8)
6768 shiftRLong (left, MSB16, result, sign);
6769 else if (shCount == 8)
6771 transferAopAop (AOP (left), 1, AOP (result), 0);
6772 transferAopAop (AOP (left), 2, AOP (result), 1);
6773 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6774 storeRegToAop (hc08_reg_a, AOP (result), 2);
6775 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6777 else if (shCount == 9)
6779 shiftRLong (left, MSB16, result, sign);
6783 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6784 XAccRsh (shCount-8, FALSE);
6785 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6786 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6787 loadRegFromConst (hc08_reg_a, zero);
6788 XAccRsh (shCount-8, sign);
6789 accopWithAop ("ora", AOP (result), 1);
6790 storeRegToAop (hc08_reg_xa, AOP (result), 1);
6791 storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
6795 { /* 1 <= shCount <= 7 */
6798 shiftRLong (left, LSB, result, sign);
6802 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6803 XAccRsh (shCount, FALSE);
6804 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6805 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6807 accopWithAop ("ora", AOP (result), 1);
6808 storeRegToAop (hc08_reg_a, AOP (result), 1);
6809 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6810 XAccRsh (shCount, sign);
6811 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6816 /*-----------------------------------------------------------------*/
6817 /* genRightShiftLiteral - right shifting by known count */
6818 /*-----------------------------------------------------------------*/
6820 genRightShiftLiteral (operand * left,
6826 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6829 D(emitcode ("; genRightShiftLiteral",""));
6831 freeAsmop (right, NULL, ic, TRUE);
6833 aopOp (left, ic, FALSE);
6834 aopOp (result, ic, FALSE);
6837 DD(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6841 size = getDataSize (left);
6842 /* test the LEFT size !!! */
6844 /* I suppose that the left size >= result size */
6847 size = getDataSize (result);
6849 transferAopAop (AOP (left), size, AOP(result), size);
6851 else if (shCount >= (size * 8))
6854 /* get sign in acc.7 */
6855 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6857 addSign (result, LSB, sign);
6864 genrshOne (result, left, shCount, sign);
6868 genrshTwo (result, left, shCount, sign);
6872 genrshFour (result, left, shCount, sign);
6878 freeAsmop (left, NULL, ic, TRUE);
6879 freeAsmop (result, NULL, ic, TRUE);
6883 /*-----------------------------------------------------------------*/
6884 /* genRightShift - generate code for right shifting */
6885 /*-----------------------------------------------------------------*/
6887 genRightShift (iCode * ic)
6889 operand *right, *left, *result;
6892 symbol *tlbl, *tlbl1;
6897 D(emitcode ("; genRightShift",""));
6899 /* if signed then we do it the hard way preserve the
6900 sign bit moving it inwards */
6901 retype = getSpec (operandType (IC_RESULT (ic)));
6902 sign = !SPEC_USIGN (retype);
6904 /* signed & unsigned types are treated the same : i.e. the
6905 signed is NOT propagated inwards : quoting from the
6906 ANSI - standard : "for E1 >> E2, is equivalent to division
6907 by 2**E2 if unsigned or if it has a non-negative value,
6908 otherwise the result is implementation defined ", MY definition
6909 is that the sign does not get propagated */
6911 right = IC_RIGHT (ic);
6912 left = IC_LEFT (ic);
6913 result = IC_RESULT (ic);
6915 aopOp (right, ic, FALSE);
6917 /* if the shift count is known then do it
6918 as efficiently as possible */
6919 if (AOP_TYPE (right) == AOP_LIT)
6921 genRightShiftLiteral (left, right, result, ic, sign);
6925 /* shift count is unknown then we have to form
6926 a loop get the loop count in X : Note: we take
6927 only the lower order byte since shifting
6928 more that 32 bits make no sense anyway, ( the
6929 largest size of an object can be only 32 bits ) */
6931 aopOp (result, ic, FALSE);
6932 aopOp (left, ic, FALSE);
6933 aopResult = AOP (result);
6935 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result))
6936 || isOperandVolatile (result, FALSE))
6937 aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result)));
6939 /* now move the left to the result if they are not the
6941 if (!sameRegs (AOP (left), aopResult))
6943 size = AOP_SIZE (result);
6947 transferAopAop (AOP (left), offset, aopResult, offset);
6951 freeAsmop (left, NULL, ic, TRUE);
6952 AOP (result) = aopResult;
6954 tlbl = newiTempLabel (NULL);
6955 size = AOP_SIZE (result);
6957 tlbl1 = newiTempLabel (NULL);
6959 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6960 emitcode ("tstx", "");
6961 emitBranch ("beq", tlbl1);
6964 shift= sign ? "asr" : "lsr";
6965 for (offset=size-1;offset>=0;offset--)
6967 rmwWithAop (shift, AOP (result), offset);
6970 rmwWithReg ("dec", hc08_reg_x);
6971 emitBranch ("bne", tlbl);
6973 hc08_freeReg (hc08_reg_x);
6975 freeAsmop (result, NULL, ic, TRUE);
6976 freeAsmop (right, NULL, ic, TRUE);
6980 /*-----------------------------------------------------------------*/
6981 /* genUnpackBits - generates code for unpacking bits */
6982 /*-----------------------------------------------------------------*/
6984 genUnpackBits (operand * result, iCode *ifx)
6986 int offset = 0; /* result byte offset */
6987 int rsize; /* result size */
6988 int rlen = 0; /* remaining bitfield length */
6989 sym_link *etype; /* bitfield type information */
6990 int blen; /* bitfield length */
6991 int bstr; /* bitfield starting bit within byte */
6993 D(emitcode ("; genUnpackBits",""));
6995 etype = getSpec (operandType (result));
6996 rsize = getSize (operandType (result));
6997 blen = SPEC_BLEN (etype);
6998 bstr = SPEC_BSTR (etype);
7000 if (ifx && blen <= 8)
7002 emitcode ("lda", ",x");
7003 hc08_dirtyReg (hc08_reg_a, FALSE);
7006 emitcode ("and", "#0x%02x",
7007 (((unsigned char) -1) >> (8 - blen)) << bstr);
7009 genIfxJump (ifx, "a");
7014 /* If the bitfield length is less than a byte */
7017 emitcode ("lda", ",x");
7018 hc08_dirtyReg (hc08_reg_a, FALSE);
7019 AccRsh (bstr, FALSE);
7020 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7021 if (!SPEC_USIGN (etype))
7023 /* signed bitfield */
7024 symbol *tlbl = newiTempLabel (NULL);
7026 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7027 emitcode ("beq", "%05d$", tlbl->key + 100);
7028 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7031 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7035 /* Bit field did not fit in a byte. Copy all
7036 but the partial byte at the end. */
7037 for (rlen=blen;rlen>=8;rlen-=8)
7039 emitcode ("lda", ",x");
7040 hc08_dirtyReg (hc08_reg_a, FALSE);
7041 storeRegToAop (hc08_reg_a, AOP (result), offset);
7044 emitcode ("aix", "#1");
7047 /* Handle the partial byte at the end */
7050 emitcode ("lda", ",x");
7051 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7052 if (!SPEC_USIGN (etype))
7054 /* signed bitfield */
7055 symbol *tlbl = newiTempLabel (NULL);
7057 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7058 emitcode ("beq", "%05d$", tlbl->key + 100);
7059 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7062 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7069 if (SPEC_USIGN (etype))
7072 storeConstToAop (zero, AOP (result), offset++);
7076 /* signed bitfield: sign extension with 0x00 or 0xff */
7077 emitcode ("rola", "");
7078 emitcode ("clra", "");
7079 emitcode ("sbc", zero);
7082 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7088 /*-----------------------------------------------------------------*/
7089 /* genUnpackBitsImmed - generates code for unpacking bits */
7090 /*-----------------------------------------------------------------*/
7092 genUnpackBitsImmed (operand * left,
7098 int offset = 0; /* result byte offset */
7099 int rsize; /* result size */
7100 int rlen = 0; /* remaining bitfield length */
7101 sym_link *etype; /* bitfield type information */
7102 int blen; /* bitfield length */
7103 int bstr; /* bitfield starting bit within byte */
7106 D(emitcode ("; genUnpackBitsImmed",""));
7108 aopOp (result, ic, TRUE);
7109 size = AOP_SIZE (result);
7111 derefaop = aopDerefAop (AOP (left));
7112 freeAsmop (left, NULL, ic, TRUE);
7113 derefaop->size = size;
7115 etype = getSpec (operandType (result));
7116 rsize = getSize (operandType (result));
7117 blen = SPEC_BLEN (etype);
7118 bstr = SPEC_BSTR (etype);
7120 /* if the bitfield is a single bit in the direct page */
7121 if (blen == 1 && derefaop->type == AOP_DIR)
7125 symbol *tlbl = newiTempLabel (NULL);
7127 loadRegFromConst (hc08_reg_a, zero);
7128 emitcode ("brclr", "#%d,%s,%05d$",
7129 bstr, aopAdrStr (derefaop, 0, FALSE),
7131 if (SPEC_USIGN (etype))
7132 rmwWithReg ("inc", hc08_reg_a);
7134 rmwWithReg ("dec", hc08_reg_a);
7136 storeRegToAop (hc08_reg_a, AOP (result), offset);
7137 hc08_freeReg (hc08_reg_a);
7143 symbol *tlbl = newiTempLabel (NULL);
7149 jlbl = IC_TRUE (ifx);
7154 jlbl = IC_FALSE (ifx);
7157 emitcode (inst, "#%d,%s,%05d$",
7158 bstr, aopAdrStr (derefaop, 0, FALSE),
7160 emitBranch ("jmp", jlbl);
7168 /* If the bitfield length is less than a byte */
7171 loadRegFromAop (hc08_reg_a, derefaop, 0);
7174 AccRsh (bstr, FALSE);
7175 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7176 hc08_dirtyReg (hc08_reg_a, FALSE);
7177 if (!SPEC_USIGN (etype))
7179 /* signed bitfield */
7180 symbol *tlbl = newiTempLabel (NULL);
7182 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7183 emitcode ("beq", "%05d$", tlbl->key + 100);
7184 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7187 storeRegToAop (hc08_reg_a, AOP (result), offset);
7191 emitcode ("and", "#0x%02x",
7192 (((unsigned char) -1) >> (8 - blen)) << bstr);
7193 hc08_dirtyReg (hc08_reg_a, FALSE);
7199 /* Bit field did not fit in a byte. Copy all
7200 but the partial byte at the end. */
7201 for (rlen=blen;rlen>=8;rlen-=8)
7203 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7205 storeRegToAop (hc08_reg_a, AOP (result), offset);
7207 emitcode ("tsta", "");
7211 /* Handle the partial byte at the end */
7214 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7215 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7216 if (!SPEC_USIGN (etype))
7218 /* signed bitfield */
7219 symbol *tlbl = newiTempLabel (NULL);
7221 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7222 emitcode ("beq", "%05d$", tlbl->key + 100);
7223 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7226 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7233 if (SPEC_USIGN (etype))
7236 storeConstToAop (zero, AOP (result), offset++);
7240 /* signed bitfield: sign extension with 0x00 or 0xff */
7241 emitcode ("rola", "");
7242 emitcode ("clra", "");
7243 emitcode ("sbc", zero);
7246 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7250 freeAsmop (NULL, derefaop, ic, TRUE);
7251 freeAsmop (result, NULL, ic, TRUE);
7253 if (ifx && !ifx->generated)
7255 genIfxJump (ifx, "a");
7260 /*-----------------------------------------------------------------*/
7261 /* genDataPointerGet - generates code when ptr offset is known */
7262 /*-----------------------------------------------------------------*/
7264 genDataPointerGet (operand * left,
7272 D(emitcode ("; genDataPointerGet",""));
7274 aopOp (result, ic, TRUE);
7275 size = AOP_SIZE (result);
7277 derefaop = aopDerefAop (AOP (left));
7278 freeAsmop (left, NULL, ic, TRUE);
7279 derefaop->size = size;
7284 transferAopAop (derefaop, size, AOP (result), size);
7286 loadRegFromAop (hc08_reg_a, derefaop, size);
7289 freeAsmop (NULL, derefaop, ic, TRUE);
7290 freeAsmop (result, NULL, ic, TRUE);
7292 if (ifx && !ifx->generated)
7294 genIfxJump (ifx, "a");
7299 /*-----------------------------------------------------------------*/
7300 /* genPointerGet - generate code for pointer get */
7301 /*-----------------------------------------------------------------*/
7303 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7305 operand *left = IC_LEFT (ic);
7306 operand *result = IC_RESULT (ic);
7308 sym_link *retype = getSpec (operandType (result));
7310 D(emitcode ("; genPointerGet",""));
7312 if (getSize (operandType (result))>1)
7315 aopOp (left, ic, FALSE);
7317 /* if left is rematerialisable and
7318 result is not bit variable type */
7319 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7321 if (!IS_BITVAR (retype))
7323 genDataPointerGet (left, result, ic, ifx);
7328 genUnpackBitsImmed (left, result, ic, ifx);
7333 /* if the operand is already in hx
7334 then we do nothing else we move the value to hx */
7335 if (AOP_TYPE (left) != AOP_STR)
7337 /* if this is remateriazable */
7338 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7341 /* so hx now contains the address */
7342 aopOp (result, ic, FALSE);
7344 /* if bit then unpack */
7345 if (IS_BITVAR (retype))
7346 genUnpackBits (result, ifx);
7349 size = AOP_SIZE (result);
7354 accopWithMisc ("lda", ",x");
7357 emitcode ("aix", "#1");
7358 hc08_dirtyReg (hc08_reg_hx, FALSE);
7361 storeRegToAop (hc08_reg_a, AOP (result), offset);
7363 hc08_freeReg (hc08_reg_a);
7367 freeAsmop (left, NULL, ic, TRUE);
7368 freeAsmop (result, NULL, ic, TRUE);
7371 aopOp (IC_RESULT (pi), pi, FALSE);
7372 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7373 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7377 if (ifx && !ifx->generated)
7379 genIfxJump (ifx, "a");
7382 hc08_freeReg (hc08_reg_hx);
7386 /*-----------------------------------------------------------------*/
7387 /* genPackBits - generates code for packed bit storage */
7388 /*-----------------------------------------------------------------*/
7390 genPackBits (sym_link * etype,
7393 int offset = 0; /* source byte offset */
7394 int rlen = 0; /* remaining bitfield length */
7395 int blen; /* bitfield length */
7396 int bstr; /* bitfield starting bit within byte */
7397 int litval; /* source literal value (if AOP_LIT) */
7398 unsigned char mask; /* bitmask within current byte */
7401 D(emitcode ("; genPackBits",""));
7403 blen = SPEC_BLEN (etype);
7404 bstr = SPEC_BSTR (etype);
7406 /* If the bitfield length is less than a byte */
7409 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7410 (unsigned char) (0xFF >> (8 - bstr)));
7412 if (AOP_TYPE (right) == AOP_LIT)
7414 /* Case with a bitfield length <8 and literal source
7416 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7418 litval &= (~mask) & 0xff;
7420 emitcode ("lda", ",x");
7421 if ((mask|litval)!=0xff)
7422 emitcode ("and","#0x%02x", mask);
7424 emitcode ("ora","#0x%02x", litval);
7425 hc08_dirtyReg (hc08_reg_a, FALSE);
7426 emitcode ("sta", ",x");
7428 hc08_freeReg (hc08_reg_a);
7432 /* Case with a bitfield length < 8 and arbitrary source
7434 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7435 /* shift and mask source value */
7437 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7438 hc08_dirtyReg (hc08_reg_a, FALSE);
7439 pushReg (hc08_reg_a, TRUE);
7441 emitcode ("lda", ",x");
7442 emitcode ("and", "#0x%02x", mask);
7443 emitcode ("ora", "1,s");
7444 emitcode ("sta", ",x");
7445 pullReg (hc08_reg_a);
7447 hc08_freeReg (hc08_reg_a);
7451 /* Bit length is greater than 7 bits. In this case, copy */
7452 /* all except the partial byte at the end */
7453 for (rlen=blen;rlen>=8;rlen-=8)
7455 if (AOP (right)->type == AOP_DIR)
7457 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7462 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7463 emitcode ("sta", "%d,x", offset);
7468 /* If there was a partial byte at the end */
7471 mask = (((unsigned char) -1 << rlen) & 0xff);
7473 if (AOP_TYPE (right) == AOP_LIT)
7475 /* Case with partial byte and literal source
7477 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7478 litval >>= (blen-rlen);
7479 litval &= (~mask) & 0xff;
7480 emitcode ("lda", "%d,x", offset - xoffset);
7481 hc08_dirtyReg (hc08_reg_a, FALSE);
7482 if ((mask|litval)!=0xff)
7483 emitcode ("and","#0x%02x", mask);
7485 emitcode ("ora","#0x%02x", litval);
7486 emitcode ("sta", "%d,x", offset - xoffset);
7487 hc08_dirtyReg (hc08_reg_a, FALSE);
7488 hc08_freeReg (hc08_reg_a);
7492 /* Case with partial byte and arbitrary source
7494 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7495 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7496 hc08_dirtyReg (hc08_reg_a, FALSE);
7497 pushReg (hc08_reg_a, TRUE);
7499 emitcode ("lda", "%d,x", offset - xoffset);
7500 emitcode ("and", "#0x%02x", mask);
7501 emitcode ("ora", "1,s");
7502 emitcode ("sta", "%d,x", offset - xoffset);
7503 pullReg (hc08_reg_a);
7506 hc08_freeReg (hc08_reg_a);
7509 /*-----------------------------------------------------------------*/
7510 /* genPackBitsImmed - generates code for packed bit storage */
7511 /*-----------------------------------------------------------------*/
7513 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7517 int offset = 0; /* source byte offset */
7518 int rlen = 0; /* remaining bitfield length */
7519 int blen; /* bitfield length */
7520 int bstr; /* bitfield starting bit within byte */
7521 int litval; /* source literal value (if AOP_LIT) */
7522 unsigned char mask; /* bitmask within current byte */
7524 D(emitcode ("; genPackBitsImmed",""));
7526 blen = SPEC_BLEN (etype);
7527 bstr = SPEC_BSTR (etype);
7529 aopOp (right, ic, FALSE);
7530 size = AOP_SIZE (right);
7532 derefaop = aopDerefAop (AOP (result));
7533 freeAsmop (result, NULL, ic, TRUE);
7534 derefaop->size = size;
7536 /* if the bitfield is a single bit in the direct page */
7537 if (blen == 1 && derefaop->type == AOP_DIR)
7539 if (AOP_TYPE (right) == AOP_LIT)
7541 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7543 emitcode ((litval & 1) ? "bset" : "bclr",
7544 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7548 symbol *tlbl1 = newiTempLabel (NULL);
7549 symbol *tlbl2 = newiTempLabel (NULL);
7551 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7552 emitcode ("bit", "#1");
7553 emitBranch ("bne", tlbl1);
7554 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7555 emitBranch ("bra", tlbl2);
7557 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7559 hc08_freeReg (hc08_reg_a);
7564 /* If the bitfield length is less than a byte */
7567 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7568 (unsigned char) (0xFF >> (8 - bstr)));
7570 if (AOP_TYPE (right) == AOP_LIT)
7572 /* Case with a bitfield length <8 and literal source
7574 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7576 litval &= (~mask) & 0xff;
7578 loadRegFromAop (hc08_reg_a, derefaop, 0);
7579 if ((mask|litval)!=0xff)
7580 emitcode ("and","#0x%02x", mask);
7582 emitcode ("ora","#0x%02x", litval);
7583 hc08_dirtyReg (hc08_reg_a, FALSE);
7584 storeRegToAop (hc08_reg_a, derefaop, 0);
7586 hc08_freeReg (hc08_reg_a);
7590 /* Case with a bitfield length < 8 and arbitrary source
7592 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7593 /* shift and mask source value */
7595 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7596 hc08_dirtyReg (hc08_reg_a, FALSE);
7597 pushReg (hc08_reg_a, TRUE);
7599 loadRegFromAop (hc08_reg_a, derefaop, 0);
7600 emitcode ("and", "#0x%02x", mask);
7601 emitcode ("ora", "1,s");
7602 storeRegToAop (hc08_reg_a, derefaop, 0);
7603 pullReg (hc08_reg_a);
7605 hc08_freeReg (hc08_reg_a);
7609 /* Bit length is greater than 7 bits. In this case, copy */
7610 /* all except the partial byte at the end */
7611 for (rlen=blen;rlen>=8;rlen-=8)
7613 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7617 /* If there was a partial byte at the end */
7620 mask = (((unsigned char) -1 << rlen) & 0xff);
7622 if (AOP_TYPE (right) == AOP_LIT)
7624 /* Case with partial byte and literal source
7626 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7627 litval >>= (blen-rlen);
7628 litval &= (~mask) & 0xff;
7629 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7630 if ((mask|litval)!=0xff)
7631 emitcode ("and","#0x%02x", mask);
7633 emitcode ("ora","#0x%02x", litval);
7634 hc08_dirtyReg (hc08_reg_a, FALSE);
7635 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7636 hc08_dirtyReg (hc08_reg_a, FALSE);
7637 hc08_freeReg (hc08_reg_a);
7641 /* Case with partial byte and arbitrary source
7643 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7644 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7645 hc08_dirtyReg (hc08_reg_a, FALSE);
7646 pushReg (hc08_reg_a, TRUE);
7648 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7649 emitcode ("and", "#0x%02x", mask);
7650 emitcode ("ora", "1,s");
7651 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7652 pullReg (hc08_reg_a);
7655 hc08_freeReg (hc08_reg_a);
7658 freeAsmop (right, NULL, ic, TRUE);
7659 freeAsmop (NULL, derefaop, ic, TRUE);
7662 /*-----------------------------------------------------------------*/
7663 /* genDataPointerSet - remat pointer to data space */
7664 /*-----------------------------------------------------------------*/
7666 genDataPointerSet (operand * right,
7673 D(emitcode ("; genDataPointerSet",""));
7675 aopOp (right, ic, FALSE);
7676 size = AOP_SIZE (right);
7678 derefaop = aopDerefAop (AOP (result));
7679 freeAsmop (result, NULL, ic, TRUE);
7680 derefaop->size = size;
7684 transferAopAop (AOP (right), size, derefaop, size);
7687 freeAsmop (right, NULL, ic, TRUE);
7688 freeAsmop (NULL, derefaop, ic, TRUE);
7692 /*-----------------------------------------------------------------*/
7693 /* genPointerSet - stores the value into a pointer location */
7694 /*-----------------------------------------------------------------*/
7696 genPointerSet (iCode * ic, iCode *pi)
7698 operand *right = IC_RIGHT (ic);
7699 operand *result = IC_RESULT (ic);
7700 sym_link *type, *etype;
7702 sym_link *retype = getSpec (operandType (right));
7703 sym_link *letype = getSpec (operandType (result));
7705 D(emitcode ("; genPointerSet",""));
7707 type = operandType (result);
7708 etype = getSpec (type);
7710 aopOp (result, ic, FALSE);
7712 /* if the result is rematerializable */
7713 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7715 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7717 genDataPointerSet (right, result, ic);
7722 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7727 /* if the operand is already in hx
7728 then we do nothing else we move the value to hx */
7729 if (AOP_TYPE (result) != AOP_STR)
7731 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7733 /* so hx now contains the address */
7734 aopOp (right, ic, FALSE);
7736 /* if bit then unpack */
7737 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7738 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7741 size = AOP_SIZE (right);
7746 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7747 accopWithMisc ("sta", ",x");
7750 emitcode ("aix", "#1");
7752 hc08_freeReg (hc08_reg_a);
7756 freeAsmop (result, NULL, ic, TRUE);
7757 freeAsmop (right, NULL, ic, TRUE);
7760 aopOp (IC_RESULT (pi), pi, FALSE);
7761 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7762 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7766 hc08_freeReg (hc08_reg_hx);
7770 /*-----------------------------------------------------------------*/
7771 /* genIfx - generate code for Ifx statement */
7772 /*-----------------------------------------------------------------*/
7774 genIfx (iCode * ic, iCode * popIc)
7776 operand *cond = IC_COND (ic);
7779 D(emitcode ("; genIfx",""));
7781 aopOp (cond, ic, FALSE);
7783 /* If the condition is a literal, we can just do an unconditional */
7784 /* branch or no branch */
7785 if (AOP_TYPE (cond) == AOP_LIT)
7787 unsigned long lit = (unsigned long) floatFromVal (AOP (cond)->aopu.aop_lit);
7788 freeAsmop (cond, NULL, ic, TRUE);
7790 /* if there was something to be popped then do it */
7796 emitBranch ("jmp", IC_TRUE (ic));
7801 emitBranch ("jmp", IC_FALSE (ic));
7807 /* get the value into acc */
7808 if (AOP_TYPE (cond) != AOP_CRY)
7809 asmopToBool (AOP (cond), FALSE);
7812 /* the result is now in the accumulator */
7813 freeAsmop (cond, NULL, ic, TRUE);
7815 /* if there was something to be popped then do it */
7819 /* if the condition is a bit variable */
7820 if (isbit && IS_ITEMP (cond) &&
7822 genIfxJump (ic, SPIL_LOC (cond)->rname);
7823 else if (isbit && !IS_ITEMP (cond))
7824 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7826 genIfxJump (ic, "a");
7831 /*-----------------------------------------------------------------*/
7832 /* genAddrOf - generates code for address of */
7833 /*-----------------------------------------------------------------*/
7835 genAddrOf (iCode * ic)
7837 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7840 D(emitcode ("; genAddrOf",""));
7842 aopOp (IC_RESULT (ic), ic, FALSE);
7844 /* if the operand is on the stack then we
7845 need to get the stack offset of this
7849 /* if it has an offset then we need to compute it */
7850 offset = _G.stackOfs + _G.stackPushes + sym->stack;
7851 hc08_useReg (hc08_reg_hx);
7852 emitcode ("tsx", "");
7853 while (offset > 127)
7855 emitcode ("aix", "#127");
7858 while (offset < -128)
7860 emitcode ("aix", "#-128");
7863 emitcode ("aix", "#%d", offset);
7864 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7865 hc08_freeReg (hc08_reg_hx);
7870 /* object not on stack then we need the name */
7871 size = AOP_SIZE (IC_RESULT (ic));
7876 char s[SDCC_NAME_MAX+10];
7879 sprintf (s, "#%s", sym->rname);
7882 sprintf (s, "#>%s", sym->rname);
7885 sprintf (s, "#(%s >> %d)",
7889 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7893 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7897 /*-----------------------------------------------------------------*/
7898 /* genAssign - generate code for assignment */
7899 /*-----------------------------------------------------------------*/
7901 genAssign (iCode * ic)
7903 operand *result, *right;
7905 // unsigned long lit = 0L;
7907 D(emitcode("; genAssign",""));
7909 result = IC_RESULT (ic);
7910 right = IC_RIGHT (ic);
7912 /* if they are the same */
7913 if (operandsEqu (result, right)) {
7917 aopOp (right, ic, FALSE);
7918 aopOp (result, ic, TRUE);
7920 /* if they are the same registers */
7921 if (sameRegs (AOP (right), AOP (result)))
7924 if ((AOP_TYPE (right) == AOP_LIT)
7925 && (IS_AOP_HX(AOP(result))))
7927 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7932 size = AOP_SIZE (result);
7935 transferAopAop (AOP (right), size, AOP (result), size);
7939 freeAsmop (right, NULL, ic, TRUE);
7940 freeAsmop (result, NULL, ic, TRUE);
7943 /*-----------------------------------------------------------------*/
7944 /* genJumpTab - generates code for jump table */
7945 /*-----------------------------------------------------------------*/
7947 genJumpTab (iCode * ic)
7950 symbol *jtablo = newiTempLabel (NULL);
7951 symbol *jtabhi = newiTempLabel (NULL);
7953 D(emitcode ("; genJumpTab",""));
7955 aopOp (IC_JTCOND (ic), ic, FALSE);
7957 if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7959 /* get the condition into x */
7960 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7961 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7962 loadRegFromConst (hc08_reg_h, zero);
7964 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7965 emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7966 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7967 emitcode ("jmp", ",x");
7969 hc08_dirtyReg (hc08_reg_a, TRUE);
7970 hc08_dirtyReg (hc08_reg_hx, TRUE);
7975 pushReg(hc08_reg_hx, TRUE);
7977 /* get the condition into x */
7978 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7979 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7980 loadRegFromConst (hc08_reg_h, zero);
7982 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7983 emitcode ("sta", "3,s");
7984 emitcode ("lda", "%05d$,x", jtablo->key + 100);
7985 emitcode ("sta", "4,s");
7987 pullReg(hc08_reg_hx);
7988 emitcode ("rts", "");
7989 _G.stackPushes += 2;
7993 /* now generate the jump labels */
7995 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7996 jtab = setNextItem (IC_JTLABELS (ic)))
7997 emitcode (".db", "%05d$", jtab->key + 100);
7999 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8000 jtab = setNextItem (IC_JTLABELS (ic)))
8001 emitcode (".db", ">%05d$", jtab->key + 100);
8005 /*-----------------------------------------------------------------*/
8006 /* genCast - gen code for casting */
8007 /*-----------------------------------------------------------------*/
8009 genCast (iCode * ic)
8011 operand *result = IC_RESULT (ic);
8012 sym_link *ctype = operandType (IC_LEFT (ic));
8013 sym_link *rtype = operandType (IC_RIGHT (ic));
8014 operand *right = IC_RIGHT (ic);
8017 D(emitcode("; genCast",""));
8019 /* if they are equivalent then do nothing */
8020 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8023 aopOp (right, ic, FALSE);
8024 aopOp (result, ic, FALSE);
8027 /* if they are the same size : or less */
8028 if (AOP_SIZE (result) <= AOP_SIZE (right))
8031 /* if they are in the same place */
8033 if (sameRegs (AOP (right), AOP (result)))
8037 /* if they in different places then copy */
8038 size = AOP_SIZE (result);
8042 transferAopAop(AOP (right), offset, AOP (result), offset);
8049 /* if the result is of type pointer */
8054 sym_link *type = operandType (right);
8055 sym_link *etype = getSpec (type);
8057 /* pointer to generic pointer */
8058 if (IS_GENPTR (ctype))
8061 p_type = DCL_TYPE (type);
8064 if (SPEC_SCLS(etype)==S_REGISTER) {
8065 // let's assume it is a generic pointer
8068 /* we have to go by the storage class */
8069 p_type = PTR_TYPE (SPEC_OCLS (etype));
8073 /* the first two bytes are known */
8074 size = GPTRSIZE - 1;
8078 transferAopAop(AOP (right), offset, AOP (result), offset);
8081 /* the last byte depending on type */
8084 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8089 // pointerTypeToGPByte will have bitched.
8093 sprintf(gpValStr, "#0x%x", gpVal);
8094 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8100 /* just copy the pointers */
8101 size = AOP_SIZE (result);
8105 transferAopAop(AOP (right), offset, AOP (result), offset);
8111 /* so we now know that the size of destination is greater
8112 than the size of the source */
8113 /* we move to result for the size of source */
8114 size = AOP_SIZE (right);
8118 transferAopAop(AOP (right), offset, AOP (result), offset);
8122 /* now depending on the sign of the source && destination */
8123 size = AOP_SIZE (result) - AOP_SIZE (right);
8124 /* if unsigned or not an integral type */
8125 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8128 storeConstToAop (zero, AOP (result), offset++);
8132 /* we need to extend the sign :{ */
8133 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
8134 accopWithMisc ("rola", "");
8135 accopWithMisc ("clra", "");
8136 accopWithMisc ("sbc", zero);
8138 storeRegToAop (hc08_reg_a, AOP (result), offset++);
8141 /* we are done hurray !!!! */
8144 freeAsmop (right, NULL, ic, TRUE);
8145 freeAsmop (result, NULL, ic, TRUE);
8149 /*-----------------------------------------------------------------*/
8150 /* genDjnz - generate decrement & jump if not zero instrucion */
8151 /*-----------------------------------------------------------------*/
8153 genDjnz (iCode * ic, iCode * ifx)
8159 D(emitcode ("; genDjnz",""));
8161 /* if the if condition has a false label
8162 then we cannot save */
8166 /* if the minus is not of the form
8168 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8169 !IS_OP_LITERAL (IC_RIGHT (ic)))
8172 if (operandLitValue (IC_RIGHT (ic)) != 1)
8175 /* dbnz doesn't support extended mode */
8176 if (isOperandInFarSpace (IC_RESULT (ic)))
8179 /* if the size of this greater than one then no
8181 // if (getSize (operandType (IC_RESULT (ic))) > 1)
8183 aopOp (IC_RESULT (ic), ic, FALSE);
8184 if (AOP_SIZE (IC_RESULT (ic))>1)
8186 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8190 /* otherwise we can save BIG */
8191 lbl = newiTempLabel (NULL);
8192 lbl1 = newiTempLabel (NULL);
8195 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
8198 emitBranch ("bra", lbl1);
8200 emitBranch ("jmp", IC_TRUE (ifx));
8203 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8208 /*-----------------------------------------------------------------*/
8209 /* genReceive - generate code for a receive iCode */
8210 /*-----------------------------------------------------------------*/
8212 genReceive (iCode * ic)
8216 D(emitcode ("; genReceive",""));
8218 aopOp (IC_RESULT (ic), ic, FALSE);
8219 size = AOP_SIZE (IC_RESULT (ic));
8224 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
8225 AOP (IC_RESULT (ic)), offset);
8226 if (hc08_aop_pass[offset]->type == AOP_REG)
8227 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
8232 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8235 /*-----------------------------------------------------------------*/
8236 /* genDummyRead - generate code for dummy read of volatiles */
8237 /*-----------------------------------------------------------------*/
8239 genDummyRead (iCode * ic)
8244 D(emitcode("; genDummyRead",""));
8247 if (op && IS_SYMOP (op))
8250 aopOp (op, ic, FALSE);
8252 size = AOP_SIZE (op);
8257 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8258 hc08_freeReg (hc08_reg_a);
8262 freeAsmop (op, NULL, ic, TRUE);
8265 if (op && IS_SYMOP (op))
8268 aopOp (op, ic, FALSE);
8270 size = AOP_SIZE (op);
8275 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8276 hc08_freeReg (hc08_reg_a);
8280 freeAsmop (op, NULL, ic, TRUE);
8284 /*-----------------------------------------------------------------*/
8285 /* genCritical - generate code for start of a critical sequence */
8286 /*-----------------------------------------------------------------*/
8288 genCritical (iCode *ic)
8290 D(emitcode("; genCritical",""));
8293 aopOp (IC_RESULT (ic), ic, TRUE);
8295 emitcode ("tpa", "");
8296 hc08_dirtyReg (hc08_reg_a, FALSE);
8297 emitcode ("sei", "");
8300 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8302 pushReg (hc08_reg_a, FALSE);
8304 hc08_freeReg (hc08_reg_a);
8306 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8309 /*-----------------------------------------------------------------*/
8310 /* genEndCritical - generate code for end of a critical sequence */
8311 /*-----------------------------------------------------------------*/
8313 genEndCritical (iCode *ic)
8315 D(emitcode("; genEndCritical",""));
8319 aopOp (IC_RIGHT (ic), ic, FALSE);
8320 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8321 emitcode ("tap", "");
8322 hc08_freeReg (hc08_reg_a);
8323 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8327 pullReg (hc08_reg_a);
8328 emitcode ("tap", "");
8334 /*-----------------------------------------------------------------*/
8335 /* genhc08Code - generate code for HC08 based controllers */
8336 /*-----------------------------------------------------------------*/
8338 genhc08Code (iCode * lic)
8345 lineHead = lineCurr = NULL;
8347 /* print the allocation information */
8348 if (allocInfo && currFunc)
8349 printAllocInfo (currFunc, codeOutFile);
8350 /* if debug information required */
8351 if (options.debug && currFunc)
8353 debugFile->writeFunction (currFunc, lic);
8356 if (IS_STATIC (currFunc->etype))
8357 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8359 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8363 /* stack pointer name */
8364 if (options.useXstack)
8369 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8371 hc08_aop_pass[0] = newAsmop (AOP_REG);
8372 hc08_aop_pass[0]->size=1;
8373 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8374 hc08_aop_pass[1] = newAsmop (AOP_REG);
8375 hc08_aop_pass[1]->size=1;
8376 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8377 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8378 hc08_aop_pass[2]->size=1;
8379 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8380 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8381 hc08_aop_pass[3]->size=1;
8382 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8384 for (ic = lic; ic; ic = ic->next)
8387 _G.current_iCode = ic;
8389 if (ic->level != clevel || ic->block != cblock)
8393 debugFile->writeScope(ic);
8399 if (ic->lineno && cln != ic->lineno)
8403 debugFile->writeCLine(ic);
8406 emitcode ("", "C$%s$%d$%d$%d ==.",
8407 FileBaseName (ic->filename), ic->lineno,
8408 ic->level, ic->block);
8412 if (!options.noCcodeInAsm) {
8413 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8414 printCLine(ic->filename, ic->lineno));
8418 if (options.iCodeInAsm) {
8422 for (i=0; i<6; i++) {
8423 sprintf (®sInUse[i],
8424 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8427 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8429 /* if the result is marked as
8430 spilt and rematerializable or code for
8431 this has already been generated then
8433 if (resultRemat (ic) || ic->generated)
8441 for (i=A_IDX;i<=XA_IDX;i++)
8443 reg = hc08_regWithIdx(i);
8445 emitcode("","; %s = %s offset %d", reg->name,
8446 aopName(reg->aop), reg->aopofs);
8449 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8451 sym = OP_SYMBOL (IC_LEFT (ic));
8452 if (sym->accuse == ACCUSE_HX)
8454 hc08_reg_h->isFree = FALSE;
8455 hc08_reg_x->isFree = FALSE;
8457 else if (sym->accuse == ACCUSE_XA)
8459 hc08_reg_a->isFree = FALSE;
8461 hc08_reg_x->isFree = FALSE;
8464 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8466 sym = OP_SYMBOL (IC_RIGHT (ic));
8467 if (sym->accuse == ACCUSE_HX)
8469 hc08_reg_h->isFree = FALSE;
8470 hc08_reg_x->isFree = FALSE;
8472 else if (sym->accuse == ACCUSE_XA)
8474 hc08_reg_a->isFree = FALSE;
8476 hc08_reg_x->isFree = FALSE;
8481 /* depending on the operation */
8501 /* IPOP happens only when trying to restore a
8502 spilt live range, if there is an ifx statement
8503 following this pop then the if statement might
8504 be using some of the registers being popped which
8505 would destory the contents of the register so
8506 we need to check for this condition and handle it */
8508 ic->next->op == IFX &&
8509 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8510 genIfx (ic->next, ic);
8528 genEndFunction (ic);
8544 if (!genPointerGetSetOfs (ic))
8549 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8569 genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
8574 genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
8586 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8590 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8594 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8621 case GET_VALUE_AT_ADDRESS:
8623 hasInc (IC_LEFT (ic), ic,
8624 getSize (operandType (IC_RESULT (ic)))),
8625 ifxForOp (IC_RESULT (ic), ic) );
8629 if (POINTER_SET (ic))
8630 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8656 addSet (&_G.sendSet, ic);
8659 case DUMMY_READ_VOLATILE:
8668 genEndCritical (ic);
8679 if (!hc08_reg_a->isFree)
8680 DD(emitcode("","; forgot to free a"));
8681 if (!hc08_reg_x->isFree)
8682 DD(emitcode("","; forgot to free x"));
8683 if (!hc08_reg_h->isFree)
8684 DD(emitcode("","; forgot to free h"));
8685 if (!hc08_reg_hx->isFree)
8686 DD(emitcode("","; forgot to free hx"));
8687 if (!hc08_reg_xa->isFree)
8688 DD(emitcode("","; forgot to free xa"));
8691 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8694 /* now we are ready to call the
8695 peep hole optimizer */
8696 if (!options.nopeep)
8697 peepHole (&lineHead);
8699 /* now do the actual printing */
8700 printLine (lineHead, codeOutFile);