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 */
31 #define D(x) do if (options.verboseAsm) {x;} while(0)
32 /* Use the DD macro for detailed debugging messages */
40 #include "SDCCglobl.h"
44 #include "SDCCpeeph.h"
48 char *aopLiteral (value * val, int offset);
49 char *aopLiteralLong (value * val, int offset, int size);
51 static int pushReg (regs *reg, bool freereg);
52 static void pullReg (regs *reg);
53 static void transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs);
55 static char *zero = "#0x00";
56 static char *one = "#0x01";
60 {"a", "x", "_ret2", "_ret3"};
61 unsigned fReturnSizeHC08 = 4; /* shared with ralloc.c */
62 char **fReturn2 = fReturnhc08;
81 static asmop *hc08_aop_pass[4];
83 extern int hc08_ptrRegReq;
84 extern int hc08_nRegs;
85 extern struct dbuf_s *codeOutBuf;
86 //static void saveRBank (int, iCode *, bool);
87 static bool operandsEqu (operand * op1, operand * op2);
88 static void loadRegFromConst (regs *reg, char *c);
89 static char *aopName (asmop *aop);
90 static asmop * newAsmop (short type);
91 static char * aopAdrStr (asmop * aop, int loffset, bool bit16);
92 #define RESULTONSTACK(x) \
93 (IC_RESULT(x) && IC_RESULT(x)->aop && \
94 IC_RESULT(x)->aop->type == AOP_STK )
96 #define IS_AOP_HX(x) \
97 (((x)->type == AOP_REG) \
98 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
99 && ((x)->aopu.aop_reg[1] == hc08_reg_h) )
101 #define IS_AOP_XA(x) \
102 (((x)->type == AOP_REG) \
103 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
104 && ((x)->aopu.aop_reg[1] == hc08_reg_x) )
106 #define IS_AOP_A(x) \
107 (((x)->type == AOP_REG) \
108 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
109 && ((x)->size == 1) )
111 #define IS_AOP_X(x) \
112 (((x)->type == AOP_REG) \
113 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
114 && ((x)->size == 1) )
116 #define IS_AOP_H(x) \
117 (((x)->type == AOP_REG) \
118 && ((x)->aopu.aop_reg[0] == hc08_reg_h) \
119 && ((x)->size == 1) )
121 #define CLRC emitcode("clc","")
123 static lineNode *lineHead = NULL;
124 static lineNode *lineCurr = NULL;
127 static unsigned char SLMask[] =
128 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
129 0xE0, 0xC0, 0x80, 0x00};
130 static unsigned char SRMask[] =
131 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
132 0x07, 0x03, 0x01, 0x00};
140 #define AOP(op) op->aop
141 #define AOP_TYPE(op) AOP(op)->type
142 #define AOP_SIZE(op) AOP(op)->size
143 #define AOP_OP(aop) aop->op
146 /*-----------------------------------------------------------------*/
147 /* emitcode - writes the code into a file : for now it is simple */
148 /*-----------------------------------------------------------------*/
150 emitcode (char *inst, char *fmt,...)
153 char lb[INITIAL_INLINEASM];
161 sprintf (lb, "%s\t", inst);
163 sprintf (lb, "%s", inst);
164 vsprintf (lb + (strlen (lb)), fmt, ap);
167 vsprintf (lb, fmt, ap);
169 while (isspace ((unsigned char)*lbp))
173 lineCurr = (lineCurr ?
174 connectLine (lineCurr, newLineNode (lb)) :
175 (lineHead = newLineNode (lb)));
176 lineCurr->isInline = _G.inLine;
177 lineCurr->isDebug = _G.debugLine;
178 lineCurr->ic = _G.current_iCode;
179 lineCurr->isComment = (*lbp==';');
181 //printf("%s\n", lb);
186 emitBranch (char *branchop, symbol *tlbl)
188 emitcode (branchop, "%05d$", (tlbl->key + 100));
192 emitLabel (symbol *tlbl)
194 emitcode ("", "%05d$:", (tlbl->key +100));
195 lineCurr->isLabel = 1;
198 /*-----------------------------------------------------------------*/
199 /* hc08_emitDebuggerSymbol - associate the current code location */
200 /* with a debugger symbol */
201 /*-----------------------------------------------------------------*/
203 hc08_emitDebuggerSymbol (char * debugSym)
206 emitcode ("", "%s ==.", debugSym);
211 /*--------------------------------------------------------------------------*/
212 /* transferRegReg - Transfer from register(s) sreg to register(s) dreg. If */
213 /* freesrc is true, sreg is marked free and available for */
214 /* reuse. sreg and dreg must be of equal size */
215 /*--------------------------------------------------------------------------*/
217 transferRegReg (regs *sreg, regs *dreg, bool freesrc)
223 /* Nothing to do if no destination. */
227 /* But it's definately an error if there's no source. */
230 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
231 "NULL sreg in transferRegReg");
235 DD(emitcode ("", "; transferRegReg(%s,%s)",
236 sreg->name, dreg->name));
249 case H_IDX: /* H to A */
250 pushReg (hc08_reg_h, FALSE);
251 pullReg (hc08_reg_a);
253 case X_IDX: /* X to A */
254 emitcode ("txa", "");
263 case A_IDX: /* A to H */
264 pushReg (hc08_reg_a, FALSE);
265 pullReg (hc08_reg_h);
267 case X_IDX: /* X to H */
268 pushReg (hc08_reg_x, FALSE);
269 pullReg (hc08_reg_h);
278 case A_IDX: /* A to X */
279 emitcode ("tax", "");
281 case H_IDX: /* H to X */
282 pushReg (hc08_reg_h, FALSE);
283 pullReg (hc08_reg_x);
292 case XA_IDX: /* XA to HX */
293 pushReg (hc08_reg_x, FALSE);
294 pullReg (hc08_reg_h);
295 emitcode ("tax", "");
304 case HX_IDX: /* HX to XA */
305 emitcode ("txa", "");
306 pushReg (hc08_reg_h, FALSE);
307 pullReg (hc08_reg_x);
317 wassertl (!error, "bad combo in transferRegReg");
322 dreg->aop = sreg->aop;
323 dreg->aopofs = sreg->aopofs;
324 dreg->isFree = FALSE;
328 /*--------------------------------------------------------------------------*/
329 /* updateCFA - update the debugger information to reflect the current */
330 /* connonical frame address relative to the stack pointer */
331 /*--------------------------------------------------------------------------*/
335 /* there is no frame unless there is a function */
339 debugFile->writeFrameAddress (NULL, hc08_reg_sp,
340 1 + _G.stackOfs + _G.stackPushes);
343 /*--------------------------------------------------------------------------*/
344 /* pushReg - Push register reg onto the stack. If freereg is true, reg is */
345 /* marked free and available for reuse. */
346 /*--------------------------------------------------------------------------*/
348 pushReg (regs *reg, bool freereg)
350 int regidx = reg->rIdx;
355 emitcode ("psha", "");
360 emitcode ("pshx", "");
365 emitcode ("pshh", "");
370 emitcode ("pshx", "");
373 emitcode ("pshh", "");
378 emitcode ("psha", "");
381 emitcode ("pshx", "");
390 return -_G.stackOfs-_G.stackPushes;
393 /*--------------------------------------------------------------------------*/
394 /* pullReg - Pull register reg off the stack. */
395 /*--------------------------------------------------------------------------*/
399 int regidx = reg->rIdx;
404 emitcode ("pula", "");
409 emitcode ("pulx", "");
414 emitcode ("pulh", "");
419 emitcode ("pulh", "");
422 emitcode ("pulx", "");
427 emitcode ("pulx", "");
430 emitcode ("pula", "");
438 hc08_dirtyReg(reg, FALSE);
441 /*--------------------------------------------------------------------------*/
442 /* pullNull - Discard n bytes off the top of the stack */
443 /*--------------------------------------------------------------------------*/
449 emitcode("ais","#%d",n);
455 /*--------------------------------------------------------------------------*/
456 /* pushRegIfUsed - Push register reg if marked in use. Returns true if the */
457 /* push was performed, false otherwise. */
458 /*--------------------------------------------------------------------------*/
460 pushRegIfUsed (regs *reg)
471 /*--------------------------------------------------------------------------*/
472 /* pullOrFreeReg - If needpull is true, register reg is pulled from the */
473 /* stack. Otherwise register reg is marked as free. */
474 /*--------------------------------------------------------------------------*/
476 pullOrFreeReg (regs *reg, bool needpull)
484 /*--------------------------------------------------------------------------*/
485 /* adjustStack - Adjust the stack pointer by n bytes. */
486 /*--------------------------------------------------------------------------*/
494 emitcode ("ais","#127");
496 _G.stackPushes -= 127;
501 emitcode ("ais","#-128");
503 _G.stackPushes += 128;
508 emitcode ("ais", "#%d", n);
517 /*--------------------------------------------------------------------------*/
518 /* aopName - Return a string with debugging information about an asmop. */
519 /*--------------------------------------------------------------------------*/
523 static char buffer[256];
527 return "(asmop*)NULL";
532 sprintf (buf,"IMMD(%s)", aop->aopu.aop_immd.aop_immd1);
535 sprintf (buf,"LIT(%s)", aopLiteral (aop->aopu.aop_lit, 0));
538 sprintf (buf,"DIR(%s)", aop->aopu.aop_dir);
541 sprintf (buf,"EXT(%s)", aop->aopu.aop_dir);
544 sprintf (buf,"SOF(%s)", OP_SYMBOL (aop->op)->name);
547 sprintf (buf, "REG(%s,%s,%s,%s)",
548 aop->aopu.aop_reg[3] ? aop->aopu.aop_reg[3]->name : "-",
549 aop->aopu.aop_reg[2] ? aop->aopu.aop_reg[2]->name : "-",
550 aop->aopu.aop_reg[1] ? aop->aopu.aop_reg[1]->name : "-",
551 aop->aopu.aop_reg[0] ? aop->aopu.aop_reg[0]->name : "-");
558 sprintf (buf,"?%d", aop->type);
566 /*--------------------------------------------------------------------------*/
567 /* loadRegFromAop - Load register reg from logical offset loffset of aop. */
568 /*--------------------------------------------------------------------------*/
570 loadRegFromAop (regs *reg, asmop *aop, int loffset)
572 int regidx = reg->rIdx;
574 if (aop->stacked && aop->stk_aop[loffset])
576 loadRegFromAop (reg, aop->stk_aop[loffset], 0);
581 printf("loadRegFromAop called\n");
584 printf(" reg = NULL\n");
587 printf(" reg = %s\n", reg->name);
590 printf(" aop = NULL\n");
593 printf(" aop->type = %d\n", aop->type);
594 printf(" loffset = %d\n", loffset);
597 printf(" aop has operand link\n");
599 printf(" aop missing operand link\n");
601 printf(" reg has operand link\n");
603 printf(" reg missing operand link\n");
606 DD(emitcode ("", "; loadRegFromAop (%s, %s, %d)",
607 reg->name, aopName (aop), loffset));
609 /* If operand is volatile, we cannot optimize. */
610 if (!aop->op || isOperandVolatile (aop->op, FALSE))
614 /* If this register already has this offset of the operand
615 then we need only mark it as in use. */
616 if (reg->aop && reg->aop->op && aop->op
617 && operandsEqu(reg->aop->op,aop->op)
618 && (reg->aopofs == loffset))
621 DD(emitcode ("","; already had correct value for %s", reg->name));
625 /* TODO: check to see if we can transfer from another register */
627 if (hc08_reg_h->aop && hc08_reg_h->aop->op && aop->op
628 && operandsEqu(hc08_reg_h->aop->op,aop->op)
629 && (hc08_reg_h->aopofs == loffset))
631 DD(emitcode ("","; found correct value for %s in h", reg->name));
632 transferRegReg (hc08_reg_h, reg, FALSE);
638 if (hc08_reg_x->aop && hc08_reg_x->aop->op && aop->op
639 && operandsEqu(hc08_reg_x->aop->op,aop->op)
640 && (hc08_reg_x->aopofs == loffset))
642 DD(emitcode ("","; found correct value for %s in x", reg->name));
643 transferRegReg (hc08_reg_x, reg, FALSE);
648 if (hc08_reg_a->aop && hc08_reg_a->aop->op && aop->op
649 && operandsEqu(hc08_reg_a->aop->op,aop->op)
650 && (hc08_reg_a->aopofs == loffset))
652 DD(emitcode ("","; found correct value for %s in a", reg->name));
653 transferRegReg (hc08_reg_a, reg, FALSE);
663 if (aop->type == AOP_REG)
665 if (loffset < aop->size)
666 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
668 emitcode ("clra", ""); /* TODO: handle sign extension */
672 char * l = aopAdrStr (aop, loffset, FALSE);
673 if (!strcmp (l, zero))
674 emitcode ("clra", "");
676 emitcode ("lda", "%s", l);
680 if (aop->type == AOP_REG)
682 if (loffset < aop->size)
683 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
685 emitcode ("clrx", ""); /* TODO: handle sign extension */
689 char * l = aopAdrStr (aop, loffset, FALSE);
690 if (!strcmp (l, zero))
691 emitcode ("clrx", "");
693 emitcode ("ldx", "%s", l);
698 char * l = aopAdrStr (aop, loffset, FALSE);
699 if (!strcmp (l, zero))
701 emitcode ("clrh", "");
705 if (hc08_reg_a->isFree)
707 loadRegFromAop (hc08_reg_a, aop, loffset);
708 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
710 else if (hc08_reg_x->isFree)
712 loadRegFromAop (hc08_reg_x, aop, loffset);
713 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
717 pushReg (hc08_reg_a, TRUE);
718 loadRegFromAop (hc08_reg_a, aop, loffset);
719 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
720 pullReg (hc08_reg_a);
726 else if (IS_AOP_XA(aop))
727 transferRegReg (hc08_reg_xa, hc08_reg_hx, FALSE);
728 else if ((aop->type == AOP_DIR))
730 if (aop->size>(loffset+1))
731 emitcode ("ldhx","%s", aopAdrStr (aop, loffset+1, TRUE));
734 loadRegFromAop (hc08_reg_x, aop, loffset);
735 loadRegFromConst (hc08_reg_h, zero);
738 else if ((aop->type == AOP_LIT) || (aop->type == AOP_IMMD))
740 emitcode ("ldhx","%s", aopAdrStr (aop, loffset, TRUE));
745 needpula = pushRegIfUsed (hc08_reg_a);
746 loadRegFromAop (hc08_reg_a, aop, loffset+1);
747 loadRegFromAop (hc08_reg_x, aop, loffset);
748 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
749 pullOrFreeReg (hc08_reg_a, needpula);
755 else if (IS_AOP_HX(aop))
756 transferRegReg (hc08_reg_hx, hc08_reg_xa, FALSE);
759 loadRegFromAop (hc08_reg_a, aop, loffset);
760 loadRegFromAop (hc08_reg_x, aop, loffset+1);
765 // ignore caching for now
768 reg->aopofs = loffset;
773 /*--------------------------------------------------------------------------*/
774 /* forceStackedAop - Reserve space on the stack for asmop aop; when */
775 /* freeAsmop is called with aop, the stacked data will */
776 /* be copied to the original aop location. */
777 /*--------------------------------------------------------------------------*/
779 forceStackedAop (asmop *aop, bool copyOrig)
783 asmop *newaop = newAsmop (aop->type);
784 memcpy (newaop, aop, sizeof(*newaop));
786 DD(emitcode("", "; forcedStackAop %s", aopName(aop)));
788 if (copyOrig && hc08_reg_a->isFree)
790 else if (copyOrig && hc08_reg_x->isFree)
795 for (loffset=0; loffset < newaop->size; loffset++)
797 asmop *aopsof = newAsmop (AOP_SOF);
801 loadRegFromAop (reg, aop, loffset);
802 aopsof->aopu.aop_stk = pushReg (reg, FALSE);
806 aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE);
808 aopsof->op = aop->op;
809 newaop->stk_aop[loffset] = aopsof;
813 if (!reg && copyOrig)
815 for (loffset=0; loffset < newaop->size; loffset++)
817 transferAopAop (aop, loffset, newaop, loffset);
825 /*--------------------------------------------------------------------------*/
826 /* storeRegToAop - Store register reg to logical offset loffset of aop. */
827 /*--------------------------------------------------------------------------*/
829 storeRegToAop (regs *reg, asmop *aop, int loffset)
831 int regidx = reg->rIdx;
837 DD(emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
838 reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr));
840 if ((reg->rIdx == HX_IDX) && aop->stacked
841 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
843 storeRegToAop (hc08_reg_h, aop, loffset+1);
844 storeRegToAop (hc08_reg_x, aop, loffset);
848 if ((reg->rIdx == XA_IDX) && aop->stacked
849 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
851 storeRegToAop (hc08_reg_x, aop, loffset+1);
852 storeRegToAop (hc08_reg_a, aop, loffset);
856 if (aop->stacked && aop->stk_aop[loffset])
858 storeRegToAop (reg, aop->stk_aop[loffset], 0);
862 if (aop->type == AOP_STR)
865 transferRegReg (reg, hc08_reg_x, FALSE);
867 transferRegReg (reg, hc08_reg_h, FALSE);
871 if (aop->type == AOP_DUMMY)
874 if (aop->type == AOP_CRY) /* This can only happen if IFX was optimized */
875 return; /* away, so just toss the result */
880 if ((aop->type == AOP_REG) && (loffset < aop->size))
881 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
883 emitcode ("sta","%s", aopAdrStr (aop, loffset, FALSE));
886 if ((aop->type == AOP_REG) && (loffset < aop->size))
887 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
889 emitcode ("stx","%s", aopAdrStr (aop, loffset, FALSE));
892 if (hc08_reg_a->isFree)
894 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
895 storeRegToAop (hc08_reg_a, aop, loffset);
896 hc08_freeReg (hc08_reg_a);
898 else if (hc08_reg_x->isFree)
900 transferRegReg (hc08_reg_h, hc08_reg_x, FALSE);
901 storeRegToAop (hc08_reg_x, aop, loffset);
902 hc08_freeReg (hc08_reg_x);
906 pushReg (hc08_reg_a, TRUE);
907 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
908 storeRegToAop (hc08_reg_a, aop, loffset);
909 pullReg (hc08_reg_a);
913 if ((aop->type == AOP_DIR) )
915 emitcode("sthx","%s", aopAdrStr (aop, loffset+1, TRUE));
917 else if (IS_AOP_XA(aop))
918 transferRegReg(reg, hc08_reg_xa, FALSE);
919 else if (IS_AOP_HX(aop))
924 needpula = pushRegIfUsed (hc08_reg_a);
925 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
926 storeRegToAop (hc08_reg_a, aop, loffset+1);
927 storeRegToAop (hc08_reg_x, aop, loffset);
928 pullOrFreeReg (hc08_reg_a, needpula);
933 transferRegReg(reg, hc08_reg_hx, FALSE);
934 else if (IS_AOP_XA(aop))
938 storeRegToAop (hc08_reg_a, aop, loffset);
939 storeRegToAop (hc08_reg_x, aop, loffset+1);
944 /* Disable the register tracking for now */
946 //if (!reg->aop || (reg->aop && (reg->aop != aop)))
949 for (otheridx=0;otheridx<hc08_nRegs;otheridx++)
951 otherreg=hc08_regWithIdx(otheridx);
952 if (otherreg && otherreg->aop
953 && otherreg->aop->op && aop->op
954 && operandsEqu(otherreg->aop->op,aop->op)
955 && (otherreg->aopofs == loffset))
957 DD(emitcode("","; marking %s stale", otherreg->name));
961 if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
963 hc08_reg_hx->aop = NULL;
964 DD(emitcode("","; marking hx stale"));
966 if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
968 hc08_reg_xa->aop = NULL;
969 DD(emitcode("","; marking xa stale"));
973 reg->aopofs = loffset;
978 /*--------------------------------------------------------------------------*/
979 /* loadRegFromConst - Load register reg from constant c. */
980 /*--------------------------------------------------------------------------*/
982 loadRegFromConst (regs *reg, char *c)
988 emitcode ("clra", "");
990 emitcode ("lda", "%s", c);
994 emitcode ("clrx", "");
996 emitcode ("ldx", "%s", c);
1000 emitcode ("clrh", "");
1001 else if (hc08_reg_a->isFree)
1003 loadRegFromConst (hc08_reg_a, c);
1004 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
1006 else if (hc08_reg_x->isFree)
1008 loadRegFromConst (hc08_reg_x, c);
1009 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
1013 pushReg (hc08_reg_a, TRUE);
1014 loadRegFromConst (hc08_reg_a, c);
1015 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
1016 pullReg (hc08_reg_a);
1020 emitcode ("ldhx", "%s", c);
1023 emitcode ("lda", "%s", c);
1024 emitcode ("ldx", "%s >> 8", c);
1027 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1028 "Bad rIdx in loadRegFromConst");
1035 /*--------------------------------------------------------------------------*/
1036 /* storeConstToAop- Store constant c to logical offset loffset of asmop aop.*/
1037 /*--------------------------------------------------------------------------*/
1039 storeConstToAop (char *c, asmop *aop, int loffset)
1041 if (aop->stacked && aop->stk_aop[loffset])
1043 storeConstToAop (c, aop->stk_aop[loffset], 0);
1050 if (!strcmp(c,zero))
1051 emitcode ("clr", "%s", aopAdrStr (aop, loffset, FALSE));
1053 emitcode ("mov", "%s,%s", c, aopAdrStr (aop, loffset, FALSE));
1056 if (loffset>(aop->size-1))
1058 loadRegFromConst (aop->aopu.aop_reg[loffset], c);
1063 if (hc08_reg_a->isFree)
1065 loadRegFromConst (hc08_reg_a, c);
1066 storeRegToAop( hc08_reg_a, aop, loffset);
1067 hc08_freeReg (hc08_reg_a);
1069 else if (hc08_reg_x->isFree)
1071 loadRegFromConst (hc08_reg_x, c);
1072 storeRegToAop( hc08_reg_x, aop, loffset);
1073 hc08_freeReg (hc08_reg_x);
1077 pushReg (hc08_reg_a, TRUE);
1078 loadRegFromConst (hc08_reg_a, c);
1079 storeRegToAop( hc08_reg_a, aop, loffset);
1080 pullReg (hc08_reg_a);
1086 /*--------------------------------------------------------------------------*/
1087 /* storeRegSignToUpperAop - If isSigned is true, the sign bit of register */
1088 /* reg is extended to fill logical offsets loffset */
1089 /* and above of asmop aop. Otherwise, logical */
1090 /* offsets loffset and above of asmop aop are */
1091 /* zeroed. reg must be an 8-bit register. */
1092 /*--------------------------------------------------------------------------*/
1094 storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned)
1096 // int regidx = reg->rIdx;
1097 int size = aop->size;
1105 while (loffset<size)
1106 storeConstToAop(zero, aop, loffset++);
1111 transferRegReg (reg, hc08_reg_a, FALSE);
1112 emitcode ("rola","");
1113 emitcode ("clra","");
1114 emitcode ("sbc", "#0");
1115 hc08_useReg (hc08_reg_a);
1116 while (loffset<size)
1117 storeRegToAop (hc08_reg_a, aop, loffset++);
1118 hc08_freeReg (hc08_reg_a);
1122 /*--------------------------------------------------------------------------*/
1123 /* storeRegToFullAop - Store register reg to asmop aop with appropriate */
1124 /* padding and/or truncation as needed. If isSigned is */
1125 /* true, sign extension will take place in the padding. */
1126 /*--------------------------------------------------------------------------*/
1128 storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
1130 int regidx = reg->rIdx;
1131 int size = aop->size;
1138 storeRegToAop (reg, aop, 0);
1139 storeRegSignToUpperAop (reg, aop, 1, isSigned);
1144 storeRegToAop (hc08_reg_x, aop, 0);
1148 storeRegToAop (reg, aop, 0);
1149 storeRegSignToUpperAop (hc08_reg_h, aop, 2, isSigned);
1155 storeRegToAop (hc08_reg_a, aop, 0);
1159 storeRegToAop (reg, aop, 0);
1160 storeRegSignToUpperAop (hc08_reg_x, aop, 2, isSigned);
1166 /*--------------------------------------------------------------------------*/
1167 /* transferAopAop - Transfer the value at logical offset srcofs of asmop */
1168 /* srcaop to logical offset dstofs of asmop dstaop. */
1169 /*--------------------------------------------------------------------------*/
1171 transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
1173 bool needpula = FALSE;
1176 bool keepreg = FALSE;
1178 /* ignore transfers at the same byte, unless its volatile */
1179 if (srcaop->op && !isOperandVolatile (srcaop->op, FALSE)
1180 && dstaop->op && !isOperandVolatile (dstaop->op, FALSE)
1181 && operandsEqu(srcaop->op, dstaop->op) && srcofs == dstofs
1182 && dstaop->type == srcaop->type)
1185 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1187 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1191 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1193 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1197 // DD(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1198 // aopName (srcaop), srcofs, aopName (dstaop), dstofs));
1199 // DD(emitcode ("", "; srcaop->type = %d", srcaop->type));
1200 // DD(emitcode ("", "; dstaop->type = %d", dstaop->type));
1202 if (dstofs >= dstaop->size)
1205 if ((dstaop->type == AOP_DIR)
1206 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1208 if (srcaop->type == AOP_LIT)
1211 unsigned long bytemask;
1213 lit = (unsigned long) floatFromVal (srcaop->aopu.aop_lit);
1214 bytemask = (lit >> (srcofs*8)) & 0xff;
1218 emitcode ("clr", "%s", aopAdrStr(dstaop, dstofs, FALSE));
1223 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1224 aopAdrStr(dstaop, dstofs, FALSE));
1228 if (dstaop->type == AOP_REG)
1230 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1231 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1233 reg = dstaop->aopu.aop_reg[dstofs];
1238 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1240 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1241 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1243 reg = srcaop->aopu.aop_reg[srcofs];
1250 if (hc08_reg_a->isFree)
1252 else if (hc08_reg_x->isFree)
1256 pushReg (hc08_reg_a, TRUE);
1262 loadRegFromAop (reg, srcaop, srcofs);
1263 storeRegToAop (reg, dstaop, dstofs);
1266 pullOrFreeReg (hc08_reg_a, needpula);
1270 /*--------------------------------------------------------------------------*/
1271 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1272 /* parameter param. */
1273 /*--------------------------------------------------------------------------*/
1275 accopWithMisc (char *accop, char *param)
1277 emitcode (accop, "%s", param);
1278 hc08_dirtyReg (hc08_reg_a, FALSE);
1281 /*--------------------------------------------------------------------------*/
1282 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1283 /* byte at logical offset loffset of asmop aop. */
1284 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1285 /*--------------------------------------------------------------------------*/
1287 accopWithAop (char *accop, asmop *aop, int loffset)
1289 if (aop->stacked && aop->stk_aop[loffset])
1291 accopWithAop (accop, aop->stk_aop[loffset], 0);
1295 if (aop->type == AOP_DUMMY)
1298 if (aop->type == AOP_REG)
1300 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1301 emitcode (accop, "1,s");
1305 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1307 hc08_dirtyReg (hc08_reg_a, FALSE);
1311 /*--------------------------------------------------------------------------*/
1312 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1313 /* byte at logical offset loffset of asmop aop. Register reg */
1314 /* must be 8-bit. */
1315 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1316 /*--------------------------------------------------------------------------*/
1318 rmwWithReg (char *rmwop, regs *reg)
1321 char *rmwaop = rmwbuf;
1323 if (reg->rIdx == A_IDX)
1325 sprintf(rmwaop,"%sa", rmwop);
1326 emitcode (rmwaop, "");
1327 hc08_dirtyReg (hc08_reg_a, FALSE);
1329 else if (reg->rIdx == X_IDX)
1331 sprintf(rmwaop,"%sx", rmwop);
1332 emitcode (rmwaop, "");
1333 hc08_dirtyReg (hc08_reg_a, FALSE);
1335 else if (hc08_reg_a->isFree)
1337 transferRegReg(reg, hc08_reg_a, FALSE);
1338 sprintf(rmwaop,"%sa", rmwop);
1339 emitcode (rmwaop, "");
1340 hc08_dirtyReg (hc08_reg_a, FALSE);
1341 transferRegReg(hc08_reg_a, reg, TRUE);
1345 pushReg (reg, FALSE);
1346 emitcode (rmwop, "1,s");
1348 hc08_dirtyReg (reg, FALSE);
1352 /*--------------------------------------------------------------------------*/
1353 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1354 /* logical offset loffset of asmop aop. */
1355 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror, tst */
1356 /*--------------------------------------------------------------------------*/
1358 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1360 bool needpula = FALSE;
1362 if (aop->stacked && aop->stk_aop[loffset])
1364 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1371 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1374 needpula = pushRegIfUsed (hc08_reg_a);
1375 loadRegFromAop (hc08_reg_a, aop, loffset);
1376 rmwWithReg (rmwop, hc08_reg_a);
1377 if (strcmp ("tst", rmwop))
1378 storeRegToAop (hc08_reg_a, aop, loffset);
1379 pullOrFreeReg (hc08_reg_a, needpula);
1384 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1390 /*-----------------------------------------------------------------*/
1391 /* newAsmop - creates a new asmOp */
1392 /*-----------------------------------------------------------------*/
1394 newAsmop (short type)
1398 aop = Safe_calloc (1, sizeof (asmop));
1405 /*-----------------------------------------------------------------*/
1406 /* pointerCode - returns the code for a pointer type */
1407 /*-----------------------------------------------------------------*/
1409 pointerCode (sym_link * etype)
1412 return PTR_TYPE (SPEC_OCLS (etype));
1417 /*-----------------------------------------------------------------*/
1418 /* aopForSym - for a true symbol */
1419 /*-----------------------------------------------------------------*/
1421 aopForSym (iCode * ic, symbol * sym, bool result)
1426 wassertl (ic != NULL, "Got a null iCode");
1427 wassertl (sym != NULL, "Got a null symbol");
1429 // printf("in aopForSym for symbol %s\n", sym->name);
1431 space = SPEC_OCLS (sym->etype);
1433 /* if already has one */
1439 /* special case for a function */
1440 if (IS_FUNC (sym->type))
1442 sym->aop = aop = newAsmop (AOP_IMMD);
1443 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1444 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1445 aop->size = FPTRSIZE;
1449 /* if it is in direct space */
1450 if (IN_DIRSPACE (space))
1452 sym->aop = aop = newAsmop (AOP_DIR);
1453 aop->aopu.aop_dir = sym->rname;
1454 aop->size = getSize (sym->type);
1458 /* if it is in far space */
1459 if (IN_FARSPACE (space))
1461 sym->aop = aop = newAsmop (AOP_EXT);
1462 aop->aopu.aop_dir = sym->rname;
1463 aop->size = getSize (sym->type);
1467 if (IN_STACK (sym->etype))
1469 sym->aop = aop = newAsmop (AOP_SOF);
1470 aop->aopu.aop_dir = sym->rname;
1471 aop->size = getSize (sym->type);
1472 aop->aopu.aop_stk = sym->stack;
1478 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1479 "aopForSym should never reach here");
1483 /* if it is in code space */
1484 if (IN_CODESPACE (space))
1490 /*-----------------------------------------------------------------*/
1491 /* aopForRemat - rematerialzes an object */
1492 /*-----------------------------------------------------------------*/
1494 aopForRemat (symbol * sym)
1496 iCode *ic = sym->rematiCode;
1504 val += (int) operandLitValue (IC_RIGHT (ic));
1505 else if (ic->op == '-')
1506 val -= (int) operandLitValue (IC_RIGHT (ic));
1507 else if (IS_CAST_ICODE(ic)) {
1508 sym_link *from_type = operandType(IC_RIGHT(ic));
1509 aop->aopu.aop_immd.from_cast_remat = 1;
1510 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1511 ptr_type = DCL_TYPE(from_type);
1512 if (ptr_type == IPOINTER) {
1519 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1522 if (ic->op == ADDRESS_OF)
1525 sprintf (buffer, "(%s %c 0x%04x)",
1526 OP_SYMBOL (IC_LEFT (ic))->rname,
1527 val >= 0 ? '+' : '-',
1528 abs (val) & 0xffff);
1530 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1532 aop = newAsmop (AOP_IMMD);
1533 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1534 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1535 /* set immd2 field if required */
1536 if (aop->aopu.aop_immd.from_cast_remat)
1538 sprintf(buffer,"#0x%02x",ptr_type);
1539 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1540 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1543 else if (ic->op == '=')
1545 val += (int) operandLitValue (IC_RIGHT (ic));
1547 sprintf (buffer, "0x%04x", val);
1548 aop = newAsmop (AOP_LIT);
1549 aop->aopu.aop_lit = constVal (buffer);
1552 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1553 "unexpected rematerialization");
1560 /*-----------------------------------------------------------------*/
1561 /* regsInCommon - two operands have some registers in common */
1562 /*-----------------------------------------------------------------*/
1564 regsInCommon (operand * op1, operand * op2)
1566 symbol *sym1, *sym2;
1569 /* if they have registers in common */
1570 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1573 sym1 = OP_SYMBOL (op1);
1574 sym2 = OP_SYMBOL (op2);
1576 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1579 for (i = 0; i < sym1->nRegs; i++)
1585 for (j = 0; j < sym2->nRegs; j++)
1590 if (sym2->regs[j] == sym1->regs[i])
1598 /*-----------------------------------------------------------------*/
1599 /* operandsEqu - equivalent */
1600 /*-----------------------------------------------------------------*/
1602 operandsEqu (operand * op1, operand * op2)
1604 symbol *sym1, *sym2;
1606 /* if they not symbols */
1607 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1610 sym1 = OP_SYMBOL (op1);
1611 sym2 = OP_SYMBOL (op2);
1613 /* if both are itemps & one is spilt
1614 and the other is not then false */
1615 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1616 sym1->isspilt != sym2->isspilt)
1619 /* if they are the same */
1623 /* if they have the same rname */
1624 if (sym1->rname[0] && sym2->rname[0]
1625 && strcmp (sym1->rname, sym2->rname) == 0)
1628 /* if left is a tmp & right is not */
1629 if (IS_ITEMP (op1) &&
1632 (sym1->usl.spillLoc == sym2))
1635 if (IS_ITEMP (op2) &&
1639 (sym2->usl.spillLoc == sym1))
1645 /*-----------------------------------------------------------------*/
1646 /* sameRegs - two asmops have the same registers */
1647 /*-----------------------------------------------------------------*/
1649 sameRegs (asmop * aop1, asmop * aop2)
1656 // if (aop1->size != aop2->size)
1659 if (aop1->type == aop2->type)
1664 for (i = 0; i < aop1->size; i++)
1665 if (aop1->aopu.aop_reg[i] !=
1666 aop2->aopu.aop_reg[i])
1670 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1673 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1680 /*-----------------------------------------------------------------*/
1681 /* aopOp - allocates an asmop for an operand : */
1682 /*-----------------------------------------------------------------*/
1684 aopOp (operand * op, iCode * ic, bool result)
1693 // Is this a pointer set result?
1695 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1699 // printf("checking literal\n");
1700 /* if this a literal */
1701 if (IS_OP_LITERAL (op))
1703 op->aop = aop = newAsmop (AOP_LIT);
1704 aop->aopu.aop_lit = op->operand.valOperand;
1705 aop->size = getSize (operandType (op));
1707 aop->isaddr = op->isaddr;
1711 // printf("checking pre-existing\n");
1712 /* if already has a asmop then continue */
1716 op->aop->isaddr = op->isaddr;
1720 // printf("checking underlying sym\n");
1721 /* if the underlying symbol has a aop */
1722 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1724 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1725 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1726 //op->aop = aop = OP_SYMBOL (op)->aop;
1727 aop->size = getSize( operandType (op));
1728 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1729 //printf (" with size = %d\n", aop->size);
1732 aop->isaddr = op->isaddr;
1733 /* if (aop->isaddr & IS_ITEMP (op))
1735 aop->psize=aop->size;
1736 aop->size = getSize( operandType (op)->next);
1741 // printf("checking true sym\n");
1742 /* if this is a true symbol */
1743 if (IS_TRUE_SYMOP (op))
1745 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1747 aop->isaddr = op->isaddr;
1748 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1749 //printf (" with size = %d\n", aop->size);
1753 /* this is a temporary : this has
1759 e) can be a return use only */
1761 sym = OP_SYMBOL (op);
1763 // printf("checking conditional\n");
1764 /* if the type is a conditional */
1765 if (sym->regType == REG_CND)
1767 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1770 aop->isaddr = op->isaddr;
1774 // printf("checking spilt\n");
1775 /* if it is spilt then two situations
1777 b) has a spill location */
1778 if (sym->isspilt || sym->nRegs == 0)
1781 // printf("checking remat\n");
1782 /* rematerialize it NOW */
1785 sym->aop = op->aop = aop =
1787 aop->size = getSize (sym->type);
1789 aop->isaddr = op->isaddr;
1790 /* if (aop->isaddr & IS_ITEMP (op))
1792 aop->psize=aop->size;
1793 aop->size = getSize( operandType (op)->next);
1798 // printf("checking accuse\n");
1801 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1802 aop->size = getSize (sym->type);
1803 switch (sym->accuse)
1806 aop->aopu.aop_reg[0] = hc08_reg_a;
1807 aop->aopu.aop_reg[1] = hc08_reg_x;
1810 aop->aopu.aop_reg[0] = hc08_reg_x;
1811 aop->aopu.aop_reg[1] = hc08_reg_h;
1815 aop->isaddr = op->isaddr;
1819 // printf("checking ruonly\n");
1825 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1826 aop->size = getSize (sym->type);
1827 for (i = 0; i < fReturnSizeHC08; i++)
1828 aop->aopu.aop_str[i] = fReturn2[i];
1830 aop->isaddr = op->isaddr;
1834 /* else spill location */
1835 if (sym->usl.spillLoc)
1837 asmop *oldAsmOp = NULL;
1839 if (sym->usl.spillLoc->aop
1840 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1842 /* force a new aop if sizes differ */
1843 oldAsmOp = sym->usl.spillLoc->aop;
1844 sym->usl.spillLoc->aop = NULL;
1845 //printf ("forcing new aop\n");
1847 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1848 if (sym->usl.spillLoc->aop->size != getSize (sym->type))
1850 /* Don't reuse the new aop, go with the last one */
1851 sym->usl.spillLoc->aop = oldAsmOp;
1853 aop->size = getSize (sym->type);
1855 aop->isaddr = op->isaddr;
1856 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1857 //printf (" with size = %d\n", aop->size);
1861 /* else must be a dummy iTemp */
1862 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1863 aop->size = getSize (sym->type);
1867 // printf("assuming register\n");
1868 /* must be in a register */
1869 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1870 aop->size = sym->nRegs;
1871 for (i = 0; i < sym->nRegs; i++)
1872 aop->aopu.aop_reg[i] = sym->regs[i];
1874 aop->isaddr = op->isaddr;
1878 /*-----------------------------------------------------------------*/
1879 /* freeAsmop - free up the asmop given to an operand */
1880 /*----------------------------------------------------------------*/
1882 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1904 DD(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1907 for (loffset=0; loffset<aop->size; loffset++)
1908 if (aop->stk_aop[loffset])
1910 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1913 pullNull (stackAdjust);
1917 /* all other cases just dealloc */
1923 OP_SYMBOL (op)->aop = NULL;
1924 /* if the symbol has a spill */
1926 SPIL_LOC (op)->aop = NULL;
1932 /*-----------------------------------------------------------------*/
1933 /* aopDerefAop - treating the aop parameter as a pointer, return */
1934 /* an asmop for the object it references */
1935 /*-----------------------------------------------------------------*/
1937 aopDerefAop (asmop *aop)
1942 asmop *newaop = NULL;
1943 sym_link *type, *etype;
1946 DD(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1950 type = operandType (aop->op);
1951 etype = getSpec (type);
1952 /* if op is of type of pointer then it is simple */
1953 if (IS_PTR (type) && !IS_FUNC (type->next))
1954 p_type = DCL_TYPE (type);
1957 /* we have to go by the storage class */
1958 p_type = PTR_TYPE (SPEC_OCLS (etype));
1967 if (p_type == POINTER)
1968 newaop = newAsmop (AOP_DIR);
1970 newaop = newAsmop (AOP_EXT);
1971 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1974 adr = (int) floatFromVal (aop->aopu.aop_lit);
1975 if (p_type == POINTER)
1980 newaop = newAsmop (AOP_DIR);
1981 sprintf (s, "0x%02x",adr);
1985 newaop = newAsmop (AOP_EXT);
1986 sprintf (s, "0x%04x",adr);
1988 rs = Safe_calloc (1, strlen (s) + 1);
1990 newaop->aopu.aop_dir = rs;
1993 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1994 "unsupported asmop");
2004 /*-----------------------------------------------------------------*/
2005 /* aopAdrStr - for referencing the address of the aop */
2006 /*-----------------------------------------------------------------*/
2008 aopAdrStr (asmop * aop, int loffset, bool bit16)
2012 int offset = aop->size - 1 - loffset;
2015 /* offset is greater than
2017 if (loffset > (aop->size - 1) &&
2018 aop->type != AOP_LIT)
2021 /* depending on type */
2029 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
2030 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
2032 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
2036 sprintf (s, "#(%s >> %d)",
2037 aop->aopu.aop_immd.aop_immd1,
2041 aop->aopu.aop_immd.aop_immd1);
2045 aop->aopu.aop_immd.aop_immd1);
2046 rs = Safe_calloc (1, strlen (s) + 1);
2052 sprintf (s, "*(%s + %d)",
2056 sprintf (s, "*%s", aop->aopu.aop_dir);
2057 rs = Safe_calloc (1, strlen (s) + 1);
2063 sprintf (s, "(%s + %d)",
2067 sprintf (s, "%s", aop->aopu.aop_dir);
2068 rs = Safe_calloc (1, strlen (s) + 1);
2073 return aop->aopu.aop_reg[loffset]->name;
2077 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
2079 return aopLiteral (aop->aopu.aop_lit, loffset);
2083 return aop->aopu.aop_str[loffset];
2086 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2088 rs = Safe_calloc (1, strlen (s) + 1);
2094 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2095 "aopAdrStr got unsupported aop->type");
2104 /*-----------------------------------------------------------------*/
2105 /* opIsGptr: returns non-zero if the passed operand is */
2106 /* a generic pointer type. */
2107 /*-----------------------------------------------------------------*/
2109 opIsGptr (operand * op)
2111 sym_link *type = operandType (op);
2113 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2121 /*-----------------------------------------------------------------*/
2122 /* getDataSize - get the operand data size */
2123 /*-----------------------------------------------------------------*/
2125 getDataSize (operand * op)
2128 size = AOP_SIZE (op);
2133 /*-----------------------------------------------------------------*/
2134 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2135 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2136 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2137 /*-----------------------------------------------------------------*/
2139 asmopToBool (asmop *aop, bool resultInA)
2141 symbol *tlbl, *tlbl1;
2142 int size = aop->size;
2143 bool needpula = FALSE;
2144 bool flagsonly = TRUE;
2149 hc08_freeReg(hc08_reg_a);
2156 emitcode ("tsta", "");
2159 else if (IS_AOP_X(aop))
2160 emitcode ("tstx", "");
2161 else if (IS_AOP_H(aop))
2163 if (hc08_reg_a->isFree)
2165 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2166 emitcode ("tsta", "");
2168 hc08_freeReg(hc08_reg_a);
2170 else if (hc08_reg_x->isFree)
2172 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2173 emitcode ("tstx", "");
2174 hc08_freeReg(hc08_reg_x);
2178 emitcode ("pshh", "");
2179 emitcode ("tst", "1,s");
2180 emitcode ("ais", "#1");
2183 else if (IS_AOP_HX(aop))
2184 emitcode ("cphx", zero);
2185 else if (IS_AOP_XA(aop))
2187 symbol *tlbl = newiTempLabel (NULL);
2188 emitcode ("tsta", "");
2189 emitcode ("bne", "%05d$", (tlbl->key + 100));
2190 emitcode ("tstx", "");
2195 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2196 "Bad rIdx in asmToBool");
2204 needpula = pushRegIfUsed (hc08_reg_a);
2205 loadRegFromAop (hc08_reg_a, aop, 0);
2206 for (offset=1; offset<size; offset++)
2207 accopWithAop ("ora", aop, offset);
2209 pullReg (hc08_reg_a);
2212 hc08_freeReg (hc08_reg_a);
2217 /* Higher levels should optimize this case away but let's be safe */
2218 if ((unsigned long) floatFromVal (aop->aopu.aop_lit))
2219 loadRegFromConst (hc08_reg_a, one);
2221 loadRegFromConst (hc08_reg_a, zero);
2222 hc08_freeReg(hc08_reg_a);
2229 loadRegFromAop (hc08_reg_a, aop, 0);
2230 hc08_freeReg (hc08_reg_a);
2234 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2239 if (hc08_reg_a->isFree)
2241 loadRegFromAop (hc08_reg_a, aop, 0);
2242 accopWithAop ("ora", aop, 1);
2243 hc08_freeReg (hc08_reg_a);
2248 tlbl = newiTempLabel (NULL);
2249 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2250 emitcode ("bne", "%05d$", (tlbl->key + 100));
2251 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2258 needpula = pushRegIfUsed (hc08_reg_a);
2259 loadRegFromAop (hc08_reg_a, aop, 0);
2260 for (offset=1; offset<size; offset++)
2261 accopWithAop ("ora", aop, offset);
2263 pullReg (hc08_reg_a);
2266 hc08_freeReg (hc08_reg_a);
2274 tlbl = newiTempLabel (NULL);
2278 tlbl1 = newiTempLabel (NULL);
2279 emitBranch ("bne", tlbl1);
2280 loadRegFromConst (hc08_reg_a, zero);
2281 emitBranch ("bra", tlbl);
2283 loadRegFromConst (hc08_reg_a, one);
2287 emitBranch ("beq", tlbl);
2288 loadRegFromConst (hc08_reg_a, one);
2291 hc08_useReg (hc08_reg_a);
2297 /*-----------------------------------------------------------------*/
2298 /* genNot - generate code for ! operation */
2299 /*-----------------------------------------------------------------*/
2303 D(emitcode ("; genNot",""));
2305 /* assign asmOps to operand & result */
2306 aopOp (IC_LEFT (ic), ic, FALSE);
2307 aopOp (IC_RESULT (ic), ic, TRUE);
2309 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2310 emitcode ("eor", one);
2311 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2313 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2314 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2318 /*-----------------------------------------------------------------*/
2319 /* genCpl - generate code for complement */
2320 /*-----------------------------------------------------------------*/
2326 regs* reg = hc08_reg_a;
2330 D(emitcode ("; genCpl",""));
2332 /* assign asmOps to operand & result */
2333 aopOp (IC_LEFT (ic), ic, FALSE);
2334 aopOp (IC_RESULT (ic), ic, TRUE);
2336 size = AOP_SIZE (IC_RESULT (ic));
2339 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2340 rmwWithReg ("com", reg);
2342 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2347 /* release the aops */
2348 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2349 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2352 /*-----------------------------------------------------------------*/
2353 /* genUminusFloat - unary minus for floating points */
2354 /*-----------------------------------------------------------------*/
2356 genUminusFloat (operand * op, operand * result)
2358 int size, offset = 0;
2361 D(emitcode ("; genUminusFloat",""));
2363 /* for this we just copy and then flip the bit */
2365 size = AOP_SIZE (op) - 1;
2369 transferAopAop (AOP (op), offset, AOP (result), offset);
2373 needpula = pushRegIfUsed (hc08_reg_a);
2374 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2375 emitcode ("eor", "#0x80");
2376 hc08_useReg (hc08_reg_a);
2377 storeRegToAop (hc08_reg_a, AOP (result), offset);
2378 pullOrFreeReg (hc08_reg_a, needpula);
2381 /*-----------------------------------------------------------------*/
2382 /* genUminus - unary minus code generation */
2383 /*-----------------------------------------------------------------*/
2385 genUminus (iCode * ic)
2388 sym_link *optype, *rtype;
2393 D(emitcode ("; genUminus",""));
2396 aopOp (IC_LEFT (ic), ic, FALSE);
2397 aopOp (IC_RESULT (ic), ic, TRUE);
2399 optype = operandType (IC_LEFT (ic));
2400 rtype = operandType (IC_RESULT (ic));
2402 /* if float then do float stuff */
2403 if (IS_FLOAT (optype))
2405 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2409 /* otherwise subtract from zero */
2410 size = AOP_SIZE (IC_LEFT (ic));
2415 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2416 needpula = pushRegIfUsed (hc08_reg_a);
2419 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2420 emitcode ("nega", "");
2421 hc08_freeReg (hc08_reg_a);
2422 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2423 SPEC_USIGN (operandType (IC_LEFT (ic))));
2424 pullOrFreeReg (hc08_reg_a, needpula);
2428 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2429 result = forceStackedAop (AOP (IC_RESULT (ic)), FALSE);
2431 result = AOP (IC_RESULT (ic));
2433 needpula = pushRegIfUsed (hc08_reg_a);
2437 loadRegFromConst (hc08_reg_a, zero);
2438 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2439 storeRegToAop (hc08_reg_a, result, offset++);
2442 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2443 SPEC_USIGN (operandType (IC_LEFT (ic))));
2444 pullOrFreeReg (hc08_reg_a, needpula);
2446 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2447 freeAsmop (NULL, result, ic, TRUE);
2453 /* release the aops */
2454 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2455 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2458 /*-----------------------------------------------------------------*/
2459 /* saveRegisters - will look for a call and save the registers */
2460 /*-----------------------------------------------------------------*/
2462 saveRegisters (iCode * lic)
2469 for (ic = lic; ic; ic = ic->next)
2470 if (ic->op == CALL || ic->op == PCALL)
2475 fprintf (stderr, "found parameter push with no function call\n");
2479 /* if the registers have been saved already or don't need to be then
2483 if (IS_SYMOP(IC_LEFT(ic)) &&
2484 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2485 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2488 /* safe the registers in use at this time but skip the
2489 ones for the result */
2490 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2491 hc08_rUmaskForOp (IC_RESULT(ic)));
2494 for (i = 0; i < hc08_nRegs; i++)
2496 if (bitVectBitValue (rsave, i))
2497 pushReg ( hc08_regWithIdx (i), FALSE);
2501 /*-----------------------------------------------------------------*/
2502 /* unsaveRegisters - pop the pushed registers */
2503 /*-----------------------------------------------------------------*/
2505 unsaveRegisters (iCode * ic)
2510 /* restore the registers in use at this time but skip the
2511 ones for the result */
2512 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2513 hc08_rUmaskForOp (IC_RESULT(ic)));
2515 for (i = hc08_nRegs; i >= 0; i--)
2517 if (bitVectBitValue (rsave, i))
2518 pullReg ( hc08_regWithIdx (i));
2524 /*-----------------------------------------------------------------*/
2526 /*-----------------------------------------------------------------*/
2528 pushSide (operand * oper, int size)
2533 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2534 pushReg ( hc08_reg_a, TRUE);
2538 /*-----------------------------------------------------------------*/
2539 /* assignResultValue - */
2540 /*-----------------------------------------------------------------*/
2542 assignResultValue (operand * oper)
2544 int size = AOP_SIZE (oper);
2548 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2549 if (hc08_aop_pass[offset]->type == AOP_REG)
2550 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2557 /*-----------------------------------------------------------------*/
2558 /* genIpush - genrate code for pushing this gets a little complex */
2559 /*-----------------------------------------------------------------*/
2561 genIpush (iCode * ic)
2563 int size, offset = 0;
2566 D(emitcode ("; genIpush",""));
2568 /* if this is not a parm push : ie. it is spill push
2569 and spill push is always done on the local stack */
2573 /* and the item is spilt then do nothing */
2574 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2577 aopOp (IC_LEFT (ic), ic, FALSE);
2578 size = AOP_SIZE (IC_LEFT (ic));
2580 /* push it on the stack */
2583 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2584 pushReg ( hc08_reg_a, TRUE);
2590 /* this is a paramter push: in this case we call
2591 the routine to find the call and save those
2592 registers that need to be saved */
2595 /* then do the push */
2596 aopOp (IC_LEFT (ic), ic, FALSE);
2599 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2600 size = AOP_SIZE (IC_LEFT (ic));
2603 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2604 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2606 if ((size==2) && hc08_reg_hx->isFree)
2608 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2609 pushReg (hc08_reg_hx, TRUE);
2616 // printf("loading %d\n", offset);
2617 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2618 // printf("pushing \n");
2619 pushReg (hc08_reg_a, TRUE);
2623 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2626 /*-----------------------------------------------------------------*/
2627 /* genIpop - recover the registers: can happen only for spilling */
2628 /*-----------------------------------------------------------------*/
2630 genIpop (iCode * ic)
2634 D(emitcode ("; genIpop",""));
2636 /* if the temp was not pushed then */
2637 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2640 aopOp (IC_LEFT (ic), ic, FALSE);
2641 size = AOP_SIZE (IC_LEFT (ic));
2645 pullReg (hc08_reg_a);
2646 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2648 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2652 /*-----------------------------------------------------------------*/
2653 /* genSend - gen code for SEND */
2654 /*-----------------------------------------------------------------*/
2655 static void genSend(set *sendSet)
2659 for (sic = setFirstItem (sendSet); sic;
2660 sic = setNextItem (sendSet)) {
2661 int size, offset = 0;
2662 aopOp (IC_LEFT (sic), sic, FALSE);
2663 size = AOP_SIZE (IC_LEFT (sic));
2668 transferAopAop( AOP (IC_LEFT (sic)), offset,
2669 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2673 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2677 /*-----------------------------------------------------------------*/
2678 /* genCall - generates a call statement */
2679 /*-----------------------------------------------------------------*/
2681 genCall (iCode * ic)
2684 // bool restoreBank = FALSE;
2685 // bool swapBanks = FALSE;
2687 D(emitcode("; genCall",""));
2689 dtype = operandType (IC_LEFT (ic));
2690 /* if send set is not empty then assign */
2693 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2694 genSend(reverseSet(_G.sendSet));
2696 genSend(_G.sendSet);
2702 /* if caller saves & we have not saved then */
2708 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2709 OP_SYMBOL (IC_LEFT (ic))->rname :
2710 OP_SYMBOL (IC_LEFT (ic))->name));
2713 /* if we need assign a result value */
2714 if ((IS_ITEMP (IC_RESULT (ic)) &&
2715 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2716 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2717 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2718 IS_TRUE_SYMOP (IC_RESULT (ic)))
2722 aopOp (IC_RESULT (ic), ic, FALSE);
2725 assignResultValue (IC_RESULT (ic));
2727 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2730 /* adjust the stack for parameters if
2734 pullNull (ic->parmBytes);
2737 /* if we had saved some registers then unsave them */
2738 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2739 unsaveRegisters (ic);
2743 /*-----------------------------------------------------------------*/
2744 /* -10l - generates a call by pointer statement */
2745 /*-----------------------------------------------------------------*/
2747 genPcall (iCode * ic)
2750 symbol *rlbl = newiTempLabel (NULL);
2751 symbol *tlbl = newiTempLabel (NULL);
2752 // bool restoreBank=FALSE;
2753 // bool swapBanks = FALSE;
2755 D(emitcode("; genPCall",""));
2757 /* if caller saves & we have not saved then */
2761 /* if we are calling a not _naked function that is not using
2762 the same register bank then we need to save the
2763 destination registers on the stack */
2764 dtype = operandType (IC_LEFT (ic))->next;
2766 /* now push the calling address */
2767 emitBranch ("bsr", tlbl);
2768 emitBranch ("bra", rlbl);
2770 _G.stackPushes += 2; /* account for the bsr return address now on stack */
2773 /* Push the function's address */
2774 aopOp (IC_LEFT (ic), ic, FALSE);
2775 pushSide (IC_LEFT (ic), FPTRSIZE);
2776 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2778 /* if send set is not empty the assign */
2781 genSend(reverseSet(_G.sendSet));
2787 emitcode ("rts", "");
2790 _G.stackPushes -= 4; /* account for rts here & in called function */
2794 /* if we need assign a result value */
2795 if ((IS_ITEMP (IC_RESULT (ic)) &&
2796 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2797 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2798 IS_TRUE_SYMOP (IC_RESULT (ic)))
2802 aopOp (IC_RESULT (ic), ic, FALSE);
2805 assignResultValue (IC_RESULT (ic));
2807 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2810 /* adjust the stack for parameters if
2814 pullNull (ic->parmBytes);
2817 /* if we hade saved some registers then
2819 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2820 unsaveRegisters (ic);
2823 /*-----------------------------------------------------------------*/
2824 /* resultRemat - result is rematerializable */
2825 /*-----------------------------------------------------------------*/
2827 resultRemat (iCode * ic)
2829 if (SKIP_IC (ic) || ic->op == IFX)
2832 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2834 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2835 if (sym->remat && !POINTER_SET (ic))
2842 /*-----------------------------------------------------------------*/
2843 /* inExcludeList - return 1 if the string is in exclude Reg list */
2844 /*-----------------------------------------------------------------*/
2846 regsCmp(void *p1, void *p2)
2848 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2852 inExcludeList (char *s)
2854 const char *p = setFirstItem(options.excludeRegsSet);
2856 if (p == NULL || STRCASECMP(p, "none") == 0)
2860 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2863 /*-----------------------------------------------------------------*/
2864 /* genFunction - generated code for function entry */
2865 /*-----------------------------------------------------------------*/
2867 genFunction (iCode * ic)
2869 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2871 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2872 int stackAdjust = sym->stack;
2873 int accIsFree = sym->recvSize == 0;
2877 /* create the function header */
2878 emitcode (";", "-----------------------------------------");
2879 emitcode (";", " function %s", sym->name);
2880 emitcode (";", "-----------------------------------------");
2882 emitcode ("", "%s:", sym->rname);
2883 lineCurr->isLabel = 1;
2884 ftype = operandType (IC_LEFT (ic));
2888 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2890 if (IFFUNC_ISNAKED(ftype))
2892 emitcode(";", "naked function: no prologue.");
2896 /* if this is an interrupt service routine then
2898 if (IFFUNC_ISISR (sym->type))
2901 if (!inExcludeList ("h"))
2902 pushReg (hc08_reg_h, FALSE);
2905 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2906 /* before setting up the stack frame completely. */
2907 while (ric && ric->next && ric->next->op == RECEIVE)
2909 while (ric && IC_RESULT (ric))
2911 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2912 int rsymSize = rsym ? getSize(rsym->type) : 0;
2916 if (rsym && rsym->regType == REG_CND)
2918 if (rsym && (rsym->accuse || rsym->ruonly))
2920 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2921 rsym = rsym->usl.spillLoc;
2924 /* If the RECEIVE operand immediately spills to the first entry on the */
2925 /* stack, we can push it directly rather than use an sp relative store. */
2926 if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize)
2930 _G.current_iCode = ric;
2931 D(emitcode ("; genReceive",""));
2932 for (ofs=0; ofs < rsymSize; ofs++)
2934 regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
2935 pushReg (reg, TRUE);
2936 if (reg->rIdx == A_IDX)
2940 _G.current_iCode = ic;
2943 ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
2946 /* adjust the stack for the function */
2949 adjustStack (-stackAdjust);
2951 _G.stackOfs = sym->stack;
2954 /* if critical function then turn interrupts off */
2955 if (IFFUNC_ISCRITICAL (ftype))
2959 /* Function was passed parameters, so make sure A is preserved */
2960 pushReg (hc08_reg_a, FALSE);
2961 pushReg (hc08_reg_a, FALSE);
2962 emitcode ("tpa", "");
2963 emitcode ("sta", "2,s");
2964 emitcode ("sei", "");
2965 pullReg (hc08_reg_a);
2969 /* No passed parameters, so A can be freely modified */
2970 emitcode ("tpa", "");
2971 pushReg (hc08_reg_a, TRUE);
2972 emitcode ("sei", "");
2978 /*-----------------------------------------------------------------*/
2979 /* genEndFunction - generates epilogue for functions */
2980 /*-----------------------------------------------------------------*/
2982 genEndFunction (iCode * ic)
2984 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2986 if (IFFUNC_ISNAKED(sym->type))
2988 emitcode(";", "naked function: no epilogue.");
2989 if (options.debug && currFunc)
2990 debugFile->writeEndFunction (currFunc, ic, 0);
2994 if (IFFUNC_ISCRITICAL (sym->type))
2996 if (!IS_VOID(sym->type->next))
2998 /* Function has return value, so make sure A is preserved */
2999 pushReg (hc08_reg_a, FALSE);
3000 emitcode ("lda", "2,s");
3001 emitcode ("tap", "");
3002 pullReg (hc08_reg_a);
3007 /* Function returns void, so A can be freely modified */
3008 pullReg (hc08_reg_a);
3009 emitcode ("tap", "");
3013 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
3019 _G.stackPushes += sym->stack;
3020 adjustStack (sym->stack);
3024 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3028 if (IFFUNC_ISISR (sym->type))
3031 if (!inExcludeList ("h"))
3032 pullReg (hc08_reg_h);
3035 /* if debug then send end of function */
3036 if (options.debug && currFunc)
3038 debugFile->writeEndFunction (currFunc, ic, 1);
3041 emitcode ("rti", "");
3045 if (IFFUNC_CALLEESAVES(sym->type))
3049 /* if any registers used */
3052 /* save the registers used */
3053 for (i = sym->regsUsed->size; i >= 0; i--)
3055 if (bitVectBitValue (sym->regsUsed, i) ||
3056 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3057 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3063 /* if debug then send end of function */
3064 if (options.debug && currFunc)
3066 debugFile->writeEndFunction (currFunc, ic, 1);
3069 emitcode ("rts", "");
3074 /*-----------------------------------------------------------------*/
3075 /* genRet - generate code for return statement */
3076 /*-----------------------------------------------------------------*/
3080 int size, offset = 0;
3083 D(emitcode ("; genRet",""));
3085 /* if we have no return value then
3086 just generate the "ret" */
3090 /* we have something to return then
3091 move the return value into place */
3092 aopOp (IC_LEFT (ic), ic, FALSE);
3093 size = AOP_SIZE (IC_LEFT (ic));
3099 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3106 /* 4 byte return: store value in the global return variable */
3110 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3111 STA (fReturn2[offset--], FALSE);
3112 hc08_freeReg (hc08_reg_a);
3116 /* 2 byte return: store value in x:a */
3117 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3118 hc08_freeReg (hc08_reg_xa);
3121 /* 1 byte return: store value in a */
3122 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3123 hc08_freeReg (hc08_reg_a);
3128 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3131 /* generate a jump to the return label
3132 if the next is not the return statement */
3133 if (!(ic->next && ic->next->op == LABEL &&
3134 IC_LABEL (ic->next) == returnLabel))
3136 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3140 /*-----------------------------------------------------------------*/
3141 /* genLabel - generates a label */
3142 /*-----------------------------------------------------------------*/
3144 genLabel (iCode * ic)
3149 /* For the high level labels we cannot depend on any */
3150 /* register's contents. Amnesia time. */
3151 for (i=A_IDX;i<=XA_IDX;i++)
3153 reg = hc08_regWithIdx(i);
3158 /* special case never generate */
3159 if (IC_LABEL (ic) == entryLabel)
3162 debugFile->writeLabel(IC_LABEL (ic), ic);
3164 emitLabel (IC_LABEL (ic));
3168 /*-----------------------------------------------------------------*/
3169 /* genGoto - generates a jmp */
3170 /*-----------------------------------------------------------------*/
3172 genGoto (iCode * ic)
3174 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3178 /*-----------------------------------------------------------------*/
3179 /* findLabelBackwards: walks back through the iCode chain looking */
3180 /* for the given label. Returns number of iCode instructions */
3181 /* between that label and given ic. */
3182 /* Returns zero if label not found. */
3183 /*-----------------------------------------------------------------*/
3185 findLabelBackwards (iCode * ic, int key)
3194 /* If we have any pushes or pops, we cannot predict the distance.
3195 I don't like this at all, this should be dealt with in the
3197 if (ic->op == IPUSH || ic->op == IPOP) {
3201 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3211 /*-----------------------------------------------------------------*/
3212 /* genPlusIncr :- does addition with increment if possible */
3213 /*-----------------------------------------------------------------*/
3215 genPlusIncr (iCode * ic)
3223 unsigned int size = getDataSize (IC_RESULT (ic));
3224 unsigned int offset;
3225 symbol *tlbl = NULL;
3227 left = IC_LEFT (ic);
3228 result = IC_RESULT (ic);
3230 /* will try to generate an increment */
3231 /* if the right side is not a literal
3233 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3236 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3238 DD(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3240 if ((IS_AOP_HX (AOP (left)) ||
3241 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3243 && (icount>=-128) && (icount<=127) && (size==2))
3245 if (!IS_AOP_HX (AOP (left)))
3247 needpulx = pushRegIfUsed (hc08_reg_x);
3248 needpulh = pushRegIfUsed (hc08_reg_h);
3255 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3256 emitcode ("aix","#%d", icount);
3257 hc08_dirtyReg (hc08_reg_hx, FALSE);
3258 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3259 pullOrFreeReg (hc08_reg_h, needpulh);
3260 pullOrFreeReg (hc08_reg_x, needpulx);
3264 DD(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3265 sameRegs (AOP (left), AOP (result))));
3267 if ((icount > 255) || (icount<0))
3270 if (!sameRegs (AOP (left), AOP (result)))
3273 D(emitcode ("; genPlusIncr",""));
3276 tlbl = newiTempLabel (NULL);
3281 rmwWithAop ("inc", AOP (result), 0);
3283 emitBranch ("bne", tlbl);
3287 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3288 needpula = pushRegIfUsed (hc08_reg_a);
3291 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3292 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3293 hc08_useReg (hc08_reg_a);
3294 storeRegToAop (hc08_reg_a, AOP (result), 0);
3295 hc08_freeReg (hc08_reg_a);
3297 emitBranch ("bcc", tlbl);
3299 for (offset=1; offset<size; offset++)
3301 rmwWithAop ("inc", AOP (result), offset);
3302 if ((offset+1)<size)
3303 emitBranch ("bne", tlbl);
3309 pullOrFreeReg (hc08_reg_a, needpula);
3316 /*-----------------------------------------------------------------*/
3317 /* genPlus - generates code for addition */
3318 /*-----------------------------------------------------------------*/
3320 genPlus (iCode * ic)
3322 int size, offset = 0;
3324 asmop *leftOp, *rightOp;
3326 /* special cases :- */
3328 D(emitcode ("; genPlus",""));
3330 aopOp (IC_LEFT (ic), ic, FALSE);
3331 aopOp (IC_RIGHT (ic), ic, FALSE);
3332 aopOp (IC_RESULT (ic), ic, TRUE);
3334 /* we want registers on the left and literals on the right */
3335 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3336 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3338 operand *t = IC_RIGHT (ic);
3339 IC_RIGHT (ic) = IC_LEFT (ic);
3344 /* if I can do an increment instead
3345 of add then GOOD for ME */
3346 if (genPlusIncr (ic) == TRUE)
3349 DD(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3350 DD(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3351 DD(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3353 size = getDataSize (IC_RESULT (ic));
3355 leftOp = AOP(IC_LEFT(ic));
3356 rightOp = AOP(IC_RIGHT(ic));
3362 loadRegFromAop (hc08_reg_a, leftOp, offset);
3363 accopWithAop(add, rightOp, offset);
3364 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3365 hc08_freeReg (hc08_reg_a);
3366 add = "adc"; /* further adds must propagate carry */
3370 // adjustArithmeticResult (ic);
3373 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3374 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3375 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3378 /*-----------------------------------------------------------------*/
3379 /* genMinusDec :- does subtraction with decrement if possible */
3380 /*-----------------------------------------------------------------*/
3382 genMinusDec (iCode * ic)
3384 unsigned int icount;
3389 unsigned int size = getDataSize (IC_RESULT (ic));
3393 left = IC_LEFT (ic);
3394 result = IC_RESULT (ic);
3396 /* will try to generate an increment */
3397 /* if the right side is not a literal
3399 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3402 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3404 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3405 && (icount>=-127) && (icount<=128) && (size==2))
3407 if (!IS_AOP_HX (AOP (left)))
3409 needpulx = pushRegIfUsed (hc08_reg_x);
3410 needpulh = pushRegIfUsed (hc08_reg_h);
3417 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3418 emitcode ("aix","#%d", -icount);
3419 hc08_dirtyReg (hc08_reg_hx, FALSE);
3420 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3421 pullOrFreeReg (hc08_reg_h, needpulh);
3422 pullOrFreeReg (hc08_reg_x, needpulx);
3426 if ((icount > 1) || (icount<0))
3429 if (!sameRegs (AOP (left), AOP (result)))
3435 D(emitcode ("; genMinusDec",""));
3437 rmwWithAop ("dec", AOP (result), 0);
3442 /*-----------------------------------------------------------------*/
3443 /* addSign - complete with sign */
3444 /*-----------------------------------------------------------------*/
3446 addSign (operand * result, int offset, int sign)
3448 int size = (getDataSize (result) - offset);
3453 emitcode ("rola", "");
3454 emitcode ("clra", "");
3455 emitcode ("sbc", zero);
3457 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3461 storeConstToAop (zero, AOP (result), offset++);
3466 /*-----------------------------------------------------------------*/
3467 /* genMinus - generates code for subtraction */
3468 /*-----------------------------------------------------------------*/
3470 genMinus (iCode * ic)
3473 int size, offset = 0;
3475 asmop *leftOp, *rightOp;
3477 D(emitcode ("; genMinus",""));
3479 aopOp (IC_LEFT (ic), ic, FALSE);
3480 aopOp (IC_RIGHT (ic), ic, FALSE);
3481 aopOp (IC_RESULT (ic), ic, TRUE);
3483 /* special cases :- */
3484 /* if I can do an decrement instead
3485 of subtract then GOOD for ME */
3486 if (genMinusDec (ic) == TRUE)
3489 size = getDataSize (IC_RESULT (ic));
3492 leftOp = AOP(IC_LEFT(ic));
3493 rightOp = AOP(IC_RIGHT(ic));
3497 if (IS_AOP_A (rightOp))
3499 loadRegFromAop ( hc08_reg_a, rightOp, offset);
3500 accopWithAop (sub, leftOp, offset);
3501 accopWithMisc ("nega", "");
3502 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3508 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3509 accopWithAop (sub, rightOp, offset);
3510 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3515 // adjustArithmeticResult (ic);
3518 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3519 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3520 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3525 /*-----------------------------------------------------------------*/
3526 /* genMultOneByte : 8*8=8/16 bit multiplication */
3527 /*-----------------------------------------------------------------*/
3529 genMultOneByte (operand * left,
3533 /* sym_link *opetype = operandType (result); */
3534 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3535 int size=AOP_SIZE(result);
3536 bool negLiteral = FALSE;
3537 bool lUnsigned, rUnsigned;
3539 D(emitcode ("; genMultOneByte",""));
3541 if (size<1 || size>2) {
3542 // this should never happen
3543 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3544 AOP_SIZE(result), __FILE__, lineno);
3548 /* (if two literals: the value is computed before) */
3549 /* if one literal, literal on the right */
3550 if (AOP_TYPE (left) == AOP_LIT)
3556 /* if an operand is in A, make sure it is on the left */
3557 if (IS_AOP_A (AOP (right)))
3564 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3565 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3567 /* lUnsigned rUnsigned negLiteral negate case */
3568 /* false false false odd 3 */
3569 /* false false true even 3 */
3570 /* false true false odd 3 */
3571 /* false true true impossible */
3572 /* true false false odd 3 */
3573 /* true false true always 2 */
3574 /* true true false never 1 */
3575 /* true true true impossible */
3579 || (lUnsigned && rUnsigned))
3581 // just an unsigned 8*8=8/16 multiply
3582 //DD(emitcode (";","unsigned"));
3584 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3585 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3586 emitcode ("mul", "");
3587 hc08_dirtyReg (hc08_reg_xa, FALSE);
3588 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3589 hc08_freeReg (hc08_reg_xa);
3594 // we have to do a signed multiply
3597 /* left unsigned, right signed literal -- literal determines sign handling */
3598 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3600 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3602 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3604 emitcode ("ldx", "#0x%02x", -val);
3606 emitcode ("ldx", "#0x%02x", val);
3608 emitcode ("mul", "");
3612 rmwWithReg ("neg", hc08_reg_a);
3613 tlbl4 = newiTempLabel (NULL);
3614 emitBranch ("bcc", tlbl4);
3615 rmwWithReg ("inc", hc08_reg_x);
3617 rmwWithReg ("neg", hc08_reg_x);
3620 hc08_dirtyReg (hc08_reg_xa, FALSE);
3621 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3622 hc08_freeReg (hc08_reg_xa);
3629 emitcode ("clr", "1,s");
3631 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3634 tlbl1 = newiTempLabel (NULL);
3635 emitcode ("tsta","");
3636 emitBranch ("bpl", tlbl1);
3637 emitcode ("inc", "1,s");
3638 rmwWithReg ("neg", hc08_reg_a);
3642 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3644 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3645 /* AND literal negative */
3647 emitcode ("ldx", "#0x%02x", -val);
3650 emitcode ("ldx", "#0x%02x", val);
3652 hc08_useReg (hc08_reg_x);
3656 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3659 tlbl2 = newiTempLabel (NULL);
3660 emitcode ("tstx", "");
3661 emitBranch ("bpl", tlbl2);
3662 emitcode ("inc", "1,s");
3663 rmwWithReg ("neg", hc08_reg_x);
3668 emitcode ("mul", "");
3669 hc08_dirtyReg (hc08_reg_xa, FALSE);
3671 tlbl3 = newiTempLabel (NULL);
3672 emitcode ("dec", "1,s");
3673 if (!lUnsigned && !rUnsigned && negLiteral)
3674 emitBranch ("beq", tlbl3);
3676 emitBranch ("bne", tlbl3);
3678 rmwWithReg ("neg", hc08_reg_a);
3679 tlbl4 = newiTempLabel (NULL);
3680 emitBranch ("bcc", tlbl4);
3681 rmwWithReg ("inc", hc08_reg_x);
3683 rmwWithReg ("neg", hc08_reg_x);
3687 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3688 hc08_freeReg (hc08_reg_xa);
3692 /*-----------------------------------------------------------------*/
3693 /* genMult - generates code for multiplication */
3694 /*-----------------------------------------------------------------*/
3696 genMult (iCode * ic)
3698 operand *left = IC_LEFT (ic);
3699 operand *right = IC_RIGHT (ic);
3700 operand *result = IC_RESULT (ic);
3702 D(emitcode ("; genMult",""));
3704 /* assign the amsops */
3705 aopOp (left, ic, FALSE);
3706 aopOp (right, ic, FALSE);
3707 aopOp (result, ic, TRUE);
3709 /* special cases first */
3710 /* if both are of size == 1 */
3711 // if (getSize(operandType(left)) == 1 &&
3712 // getSize(operandType(right)) == 1)
3713 if (AOP_SIZE (left) == 1 &&
3714 AOP_SIZE (right) == 1)
3716 genMultOneByte (left, right, result);
3720 /* should have been converted to function call */
3721 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3722 getSize(OP_SYMBOL(right)->type));
3723 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3728 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3729 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3730 freeAsmop (result, NULL, ic, TRUE);
3733 /*-----------------------------------------------------------------*/
3734 /* genDivOneByte : 8 bit division */
3735 /*-----------------------------------------------------------------*/
3737 genDivOneByte (operand * left,
3741 symbol *tlbl1, *tlbl2, *tlbl3;
3744 bool lUnsigned, rUnsigned;
3745 bool runtimeSign, compiletimeSign;
3747 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3748 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3750 D(emitcode ("; genDivOneByte",""));
3752 size = AOP_SIZE (result);
3753 /* signed or unsigned */
3754 if (lUnsigned && rUnsigned)
3756 /* unsigned is easy */
3757 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3758 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3759 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3760 emitcode ("div", "");
3761 hc08_dirtyReg (hc08_reg_a, FALSE);
3762 hc08_dirtyReg (hc08_reg_h, FALSE);
3763 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3764 hc08_freeReg (hc08_reg_a);
3765 hc08_freeReg (hc08_reg_x);
3766 hc08_freeReg (hc08_reg_h);
3770 /* signed is a little bit more difficult */
3772 /* now sign adjust for both left & right */
3774 /* let's see what's needed: */
3775 /* apply negative sign during runtime */
3776 runtimeSign = FALSE;
3777 /* negative sign from literals */
3778 compiletimeSign = FALSE;
3782 if (AOP_TYPE(left) == AOP_LIT)
3784 /* signed literal */
3785 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3787 compiletimeSign = TRUE;
3790 /* signed but not literal */
3796 if (AOP_TYPE(right) == AOP_LIT)
3798 /* signed literal */
3799 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3801 compiletimeSign ^= TRUE;
3804 /* signed but not literal */
3808 /* initialize the runtime sign */
3811 if (compiletimeSign)
3812 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3814 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3815 pushReg (hc08_reg_x, TRUE);
3818 /* save the signs of the operands */
3819 if (AOP_TYPE(right) == AOP_LIT)
3821 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3823 if (!rUnsigned && val < 0)
3824 emitcode ("ldx", "#0x%02x", -val);
3826 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3828 else /* ! literal */
3830 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3833 tlbl1 = newiTempLabel (NULL);
3834 emitcode ("tstx", "");
3835 emitBranch ("bpl", tlbl1);
3836 emitcode ("inc", "1,s");
3837 rmwWithReg ("neg", hc08_reg_x);
3842 if (AOP_TYPE(left) == AOP_LIT)
3844 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3846 if (!lUnsigned && val < 0)
3847 emitcode ("lda", "#0x%02x", -val);
3849 emitcode ("lda", "#0x%02x", (unsigned char) val);
3851 else /* ! literal */
3853 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3856 tlbl2 = newiTempLabel (NULL);
3857 emitcode ("tsta", "");
3858 emitBranch ("bpl", tlbl2);
3859 emitcode ("inc", "1,s");
3860 rmwWithReg ("neg", hc08_reg_a);
3865 loadRegFromConst (hc08_reg_h, zero);
3866 emitcode ("div", "");
3867 hc08_dirtyReg (hc08_reg_x, FALSE);
3868 hc08_dirtyReg (hc08_reg_a, FALSE);
3869 hc08_dirtyReg (hc08_reg_h, FALSE);
3871 if (runtimeSign || compiletimeSign)
3873 tlbl3 = newiTempLabel (NULL);
3876 pullReg (hc08_reg_x);
3877 rmwWithReg ("lsr", hc08_reg_x);
3878 rmwWithReg ("ror", hc08_reg_x);
3879 emitBranch ("bpl", tlbl3);
3882 rmwWithReg ("neg", hc08_reg_a);
3886 storeRegToAop (hc08_reg_a, AOP (result), 0);
3890 /* msb is 0x00 or 0xff depending on the sign */
3893 rmwWithReg ("lsl", hc08_reg_x);
3894 emitcode ("clra", "");
3895 emitcode ("sbc", "#0");
3897 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3899 else /* compiletimeSign */
3901 storeConstToAop ("#0xff", AOP (result), ++offset);
3906 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3909 hc08_freeReg (hc08_reg_a);
3910 hc08_freeReg (hc08_reg_x);
3911 hc08_freeReg (hc08_reg_h);
3914 /*-----------------------------------------------------------------*/
3915 /* genDiv - generates code for division */
3916 /*-----------------------------------------------------------------*/
3920 operand *left = IC_LEFT (ic);
3921 operand *right = IC_RIGHT (ic);
3922 operand *result = IC_RESULT (ic);
3924 D(emitcode ("; genDiv",""));
3926 /* assign the amsops */
3927 aopOp (left, ic, FALSE);
3928 aopOp (right, ic, FALSE);
3929 aopOp (result, ic, TRUE);
3931 /* special cases first */
3932 /* if both are of size == 1 */
3933 if (AOP_SIZE (left) <= 2 &&
3934 AOP_SIZE (right) == 1)
3936 genDivOneByte (left, right, result);
3940 /* should have been converted to function call */
3943 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3944 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3945 freeAsmop (result, NULL, ic, TRUE);
3948 /*-----------------------------------------------------------------*/
3949 /* genModOneByte : 8 bit modulus */
3950 /*-----------------------------------------------------------------*/
3952 genModOneByte (operand * left,
3956 symbol *tlbl1, *tlbl2, *tlbl3;
3959 bool lUnsigned, rUnsigned;
3960 bool runtimeSign, compiletimeSign;
3962 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3963 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3965 D(emitcode ("; genModOneByte",""));
3967 size = AOP_SIZE (result);
3969 if (lUnsigned && rUnsigned)
3971 /* unsigned is easy */
3972 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3973 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3974 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3975 emitcode ("div", "");
3976 hc08_freeReg (hc08_reg_a);
3977 hc08_freeReg (hc08_reg_x);
3978 hc08_dirtyReg (hc08_reg_h, FALSE);
3979 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3980 hc08_freeReg (hc08_reg_h);
3984 /* signed is a little bit more difficult */
3986 if (AOP_TYPE(right) == AOP_LIT)
3988 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3990 if (!rUnsigned && val < 0)
3991 emitcode ("ldx", "#0x%02x", -val);
3993 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3995 else /* ! literal */
3997 loadRegFromAop (hc08_reg_x, AOP (right), 0);
4000 tlbl1 = newiTempLabel (NULL);
4001 emitcode ("tstx", "");
4002 emitBranch ("bpl", tlbl1);
4003 rmwWithReg ("neg", hc08_reg_x);
4008 /* let's see what's needed: */
4009 /* apply negative sign during runtime */
4010 runtimeSign = FALSE;
4011 /* negative sign from literals */
4012 compiletimeSign = FALSE;
4014 /* sign adjust left side */
4015 if (AOP_TYPE(left) == AOP_LIT)
4017 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4019 if (!lUnsigned && val < 0)
4021 compiletimeSign = TRUE; /* set sign flag */
4022 emitcode ("lda", "#0x%02x", -val);
4025 emitcode ("lda", "#0x%02x", (unsigned char) val);
4027 else /* ! literal */
4030 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4035 emitcode ("clr", "1,s");
4037 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4038 tlbl2 = newiTempLabel (NULL);
4039 emitcode ("tsta", "");
4040 emitBranch ("bpl", tlbl2);
4041 emitcode ("inc", "1,s");
4042 rmwWithReg ("neg", hc08_reg_a);
4047 loadRegFromConst (hc08_reg_h, zero);
4048 emitcode ("div", "");
4049 hc08_freeReg (hc08_reg_a);
4050 hc08_freeReg (hc08_reg_x);
4051 hc08_dirtyReg (hc08_reg_h, FALSE);
4053 if (runtimeSign || compiletimeSign)
4055 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4056 tlbl3 = newiTempLabel (NULL);
4059 pullReg (hc08_reg_x);
4060 rmwWithReg ("lsr", hc08_reg_x);
4061 rmwWithReg ("ror", hc08_reg_x);
4062 emitBranch ("bpl", tlbl3);
4065 rmwWithReg ("neg", hc08_reg_a);
4069 storeRegToAop (hc08_reg_a, AOP (result), 0);
4073 /* msb is 0x00 or 0xff depending on the sign */
4076 rmwWithReg ("lsl", hc08_reg_x);
4077 emitcode ("clra", "");
4078 emitcode ("sbc", "#0");
4080 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4082 else /* compiletimeSign */
4084 storeConstToAop ("#0xff", AOP (result), ++offset);
4089 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4092 hc08_freeReg (hc08_reg_a);
4093 hc08_freeReg (hc08_reg_x);
4094 hc08_freeReg (hc08_reg_h);
4097 /*-----------------------------------------------------------------*/
4098 /* genMod - generates code for division */
4099 /*-----------------------------------------------------------------*/
4103 operand *left = IC_LEFT (ic);
4104 operand *right = IC_RIGHT (ic);
4105 operand *result = IC_RESULT (ic);
4107 D(emitcode ("; genMod",""));
4109 /* assign the amsops */
4110 aopOp (left, ic, FALSE);
4111 aopOp (right, ic, FALSE);
4112 aopOp (result, ic, TRUE);
4114 /* special cases first */
4115 /* if both are of size == 1 */
4116 if (AOP_SIZE (left) <= 2 &&
4117 AOP_SIZE (right) == 1)
4119 genModOneByte (left, right, result);
4123 /* should have been converted to function call */
4127 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4128 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4129 freeAsmop (result, NULL, ic, TRUE);
4132 /*-----------------------------------------------------------------*/
4133 /* genIfxJump :- will create a jump depending on the ifx */
4134 /*-----------------------------------------------------------------*/
4136 genIfxJump (iCode * ic, char *jval)
4139 symbol *tlbl = newiTempLabel (NULL);
4142 D(emitcode ("; genIfxJump",""));
4144 /* if true label then we jump if condition
4148 jlbl = IC_TRUE (ic);
4149 if (!strcmp (jval, "a"))
4151 else if (!strcmp (jval, "c"))
4158 /* false label is present */
4159 jlbl = IC_FALSE (ic);
4160 if (!strcmp (jval, "a"))
4162 else if (!strcmp (jval, "c"))
4167 emitBranch (inst, tlbl);
4168 emitBranch ("jmp", jlbl);
4171 /* mark the icode as generated */
4176 /*-----------------------------------------------------------------*/
4177 /* exchangedCmp : returns the opcode need if the two operands are */
4178 /* exchanged in a comparison */
4179 /*-----------------------------------------------------------------*/
4181 exchangedCmp (int opcode)
4198 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4199 "opcode not a comparison");
4201 return EQ_OP; /* shouldn't happen, but need to return something */
4204 /*------------------------------------------------------------------*/
4205 /* negatedCmp : returns the equivalent opcode for when a comparison */
4207 /*------------------------------------------------------------------*/
4209 negatedCmp (int opcode)
4226 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4227 "opcode not a comparison");
4229 return EQ_OP; /* shouldn't happen, but need to return something */
4232 /*------------------------------------------------------------------*/
4233 /* nameCmp : helper function for human readable debug output */
4234 /*------------------------------------------------------------------*/
4236 nameCmp (int opcode)
4257 /*------------------------------------------------------------------*/
4258 /* branchInstCmp : returns the conditional branch instruction that */
4259 /* will branch if the comparison is true */
4260 /*------------------------------------------------------------------*/
4262 branchInstCmp (int opcode, int sign)
4270 return "bcs"; /* same as blo */
4285 return "bcc"; /* same as bhs */
4291 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4292 "opcode not a comparison");
4298 /*------------------------------------------------------------------*/
4299 /* genCmp :- greater or less than (and maybe with equal) comparison */
4300 /*------------------------------------------------------------------*/
4302 genCmp (iCode * ic, iCode * ifx)
4304 operand *left, *right, *result;
4305 sym_link *letype, *retype;
4307 int size, offset = 0;
4308 unsigned long lit = 0L;
4310 symbol *jlbl = NULL;
4314 D(emitcode ("; genCmp", "(%s)",nameCmp (opcode)));
4316 result = IC_RESULT (ic);
4317 left = IC_LEFT (ic);
4318 right = IC_RIGHT (ic);
4320 letype = getSpec (operandType (left));
4321 retype = getSpec (operandType (right));
4322 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4323 /* assign the amsops */
4324 aopOp (left, ic, FALSE);
4325 aopOp (right, ic, FALSE);
4326 aopOp (result, ic, TRUE);
4328 /* need register operand on left, prefer literal operand on right */
4329 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4331 operand *temp = left;
4334 opcode = exchangedCmp (opcode);
4341 jlbl = IC_TRUE (ifx);
4342 opcode = negatedCmp (opcode);
4346 /* false label is present */
4347 jlbl = IC_FALSE (ifx);
4351 size = max (AOP_SIZE (left), AOP_SIZE (right));
4354 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4355 && ((AOP_TYPE (right) == AOP_LIT) ||
4356 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4357 && hc08_reg_hx->isFree)
4359 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4360 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4361 hc08_freeReg (hc08_reg_hx);
4372 /* These conditions depend on the Z flag bit, but Z is */
4373 /* only valid for the last byte of the comparison, not */
4374 /* the whole value. So exchange the operands to get a */
4375 /* comparison that doesn't depend on Z. (This is safe */
4376 /* to do here since ralloc won't assign multi-byte */
4377 /* operands to registers for comparisons) */
4378 if ((opcode == '>') || (opcode == LE_OP))
4380 operand *temp = left;
4383 opcode = exchangedCmp (opcode);
4386 if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
4388 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4389 while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
4398 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4399 accopWithAop (sub, AOP (right), offset);
4400 hc08_freeReg (hc08_reg_a);
4405 freeAsmop (right, NULL, ic, FALSE);
4406 freeAsmop (left, NULL, ic, FALSE);
4410 symbol *tlbl = newiTempLabel (NULL);
4413 freeAsmop (result, NULL, ic, TRUE);
4415 inst = branchInstCmp (opcode, sign);
4416 emitBranch (inst, tlbl);
4417 emitBranch ("jmp", jlbl);
4420 /* mark the icode as generated */
4425 symbol *tlbl1 = newiTempLabel (NULL);
4426 symbol *tlbl2 = newiTempLabel (NULL);
4428 emitBranch (branchInstCmp (opcode, sign), tlbl1);
4429 loadRegFromConst (hc08_reg_a, zero);
4430 emitBranch ("bra", tlbl2);
4432 loadRegFromConst (hc08_reg_a, one);
4434 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4435 freeAsmop (result, NULL, ic, TRUE);
4440 /*-----------------------------------------------------------------*/
4441 /* genCmpEQorNE - equal or not equal comparison */
4442 /*-----------------------------------------------------------------*/
4444 genCmpEQorNE (iCode * ic, iCode * ifx)
4446 operand *left, *right, *result;
4447 sym_link *letype, *retype;
4449 int size, offset = 0;
4451 symbol *jlbl = NULL;
4452 symbol *tlbl_NE = NULL;
4453 symbol *tlbl_EQ = NULL;
4457 D(emitcode ("; genCmpEQorNE", "(%s)",nameCmp (opcode)));
4459 result = IC_RESULT (ic);
4460 left = IC_LEFT (ic);
4461 right = IC_RIGHT (ic);
4463 letype = getSpec (operandType (left));
4464 retype = getSpec (operandType (right));
4465 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4466 /* assign the amsops */
4467 aopOp (left, ic, FALSE);
4468 aopOp (right, ic, FALSE);
4469 aopOp (result, ic, TRUE);
4471 /* need register operand on left, prefer literal operand on right */
4472 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4474 operand *temp = left;
4477 opcode = exchangedCmp (opcode);
4484 jlbl = IC_TRUE (ifx);
4485 opcode = negatedCmp (opcode);
4489 /* false label is present */
4490 jlbl = IC_FALSE (ifx);
4494 size = max (AOP_SIZE (left), AOP_SIZE (right));
4497 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4498 && ((AOP_TYPE (right) == AOP_LIT) ||
4499 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4500 && hc08_reg_hx->isFree)
4502 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4503 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4504 hc08_freeReg (hc08_reg_hx);
4512 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4513 accopWithAop (sub, AOP (right), offset);
4517 tlbl_NE = newiTempLabel (NULL);
4518 emitBranch ("bne", tlbl_NE);
4520 hc08_freeReg (hc08_reg_a);
4524 freeAsmop (right, NULL, ic, FALSE);
4525 freeAsmop (left, NULL, ic, FALSE);
4529 freeAsmop (result, NULL, ic, TRUE);
4531 if (opcode == EQ_OP)
4534 tlbl_EQ = newiTempLabel (NULL);
4535 emitBranch ("beq", tlbl_EQ);
4537 emitLabel (tlbl_NE);
4538 emitBranch ("jmp", jlbl);
4539 emitLabel (tlbl_EQ);
4544 tlbl_NE = newiTempLabel (NULL);
4545 emitBranch ("bne", tlbl_NE);
4546 emitBranch ("jmp", jlbl);
4547 emitLabel (tlbl_NE);
4550 /* mark the icode as generated */
4555 symbol *tlbl = newiTempLabel (NULL);
4557 if (opcode == EQ_OP)
4560 tlbl_EQ = newiTempLabel (NULL);
4561 emitBranch ("beq", tlbl_EQ);
4563 emitLabel (tlbl_NE);
4564 loadRegFromConst (hc08_reg_a, zero);
4565 emitBranch ("bra", tlbl);
4566 emitLabel (tlbl_EQ);
4567 loadRegFromConst (hc08_reg_a, one);
4572 tlbl_NE = newiTempLabel (NULL);
4573 emitBranch ("bne", tlbl_NE);
4574 loadRegFromConst (hc08_reg_a, zero);
4575 emitBranch ("bra", tlbl);
4576 emitLabel (tlbl_NE);
4577 loadRegFromConst (hc08_reg_a, one);
4581 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4582 freeAsmop (result, NULL, ic, TRUE);
4588 /*-----------------------------------------------------------------*/
4589 /* ifxForOp - returns the icode containing the ifx for operand */
4590 /*-----------------------------------------------------------------*/
4592 ifxForOp (operand * op, iCode * ic)
4594 /* if true symbol then needs to be assigned */
4595 if (IS_TRUE_SYMOP (op))
4598 /* if this has register type condition and
4599 the next instruction is ifx with the same operand
4600 and live to of the operand is upto the ifx only then */
4602 ic->next->op == IFX &&
4603 IC_COND (ic->next)->key == op->key &&
4604 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4611 genPointerGetSetOfs (iCode *ic)
4613 iCode *lic = ic->next;
4619 /* Make sure we have a next iCode */
4620 DD(emitcode("","; checking lic"));
4624 /* Make sure the result of the addition is an iCode */
4625 DD(emitcode("","; checking IS_ITEMP"));
4626 if (!IS_ITEMP (IC_RESULT (ic)))
4629 /* Make sure the next iCode is a pointer set or get */
4630 pset = POINTER_SET(lic);
4631 pget = POINTER_GET(lic);
4632 DD(emitcode("","; pset=%d, pget=%d",pset,pget));
4636 /* Make sure this is the only use of the pointer */
4637 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4640 DD(emitcode("", "; checking pset operandsEqu"));
4641 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4644 DD(emitcode("", "; checking pget operandsEqu"));
4645 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4648 DD(emitcode("", "; checking IS_SYMOP"));
4649 if (!IS_SYMOP (IC_LEFT (ic)))
4652 DD(emitcode("", "; checking !IS_TRUE_SYMOP"));
4653 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4656 sym = OP_SYMBOL (IC_LEFT (ic));
4658 DD(emitcode("", "; checking remat"));
4665 D(emitcode ("; genPointerGetOfs",""));
4666 aopOp (IC_LEFT(ic), ic, FALSE);
4667 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4668 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4670 aopOp (IC_RIGHT(ic), ic, FALSE);
4671 aopOp (IC_RESULT(lic), lic, FALSE);
4673 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4675 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4677 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4678 loadRegFromConst (hc08_reg_h, zero);
4682 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4683 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4684 emitcode ("rola","");
4685 emitcode ("clra","");
4686 emitcode ("sbc", "#0");
4687 hc08_useReg (hc08_reg_a);
4688 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4692 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4693 size = AOP_SIZE (IC_RESULT(lic));
4694 derefaop->size = size;
4698 emitcode ("lda", "%s,x",
4699 aopAdrStr (derefaop, size, TRUE));
4700 hc08_useReg (hc08_reg_a);
4701 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
4702 hc08_freeReg (hc08_reg_a);
4706 hc08_freeReg (hc08_reg_hx);
4708 freeAsmop (NULL, derefaop, ic, TRUE);
4709 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4710 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4717 D(emitcode ("; genPointerSetOfs",""));
4718 aopOp (IC_LEFT(ic), ic, FALSE);
4719 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4720 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4722 aopOp (IC_RIGHT(ic), ic, FALSE);
4723 aopOp (IC_RIGHT(lic), lic, FALSE);
4725 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4727 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4729 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4730 loadRegFromConst (hc08_reg_h, zero);
4734 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4735 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4736 emitcode ("rola","");
4737 emitcode ("clra","");
4738 emitcode ("sbc", "#0");
4739 hc08_useReg (hc08_reg_a);
4740 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4744 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4745 size = AOP_SIZE (IC_RIGHT(lic));
4746 derefaop->size = size;
4750 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
4751 emitcode ("sta", "%s,x",
4752 aopAdrStr (derefaop, size, TRUE));
4753 hc08_freeReg (hc08_reg_a);
4757 hc08_freeReg (hc08_reg_hx);
4759 freeAsmop (NULL, derefaop, ic, TRUE);
4760 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4761 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4770 /*-----------------------------------------------------------------*/
4771 /* hasInc - operand is incremented before any other use */
4772 /*-----------------------------------------------------------------*/
4774 hasInc (operand *op, iCode *ic,int osize)
4776 sym_link *type = operandType(op);
4777 sym_link *retype = getSpec (type);
4778 iCode *lic = ic->next;
4781 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4782 if (!IS_SYMOP(op)) return NULL;
4784 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4785 if (IS_AGGREGATE(type->next)) return NULL;
4786 if (osize != (isize = getSize(type->next))) return NULL;
4789 /* if operand of the form op = op + <sizeof *op> */
4790 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4791 isOperandEqual(IC_RESULT(lic),op) &&
4792 isOperandLiteral(IC_RIGHT(lic)) &&
4793 operandLitValue(IC_RIGHT(lic)) == isize) {
4796 /* if the operand used or deffed */
4797 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
4800 /* if GOTO or IFX */
4801 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4807 /*-----------------------------------------------------------------*/
4808 /* genAndOp - for && operation */
4809 /*-----------------------------------------------------------------*/
4811 genAndOp (iCode * ic)
4813 operand *left, *right, *result;
4814 symbol *tlbl, *tlbl0;
4816 D(emitcode ("; genAndOp",""));
4818 /* note here that && operations that are in an
4819 if statement are taken away by backPatchLabels
4820 only those used in arthmetic operations remain */
4821 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4822 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4823 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4825 tlbl = newiTempLabel (NULL);
4826 tlbl0 = newiTempLabel (NULL);
4828 asmopToBool (AOP (left), FALSE);
4829 emitBranch ("beq", tlbl0);
4830 asmopToBool (AOP (right), FALSE);
4831 emitBranch ("beq", tlbl0);
4832 loadRegFromConst (hc08_reg_a,one);
4833 emitBranch ("bra", tlbl);
4835 loadRegFromConst (hc08_reg_a,zero);
4838 hc08_useReg (hc08_reg_a);
4839 hc08_freeReg (hc08_reg_a);
4841 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4843 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4844 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4845 freeAsmop (result, NULL, ic, TRUE);
4849 /*-----------------------------------------------------------------*/
4850 /* genOrOp - for || operation */
4851 /*-----------------------------------------------------------------*/
4853 genOrOp (iCode * ic)
4855 operand *left, *right, *result;
4856 symbol *tlbl, *tlbl0;
4858 D(emitcode ("; genOrOp",""));
4860 /* note here that || operations that are in an
4861 if statement are taken away by backPatchLabels
4862 only those used in arthmetic operations remain */
4863 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4864 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4865 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4867 tlbl = newiTempLabel (NULL);
4868 tlbl0 = newiTempLabel (NULL);
4870 asmopToBool (AOP (left), FALSE);
4871 emitBranch ("bne", tlbl0);
4872 asmopToBool (AOP (right), FALSE);
4873 emitBranch ("bne", tlbl0);
4874 loadRegFromConst (hc08_reg_a,zero);
4875 emitBranch ("bra", tlbl);
4877 loadRegFromConst (hc08_reg_a,one);
4880 hc08_useReg (hc08_reg_a);
4881 hc08_freeReg (hc08_reg_a);
4883 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4886 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4887 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4888 freeAsmop (result, NULL, ic, TRUE);
4891 /*-----------------------------------------------------------------*/
4892 /* isLiteralBit - test if lit == 2^n */
4893 /*-----------------------------------------------------------------*/
4895 isLiteralBit (unsigned long lit)
4897 unsigned long pw[32] =
4898 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4899 0x100L, 0x200L, 0x400L, 0x800L,
4900 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4901 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4902 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4903 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4904 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4907 for (idx = 0; idx < 32; idx++)
4914 /*-----------------------------------------------------------------*/
4915 /* continueIfTrue - */
4916 /*-----------------------------------------------------------------*/
4918 continueIfTrue (iCode * ic)
4921 emitBranch ("jmp", IC_TRUE (ic));
4925 /*-----------------------------------------------------------------*/
4927 /*-----------------------------------------------------------------*/
4929 jumpIfTrue (iCode * ic)
4932 emitBranch ("jmp", IC_FALSE (ic));
4936 /*-----------------------------------------------------------------*/
4937 /* jmpTrueOrFalse - */
4938 /*-----------------------------------------------------------------*/
4940 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4942 // ugly but optimized by peephole
4945 symbol *nlbl = newiTempLabel (NULL);
4946 emitBranch ("bra", nlbl);
4948 emitBranch ("jmp", IC_TRUE (ic));
4953 emitBranch ("jmp", IC_FALSE (ic));
4960 /*-----------------------------------------------------------------*/
4961 /* genAnd - code for and */
4962 /*-----------------------------------------------------------------*/
4964 genAnd (iCode * ic, iCode * ifx)
4966 operand *left, *right, *result;
4967 int size, offset = 0;
4968 unsigned long lit = 0L;
4969 unsigned long litinv;
4970 unsigned char bytemask;
4976 D(emitcode ("; genAnd",""));
4978 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4979 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4980 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4983 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4985 AOP_TYPE (left), AOP_TYPE (right)));
4986 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4988 AOP_SIZE (left), AOP_SIZE (right)));
4991 /* if left is a literal & right is not then exchange them */
4992 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4994 operand *tmp = right;
4999 /* if right is accumulator & left is not then exchange them */
5000 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5002 operand *tmp = right;
5007 if (AOP_TYPE (right) == AOP_LIT)
5008 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5010 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5012 if (AOP_TYPE (result) == AOP_CRY
5014 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5016 /* this generates ugly code, but meets volatility requirements */
5017 loadRegFromConst (hc08_reg_a, zero);
5018 pushReg (hc08_reg_a, TRUE);
5023 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5024 accopWithAop ("and", AOP (right), offset);
5025 emitcode ("ora", "1,s");
5026 emitcode ("sta", "1,s");
5030 pullReg (hc08_reg_a);
5031 emitcode ("tsta", "");
5032 genIfxJump (ifx, "a");
5036 if (AOP_TYPE (result) == AOP_CRY)
5038 symbol *tlbl = NULL;
5039 wassertl (ifx, "AOP_CRY result without ifx");
5044 bytemask = (lit >> (offset*8)) & 0xff;
5046 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5050 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5052 rmwWithAop ("tst", AOP (left), offset);
5056 tlbl = newiTempLabel (NULL);
5057 emitBranch ("bne", tlbl);
5062 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5063 accopWithAop ("and", AOP (right), offset);
5064 hc08_freeReg( hc08_reg_a);
5068 tlbl = newiTempLabel (NULL);
5069 emitBranch ("bne", tlbl);
5076 genIfxJump (ifx, "a");
5080 size = AOP_SIZE (result);
5082 if (AOP_TYPE (right) == AOP_LIT)
5084 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
5085 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5086 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
5088 int bitpos = isLiteralBit(litinv)-1;
5089 emitcode ("bclr","#%d,%s",bitpos & 7,
5090 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5098 bytemask = (lit >> (offset*8)) & 0xff;
5100 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5102 if (isOperandVolatile (left, FALSE))
5104 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5105 hc08_freeReg( hc08_reg_a);
5107 storeConstToAop (zero, AOP (result), offset);
5109 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5111 transferAopAop (AOP (left), offset, AOP (result), offset);
5115 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5116 accopWithAop ("and", AOP (right), offset);
5117 storeRegToAop (hc08_reg_a, AOP (result), offset);
5118 hc08_freeReg (hc08_reg_a);
5124 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5125 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5126 freeAsmop (result, NULL, ic, TRUE);
5129 /*-----------------------------------------------------------------*/
5130 /* genOr - code for or */
5131 /*-----------------------------------------------------------------*/
5133 genOr (iCode * ic, iCode * ifx)
5135 operand *left, *right, *result;
5136 int size, offset = 0;
5137 unsigned long lit = 0L;
5138 unsigned char bytemask;
5140 D(emitcode ("; genOr",""));
5142 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5143 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5144 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5147 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5149 AOP_TYPE (left), AOP_TYPE (right)));
5150 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5152 AOP_SIZE (left), AOP_SIZE (right)));
5155 /* if left is a literal & right is not then exchange them */
5156 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5158 operand *tmp = right;
5163 /* if left is accumulator & right is not then exchange them */
5164 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5166 operand *tmp = right;
5171 if (AOP_TYPE (right) == AOP_LIT)
5172 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5174 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5176 if (AOP_TYPE (result) == AOP_CRY
5178 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5180 /* this generates ugly code, but meets volatility requirements */
5181 loadRegFromConst (hc08_reg_a, zero);
5182 pushReg (hc08_reg_a, TRUE);
5187 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5188 accopWithAop ("ora", AOP (right), offset);
5189 emitcode ("ora", "1,s");
5190 emitcode ("sta", "1,s");
5194 pullReg (hc08_reg_a);
5195 emitcode ("tsta", "");
5196 genIfxJump (ifx, "a");
5200 if (AOP_TYPE (result) == AOP_CRY)
5202 symbol *tlbl = NULL;
5203 wassertl (ifx, "AOP_CRY result without ifx");
5208 bytemask = (lit >> (offset*8)) & 0xff;
5210 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5212 rmwWithAop ("tst", AOP (left), offset);
5216 tlbl = newiTempLabel (NULL);
5217 emitBranch ("bne", tlbl);
5222 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5223 accopWithAop ("ora", AOP (right), offset);
5224 hc08_freeReg( hc08_reg_a);
5228 tlbl = newiTempLabel (NULL);
5229 emitBranch ("bne", tlbl);
5236 genIfxJump (ifx, "a");
5239 if (AOP_TYPE (right) == AOP_LIT)
5240 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5242 size = AOP_SIZE (result);
5244 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5245 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5246 (AOP_TYPE (left) == AOP_DIR))
5248 int bitpos = isLiteralBit(lit)-1;
5249 emitcode ("bset","#%d,%s",bitpos & 7,
5250 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5257 bytemask = (lit >> (offset*8)) & 0xff;
5259 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5261 if (isOperandVolatile (left, FALSE))
5263 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5264 hc08_freeReg( hc08_reg_a);
5266 transferAopAop (AOP (right), offset, AOP (result), offset);
5268 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5270 transferAopAop (AOP (left), offset, AOP (result), offset);
5274 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5275 accopWithAop ("ora", AOP (right), offset);
5276 storeRegToAop (hc08_reg_a, AOP (result), offset);
5277 hc08_freeReg (hc08_reg_a);
5284 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5285 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5286 freeAsmop (result, NULL, ic, TRUE);
5289 /*-----------------------------------------------------------------*/
5290 /* genXor - code for xclusive or */
5291 /*-----------------------------------------------------------------*/
5293 genXor (iCode * ic, iCode * ifx)
5295 operand *left, *right, *result;
5296 int size, offset = 0;
5297 unsigned long lit = 0L;
5299 D(emitcode ("; genXor",""));
5301 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5302 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5303 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5306 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5308 AOP_TYPE (left), AOP_TYPE (right)));
5309 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5311 AOP_SIZE (left), AOP_SIZE (right)));
5314 /* if left is a literal & right is not ||
5315 if left needs acc & right does not */
5316 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5318 operand *tmp = right;
5323 /* if left is accumulator & right is not then exchange them */
5324 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5326 operand *tmp = right;
5331 if (AOP_TYPE (result) == AOP_CRY)
5334 wassertl (ifx, "AOP_CPY result without ifx");
5336 tlbl = newiTempLabel (NULL);
5337 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5341 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5342 if ((AOP_TYPE (right) == AOP_LIT)
5343 && (((lit >> (offset*8)) & 0xff) == 0))
5344 emitcode ("tsta","");
5346 accopWithAop ("eor", AOP (right), offset);
5347 hc08_freeReg( hc08_reg_a);
5349 emitBranch ("bne", tlbl);
5353 genIfxJump (ifx, "a");
5359 if (AOP_TYPE (right) == AOP_LIT)
5360 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5362 size = AOP_SIZE (result);
5366 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5367 accopWithAop ("eor", AOP (right), offset);
5368 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5369 hc08_freeReg( hc08_reg_a);
5373 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5374 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5375 freeAsmop (result, NULL, ic, TRUE);
5379 emitinline (iCode * ic, char *inlin)
5385 symbol *sym, *tempsym;
5394 while (isalnum((unsigned char)*inlin) || (*inlin == '_'))
5398 //printf("Found possible symbol '%s'\n",symname);
5399 tempsym = newSymbol (symname, ic->level);
5400 tempsym->block = ic->block;
5401 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5410 aop = aopForSym (ic, sym, FALSE);
5411 l = aopAdrStr (aop, aop->size - 1, TRUE);
5415 if (sym->level && !sym->allocreq && !sym->ismyparm)
5417 werror (E_ID_UNDEF, sym->name);
5419 " Add 'volatile' to the variable declaration so that it\n"
5420 " can be referenced within inline assembly");
5422 //printf("Replacing with '%s'\n",l);
5426 if ((2+bp-buffer)>sizeof(buffer))
5435 if ((2+bp-buffer)>sizeof(buffer))
5442 if ((2+bp-buffer)>sizeof(buffer))
5443 fprintf(stderr, "Inline assembly buffer overflow\n");
5445 //printf("%s\n",buffer);
5446 emitcode (buffer,"");
5450 /*-----------------------------------------------------------------*/
5451 /* genInline - write the inline code out */
5452 /*-----------------------------------------------------------------*/
5454 genInline (iCode * ic)
5456 char *buffer, *bp, *bp1;
5457 bool inComment = FALSE;
5459 D(emitcode ("; genInline",""));
5461 _G.inLine += (!options.asmpeep);
5463 buffer = bp = bp1 = Safe_strdup (IC_INLINE(ic));
5465 /* emit each line as a code */
5478 emitinline (ic, bp1);
5483 /* Add \n for labels, not dirs such as c:\mydir */
5484 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
5498 emitinline (ic, bp1);
5502 _G.inLine -= (!options.asmpeep);
5505 /*-----------------------------------------------------------------*/
5506 /* genRRC - rotate right with carry */
5507 /*-----------------------------------------------------------------*/
5511 operand *left, *result;
5512 int size, offset = 0;
5513 bool needpula = FALSE;
5514 bool resultInA = FALSE;
5517 D(emitcode ("; genRRC",""));
5519 /* rotate right with carry */
5520 left = IC_LEFT (ic);
5521 result = IC_RESULT (ic);
5522 aopOp (left, ic, FALSE);
5523 aopOp (result, ic, FALSE);
5525 if ((AOP_TYPE (result) == AOP_REG)
5526 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5529 size = AOP_SIZE (result);
5533 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5537 rmwWithAop (shift, AOP (result), offset--);
5545 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5546 rmwWithReg (shift, hc08_reg_a);
5547 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5548 hc08_freeReg (hc08_reg_a);
5553 if ((!hc08_reg_a->isFree) || resultInA)
5555 pushReg (hc08_reg_a, TRUE);
5559 /* now we need to put the carry into the
5560 highest order byte of the result */
5561 offset = AOP_SIZE (result) - 1;
5562 emitcode ("clra","");
5563 emitcode ("rora","");
5564 hc08_dirtyReg (hc08_reg_a, FALSE);
5567 emitcode ("ora", "1,s");
5568 emitcode ("ais", "#1");
5569 hc08_dirtyReg (hc08_reg_a, FALSE);
5573 accopWithAop ("ora", AOP (result), offset);
5574 storeRegToAop (hc08_reg_a, AOP (result), offset);
5576 pullOrFreeReg (hc08_reg_a, needpula);
5578 freeAsmop (left, NULL, ic, TRUE);
5579 freeAsmop (result, NULL, ic, TRUE);
5582 /*-----------------------------------------------------------------*/
5583 /* genRLC - generate code for rotate left with carry */
5584 /*-----------------------------------------------------------------*/
5588 operand *left, *result;
5589 int size, offset = 0;
5591 bool resultInA = FALSE;
5592 bool needpula = FALSE;
5594 D(emitcode ("; genRLC",""));
5596 /* rotate right with carry */
5597 left = IC_LEFT (ic);
5598 result = IC_RESULT (ic);
5599 aopOp (left, ic, FALSE);
5600 aopOp (result, ic, FALSE);
5602 if ((AOP_TYPE (result) == AOP_REG)
5603 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5606 size = AOP_SIZE (result);
5610 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5614 rmwWithAop (shift, AOP (result), offset--);
5622 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5623 rmwWithReg (shift, hc08_reg_a);
5624 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5625 hc08_freeReg (hc08_reg_a);
5630 if ((!hc08_reg_a->isFree) || resultInA)
5632 pushReg (hc08_reg_a, TRUE);
5636 /* now we need to put the carry into the
5637 lowest order byte of the result */
5639 emitcode ("clra","");
5640 emitcode ("rola","");
5641 hc08_dirtyReg (hc08_reg_a, FALSE);
5644 emitcode ("ora", "1,s");
5645 emitcode ("ais", "#1");
5646 hc08_dirtyReg (hc08_reg_a, FALSE);
5650 accopWithAop ("ora", AOP (result), offset);
5651 storeRegToAop (hc08_reg_a, AOP (result), offset);
5653 pullOrFreeReg (hc08_reg_a, needpula);
5655 freeAsmop (left, NULL, ic, TRUE);
5656 freeAsmop (result, NULL, ic, TRUE);
5659 /*-----------------------------------------------------------------*/
5660 /* genGetHbit - generates code get highest order bit */
5661 /*-----------------------------------------------------------------*/
5663 genGetHbit (iCode * ic)
5665 operand *left, *result;
5667 D(emitcode ("; genGetHbit",""));
5669 left = IC_LEFT (ic);
5670 result = IC_RESULT (ic);
5671 aopOp (left, ic, FALSE);
5672 aopOp (result, ic, FALSE);
5674 /* get the highest order byte into a */
5675 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5676 emitcode ("rola", "");
5677 emitcode ("clra", "");
5678 emitcode ("rola", "");
5679 hc08_dirtyReg (hc08_reg_a, FALSE);
5680 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5681 hc08_freeReg (hc08_reg_a);
5683 freeAsmop (left, NULL, ic, TRUE);
5684 freeAsmop (result, NULL, ic, TRUE);
5687 /*-----------------------------------------------------------------*/
5688 /* genSwap - generates code to swap nibbles or bytes */
5689 /*-----------------------------------------------------------------*/
5691 genSwap (iCode * ic)
5693 operand *left, *result;
5695 D(emitcode ("; genSwap",""));
5697 left = IC_LEFT (ic);
5698 result = IC_RESULT (ic);
5699 aopOp (left, ic, FALSE);
5700 aopOp (result, ic, FALSE);
5702 switch (AOP_SIZE (left))
5704 case 1: /* swap nibbles in byte */
5705 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5706 emitcode ("nsa", "");
5707 hc08_dirtyReg (hc08_reg_a, FALSE);
5708 storeRegToAop (hc08_reg_a, AOP (result), 0);
5709 hc08_freeReg (hc08_reg_a);
5711 case 2: /* swap bytes in a word */
5712 if (operandsEqu (left, result) || sameRegs (AOP (left), AOP (result)))
5714 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5715 hc08_useReg (hc08_reg_a);
5716 transferAopAop (AOP (left), 1, AOP (result), 0);
5717 storeRegToAop (hc08_reg_a, AOP (result), 1);
5718 hc08_freeReg (hc08_reg_a);
5722 transferAopAop (AOP (left), 0, AOP (result), 1);
5723 transferAopAop (AOP (left), 1, AOP (result), 0);
5727 wassertl(FALSE, "unsupported SWAP operand size");
5730 freeAsmop (left, NULL, ic, TRUE);
5731 freeAsmop (result, NULL, ic, TRUE);
5735 /*-----------------------------------------------------------------*/
5736 /* AccRol - rotate left accumulator by known count */
5737 /*-----------------------------------------------------------------*/
5739 AccRol (int shCount)
5741 shCount &= 0x0007; // shCount : 0..7
5748 emitcode ("rola", ""); /* 1 cycle */
5751 emitcode ("rola", ""); /* 1 cycle */
5752 emitcode ("rola", ""); /* 1 cycle */
5755 emitcode ("nsa", "");
5756 emitcode ("rora", "");
5759 emitcode ("nsa", ""); /* 3 cycles */
5762 emitcode ("nsa", ""); /* 3 cycles */
5763 emitcode ("rola", ""); /* 1 cycle */
5766 emitcode ("nsa", ""); /* 3 cycles */
5767 emitcode ("rola", ""); /* 1 cycle */
5768 emitcode ("rola", ""); /* 1 cycle */
5771 emitcode ("nsa", ""); /* 3 cycles */
5772 emitcode ("rola", ""); /* 1 cycle */
5773 emitcode ("rola", ""); /* 1 cycle */
5774 emitcode ("rola", ""); /* 1 cycle */
5781 /*-----------------------------------------------------------------*/
5782 /* AccLsh - left shift accumulator by known count */
5783 /*-----------------------------------------------------------------*/
5785 AccLsh (int shCount)
5789 shCount &= 0x0007; // shCount : 0..7
5791 /* Shift counts of 4 and 5 are currently optimized for code size. */
5792 /* Falling through to the unrolled loop would be optimal for code speed. */
5793 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5797 if (optimize.codeSpeed)
5799 accopWithMisc ("nsa", "");
5800 accopWithMisc ("and", "#0xf0");
5801 /* total: 5 cycles, 3 bytes */
5804 if (optimize.codeSpeed)
5806 accopWithMisc ("nsa", "");
5807 accopWithMisc ("and", "#0xf0");
5808 accopWithMisc ("lsla", "");
5809 /* total: 6 cycles, 4 bytes */
5812 accopWithMisc ("rora", "");
5813 accopWithMisc ("rora", "");
5814 accopWithMisc ("rora", "");
5815 accopWithMisc ("and", "#0xc0");
5816 /* total: 5 cycles, 5 bytes */
5819 accopWithMisc ("rora", "");
5820 accopWithMisc ("clra", "");
5821 accopWithMisc ("rora", "");
5822 /* total: 3 cycles, 3 bytes */
5826 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5827 /* the fastest (shCount<6) and shortest (shCount<4). */
5828 for (i=0;i<shCount;i++)
5829 accopWithMisc ("lsla", "");
5833 /*-----------------------------------------------------------------*/
5834 /* AccSRsh - signed right shift accumulator by known count */
5835 /*-----------------------------------------------------------------*/
5837 AccSRsh (int shCount)
5841 shCount &= 0x0007; // shCount : 0..7
5845 accopWithMisc ("rola", "");
5846 accopWithMisc ("clra", "");
5847 accopWithMisc ("sbc", zero);
5848 /* total: 4 cycles, 4 bytes */
5852 for (i=0;i<shCount;i++)
5853 accopWithMisc ("asra", "");
5856 /*-----------------------------------------------------------------*/
5857 /* AccRsh - right shift accumulator by known count */
5858 /*-----------------------------------------------------------------*/
5860 AccRsh (int shCount, bool sign)
5870 shCount &= 0x0007; // shCount : 0..7
5872 /* Shift counts of 4 and 5 are currently optimized for code size. */
5873 /* Falling through to the unrolled loop would be optimal for code speed. */
5874 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5878 if (optimize.codeSpeed)
5880 accopWithMisc ("nsa", "");
5881 accopWithMisc ("and", "#0x0f");
5882 /* total: 5 cycles, 3 bytes */
5885 if (optimize.codeSpeed)
5887 accopWithMisc ("nsa", "");
5888 accopWithMisc ("and", "#0x0f");
5889 accopWithMisc ("lsra", "");
5890 /* total: 6 cycles, 4 bytes */
5893 accopWithMisc ("rola", "");
5894 accopWithMisc ("rola", "");
5895 accopWithMisc ("rola", "");
5896 accopWithMisc ("and", "#0x03");
5897 /* total: 5 cycles, 5 bytes */
5900 accopWithMisc ("rola", "");
5901 accopWithMisc ("clra", "");
5902 accopWithMisc ("rola", "");
5903 /* total: 3 cycles, 3 bytes */
5907 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5908 /* the fastest (shCount<6) and shortest (shCount<4). */
5909 for (i=0;i<shCount;i++)
5910 accopWithMisc ("lsra", "");
5914 /*-----------------------------------------------------------------*/
5915 /* XAccLsh - left shift register pair XA by known count */
5916 /*-----------------------------------------------------------------*/
5918 XAccLsh (int shCount)
5922 shCount &= 0x000f; // shCount : 0..15
5927 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5928 loadRegFromConst (hc08_reg_a, zero);
5932 /* if we can beat 2n cycles or bytes for some special case, do it here */
5936 /* bytes cycles reg x reg a carry
5937 ** abcd efgh ijkl mnop ?
5938 ** lsrx 1 1 0abc defg ijkl mnop h
5939 ** rora 1 1 0abc defg hijk lmno p
5940 ** tax 1 1 hijk lmno hijk lmno p
5941 ** clra 1 1 hijk lmno 0000 0000 p
5942 ** rora 1 1 hijk lmno p000 0000 0
5943 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5945 rmwWithReg ("lsr", hc08_reg_x);
5946 rmwWithReg ("ror", hc08_reg_a);
5947 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5948 loadRegFromConst (hc08_reg_a, zero);
5949 rmwWithReg ("ror", hc08_reg_a);
5956 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5957 /* the fastest and shortest. */
5958 for (i=0;i<shCount;i++)
5960 rmwWithReg ("lsl", hc08_reg_a);
5961 rmwWithReg ("rol", hc08_reg_x);
5965 /*-----------------------------------------------------------------*/
5966 /* XAccSRsh - signed right shift register pair XA by known count */
5967 /*-----------------------------------------------------------------*/
5969 XAccSRsh (int shCount)
5973 shCount &= 0x000f; // shCount : 0..7
5975 /* if we can beat 2n cycles or bytes for some special case, do it here */
5979 /* bytes cycles reg x reg a carry
5980 ** abcd efgh ijkl mnop ?
5981 ** lslx 1 1 bcde fgh0 ijkl mnop a
5982 ** clra 1 1 bcde fgh0 0000 0000 a
5983 ** rola 1 1 bcde fgh0 0000 000a 0
5984 ** nega 1 1 bcde fgh0 aaaa aaaa a
5985 ** tax 1 1 aaaa aaaa aaaa aaaa a
5986 ** total: 5 cycles, 5 bytes
5988 rmwWithReg ("lsl", hc08_reg_x);
5989 loadRegFromConst (hc08_reg_a, zero);
5990 rmwWithReg ("rol", hc08_reg_a);
5991 rmwWithReg ("neg", hc08_reg_a);
5992 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6002 /* bytes cycles reg x reg a carry
6003 ** abcd efgh ijkl mnop ?
6004 ** txa 1 1 abcd efgh abcd efgh ?
6005 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
6006 ** lsla 1 1 abcd efgh ???? ???? a
6007 ** clrx 1 1 0000 0000 ???? ???? a
6008 ** rolx 1 1 0000 000a ???? ???? 0
6009 ** negx 1 1 aaaa aaaa ???? ???? a
6010 ** rora 1 1 aaaa aaaa LSBresult 0
6011 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
6013 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6014 AccSRsh (shCount-8);
6015 rmwWithReg ("lsl", hc08_reg_a);
6016 loadRegFromConst (hc08_reg_x, zero);
6017 rmwWithReg ("rol", hc08_reg_x);
6018 rmwWithReg ("neg", hc08_reg_x);
6019 rmwWithReg ("ror", hc08_reg_a);
6026 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6027 /* the fastest and shortest. */
6028 for (i=0;i<shCount;i++)
6030 rmwWithReg ("asr", hc08_reg_x);
6031 rmwWithReg ("ror", hc08_reg_a);
6035 /*-----------------------------------------------------------------*/
6036 /* XAccRsh - right shift register pair XA by known count */
6037 /*-----------------------------------------------------------------*/
6039 XAccRsh (int shCount, bool sign)
6049 shCount &= 0x000f; // shCount : 0..f
6051 /* if we can beat 2n cycles or bytes for some special case, do it here */
6055 /* bytes cycles reg x reg a carry
6056 ** abcd efgh ijkl mnop ?
6057 ** clra 1 1 abcd efgh 0000 0000 a
6058 ** lslx 1 1 bcde fgh0 0000 0000 a
6059 ** rola 1 1 bcde fgh0 0000 000a 0
6060 ** clrx 1 1 0000 0000 0000 000a 0
6061 ** total: 4 cycles, 4 bytes
6063 loadRegFromConst (hc08_reg_x, zero);
6064 rmwWithReg ("lsl", hc08_reg_x);
6065 rmwWithReg ("rol", hc08_reg_a);
6066 loadRegFromConst (hc08_reg_a, zero);
6070 /* bytes cycles reg x reg a carry
6071 ** abcd efgh ijkl mnop ?
6072 ** clra 1 1 abcd efgh 0000 0000 a
6073 ** lslx 1 1 bcde fgh0 0000 0000 a
6074 ** rola 1 1 bcde fgh0 0000 000a 0
6075 ** lslx 1 1 cdef gh00 0000 000a b
6076 ** rola 1 1 cdef gh00 0000 00ab 0
6077 ** clrx 1 1 0000 0000 0000 00ab 0
6078 ** total: 6 cycles, 6 bytes
6080 loadRegFromConst (hc08_reg_x, zero);
6081 rmwWithReg ("lsl", hc08_reg_x);
6082 rmwWithReg ("rol", hc08_reg_a);
6083 rmwWithReg ("lsl", hc08_reg_x);
6084 rmwWithReg ("rol", hc08_reg_a);
6085 loadRegFromConst (hc08_reg_a, zero);
6094 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6095 AccRsh (shCount-8, FALSE);
6096 loadRegFromConst (hc08_reg_x, zero);
6100 /* bytes cycles reg x reg a carry
6101 ** abcd efgh ijkl mnop ?
6102 ** lsla 1 1 abcd efgh jklm nop0 i
6103 ** txa 1 1 abcd efgh abcd efgh i
6104 ** rola 1 1 abcd efgh bcde fghi a
6105 ** clrx 1 1 0000 0000 bcde fghi a
6106 ** rolx 1 1 0000 000a bcde fghi 0
6107 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
6109 rmwWithReg ("lsl", hc08_reg_a);
6110 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6111 rmwWithReg ("rol", hc08_reg_a);
6112 loadRegFromConst (hc08_reg_x, zero);
6113 rmwWithReg ("rol", hc08_reg_x);
6116 /* bytes cycles reg x reg a carry
6117 ** abcd efgh ijkl mnop ?
6118 ** lsla 1 1 abcd efgh jklm nop0 i
6119 ** rolx 1 1 bcde fghi jklm nop0 a
6120 ** rola 1 1 bcde fghi klmn op0a j
6121 ** rolx 1 1 cdef ghij klmn op0a b
6122 ** rola 1 1 cdef ghij lmno p0ab k
6123 ** and #3 2 2 cdef ghij 0000 00ab k
6124 ** psha 1 2 cdef ghij 0000 00ab k
6125 ** txa 1 1 cdef ghij cdef ghij k
6126 ** pula 1 2 0000 00ab cdef ghij k
6127 ** total: 12 cycles, 10 bytes (beats 12 bytes)
6133 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6134 /* the fastest and shortest. */
6135 for (i=0;i<shCount;i++)
6137 rmwWithReg ("lsr", hc08_reg_x);
6138 rmwWithReg ("ror", hc08_reg_a);
6145 /*-----------------------------------------------------------------*/
6146 /* shiftR1Left2Result - shift right one byte from left to result */
6147 /*-----------------------------------------------------------------*/
6149 shiftR1Left2Result (operand * left, int offl,
6150 operand * result, int offr,
6151 int shCount, int sign)
6153 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6154 /* shift right accumulator */
6155 AccRsh (shCount, sign);
6156 storeRegToAop (hc08_reg_a, AOP (result), offr);
6160 /*-----------------------------------------------------------------*/
6161 /* shiftL1Left2Result - shift left one byte from left to result */
6162 /*-----------------------------------------------------------------*/
6164 shiftL1Left2Result (operand * left, int offl,
6165 operand * result, int offr, int shCount)
6167 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6168 /* shift left accumulator */
6170 storeRegToAop (hc08_reg_a, AOP (result), offr);
6173 /*-----------------------------------------------------------------*/
6174 /* movLeft2Result - move byte from left to result */
6175 /*-----------------------------------------------------------------*/
6177 movLeft2Result (operand * left, int offl,
6178 operand * result, int offr, int sign)
6180 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6182 transferAopAop (AOP (left), offl, AOP (result), offr);
6187 /*-----------------------------------------------------------------*/
6188 /* shiftL2Left2Result - shift left two bytes from left to result */
6189 /*-----------------------------------------------------------------*/
6191 shiftL2Left2Result (operand * left, int offl,
6192 operand * result, int offr, int shCount)
6195 bool needpula = FALSE;
6196 bool needpulx = FALSE;
6198 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6199 needpula = pushRegIfUsed (hc08_reg_a);
6202 if (!IS_AOP_XA (AOP (left)))
6203 needpulx = pushRegIfUsed (hc08_reg_x);
6207 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6212 rmwWithReg ("lsr", hc08_reg_x);
6213 rmwWithReg ("ror", hc08_reg_a);
6214 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6215 rmwWithReg ("clr", hc08_reg_a);
6216 rmwWithReg ("ror", hc08_reg_a);
6219 for (i=0; i<shCount; i++)
6221 rmwWithReg ("lsl", hc08_reg_a);
6222 rmwWithReg ("rol", hc08_reg_x);
6225 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6227 pullOrFreeReg (hc08_reg_x, needpulx);
6228 pullOrFreeReg (hc08_reg_a, needpula);
6234 /*-----------------------------------------------------------------*/
6235 /* shiftR2Left2Result - shift right two bytes from left to result */
6236 /*-----------------------------------------------------------------*/
6238 shiftR2Left2Result (operand * left, int offl,
6239 operand * result, int offr,
6240 int shCount, int sign)
6243 bool needpula = FALSE;
6244 bool needpulx = FALSE;
6246 needpula = pushRegIfUsed (hc08_reg_a);
6247 needpulx = pushRegIfUsed (hc08_reg_x);
6249 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6250 for (i=0; i<shCount; i++)
6253 rmwWithReg ("asr", hc08_reg_x);
6255 rmwWithReg ("lsr", hc08_reg_x);
6256 rmwWithReg ("ror", hc08_reg_a);
6258 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6260 pullOrFreeReg (hc08_reg_x, needpulx);
6261 pullOrFreeReg (hc08_reg_a, needpula);
6266 /*-----------------------------------------------------------------*/
6267 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6268 /*-----------------------------------------------------------------*/
6270 shiftLLeftOrResult (operand * left, int offl,
6271 operand * result, int offr, int shCount)
6273 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6274 /* shift left accumulator */
6276 /* or with result */
6277 accopWithAop ("ora", AOP (result), offr);
6278 /* back to result */
6279 storeRegToAop (hc08_reg_a, AOP (result), offr);
6280 hc08_freeReg (hc08_reg_a);
6284 /*-----------------------------------------------------------------*/
6285 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6286 /*-----------------------------------------------------------------*/
6288 shiftRLeftOrResult (operand * left, int offl,
6289 operand * result, int offr, int shCount)
6291 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6292 /* shift left accumulator */
6293 AccRsh (shCount, FALSE);
6294 /* or with result */
6295 accopWithAop ("ora", AOP (result), offr);
6296 /* back to result */
6297 storeRegToAop (hc08_reg_a, AOP (result), offr);
6298 hc08_freeReg (hc08_reg_a);
6301 /*-----------------------------------------------------------------*/
6302 /* genlshOne - left shift a one byte quantity by known count */
6303 /*-----------------------------------------------------------------*/
6305 genlshOne (operand * result, operand * left, int shCount)
6307 D(emitcode ("; genlshOne",""));
6309 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6312 /*-----------------------------------------------------------------*/
6313 /* genlshTwo - left shift two bytes by known amount != 0 */
6314 /*-----------------------------------------------------------------*/
6316 genlshTwo (operand * result, operand * left, int shCount)
6320 D(emitcode ("; genlshTwo",""));
6323 size = getDataSize (result);
6325 /* if shCount >= 8 */
6332 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6334 storeRegToAop (hc08_reg_a, AOP (result), 1);
6336 storeConstToAop(zero, AOP (result), LSB);
6339 /* 1 <= shCount <= 7 */
6342 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6344 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6348 /*-----------------------------------------------------------------*/
6349 /* shiftLLong - shift left one long from left to result */
6350 /* offr = LSB or MSB16 */
6351 /*-----------------------------------------------------------------*/
6353 shiftLLong (operand * left, operand * result, int offr)
6356 // int size = AOP_SIZE (result);
6358 bool needpula = FALSE;
6359 bool needpulx = FALSE;
6361 needpula = pushRegIfUsed (hc08_reg_a);
6362 needpulx = pushRegIfUsed (hc08_reg_x);
6364 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6365 rmwWithReg ("lsl", hc08_reg_a);
6366 rmwWithReg ("rol", hc08_reg_x);
6370 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6371 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6372 rmwWithReg ("rol", hc08_reg_a);
6373 rmwWithReg ("rol", hc08_reg_x);
6374 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6376 else if (offr==MSB16)
6378 storeRegToAop (hc08_reg_a, AOP (result), offr);
6379 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6380 storeRegToAop (hc08_reg_x, AOP (result), offr+1);
6381 rmwWithReg ("rol", hc08_reg_a);
6382 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6383 storeConstToAop (zero, AOP (result), 0);
6386 pullOrFreeReg (hc08_reg_x, needpulx);
6387 pullOrFreeReg (hc08_reg_a, needpula);
6390 /*-----------------------------------------------------------------*/
6391 /* genlshFour - shift four byte by a known amount != 0 */
6392 /*-----------------------------------------------------------------*/
6394 genlshFour (operand * result, operand * left, int shCount)
6398 D(emitcode ("; genlshFour",""));
6400 size = AOP_SIZE (result);
6402 /* TODO: deal with the &result == &left case */
6404 /* if shifting more that 3 bytes */
6409 /* lowest order of left goes to the highest
6410 order of the destination */
6411 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6413 movLeft2Result (left, LSB, result, MSB32, 0);
6414 storeConstToAop (zero, AOP (result), LSB);
6415 storeConstToAop (zero, AOP (result), MSB16);
6416 storeConstToAop (zero, AOP (result), MSB24);
6420 /* more than two bytes */
6421 else if (shCount >= 16)
6423 /* lower order two bytes goes to higher order two bytes */
6425 /* if some more remaining */
6427 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6430 movLeft2Result (left, MSB16, result, MSB32, 0);
6431 movLeft2Result (left, LSB, result, MSB24, 0);
6433 storeConstToAop (zero, AOP (result), LSB);
6434 storeConstToAop (zero, AOP (result), MSB16);
6438 /* if more than 1 byte */
6439 else if (shCount >= 8)
6441 /* lower order three bytes goes to higher order three bytes */
6446 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6448 movLeft2Result (left, LSB, result, MSB16, 0);
6454 movLeft2Result (left, MSB24, result, MSB32, 0);
6455 movLeft2Result (left, MSB16, result, MSB24, 0);
6456 movLeft2Result (left, LSB, result, MSB16, 0);
6457 storeConstToAop (zero, AOP (result), LSB);
6459 else if (shCount == 1)
6460 shiftLLong (left, result, MSB16);
6463 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6464 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6465 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6466 storeConstToAop (zero, AOP (result), LSB);
6471 /* 1 <= shCount <= 7 */
6472 else if (shCount <= 2)
6474 shiftLLong (left, result, LSB);
6476 shiftLLong (result, result, LSB);
6478 /* 3 <= shCount <= 7, optimize */
6481 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6482 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6483 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6487 /*-----------------------------------------------------------------*/
6488 /* genLeftShiftLiteral - left shifting by known count */
6489 /*-----------------------------------------------------------------*/
6491 genLeftShiftLiteral (operand * left,
6496 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6499 D(emitcode ("; genLeftShiftLiteral",""));
6501 freeAsmop (right, NULL, ic, TRUE);
6503 aopOp (left, ic, FALSE);
6504 aopOp (result, ic, FALSE);
6506 // size = getSize (operandType (result));
6507 size = AOP_SIZE (result);
6510 DD(emitcode ("; shift left ", "result %d, left %d", size,
6517 transferAopAop( AOP(left), size, AOP(result), size);
6519 else if (shCount >= (size * 8))
6522 storeConstToAop (zero, AOP (result), size);
6529 genlshOne (result, left, shCount);
6533 genlshTwo (result, left, shCount);
6537 genlshFour (result, left, shCount);
6540 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6541 "*** ack! mystery literal shift!\n");
6545 freeAsmop (left, NULL, ic, TRUE);
6546 freeAsmop (result, NULL, ic, TRUE);
6549 /*-----------------------------------------------------------------*/
6550 /* genLeftShift - generates code for left shifting */
6551 /*-----------------------------------------------------------------*/
6553 genLeftShift (iCode * ic)
6555 operand *left, *right, *result;
6557 symbol *tlbl, *tlbl1;
6561 D(emitcode ("; genLeftShift",""));
6563 right = IC_RIGHT (ic);
6564 left = IC_LEFT (ic);
6565 result = IC_RESULT (ic);
6567 aopOp (right, ic, FALSE);
6569 /* if the shift count is known then do it
6570 as efficiently as possible */
6571 if (AOP_TYPE (right) == AOP_LIT)
6573 genLeftShiftLiteral (left, right, result, ic);
6577 /* shift count is unknown then we have to form
6578 a loop get the loop count in X : Note: we take
6579 only the lower order byte since shifting
6580 more that 32 bits make no sense anyway, ( the
6581 largest size of an object can be only 32 bits ) */
6583 aopOp (result, ic, FALSE);
6584 aopOp (left, ic, FALSE);
6585 aopResult = AOP (result);
6587 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result))
6588 || isOperandVolatile (result, FALSE))
6589 aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result)));
6591 /* now move the left to the result if they are not the
6593 if (!sameRegs (AOP (left), aopResult))
6595 size = AOP_SIZE (result);
6599 transferAopAop (AOP (left), offset, aopResult, offset);
6603 freeAsmop (left, NULL, ic, TRUE);
6604 AOP (result) = aopResult;
6606 tlbl = newiTempLabel (NULL);
6607 size = AOP_SIZE (result);
6609 tlbl1 = newiTempLabel (NULL);
6611 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6612 emitcode ("tstx", "");
6613 emitBranch ("beq", tlbl1);
6617 for (offset=0;offset<size;offset++)
6619 rmwWithAop (shift, AOP (result), offset);
6622 rmwWithReg ("dec", hc08_reg_x);
6623 emitBranch ("bne", tlbl);
6625 hc08_freeReg (hc08_reg_x);
6627 freeAsmop (result, NULL, ic, TRUE);
6628 freeAsmop (right, NULL, ic, TRUE);
6631 /*-----------------------------------------------------------------*/
6632 /* genrshOne - right shift a one byte quantity by known count */
6633 /*-----------------------------------------------------------------*/
6635 genrshOne (operand * result, operand * left,
6636 int shCount, int sign)
6638 D(emitcode ("; genrshOne",""));
6640 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6641 AccRsh (shCount, sign);
6642 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6645 /*-----------------------------------------------------------------*/
6646 /* genrshTwo - right shift two bytes by known amount != 0 */
6647 /*-----------------------------------------------------------------*/
6649 genrshTwo (operand * result, operand * left,
6650 int shCount, int sign)
6652 D(emitcode ("; genrshTwo",""));
6654 /* if shCount >= 8 */
6657 if (shCount || sign)
6659 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6660 AccRsh (shCount-8, sign);
6661 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6665 transferAopAop (AOP (left), 1, AOP (result), 0);
6666 storeConstToAop (zero, AOP (result), 1);
6670 /* 1 <= shCount <= 7 */
6673 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6674 XAccRsh (shCount, sign);
6675 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6679 /*-----------------------------------------------------------------*/
6680 /* shiftRLong - shift right one long from left to result */
6681 /* offl = LSB or MSB16 */
6682 /*-----------------------------------------------------------------*/
6684 shiftRLong (operand * left, int offl,
6685 operand * result, int sign)
6688 // int size = AOP_SIZE (result);
6690 bool needpula = FALSE;
6691 bool needpulx = FALSE;
6693 needpula = pushRegIfUsed (hc08_reg_a);
6694 needpulx = pushRegIfUsed (hc08_reg_x);
6698 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6700 rmwWithReg ("asr", hc08_reg_x);
6702 rmwWithReg ("lsr", hc08_reg_x);
6703 rmwWithReg ("ror", hc08_reg_a);
6704 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6705 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6707 else if (offl==MSB16)
6709 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6711 rmwWithReg ("asr", hc08_reg_a);
6713 rmwWithReg ("lsr", hc08_reg_a);
6714 loadRegFromAop (hc08_reg_x, AOP (left), MSB24);
6715 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6716 loadRegFromAop (hc08_reg_a, AOP (left), MSB16);
6719 rmwWithReg ("ror", hc08_reg_x);
6720 rmwWithReg ("ror", hc08_reg_a);
6721 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6727 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6728 storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
6732 storeConstToAop (zero, AOP (result), MSB32);
6736 pullOrFreeReg (hc08_reg_x, needpulx);
6737 pullOrFreeReg (hc08_reg_a, needpula);
6740 /*-----------------------------------------------------------------*/
6741 /* genrshFour - shift four byte by a known amount != 0 */
6742 /*-----------------------------------------------------------------*/
6744 genrshFour (operand * result, operand * left,
6745 int shCount, int sign)
6747 /* TODO: handle cases where left == result */
6749 D(emitcode ("; genrshFour",""));
6751 /* if shifting more that 3 bytes */
6754 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6755 AccRsh (shCount-24, sign);
6756 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6759 else if (shCount >= 16)
6761 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6762 XAccRsh (shCount-16, sign);
6763 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6766 else if (shCount >= 8)
6769 shiftRLong (left, MSB16, result, sign);
6770 else if (shCount == 8)
6772 transferAopAop (AOP (left), 1, AOP (result), 0);
6773 transferAopAop (AOP (left), 2, AOP (result), 1);
6774 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6775 storeRegToAop (hc08_reg_a, AOP (result), 2);
6776 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6778 else if (shCount == 9)
6780 shiftRLong (left, MSB16, result, sign);
6784 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6785 XAccRsh (shCount-8, FALSE);
6786 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6787 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6788 loadRegFromConst (hc08_reg_a, zero);
6789 XAccRsh (shCount-8, sign);
6790 accopWithAop ("ora", AOP (result), 1);
6791 storeRegToAop (hc08_reg_xa, AOP (result), 1);
6792 storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
6796 { /* 1 <= shCount <= 7 */
6799 shiftRLong (left, LSB, result, sign);
6803 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6804 XAccRsh (shCount, FALSE);
6805 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6806 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6808 accopWithAop ("ora", AOP (result), 1);
6809 storeRegToAop (hc08_reg_a, AOP (result), 1);
6810 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6811 XAccRsh (shCount, sign);
6812 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6817 /*-----------------------------------------------------------------*/
6818 /* genRightShiftLiteral - right shifting by known count */
6819 /*-----------------------------------------------------------------*/
6821 genRightShiftLiteral (operand * left,
6827 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6830 D(emitcode ("; genRightShiftLiteral",""));
6832 freeAsmop (right, NULL, ic, TRUE);
6834 aopOp (left, ic, FALSE);
6835 aopOp (result, ic, FALSE);
6838 DD(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6842 size = getDataSize (left);
6843 /* test the LEFT size !!! */
6845 /* I suppose that the left size >= result size */
6848 size = getDataSize (result);
6850 transferAopAop (AOP (left), size, AOP(result), size);
6852 else if (shCount >= (size * 8))
6855 /* get sign in acc.7 */
6856 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6858 addSign (result, LSB, sign);
6865 genrshOne (result, left, shCount, sign);
6869 genrshTwo (result, left, shCount, sign);
6873 genrshFour (result, left, shCount, sign);
6879 freeAsmop (left, NULL, ic, TRUE);
6880 freeAsmop (result, NULL, ic, TRUE);
6884 /*-----------------------------------------------------------------*/
6885 /* genRightShift - generate code for right shifting */
6886 /*-----------------------------------------------------------------*/
6888 genRightShift (iCode * ic)
6890 operand *right, *left, *result;
6893 symbol *tlbl, *tlbl1;
6898 D(emitcode ("; genRightShift",""));
6900 /* if signed then we do it the hard way preserve the
6901 sign bit moving it inwards */
6902 retype = getSpec (operandType (IC_RESULT (ic)));
6903 sign = !SPEC_USIGN (retype);
6905 /* signed & unsigned types are treated the same : i.e. the
6906 signed is NOT propagated inwards : quoting from the
6907 ANSI - standard : "for E1 >> E2, is equivalent to division
6908 by 2**E2 if unsigned or if it has a non-negative value,
6909 otherwise the result is implementation defined ", MY definition
6910 is that the sign does not get propagated */
6912 right = IC_RIGHT (ic);
6913 left = IC_LEFT (ic);
6914 result = IC_RESULT (ic);
6916 aopOp (right, ic, FALSE);
6918 /* if the shift count is known then do it
6919 as efficiently as possible */
6920 if (AOP_TYPE (right) == AOP_LIT)
6922 genRightShiftLiteral (left, right, result, ic, sign);
6926 /* shift count is unknown then we have to form
6927 a loop get the loop count in X : Note: we take
6928 only the lower order byte since shifting
6929 more that 32 bits make no sense anyway, ( the
6930 largest size of an object can be only 32 bits ) */
6932 aopOp (result, ic, FALSE);
6933 aopOp (left, ic, FALSE);
6934 aopResult = AOP (result);
6936 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result))
6937 || isOperandVolatile (result, FALSE))
6938 aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result)));
6940 /* now move the left to the result if they are not the
6942 if (!sameRegs (AOP (left), aopResult))
6944 size = AOP_SIZE (result);
6948 transferAopAop (AOP (left), offset, aopResult, offset);
6952 freeAsmop (left, NULL, ic, TRUE);
6953 AOP (result) = aopResult;
6955 tlbl = newiTempLabel (NULL);
6956 size = AOP_SIZE (result);
6958 tlbl1 = newiTempLabel (NULL);
6960 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6961 emitcode ("tstx", "");
6962 emitBranch ("beq", tlbl1);
6965 shift= sign ? "asr" : "lsr";
6966 for (offset=size-1;offset>=0;offset--)
6968 rmwWithAop (shift, AOP (result), offset);
6971 rmwWithReg ("dec", hc08_reg_x);
6972 emitBranch ("bne", tlbl);
6974 hc08_freeReg (hc08_reg_x);
6976 freeAsmop (result, NULL, ic, TRUE);
6977 freeAsmop (right, NULL, ic, TRUE);
6981 /*-----------------------------------------------------------------*/
6982 /* genUnpackBits - generates code for unpacking bits */
6983 /*-----------------------------------------------------------------*/
6985 genUnpackBits (operand * result, iCode *ifx)
6987 int offset = 0; /* result byte offset */
6988 int rsize; /* result size */
6989 int rlen = 0; /* remaining bitfield length */
6990 sym_link *etype; /* bitfield type information */
6991 int blen; /* bitfield length */
6992 int bstr; /* bitfield starting bit within byte */
6994 D(emitcode ("; genUnpackBits",""));
6996 etype = getSpec (operandType (result));
6997 rsize = getSize (operandType (result));
6998 blen = SPEC_BLEN (etype);
6999 bstr = SPEC_BSTR (etype);
7001 if (ifx && blen <= 8)
7003 emitcode ("lda", ",x");
7004 hc08_dirtyReg (hc08_reg_a, FALSE);
7007 emitcode ("and", "#0x%02x",
7008 (((unsigned char) -1) >> (8 - blen)) << bstr);
7010 genIfxJump (ifx, "a");
7015 /* If the bitfield length is less than a byte */
7018 emitcode ("lda", ",x");
7019 hc08_dirtyReg (hc08_reg_a, FALSE);
7020 AccRsh (bstr, FALSE);
7021 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7022 if (!SPEC_USIGN (etype))
7024 /* signed bitfield */
7025 symbol *tlbl = newiTempLabel (NULL);
7027 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7028 emitcode ("beq", "%05d$", tlbl->key + 100);
7029 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7032 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7036 /* Bit field did not fit in a byte. Copy all
7037 but the partial byte at the end. */
7038 for (rlen=blen;rlen>=8;rlen-=8)
7040 emitcode ("lda", ",x");
7041 hc08_dirtyReg (hc08_reg_a, FALSE);
7042 storeRegToAop (hc08_reg_a, AOP (result), offset);
7045 emitcode ("aix", "#1");
7048 /* Handle the partial byte at the end */
7051 emitcode ("lda", ",x");
7052 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7053 if (!SPEC_USIGN (etype))
7055 /* signed bitfield */
7056 symbol *tlbl = newiTempLabel (NULL);
7058 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7059 emitcode ("beq", "%05d$", tlbl->key + 100);
7060 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7063 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7070 if (SPEC_USIGN (etype))
7073 storeConstToAop (zero, AOP (result), offset++);
7077 /* signed bitfield: sign extension with 0x00 or 0xff */
7078 emitcode ("rola", "");
7079 emitcode ("clra", "");
7080 emitcode ("sbc", zero);
7083 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7089 /*-----------------------------------------------------------------*/
7090 /* genUnpackBitsImmed - generates code for unpacking bits */
7091 /*-----------------------------------------------------------------*/
7093 genUnpackBitsImmed (operand * left,
7099 int offset = 0; /* result byte offset */
7100 int rsize; /* result size */
7101 int rlen = 0; /* remaining bitfield length */
7102 sym_link *etype; /* bitfield type information */
7103 int blen; /* bitfield length */
7104 int bstr; /* bitfield starting bit within byte */
7107 D(emitcode ("; genUnpackBitsImmed",""));
7109 aopOp (result, ic, TRUE);
7110 size = AOP_SIZE (result);
7112 derefaop = aopDerefAop (AOP (left));
7113 freeAsmop (left, NULL, ic, TRUE);
7114 derefaop->size = size;
7116 etype = getSpec (operandType (result));
7117 rsize = getSize (operandType (result));
7118 blen = SPEC_BLEN (etype);
7119 bstr = SPEC_BSTR (etype);
7121 /* if the bitfield is a single bit in the direct page */
7122 if (blen == 1 && derefaop->type == AOP_DIR)
7126 symbol *tlbl = newiTempLabel (NULL);
7128 loadRegFromConst (hc08_reg_a, zero);
7129 emitcode ("brclr", "#%d,%s,%05d$",
7130 bstr, aopAdrStr (derefaop, 0, FALSE),
7132 if (SPEC_USIGN (etype))
7133 rmwWithReg ("inc", hc08_reg_a);
7135 rmwWithReg ("dec", hc08_reg_a);
7137 storeRegToAop (hc08_reg_a, AOP (result), offset);
7138 hc08_freeReg (hc08_reg_a);
7144 symbol *tlbl = newiTempLabel (NULL);
7150 jlbl = IC_TRUE (ifx);
7155 jlbl = IC_FALSE (ifx);
7158 emitcode (inst, "#%d,%s,%05d$",
7159 bstr, aopAdrStr (derefaop, 0, FALSE),
7161 emitBranch ("jmp", jlbl);
7169 /* If the bitfield length is less than a byte */
7172 loadRegFromAop (hc08_reg_a, derefaop, 0);
7175 AccRsh (bstr, FALSE);
7176 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7177 hc08_dirtyReg (hc08_reg_a, FALSE);
7178 if (!SPEC_USIGN (etype))
7180 /* signed bitfield */
7181 symbol *tlbl = newiTempLabel (NULL);
7183 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7184 emitcode ("beq", "%05d$", tlbl->key + 100);
7185 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7188 storeRegToAop (hc08_reg_a, AOP (result), offset);
7192 emitcode ("and", "#0x%02x",
7193 (((unsigned char) -1) >> (8 - blen)) << bstr);
7194 hc08_dirtyReg (hc08_reg_a, FALSE);
7200 /* Bit field did not fit in a byte. Copy all
7201 but the partial byte at the end. */
7202 for (rlen=blen;rlen>=8;rlen-=8)
7204 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7206 storeRegToAop (hc08_reg_a, AOP (result), offset);
7208 emitcode ("tsta", "");
7212 /* Handle the partial byte at the end */
7215 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7216 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7217 if (!SPEC_USIGN (etype))
7219 /* signed bitfield */
7220 symbol *tlbl = newiTempLabel (NULL);
7222 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7223 emitcode ("beq", "%05d$", tlbl->key + 100);
7224 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7227 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7234 if (SPEC_USIGN (etype))
7237 storeConstToAop (zero, AOP (result), offset++);
7241 /* signed bitfield: sign extension with 0x00 or 0xff */
7242 emitcode ("rola", "");
7243 emitcode ("clra", "");
7244 emitcode ("sbc", zero);
7247 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7251 freeAsmop (NULL, derefaop, ic, TRUE);
7252 freeAsmop (result, NULL, ic, TRUE);
7254 if (ifx && !ifx->generated)
7256 genIfxJump (ifx, "a");
7261 /*-----------------------------------------------------------------*/
7262 /* genDataPointerGet - generates code when ptr offset is known */
7263 /*-----------------------------------------------------------------*/
7265 genDataPointerGet (operand * left,
7273 D(emitcode ("; genDataPointerGet",""));
7275 aopOp (result, ic, TRUE);
7276 size = AOP_SIZE (result);
7278 derefaop = aopDerefAop (AOP (left));
7279 freeAsmop (left, NULL, ic, TRUE);
7280 derefaop->size = size;
7285 transferAopAop (derefaop, size, AOP (result), size);
7287 loadRegFromAop (hc08_reg_a, derefaop, size);
7290 freeAsmop (NULL, derefaop, ic, TRUE);
7291 freeAsmop (result, NULL, ic, TRUE);
7293 if (ifx && !ifx->generated)
7295 genIfxJump (ifx, "a");
7300 /*-----------------------------------------------------------------*/
7301 /* genPointerGet - generate code for pointer get */
7302 /*-----------------------------------------------------------------*/
7304 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7306 operand *left = IC_LEFT (ic);
7307 operand *result = IC_RESULT (ic);
7309 sym_link *retype = getSpec (operandType (result));
7311 D(emitcode ("; genPointerGet",""));
7313 if (getSize (operandType (result))>1)
7316 aopOp (left, ic, FALSE);
7318 /* if left is rematerialisable and
7319 result is not bit variable type */
7320 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7322 if (!IS_BITVAR (retype))
7324 genDataPointerGet (left, result, ic, ifx);
7329 genUnpackBitsImmed (left, result, ic, ifx);
7334 /* if the operand is already in hx
7335 then we do nothing else we move the value to hx */
7336 if (AOP_TYPE (left) != AOP_STR)
7338 /* if this is remateriazable */
7339 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7342 /* so hx now contains the address */
7343 aopOp (result, ic, FALSE);
7345 /* if bit then unpack */
7346 if (IS_BITVAR (retype))
7347 genUnpackBits (result, ifx);
7350 size = AOP_SIZE (result);
7355 accopWithMisc ("lda", ",x");
7358 emitcode ("aix", "#1");
7359 hc08_dirtyReg (hc08_reg_hx, FALSE);
7362 storeRegToAop (hc08_reg_a, AOP (result), offset);
7364 hc08_freeReg (hc08_reg_a);
7368 freeAsmop (left, NULL, ic, TRUE);
7369 freeAsmop (result, NULL, ic, TRUE);
7372 aopOp (IC_RESULT (pi), pi, FALSE);
7373 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7374 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7378 if (ifx && !ifx->generated)
7380 genIfxJump (ifx, "a");
7383 hc08_freeReg (hc08_reg_hx);
7387 /*-----------------------------------------------------------------*/
7388 /* genPackBits - generates code for packed bit storage */
7389 /*-----------------------------------------------------------------*/
7391 genPackBits (sym_link * etype,
7394 int offset = 0; /* source byte offset */
7395 int rlen = 0; /* remaining bitfield length */
7396 int blen; /* bitfield length */
7397 int bstr; /* bitfield starting bit within byte */
7398 int litval; /* source literal value (if AOP_LIT) */
7399 unsigned char mask; /* bitmask within current byte */
7402 D(emitcode ("; genPackBits",""));
7404 blen = SPEC_BLEN (etype);
7405 bstr = SPEC_BSTR (etype);
7407 /* If the bitfield length is less than a byte */
7410 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7411 (unsigned char) (0xFF >> (8 - bstr)));
7413 if (AOP_TYPE (right) == AOP_LIT)
7415 /* Case with a bitfield length <8 and literal source
7417 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7419 litval &= (~mask) & 0xff;
7421 emitcode ("lda", ",x");
7422 if ((mask|litval)!=0xff)
7423 emitcode ("and","#0x%02x", mask);
7425 emitcode ("ora","#0x%02x", litval);
7426 hc08_dirtyReg (hc08_reg_a, FALSE);
7427 emitcode ("sta", ",x");
7429 hc08_freeReg (hc08_reg_a);
7433 /* Case with a bitfield length < 8 and arbitrary source
7435 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7436 /* shift and mask source value */
7438 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7439 hc08_dirtyReg (hc08_reg_a, FALSE);
7440 pushReg (hc08_reg_a, TRUE);
7442 emitcode ("lda", ",x");
7443 emitcode ("and", "#0x%02x", mask);
7444 emitcode ("ora", "1,s");
7445 emitcode ("sta", ",x");
7446 pullReg (hc08_reg_a);
7448 hc08_freeReg (hc08_reg_a);
7452 /* Bit length is greater than 7 bits. In this case, copy */
7453 /* all except the partial byte at the end */
7454 for (rlen=blen;rlen>=8;rlen-=8)
7456 if (AOP (right)->type == AOP_DIR)
7458 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7463 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7464 emitcode ("sta", "%d,x", offset);
7469 /* If there was a partial byte at the end */
7472 mask = (((unsigned char) -1 << rlen) & 0xff);
7474 if (AOP_TYPE (right) == AOP_LIT)
7476 /* Case with partial byte and literal source
7478 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7479 litval >>= (blen-rlen);
7480 litval &= (~mask) & 0xff;
7481 emitcode ("lda", "%d,x", offset - xoffset);
7482 hc08_dirtyReg (hc08_reg_a, FALSE);
7483 if ((mask|litval)!=0xff)
7484 emitcode ("and","#0x%02x", mask);
7486 emitcode ("ora","#0x%02x", litval);
7487 emitcode ("sta", "%d,x", offset - xoffset);
7488 hc08_dirtyReg (hc08_reg_a, FALSE);
7489 hc08_freeReg (hc08_reg_a);
7493 /* Case with partial byte and arbitrary source
7495 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7496 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7497 hc08_dirtyReg (hc08_reg_a, FALSE);
7498 pushReg (hc08_reg_a, TRUE);
7500 emitcode ("lda", "%d,x", offset - xoffset);
7501 emitcode ("and", "#0x%02x", mask);
7502 emitcode ("ora", "1,s");
7503 emitcode ("sta", "%d,x", offset - xoffset);
7504 pullReg (hc08_reg_a);
7507 hc08_freeReg (hc08_reg_a);
7510 /*-----------------------------------------------------------------*/
7511 /* genPackBitsImmed - generates code for packed bit storage */
7512 /*-----------------------------------------------------------------*/
7514 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7518 int offset = 0; /* source byte offset */
7519 int rlen = 0; /* remaining bitfield length */
7520 int blen; /* bitfield length */
7521 int bstr; /* bitfield starting bit within byte */
7522 int litval; /* source literal value (if AOP_LIT) */
7523 unsigned char mask; /* bitmask within current byte */
7525 D(emitcode ("; genPackBitsImmed",""));
7527 blen = SPEC_BLEN (etype);
7528 bstr = SPEC_BSTR (etype);
7530 aopOp (right, ic, FALSE);
7531 size = AOP_SIZE (right);
7533 derefaop = aopDerefAop (AOP (result));
7534 freeAsmop (result, NULL, ic, TRUE);
7535 derefaop->size = size;
7537 /* if the bitfield is a single bit in the direct page */
7538 if (blen == 1 && derefaop->type == AOP_DIR)
7540 if (AOP_TYPE (right) == AOP_LIT)
7542 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7544 emitcode ((litval & 1) ? "bset" : "bclr",
7545 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7549 symbol *tlbl1 = newiTempLabel (NULL);
7550 symbol *tlbl2 = newiTempLabel (NULL);
7552 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7553 emitcode ("bit", "#1");
7554 emitBranch ("bne", tlbl1);
7555 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7556 emitBranch ("bra", tlbl2);
7558 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7560 hc08_freeReg (hc08_reg_a);
7565 /* If the bitfield length is less than a byte */
7568 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7569 (unsigned char) (0xFF >> (8 - bstr)));
7571 if (AOP_TYPE (right) == AOP_LIT)
7573 /* Case with a bitfield length <8 and literal source
7575 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7577 litval &= (~mask) & 0xff;
7579 loadRegFromAop (hc08_reg_a, derefaop, 0);
7580 if ((mask|litval)!=0xff)
7581 emitcode ("and","#0x%02x", mask);
7583 emitcode ("ora","#0x%02x", litval);
7584 hc08_dirtyReg (hc08_reg_a, FALSE);
7585 storeRegToAop (hc08_reg_a, derefaop, 0);
7587 hc08_freeReg (hc08_reg_a);
7591 /* Case with a bitfield length < 8 and arbitrary source
7593 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7594 /* shift and mask source value */
7596 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7597 hc08_dirtyReg (hc08_reg_a, FALSE);
7598 pushReg (hc08_reg_a, TRUE);
7600 loadRegFromAop (hc08_reg_a, derefaop, 0);
7601 emitcode ("and", "#0x%02x", mask);
7602 emitcode ("ora", "1,s");
7603 storeRegToAop (hc08_reg_a, derefaop, 0);
7604 pullReg (hc08_reg_a);
7606 hc08_freeReg (hc08_reg_a);
7610 /* Bit length is greater than 7 bits. In this case, copy */
7611 /* all except the partial byte at the end */
7612 for (rlen=blen;rlen>=8;rlen-=8)
7614 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7618 /* If there was a partial byte at the end */
7621 mask = (((unsigned char) -1 << rlen) & 0xff);
7623 if (AOP_TYPE (right) == AOP_LIT)
7625 /* Case with partial byte and literal source
7627 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7628 litval >>= (blen-rlen);
7629 litval &= (~mask) & 0xff;
7630 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7631 if ((mask|litval)!=0xff)
7632 emitcode ("and","#0x%02x", mask);
7634 emitcode ("ora","#0x%02x", litval);
7635 hc08_dirtyReg (hc08_reg_a, FALSE);
7636 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7637 hc08_dirtyReg (hc08_reg_a, FALSE);
7638 hc08_freeReg (hc08_reg_a);
7642 /* Case with partial byte and arbitrary source
7644 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7645 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7646 hc08_dirtyReg (hc08_reg_a, FALSE);
7647 pushReg (hc08_reg_a, TRUE);
7649 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7650 emitcode ("and", "#0x%02x", mask);
7651 emitcode ("ora", "1,s");
7652 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7653 pullReg (hc08_reg_a);
7656 hc08_freeReg (hc08_reg_a);
7659 freeAsmop (right, NULL, ic, TRUE);
7660 freeAsmop (NULL, derefaop, ic, TRUE);
7663 /*-----------------------------------------------------------------*/
7664 /* genDataPointerSet - remat pointer to data space */
7665 /*-----------------------------------------------------------------*/
7667 genDataPointerSet (operand * right,
7674 D(emitcode ("; genDataPointerSet",""));
7676 aopOp (right, ic, FALSE);
7677 size = AOP_SIZE (right);
7679 derefaop = aopDerefAop (AOP (result));
7680 freeAsmop (result, NULL, ic, TRUE);
7681 derefaop->size = size;
7685 transferAopAop (AOP (right), size, derefaop, size);
7688 freeAsmop (right, NULL, ic, TRUE);
7689 freeAsmop (NULL, derefaop, ic, TRUE);
7693 /*-----------------------------------------------------------------*/
7694 /* genPointerSet - stores the value into a pointer location */
7695 /*-----------------------------------------------------------------*/
7697 genPointerSet (iCode * ic, iCode *pi)
7699 operand *right = IC_RIGHT (ic);
7700 operand *result = IC_RESULT (ic);
7701 sym_link *type, *etype;
7703 sym_link *retype = getSpec (operandType (right));
7704 sym_link *letype = getSpec (operandType (result));
7706 D(emitcode ("; genPointerSet",""));
7708 type = operandType (result);
7709 etype = getSpec (type);
7711 aopOp (result, ic, FALSE);
7713 /* if the result is rematerializable */
7714 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7716 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7718 genDataPointerSet (right, result, ic);
7723 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7728 /* if the operand is already in hx
7729 then we do nothing else we move the value to hx */
7730 if (AOP_TYPE (result) != AOP_STR)
7732 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7734 /* so hx now contains the address */
7735 aopOp (right, ic, FALSE);
7737 /* if bit then unpack */
7738 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7739 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7742 size = AOP_SIZE (right);
7747 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7748 accopWithMisc ("sta", ",x");
7751 emitcode ("aix", "#1");
7753 hc08_freeReg (hc08_reg_a);
7757 freeAsmop (result, NULL, ic, TRUE);
7758 freeAsmop (right, NULL, ic, TRUE);
7761 aopOp (IC_RESULT (pi), pi, FALSE);
7762 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7763 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7767 hc08_freeReg (hc08_reg_hx);
7771 /*-----------------------------------------------------------------*/
7772 /* genIfx - generate code for Ifx statement */
7773 /*-----------------------------------------------------------------*/
7775 genIfx (iCode * ic, iCode * popIc)
7777 operand *cond = IC_COND (ic);
7780 D(emitcode ("; genIfx",""));
7782 aopOp (cond, ic, FALSE);
7784 /* If the condition is a literal, we can just do an unconditional */
7785 /* branch or no branch */
7786 if (AOP_TYPE (cond) == AOP_LIT)
7788 unsigned long lit = (unsigned long) floatFromVal (AOP (cond)->aopu.aop_lit);
7789 freeAsmop (cond, NULL, ic, TRUE);
7791 /* if there was something to be popped then do it */
7797 emitBranch ("jmp", IC_TRUE (ic));
7802 emitBranch ("jmp", IC_FALSE (ic));
7808 /* get the value into acc */
7809 if (AOP_TYPE (cond) != AOP_CRY)
7810 asmopToBool (AOP (cond), FALSE);
7813 /* the result is now in the accumulator */
7814 freeAsmop (cond, NULL, ic, TRUE);
7816 /* if there was something to be popped then do it */
7820 /* if the condition is a bit variable */
7821 if (isbit && IS_ITEMP (cond) &&
7823 genIfxJump (ic, SPIL_LOC (cond)->rname);
7824 else if (isbit && !IS_ITEMP (cond))
7825 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7827 genIfxJump (ic, "a");
7832 /*-----------------------------------------------------------------*/
7833 /* genAddrOf - generates code for address of */
7834 /*-----------------------------------------------------------------*/
7836 genAddrOf (iCode * ic)
7838 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7841 D(emitcode ("; genAddrOf",""));
7843 aopOp (IC_RESULT (ic), ic, FALSE);
7845 /* if the operand is on the stack then we
7846 need to get the stack offset of this
7850 /* if it has an offset then we need to compute it */
7851 offset = _G.stackOfs + _G.stackPushes + sym->stack;
7852 hc08_useReg (hc08_reg_hx);
7853 emitcode ("tsx", "");
7854 while (offset > 127)
7856 emitcode ("aix", "#127");
7859 while (offset < -128)
7861 emitcode ("aix", "#-128");
7864 emitcode ("aix", "#%d", offset);
7865 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7866 hc08_freeReg (hc08_reg_hx);
7871 /* object not on stack then we need the name */
7872 size = AOP_SIZE (IC_RESULT (ic));
7877 char s[SDCC_NAME_MAX+10];
7880 sprintf (s, "#%s", sym->rname);
7883 sprintf (s, "#>%s", sym->rname);
7886 sprintf (s, "#(%s >> %d)",
7890 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7894 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7898 /*-----------------------------------------------------------------*/
7899 /* genAssign - generate code for assignment */
7900 /*-----------------------------------------------------------------*/
7902 genAssign (iCode * ic)
7904 operand *result, *right;
7906 // unsigned long lit = 0L;
7908 D(emitcode("; genAssign",""));
7910 result = IC_RESULT (ic);
7911 right = IC_RIGHT (ic);
7913 /* if they are the same */
7914 if (operandsEqu (result, right)) {
7918 aopOp (right, ic, FALSE);
7919 aopOp (result, ic, TRUE);
7921 /* if they are the same registers */
7922 if (sameRegs (AOP (right), AOP (result)))
7925 if ((AOP_TYPE (right) == AOP_LIT)
7926 && (IS_AOP_HX(AOP(result))))
7928 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7933 size = AOP_SIZE (result);
7936 transferAopAop (AOP (right), size, AOP (result), size);
7940 freeAsmop (right, NULL, ic, TRUE);
7941 freeAsmop (result, NULL, ic, TRUE);
7944 /*-----------------------------------------------------------------*/
7945 /* genJumpTab - generates code for jump table */
7946 /*-----------------------------------------------------------------*/
7948 genJumpTab (iCode * ic)
7951 symbol *jtablo = newiTempLabel (NULL);
7952 symbol *jtabhi = newiTempLabel (NULL);
7954 D(emitcode ("; genJumpTab",""));
7956 aopOp (IC_JTCOND (ic), ic, FALSE);
7958 if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7960 /* get the condition into x */
7961 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7962 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7963 loadRegFromConst (hc08_reg_h, zero);
7965 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7966 emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7967 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7968 emitcode ("jmp", ",x");
7970 hc08_dirtyReg (hc08_reg_a, TRUE);
7971 hc08_dirtyReg (hc08_reg_hx, TRUE);
7976 pushReg(hc08_reg_hx, TRUE);
7978 /* get the condition into x */
7979 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7980 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7981 loadRegFromConst (hc08_reg_h, zero);
7983 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7984 emitcode ("sta", "3,s");
7985 emitcode ("lda", "%05d$,x", jtablo->key + 100);
7986 emitcode ("sta", "4,s");
7988 pullReg(hc08_reg_hx);
7989 emitcode ("rts", "");
7990 _G.stackPushes += 2;
7994 /* now generate the jump labels */
7996 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7997 jtab = setNextItem (IC_JTLABELS (ic)))
7998 emitcode (".db", "%05d$", jtab->key + 100);
8000 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8001 jtab = setNextItem (IC_JTLABELS (ic)))
8002 emitcode (".db", ">%05d$", jtab->key + 100);
8006 /*-----------------------------------------------------------------*/
8007 /* genCast - gen code for casting */
8008 /*-----------------------------------------------------------------*/
8010 genCast (iCode * ic)
8012 operand *result = IC_RESULT (ic);
8013 sym_link *ctype = operandType (IC_LEFT (ic));
8014 sym_link *rtype = operandType (IC_RIGHT (ic));
8015 operand *right = IC_RIGHT (ic);
8018 D(emitcode("; genCast",""));
8020 /* if they are equivalent then do nothing */
8021 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8024 aopOp (right, ic, FALSE);
8025 aopOp (result, ic, FALSE);
8028 /* if they are the same size : or less */
8029 if (AOP_SIZE (result) <= AOP_SIZE (right))
8032 /* if they are in the same place */
8034 if (sameRegs (AOP (right), AOP (result)))
8038 /* if they in different places then copy */
8039 size = AOP_SIZE (result);
8043 transferAopAop(AOP (right), offset, AOP (result), offset);
8050 /* if the result is of type pointer */
8055 sym_link *type = operandType (right);
8056 sym_link *etype = getSpec (type);
8058 /* pointer to generic pointer */
8059 if (IS_GENPTR (ctype))
8062 p_type = DCL_TYPE (type);
8065 if (SPEC_SCLS(etype)==S_REGISTER) {
8066 // let's assume it is a generic pointer
8069 /* we have to go by the storage class */
8070 p_type = PTR_TYPE (SPEC_OCLS (etype));
8074 /* the first two bytes are known */
8075 size = GPTRSIZE - 1;
8079 transferAopAop(AOP (right), offset, AOP (result), offset);
8082 /* the last byte depending on type */
8085 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8090 // pointerTypeToGPByte will have bitched.
8094 sprintf(gpValStr, "#0x%x", gpVal);
8095 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8101 /* just copy the pointers */
8102 size = AOP_SIZE (result);
8106 transferAopAop(AOP (right), offset, AOP (result), offset);
8112 /* so we now know that the size of destination is greater
8113 than the size of the source */
8114 /* we move to result for the size of source */
8115 size = AOP_SIZE (right);
8119 transferAopAop(AOP (right), offset, AOP (result), offset);
8123 /* now depending on the sign of the source && destination */
8124 size = AOP_SIZE (result) - AOP_SIZE (right);
8125 /* if unsigned or not an integral type */
8126 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8129 storeConstToAop (zero, AOP (result), offset++);
8133 /* we need to extend the sign :{ */
8134 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
8135 accopWithMisc ("rola", "");
8136 accopWithMisc ("clra", "");
8137 accopWithMisc ("sbc", zero);
8139 storeRegToAop (hc08_reg_a, AOP (result), offset++);
8142 /* we are done hurray !!!! */
8145 freeAsmop (right, NULL, ic, TRUE);
8146 freeAsmop (result, NULL, ic, TRUE);
8150 /*-----------------------------------------------------------------*/
8151 /* genDjnz - generate decrement & jump if not zero instrucion */
8152 /*-----------------------------------------------------------------*/
8154 genDjnz (iCode * ic, iCode * ifx)
8160 D(emitcode ("; genDjnz",""));
8162 /* if the if condition has a false label
8163 then we cannot save */
8167 /* if the minus is not of the form
8169 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8170 !IS_OP_LITERAL (IC_RIGHT (ic)))
8173 if (operandLitValue (IC_RIGHT (ic)) != 1)
8176 /* dbnz doesn't support extended mode */
8177 if (isOperandInFarSpace (IC_RESULT (ic)))
8180 /* if the size of this greater than one then no
8182 // if (getSize (operandType (IC_RESULT (ic))) > 1)
8184 aopOp (IC_RESULT (ic), ic, FALSE);
8185 if (AOP_SIZE (IC_RESULT (ic))>1)
8187 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8191 /* otherwise we can save BIG */
8192 lbl = newiTempLabel (NULL);
8193 lbl1 = newiTempLabel (NULL);
8196 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
8199 emitBranch ("bra", lbl1);
8201 emitBranch ("jmp", IC_TRUE (ifx));
8204 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8209 /*-----------------------------------------------------------------*/
8210 /* genReceive - generate code for a receive iCode */
8211 /*-----------------------------------------------------------------*/
8213 genReceive (iCode * ic)
8217 D(emitcode ("; genReceive",""));
8219 aopOp (IC_RESULT (ic), ic, FALSE);
8220 size = AOP_SIZE (IC_RESULT (ic));
8225 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
8226 AOP (IC_RESULT (ic)), offset);
8227 if (hc08_aop_pass[offset]->type == AOP_REG)
8228 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
8233 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8236 /*-----------------------------------------------------------------*/
8237 /* genDummyRead - generate code for dummy read of volatiles */
8238 /*-----------------------------------------------------------------*/
8240 genDummyRead (iCode * ic)
8245 D(emitcode("; genDummyRead",""));
8248 if (op && IS_SYMOP (op))
8251 aopOp (op, ic, FALSE);
8253 size = AOP_SIZE (op);
8258 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8259 hc08_freeReg (hc08_reg_a);
8263 freeAsmop (op, NULL, ic, TRUE);
8266 if (op && IS_SYMOP (op))
8269 aopOp (op, ic, FALSE);
8271 size = AOP_SIZE (op);
8276 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8277 hc08_freeReg (hc08_reg_a);
8281 freeAsmop (op, NULL, ic, TRUE);
8285 /*-----------------------------------------------------------------*/
8286 /* genCritical - generate code for start of a critical sequence */
8287 /*-----------------------------------------------------------------*/
8289 genCritical (iCode *ic)
8291 D(emitcode("; genCritical",""));
8294 aopOp (IC_RESULT (ic), ic, TRUE);
8296 emitcode ("tpa", "");
8297 hc08_dirtyReg (hc08_reg_a, FALSE);
8298 emitcode ("sei", "");
8301 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8303 pushReg (hc08_reg_a, FALSE);
8305 hc08_freeReg (hc08_reg_a);
8307 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8310 /*-----------------------------------------------------------------*/
8311 /* genEndCritical - generate code for end of a critical sequence */
8312 /*-----------------------------------------------------------------*/
8314 genEndCritical (iCode *ic)
8316 D(emitcode("; genEndCritical",""));
8320 aopOp (IC_RIGHT (ic), ic, FALSE);
8321 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8322 emitcode ("tap", "");
8323 hc08_freeReg (hc08_reg_a);
8324 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8328 pullReg (hc08_reg_a);
8329 emitcode ("tap", "");
8335 /*-----------------------------------------------------------------*/
8336 /* genhc08Code - generate code for HC08 based controllers */
8337 /*-----------------------------------------------------------------*/
8339 genhc08Code (iCode * lic)
8346 lineHead = lineCurr = NULL;
8348 /* print the allocation information */
8349 if (allocInfo && currFunc)
8350 printAllocInfo (currFunc, codeOutBuf);
8351 /* if debug information required */
8352 if (options.debug && currFunc)
8354 debugFile->writeFunction (currFunc, lic);
8357 if (IS_STATIC (currFunc->etype))
8358 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8360 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8364 /* stack pointer name */
8365 if (options.useXstack)
8370 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8372 hc08_aop_pass[0] = newAsmop (AOP_REG);
8373 hc08_aop_pass[0]->size=1;
8374 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8375 hc08_aop_pass[1] = newAsmop (AOP_REG);
8376 hc08_aop_pass[1]->size=1;
8377 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8378 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8379 hc08_aop_pass[2]->size=1;
8380 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8381 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8382 hc08_aop_pass[3]->size=1;
8383 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8385 for (ic = lic; ic; ic = ic->next)
8388 _G.current_iCode = ic;
8390 if (ic->level != clevel || ic->block != cblock)
8394 debugFile->writeScope(ic);
8400 if (ic->lineno && cln != ic->lineno)
8404 debugFile->writeCLine(ic);
8407 emitcode ("", "C$%s$%d$%d$%d ==.",
8408 FileBaseName (ic->filename), ic->lineno,
8409 ic->level, ic->block);
8413 if (!options.noCcodeInAsm) {
8414 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8415 printCLine(ic->filename, ic->lineno));
8419 if (options.iCodeInAsm) {
8424 for (i=0; i<6; i++) {
8425 sprintf (®sInUse[i],
8426 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8429 iLine = printILine(ic);
8430 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8433 /* if the result is marked as
8434 spilt and rematerializable or code for
8435 this has already been generated then
8437 if (resultRemat (ic) || ic->generated)
8445 for (i=A_IDX;i<=XA_IDX;i++)
8447 reg = hc08_regWithIdx(i);
8449 emitcode("","; %s = %s offset %d", reg->name,
8450 aopName(reg->aop), reg->aopofs);
8453 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8455 sym = OP_SYMBOL (IC_LEFT (ic));
8456 if (sym->accuse == ACCUSE_HX)
8458 hc08_reg_h->isFree = FALSE;
8459 hc08_reg_x->isFree = FALSE;
8461 else if (sym->accuse == ACCUSE_XA)
8463 hc08_reg_a->isFree = FALSE;
8465 hc08_reg_x->isFree = FALSE;
8468 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8470 sym = OP_SYMBOL (IC_RIGHT (ic));
8471 if (sym->accuse == ACCUSE_HX)
8473 hc08_reg_h->isFree = FALSE;
8474 hc08_reg_x->isFree = FALSE;
8476 else if (sym->accuse == ACCUSE_XA)
8478 hc08_reg_a->isFree = FALSE;
8480 hc08_reg_x->isFree = FALSE;
8485 /* depending on the operation */
8505 /* IPOP happens only when trying to restore a
8506 spilt live range, if there is an ifx statement
8507 following this pop then the if statement might
8508 be using some of the registers being popped which
8509 would destory the contents of the register so
8510 we need to check for this condition and handle it */
8512 ic->next->op == IFX &&
8513 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8514 genIfx (ic->next, ic);
8532 genEndFunction (ic);
8548 if (!genPointerGetSetOfs (ic))
8553 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8573 genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
8578 genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
8590 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8594 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8598 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8625 case GET_VALUE_AT_ADDRESS:
8627 hasInc (IC_LEFT (ic), ic,
8628 getSize (operandType (IC_RESULT (ic)))),
8629 ifxForOp (IC_RESULT (ic), ic) );
8633 if (POINTER_SET (ic))
8634 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8660 addSet (&_G.sendSet, ic);
8663 case DUMMY_READ_VOLATILE:
8672 genEndCritical (ic);
8683 if (!hc08_reg_a->isFree)
8684 DD(emitcode("","; forgot to free a"));
8685 if (!hc08_reg_x->isFree)
8686 DD(emitcode("","; forgot to free x"));
8687 if (!hc08_reg_h->isFree)
8688 DD(emitcode("","; forgot to free h"));
8689 if (!hc08_reg_hx->isFree)
8690 DD(emitcode("","; forgot to free hx"));
8691 if (!hc08_reg_xa->isFree)
8692 DD(emitcode("","; forgot to free xa"));
8695 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8698 /* now we are ready to call the
8699 peep hole optimizer */
8700 if (!options.nopeep)
8701 peepHole (&lineHead);
8703 /* now do the actual printing */
8704 printLine (lineHead, codeOutBuf);