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 = ulFromVal (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) ulFromVal (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 (ulFromVal (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;
2328 D(emitcode ("; genCpl",""));
2330 /* assign asmOps to operand & result */
2331 aopOp (IC_LEFT (ic), ic, FALSE);
2332 aopOp (IC_RESULT (ic), ic, TRUE);
2334 size = AOP_SIZE (IC_RESULT (ic));
2337 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2338 rmwWithReg ("com", reg);
2340 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2345 /* release the aops */
2346 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2347 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2350 /*-----------------------------------------------------------------*/
2351 /* genUminusFloat - unary minus for floating points */
2352 /*-----------------------------------------------------------------*/
2354 genUminusFloat (operand * op, operand * result)
2356 int size, offset = 0;
2359 D(emitcode ("; genUminusFloat",""));
2361 /* for this we just copy and then flip the bit */
2363 size = AOP_SIZE (op) - 1;
2367 transferAopAop (AOP (op), offset, AOP (result), offset);
2371 needpula = pushRegIfUsed (hc08_reg_a);
2372 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2373 emitcode ("eor", "#0x80");
2374 hc08_useReg (hc08_reg_a);
2375 storeRegToAop (hc08_reg_a, AOP (result), offset);
2376 pullOrFreeReg (hc08_reg_a, needpula);
2379 /*-----------------------------------------------------------------*/
2380 /* genUminus - unary minus code generation */
2381 /*-----------------------------------------------------------------*/
2383 genUminus (iCode * ic)
2386 sym_link *optype, *rtype;
2391 D(emitcode ("; genUminus",""));
2394 aopOp (IC_LEFT (ic), ic, FALSE);
2395 aopOp (IC_RESULT (ic), ic, TRUE);
2397 optype = operandType (IC_LEFT (ic));
2398 rtype = operandType (IC_RESULT (ic));
2400 /* if float then do float stuff */
2401 if (IS_FLOAT (optype))
2403 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2407 /* otherwise subtract from zero */
2408 size = AOP_SIZE (IC_LEFT (ic));
2413 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2414 needpula = pushRegIfUsed (hc08_reg_a);
2417 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2418 emitcode ("nega", "");
2419 hc08_freeReg (hc08_reg_a);
2420 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2421 SPEC_USIGN (operandType (IC_LEFT (ic))));
2422 pullOrFreeReg (hc08_reg_a, needpula);
2426 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2427 result = forceStackedAop (AOP (IC_RESULT (ic)), FALSE);
2429 result = AOP (IC_RESULT (ic));
2431 needpula = pushRegIfUsed (hc08_reg_a);
2435 loadRegFromConst (hc08_reg_a, zero);
2436 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2437 storeRegToAop (hc08_reg_a, result, offset++);
2440 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2441 SPEC_USIGN (operandType (IC_LEFT (ic))));
2442 pullOrFreeReg (hc08_reg_a, needpula);
2444 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2445 freeAsmop (NULL, result, ic, TRUE);
2451 /* release the aops */
2452 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2453 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2456 /*-----------------------------------------------------------------*/
2457 /* saveRegisters - will look for a call and save the registers */
2458 /*-----------------------------------------------------------------*/
2460 saveRegisters (iCode * lic)
2467 for (ic = lic; ic; ic = ic->next)
2468 if (ic->op == CALL || ic->op == PCALL)
2473 fprintf (stderr, "found parameter push with no function call\n");
2477 /* if the registers have been saved already or don't need to be then
2481 if (IS_SYMOP(IC_LEFT(ic)) &&
2482 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2483 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2486 /* safe the registers in use at this time but skip the
2487 ones for the result */
2488 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2489 hc08_rUmaskForOp (IC_RESULT(ic)));
2492 for (i = 0; i < hc08_nRegs; i++)
2494 if (bitVectBitValue (rsave, i))
2495 pushReg ( hc08_regWithIdx (i), FALSE);
2499 /*-----------------------------------------------------------------*/
2500 /* unsaveRegisters - pop the pushed registers */
2501 /*-----------------------------------------------------------------*/
2503 unsaveRegisters (iCode * ic)
2508 /* restore the registers in use at this time but skip the
2509 ones for the result */
2510 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2511 hc08_rUmaskForOp (IC_RESULT(ic)));
2513 for (i = hc08_nRegs; i >= 0; i--)
2515 if (bitVectBitValue (rsave, i))
2516 pullReg ( hc08_regWithIdx (i));
2522 /*-----------------------------------------------------------------*/
2524 /*-----------------------------------------------------------------*/
2526 pushSide (operand * oper, int size)
2531 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2532 pushReg ( hc08_reg_a, TRUE);
2536 /*-----------------------------------------------------------------*/
2537 /* assignResultValue - */
2538 /*-----------------------------------------------------------------*/
2540 assignResultValue (operand * oper)
2542 int size = AOP_SIZE (oper);
2546 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2547 if (hc08_aop_pass[offset]->type == AOP_REG)
2548 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2555 /*-----------------------------------------------------------------*/
2556 /* genIpush - genrate code for pushing this gets a little complex */
2557 /*-----------------------------------------------------------------*/
2559 genIpush (iCode * ic)
2561 int size, offset = 0;
2563 D(emitcode ("; genIpush",""));
2565 /* if this is not a parm push : ie. it is spill push
2566 and spill push is always done on the local stack */
2570 /* and the item is spilt then do nothing */
2571 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2574 aopOp (IC_LEFT (ic), ic, FALSE);
2575 size = AOP_SIZE (IC_LEFT (ic));
2577 /* push it on the stack */
2580 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2581 pushReg ( hc08_reg_a, TRUE);
2587 /* this is a paramter push: in this case we call
2588 the routine to find the call and save those
2589 registers that need to be saved */
2592 /* then do the push */
2593 aopOp (IC_LEFT (ic), ic, FALSE);
2596 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2597 size = AOP_SIZE (IC_LEFT (ic));
2600 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2601 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2603 if ((size==2) && hc08_reg_hx->isFree)
2605 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2606 pushReg (hc08_reg_hx, TRUE);
2613 // printf("loading %d\n", offset);
2614 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2615 // printf("pushing \n");
2616 pushReg (hc08_reg_a, TRUE);
2620 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2623 /*-----------------------------------------------------------------*/
2624 /* genIpop - recover the registers: can happen only for spilling */
2625 /*-----------------------------------------------------------------*/
2627 genIpop (iCode * ic)
2631 D(emitcode ("; genIpop",""));
2633 /* if the temp was not pushed then */
2634 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2637 aopOp (IC_LEFT (ic), ic, FALSE);
2638 size = AOP_SIZE (IC_LEFT (ic));
2642 pullReg (hc08_reg_a);
2643 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2645 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2649 /*-----------------------------------------------------------------*/
2650 /* genSend - gen code for SEND */
2651 /*-----------------------------------------------------------------*/
2652 static void genSend(set *sendSet)
2656 for (sic = setFirstItem (sendSet); sic;
2657 sic = setNextItem (sendSet)) {
2658 int size, offset = 0;
2659 aopOp (IC_LEFT (sic), sic, FALSE);
2660 size = AOP_SIZE (IC_LEFT (sic));
2665 transferAopAop( AOP (IC_LEFT (sic)), offset,
2666 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2670 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2674 /*-----------------------------------------------------------------*/
2675 /* genCall - generates a call statement */
2676 /*-----------------------------------------------------------------*/
2678 genCall (iCode * ic)
2681 // bool restoreBank = FALSE;
2682 // bool swapBanks = FALSE;
2684 D(emitcode("; genCall",""));
2686 dtype = operandType (IC_LEFT (ic));
2687 /* if send set is not empty then assign */
2690 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2691 genSend(reverseSet(_G.sendSet));
2693 genSend(_G.sendSet);
2699 /* if caller saves & we have not saved then */
2705 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2706 OP_SYMBOL (IC_LEFT (ic))->rname :
2707 OP_SYMBOL (IC_LEFT (ic))->name));
2710 /* if we need assign a result value */
2711 if ((IS_ITEMP (IC_RESULT (ic)) &&
2712 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2713 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2714 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2715 IS_TRUE_SYMOP (IC_RESULT (ic)))
2719 aopOp (IC_RESULT (ic), ic, FALSE);
2722 assignResultValue (IC_RESULT (ic));
2724 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2727 /* adjust the stack for parameters if
2731 pullNull (ic->parmBytes);
2734 /* if we had saved some registers then unsave them */
2735 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2736 unsaveRegisters (ic);
2740 /*-----------------------------------------------------------------*/
2741 /* -10l - generates a call by pointer statement */
2742 /*-----------------------------------------------------------------*/
2744 genPcall (iCode * ic)
2747 symbol *rlbl = newiTempLabel (NULL);
2748 symbol *tlbl = newiTempLabel (NULL);
2749 // bool restoreBank=FALSE;
2750 // bool swapBanks = FALSE;
2752 D(emitcode("; genPCall",""));
2754 /* if caller saves & we have not saved then */
2758 /* if we are calling a not _naked function that is not using
2759 the same register bank then we need to save the
2760 destination registers on the stack */
2761 dtype = operandType (IC_LEFT (ic))->next;
2763 /* now push the calling address */
2764 emitBranch ("bsr", tlbl);
2765 emitBranch ("bra", rlbl);
2767 _G.stackPushes += 2; /* account for the bsr return address now on stack */
2770 /* Push the function's address */
2771 aopOp (IC_LEFT (ic), ic, FALSE);
2772 pushSide (IC_LEFT (ic), FPTRSIZE);
2773 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2775 /* if send set is not empty the assign */
2778 genSend(reverseSet(_G.sendSet));
2784 emitcode ("rts", "");
2787 _G.stackPushes -= 4; /* account for rts here & in called function */
2791 /* if we need assign a result value */
2792 if ((IS_ITEMP (IC_RESULT (ic)) &&
2793 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2794 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2795 IS_TRUE_SYMOP (IC_RESULT (ic)))
2799 aopOp (IC_RESULT (ic), ic, FALSE);
2802 assignResultValue (IC_RESULT (ic));
2804 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2807 /* adjust the stack for parameters if
2811 pullNull (ic->parmBytes);
2814 /* if we hade saved some registers then
2816 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2817 unsaveRegisters (ic);
2820 /*-----------------------------------------------------------------*/
2821 /* resultRemat - result is rematerializable */
2822 /*-----------------------------------------------------------------*/
2824 resultRemat (iCode * ic)
2826 if (SKIP_IC (ic) || ic->op == IFX)
2829 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2831 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2832 if (sym->remat && !POINTER_SET (ic))
2839 /*-----------------------------------------------------------------*/
2840 /* inExcludeList - return 1 if the string is in exclude Reg list */
2841 /*-----------------------------------------------------------------*/
2843 regsCmp(void *p1, void *p2)
2845 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2849 inExcludeList (char *s)
2851 const char *p = setFirstItem(options.excludeRegsSet);
2853 if (p == NULL || STRCASECMP(p, "none") == 0)
2857 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2860 /*-----------------------------------------------------------------*/
2861 /* genFunction - generated code for function entry */
2862 /*-----------------------------------------------------------------*/
2864 genFunction (iCode * ic)
2866 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2868 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2869 int stackAdjust = sym->stack;
2870 int accIsFree = sym->recvSize == 0;
2874 /* create the function header */
2875 emitcode (";", "-----------------------------------------");
2876 emitcode (";", " function %s", sym->name);
2877 emitcode (";", "-----------------------------------------");
2879 emitcode ("", "%s:", sym->rname);
2880 lineCurr->isLabel = 1;
2881 ftype = operandType (IC_LEFT (ic));
2885 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2887 if (IFFUNC_ISNAKED(ftype))
2889 emitcode(";", "naked function: no prologue.");
2893 /* if this is an interrupt service routine then
2895 if (IFFUNC_ISISR (sym->type))
2898 if (!inExcludeList ("h"))
2899 pushReg (hc08_reg_h, FALSE);
2902 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2903 /* before setting up the stack frame completely. */
2904 while (ric && ric->next && ric->next->op == RECEIVE)
2906 while (ric && IC_RESULT (ric))
2908 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2909 int rsymSize = rsym ? getSize(rsym->type) : 0;
2913 if (rsym && rsym->regType == REG_CND)
2915 if (rsym && (rsym->accuse || rsym->ruonly))
2917 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2918 rsym = rsym->usl.spillLoc;
2921 /* If the RECEIVE operand immediately spills to the first entry on the */
2922 /* stack, we can push it directly rather than use an sp relative store. */
2923 if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize)
2927 _G.current_iCode = ric;
2928 D(emitcode ("; genReceive",""));
2929 for (ofs=0; ofs < rsymSize; ofs++)
2931 regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
2932 pushReg (reg, TRUE);
2933 if (reg->rIdx == A_IDX)
2937 _G.current_iCode = ic;
2940 ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
2943 /* adjust the stack for the function */
2946 adjustStack (-stackAdjust);
2948 _G.stackOfs = sym->stack;
2951 /* if critical function then turn interrupts off */
2952 if (IFFUNC_ISCRITICAL (ftype))
2956 /* Function was passed parameters, so make sure A is preserved */
2957 pushReg (hc08_reg_a, FALSE);
2958 pushReg (hc08_reg_a, FALSE);
2959 emitcode ("tpa", "");
2960 emitcode ("sta", "2,s");
2961 emitcode ("sei", "");
2962 pullReg (hc08_reg_a);
2966 /* No passed parameters, so A can be freely modified */
2967 emitcode ("tpa", "");
2968 pushReg (hc08_reg_a, TRUE);
2969 emitcode ("sei", "");
2975 /*-----------------------------------------------------------------*/
2976 /* genEndFunction - generates epilogue for functions */
2977 /*-----------------------------------------------------------------*/
2979 genEndFunction (iCode * ic)
2981 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2983 if (IFFUNC_ISNAKED(sym->type))
2985 emitcode(";", "naked function: no epilogue.");
2986 if (options.debug && currFunc)
2987 debugFile->writeEndFunction (currFunc, ic, 0);
2991 if (IFFUNC_ISCRITICAL (sym->type))
2993 if (!IS_VOID(sym->type->next))
2995 /* Function has return value, so make sure A is preserved */
2996 pushReg (hc08_reg_a, FALSE);
2997 emitcode ("lda", "2,s");
2998 emitcode ("tap", "");
2999 pullReg (hc08_reg_a);
3004 /* Function returns void, so A can be freely modified */
3005 pullReg (hc08_reg_a);
3006 emitcode ("tap", "");
3010 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
3016 _G.stackPushes += sym->stack;
3017 adjustStack (sym->stack);
3021 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3025 if (IFFUNC_ISISR (sym->type))
3028 if (!inExcludeList ("h"))
3029 pullReg (hc08_reg_h);
3032 /* if debug then send end of function */
3033 if (options.debug && currFunc)
3035 debugFile->writeEndFunction (currFunc, ic, 1);
3038 emitcode ("rti", "");
3042 if (IFFUNC_CALLEESAVES(sym->type))
3046 /* if any registers used */
3049 /* save the registers used */
3050 for (i = sym->regsUsed->size; i >= 0; i--)
3052 if (bitVectBitValue (sym->regsUsed, i) ||
3053 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3054 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3060 /* if debug then send end of function */
3061 if (options.debug && currFunc)
3063 debugFile->writeEndFunction (currFunc, ic, 1);
3066 emitcode ("rts", "");
3071 /*-----------------------------------------------------------------*/
3072 /* genRet - generate code for return statement */
3073 /*-----------------------------------------------------------------*/
3077 int size, offset = 0;
3080 D(emitcode ("; genRet",""));
3082 /* if we have no return value then
3083 just generate the "ret" */
3087 /* we have something to return then
3088 move the return value into place */
3089 aopOp (IC_LEFT (ic), ic, FALSE);
3090 size = AOP_SIZE (IC_LEFT (ic));
3096 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3103 /* 4 byte return: store value in the global return variable */
3107 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3108 STA (fReturn2[offset--], FALSE);
3109 hc08_freeReg (hc08_reg_a);
3113 /* 2 byte return: store value in x:a */
3114 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3115 hc08_freeReg (hc08_reg_xa);
3118 /* 1 byte return: store value in a */
3119 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3120 hc08_freeReg (hc08_reg_a);
3125 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3128 /* generate a jump to the return label
3129 if the next is not the return statement */
3130 if (!(ic->next && ic->next->op == LABEL &&
3131 IC_LABEL (ic->next) == returnLabel))
3133 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3137 /*-----------------------------------------------------------------*/
3138 /* genLabel - generates a label */
3139 /*-----------------------------------------------------------------*/
3141 genLabel (iCode * ic)
3146 /* For the high level labels we cannot depend on any */
3147 /* register's contents. Amnesia time. */
3148 for (i=A_IDX;i<=XA_IDX;i++)
3150 reg = hc08_regWithIdx(i);
3155 /* special case never generate */
3156 if (IC_LABEL (ic) == entryLabel)
3159 debugFile->writeLabel(IC_LABEL (ic), ic);
3161 emitLabel (IC_LABEL (ic));
3165 /*-----------------------------------------------------------------*/
3166 /* genGoto - generates a jmp */
3167 /*-----------------------------------------------------------------*/
3169 genGoto (iCode * ic)
3171 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3175 /*-----------------------------------------------------------------*/
3176 /* findLabelBackwards: walks back through the iCode chain looking */
3177 /* for the given label. Returns number of iCode instructions */
3178 /* between that label and given ic. */
3179 /* Returns zero if label not found. */
3180 /*-----------------------------------------------------------------*/
3182 findLabelBackwards (iCode * ic, int key)
3191 /* If we have any pushes or pops, we cannot predict the distance.
3192 I don't like this at all, this should be dealt with in the
3194 if (ic->op == IPUSH || ic->op == IPOP) {
3198 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3208 /*-----------------------------------------------------------------*/
3209 /* genPlusIncr :- does addition with increment if possible */
3210 /*-----------------------------------------------------------------*/
3212 genPlusIncr (iCode * ic)
3220 unsigned int size = getDataSize (IC_RESULT (ic));
3221 unsigned int offset;
3222 symbol *tlbl = NULL;
3224 left = IC_LEFT (ic);
3225 result = IC_RESULT (ic);
3227 /* will try to generate an increment */
3228 /* if the right side is not a literal
3230 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3233 icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3235 DD(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3237 if ((IS_AOP_HX (AOP (left)) ||
3238 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3240 && (icount>=-128) && (icount<=127) && (size==2))
3242 if (!IS_AOP_HX (AOP (left)))
3244 needpulx = pushRegIfUsed (hc08_reg_x);
3245 needpulh = pushRegIfUsed (hc08_reg_h);
3252 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3253 emitcode ("aix","#%d", icount);
3254 hc08_dirtyReg (hc08_reg_hx, FALSE);
3255 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3256 pullOrFreeReg (hc08_reg_h, needpulh);
3257 pullOrFreeReg (hc08_reg_x, needpulx);
3261 DD(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3262 sameRegs (AOP (left), AOP (result))));
3264 if ((icount > 255) || (icount<0))
3267 if (!sameRegs (AOP (left), AOP (result)))
3270 D(emitcode ("; genPlusIncr",""));
3273 tlbl = newiTempLabel (NULL);
3278 rmwWithAop ("inc", AOP (result), 0);
3280 emitBranch ("bne", tlbl);
3284 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3285 needpula = pushRegIfUsed (hc08_reg_a);
3288 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3289 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3290 hc08_useReg (hc08_reg_a);
3291 storeRegToAop (hc08_reg_a, AOP (result), 0);
3292 hc08_freeReg (hc08_reg_a);
3294 emitBranch ("bcc", tlbl);
3296 for (offset=1; offset<size; offset++)
3298 rmwWithAop ("inc", AOP (result), offset);
3299 if ((offset+1)<size)
3300 emitBranch ("bne", tlbl);
3306 pullOrFreeReg (hc08_reg_a, needpula);
3313 /*-----------------------------------------------------------------*/
3314 /* genPlus - generates code for addition */
3315 /*-----------------------------------------------------------------*/
3317 genPlus (iCode * ic)
3319 int size, offset = 0;
3321 asmop *leftOp, *rightOp;
3323 /* special cases :- */
3325 D(emitcode ("; genPlus",""));
3327 aopOp (IC_LEFT (ic), ic, FALSE);
3328 aopOp (IC_RIGHT (ic), ic, FALSE);
3329 aopOp (IC_RESULT (ic), ic, TRUE);
3331 /* we want registers on the left and literals on the right */
3332 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3333 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3335 operand *t = IC_RIGHT (ic);
3336 IC_RIGHT (ic) = IC_LEFT (ic);
3341 /* if I can do an increment instead
3342 of add then GOOD for ME */
3343 if (genPlusIncr (ic) == TRUE)
3346 DD(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3347 DD(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3348 DD(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3350 size = getDataSize (IC_RESULT (ic));
3352 leftOp = AOP(IC_LEFT(ic));
3353 rightOp = AOP(IC_RIGHT(ic));
3359 loadRegFromAop (hc08_reg_a, leftOp, offset);
3360 accopWithAop(add, rightOp, offset);
3361 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3362 hc08_freeReg (hc08_reg_a);
3363 add = "adc"; /* further adds must propagate carry */
3367 // adjustArithmeticResult (ic);
3370 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3371 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3372 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3375 /*-----------------------------------------------------------------*/
3376 /* genMinusDec :- does subtraction with decrement if possible */
3377 /*-----------------------------------------------------------------*/
3379 genMinusDec (iCode * ic)
3381 unsigned int icount;
3386 unsigned int size = getDataSize (IC_RESULT (ic));
3390 left = IC_LEFT (ic);
3391 result = IC_RESULT (ic);
3393 /* will try to generate an increment */
3394 /* if the right side is not a literal
3396 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3399 icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3401 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3402 && (icount>=-127) && (icount<=128) && (size==2))
3404 if (!IS_AOP_HX (AOP (left)))
3406 needpulx = pushRegIfUsed (hc08_reg_x);
3407 needpulh = pushRegIfUsed (hc08_reg_h);
3414 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3415 emitcode ("aix","#%d", -icount);
3416 hc08_dirtyReg (hc08_reg_hx, FALSE);
3417 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3418 pullOrFreeReg (hc08_reg_h, needpulh);
3419 pullOrFreeReg (hc08_reg_x, needpulx);
3423 if ((icount > 1) || (icount<0))
3426 if (!sameRegs (AOP (left), AOP (result)))
3432 D(emitcode ("; genMinusDec",""));
3434 rmwWithAop ("dec", AOP (result), 0);
3439 /*-----------------------------------------------------------------*/
3440 /* addSign - complete with sign */
3441 /*-----------------------------------------------------------------*/
3443 addSign (operand * result, int offset, int sign)
3445 int size = (getDataSize (result) - offset);
3450 emitcode ("rola", "");
3451 emitcode ("clra", "");
3452 emitcode ("sbc", zero);
3454 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3458 storeConstToAop (zero, AOP (result), offset++);
3463 /*-----------------------------------------------------------------*/
3464 /* genMinus - generates code for subtraction */
3465 /*-----------------------------------------------------------------*/
3467 genMinus (iCode * ic)
3470 int size, offset = 0;
3472 asmop *leftOp, *rightOp;
3474 D(emitcode ("; genMinus",""));
3476 aopOp (IC_LEFT (ic), ic, FALSE);
3477 aopOp (IC_RIGHT (ic), ic, FALSE);
3478 aopOp (IC_RESULT (ic), ic, TRUE);
3480 /* special cases :- */
3481 /* if I can do an decrement instead
3482 of subtract then GOOD for ME */
3483 if (genMinusDec (ic) == TRUE)
3486 size = getDataSize (IC_RESULT (ic));
3489 leftOp = AOP(IC_LEFT(ic));
3490 rightOp = AOP(IC_RIGHT(ic));
3494 if (IS_AOP_A (rightOp))
3496 loadRegFromAop ( hc08_reg_a, rightOp, offset);
3497 accopWithAop (sub, leftOp, offset);
3498 accopWithMisc ("nega", "");
3499 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3505 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3506 accopWithAop (sub, rightOp, offset);
3507 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3512 // adjustArithmeticResult (ic);
3515 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3516 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3517 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3522 /*-----------------------------------------------------------------*/
3523 /* genMultOneByte : 8*8=8/16 bit multiplication */
3524 /*-----------------------------------------------------------------*/
3526 genMultOneByte (operand * left,
3530 /* sym_link *opetype = operandType (result); */
3531 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3532 int size=AOP_SIZE(result);
3533 bool negLiteral = FALSE;
3534 bool lUnsigned, rUnsigned;
3536 D(emitcode ("; genMultOneByte",""));
3538 if (size<1 || size>2) {
3539 // this should never happen
3540 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3541 AOP_SIZE(result), __FILE__, lineno);
3545 /* (if two literals: the value is computed before) */
3546 /* if one literal, literal on the right */
3547 if (AOP_TYPE (left) == AOP_LIT)
3553 /* if an operand is in A, make sure it is on the left */
3554 if (IS_AOP_A (AOP (right)))
3561 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3562 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3564 /* lUnsigned rUnsigned negLiteral negate case */
3565 /* false false false odd 3 */
3566 /* false false true even 3 */
3567 /* false true false odd 3 */
3568 /* false true true impossible */
3569 /* true false false odd 3 */
3570 /* true false true always 2 */
3571 /* true true false never 1 */
3572 /* true true true impossible */
3576 || (lUnsigned && rUnsigned))
3578 // just an unsigned 8*8=8/16 multiply
3579 //DD(emitcode (";","unsigned"));
3581 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3582 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3583 emitcode ("mul", "");
3584 hc08_dirtyReg (hc08_reg_xa, FALSE);
3585 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3586 hc08_freeReg (hc08_reg_xa);
3591 // we have to do a signed multiply
3594 /* left unsigned, right signed literal -- literal determines sign handling */
3595 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3597 signed char val=(signed char) ulFromVal (AOP (right)->aopu.aop_lit);
3599 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3601 emitcode ("ldx", "#0x%02x", -val);
3603 emitcode ("ldx", "#0x%02x", val);
3605 emitcode ("mul", "");
3609 rmwWithReg ("neg", hc08_reg_a);
3610 tlbl4 = newiTempLabel (NULL);
3611 emitBranch ("bcc", tlbl4);
3612 rmwWithReg ("inc", hc08_reg_x);
3614 rmwWithReg ("neg", hc08_reg_x);
3617 hc08_dirtyReg (hc08_reg_xa, FALSE);
3618 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3619 hc08_freeReg (hc08_reg_xa);
3626 emitcode ("clr", "1,s");
3628 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3631 tlbl1 = newiTempLabel (NULL);
3632 emitcode ("tsta","");
3633 emitBranch ("bpl", tlbl1);
3634 emitcode ("inc", "1,s");
3635 rmwWithReg ("neg", hc08_reg_a);
3639 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3641 signed char val=(signed char) ulFromVal (AOP (right)->aopu.aop_lit);
3642 /* AND literal negative */
3644 emitcode ("ldx", "#0x%02x", -val);
3647 emitcode ("ldx", "#0x%02x", val);
3649 hc08_useReg (hc08_reg_x);
3653 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3656 tlbl2 = newiTempLabel (NULL);
3657 emitcode ("tstx", "");
3658 emitBranch ("bpl", tlbl2);
3659 emitcode ("inc", "1,s");
3660 rmwWithReg ("neg", hc08_reg_x);
3665 emitcode ("mul", "");
3666 hc08_dirtyReg (hc08_reg_xa, FALSE);
3668 tlbl3 = newiTempLabel (NULL);
3669 emitcode ("dec", "1,s");
3670 if (!lUnsigned && !rUnsigned && negLiteral)
3671 emitBranch ("beq", tlbl3);
3673 emitBranch ("bne", tlbl3);
3675 rmwWithReg ("neg", hc08_reg_a);
3676 tlbl4 = newiTempLabel (NULL);
3677 emitBranch ("bcc", tlbl4);
3678 rmwWithReg ("inc", hc08_reg_x);
3680 rmwWithReg ("neg", hc08_reg_x);
3684 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3685 hc08_freeReg (hc08_reg_xa);
3689 /*-----------------------------------------------------------------*/
3690 /* genMult - generates code for multiplication */
3691 /*-----------------------------------------------------------------*/
3693 genMult (iCode * ic)
3695 operand *left = IC_LEFT (ic);
3696 operand *right = IC_RIGHT (ic);
3697 operand *result = IC_RESULT (ic);
3699 D(emitcode ("; genMult",""));
3701 /* assign the amsops */
3702 aopOp (left, ic, FALSE);
3703 aopOp (right, ic, FALSE);
3704 aopOp (result, ic, TRUE);
3706 /* special cases first */
3707 /* if both are of size == 1 */
3708 // if (getSize(operandType(left)) == 1 &&
3709 // getSize(operandType(right)) == 1)
3710 if (AOP_SIZE (left) == 1 &&
3711 AOP_SIZE (right) == 1)
3713 genMultOneByte (left, right, result);
3717 /* should have been converted to function call */
3718 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3719 getSize(OP_SYMBOL(right)->type));
3720 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3725 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3726 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3727 freeAsmop (result, NULL, ic, TRUE);
3730 /*-----------------------------------------------------------------*/
3731 /* genDivOneByte : 8 bit division */
3732 /*-----------------------------------------------------------------*/
3734 genDivOneByte (operand * left,
3738 symbol *tlbl1, *tlbl2, *tlbl3;
3741 bool lUnsigned, rUnsigned;
3742 bool runtimeSign, compiletimeSign;
3744 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3745 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3747 D(emitcode ("; genDivOneByte",""));
3749 size = AOP_SIZE (result);
3750 /* signed or unsigned */
3751 if (lUnsigned && rUnsigned)
3753 /* unsigned is easy */
3754 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3755 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3756 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3757 emitcode ("div", "");
3758 hc08_dirtyReg (hc08_reg_a, FALSE);
3759 hc08_dirtyReg (hc08_reg_h, FALSE);
3760 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3761 hc08_freeReg (hc08_reg_a);
3762 hc08_freeReg (hc08_reg_x);
3763 hc08_freeReg (hc08_reg_h);
3767 /* signed is a little bit more difficult */
3769 /* now sign adjust for both left & right */
3771 /* let's see what's needed: */
3772 /* apply negative sign during runtime */
3773 runtimeSign = FALSE;
3774 /* negative sign from literals */
3775 compiletimeSign = FALSE;
3779 if (AOP_TYPE(left) == AOP_LIT)
3781 /* signed literal */
3782 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
3784 compiletimeSign = TRUE;
3787 /* signed but not literal */
3793 if (AOP_TYPE(right) == AOP_LIT)
3795 /* signed literal */
3796 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
3798 compiletimeSign ^= TRUE;
3801 /* signed but not literal */
3805 /* initialize the runtime sign */
3808 if (compiletimeSign)
3809 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3811 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3812 pushReg (hc08_reg_x, TRUE);
3815 /* save the signs of the operands */
3816 if (AOP_TYPE(right) == AOP_LIT)
3818 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
3820 if (!rUnsigned && val < 0)
3821 emitcode ("ldx", "#0x%02x", -val);
3823 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3825 else /* ! literal */
3827 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3830 tlbl1 = newiTempLabel (NULL);
3831 emitcode ("tstx", "");
3832 emitBranch ("bpl", tlbl1);
3833 emitcode ("inc", "1,s");
3834 rmwWithReg ("neg", hc08_reg_x);
3839 if (AOP_TYPE(left) == AOP_LIT)
3841 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
3843 if (!lUnsigned && val < 0)
3844 emitcode ("lda", "#0x%02x", -val);
3846 emitcode ("lda", "#0x%02x", (unsigned char) val);
3848 else /* ! literal */
3850 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3853 tlbl2 = newiTempLabel (NULL);
3854 emitcode ("tsta", "");
3855 emitBranch ("bpl", tlbl2);
3856 emitcode ("inc", "1,s");
3857 rmwWithReg ("neg", hc08_reg_a);
3862 loadRegFromConst (hc08_reg_h, zero);
3863 emitcode ("div", "");
3864 hc08_dirtyReg (hc08_reg_x, FALSE);
3865 hc08_dirtyReg (hc08_reg_a, FALSE);
3866 hc08_dirtyReg (hc08_reg_h, FALSE);
3868 if (runtimeSign || compiletimeSign)
3870 tlbl3 = newiTempLabel (NULL);
3873 pullReg (hc08_reg_x);
3874 rmwWithReg ("lsr", hc08_reg_x);
3875 rmwWithReg ("ror", hc08_reg_x);
3876 emitBranch ("bpl", tlbl3);
3879 rmwWithReg ("neg", hc08_reg_a);
3883 storeRegToAop (hc08_reg_a, AOP (result), 0);
3887 /* msb is 0x00 or 0xff depending on the sign */
3890 rmwWithReg ("lsl", hc08_reg_x);
3891 emitcode ("clra", "");
3892 emitcode ("sbc", "#0");
3894 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3896 else /* compiletimeSign */
3898 storeConstToAop ("#0xff", AOP (result), ++offset);
3903 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3906 hc08_freeReg (hc08_reg_a);
3907 hc08_freeReg (hc08_reg_x);
3908 hc08_freeReg (hc08_reg_h);
3911 /*-----------------------------------------------------------------*/
3912 /* genDiv - generates code for division */
3913 /*-----------------------------------------------------------------*/
3917 operand *left = IC_LEFT (ic);
3918 operand *right = IC_RIGHT (ic);
3919 operand *result = IC_RESULT (ic);
3921 D(emitcode ("; genDiv",""));
3923 /* assign the amsops */
3924 aopOp (left, ic, FALSE);
3925 aopOp (right, ic, FALSE);
3926 aopOp (result, ic, TRUE);
3928 /* special cases first */
3929 /* if both are of size == 1 */
3930 if (AOP_SIZE (left) <= 2 &&
3931 AOP_SIZE (right) == 1)
3933 genDivOneByte (left, right, result);
3937 /* should have been converted to function call */
3940 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3941 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3942 freeAsmop (result, NULL, ic, TRUE);
3945 /*-----------------------------------------------------------------*/
3946 /* genModOneByte : 8 bit modulus */
3947 /*-----------------------------------------------------------------*/
3949 genModOneByte (operand * left,
3953 symbol *tlbl1, *tlbl2, *tlbl3;
3956 bool lUnsigned, rUnsigned;
3957 bool runtimeSign, compiletimeSign;
3959 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3960 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3962 D(emitcode ("; genModOneByte",""));
3964 size = AOP_SIZE (result);
3966 if (lUnsigned && rUnsigned)
3968 /* unsigned is easy */
3969 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3970 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3971 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3972 emitcode ("div", "");
3973 hc08_freeReg (hc08_reg_a);
3974 hc08_freeReg (hc08_reg_x);
3975 hc08_dirtyReg (hc08_reg_h, FALSE);
3976 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3977 hc08_freeReg (hc08_reg_h);
3981 /* signed is a little bit more difficult */
3983 if (AOP_TYPE(right) == AOP_LIT)
3985 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
3987 if (!rUnsigned && val < 0)
3988 emitcode ("ldx", "#0x%02x", -val);
3990 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3992 else /* ! literal */
3994 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3997 tlbl1 = newiTempLabel (NULL);
3998 emitcode ("tstx", "");
3999 emitBranch ("bpl", tlbl1);
4000 rmwWithReg ("neg", hc08_reg_x);
4005 /* let's see what's needed: */
4006 /* apply negative sign during runtime */
4007 runtimeSign = FALSE;
4008 /* negative sign from literals */
4009 compiletimeSign = FALSE;
4011 /* sign adjust left side */
4012 if (AOP_TYPE(left) == AOP_LIT)
4014 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
4016 if (!lUnsigned && val < 0)
4018 compiletimeSign = TRUE; /* set sign flag */
4019 emitcode ("lda", "#0x%02x", -val);
4022 emitcode ("lda", "#0x%02x", (unsigned char) val);
4024 else /* ! literal */
4027 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4032 emitcode ("clr", "1,s");
4034 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4035 tlbl2 = newiTempLabel (NULL);
4036 emitcode ("tsta", "");
4037 emitBranch ("bpl", tlbl2);
4038 emitcode ("inc", "1,s");
4039 rmwWithReg ("neg", hc08_reg_a);
4044 loadRegFromConst (hc08_reg_h, zero);
4045 emitcode ("div", "");
4046 hc08_freeReg (hc08_reg_a);
4047 hc08_freeReg (hc08_reg_x);
4048 hc08_dirtyReg (hc08_reg_h, FALSE);
4050 if (runtimeSign || compiletimeSign)
4052 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4053 tlbl3 = newiTempLabel (NULL);
4056 pullReg (hc08_reg_x);
4057 rmwWithReg ("lsr", hc08_reg_x);
4058 rmwWithReg ("ror", hc08_reg_x);
4059 emitBranch ("bpl", tlbl3);
4062 rmwWithReg ("neg", hc08_reg_a);
4066 storeRegToAop (hc08_reg_a, AOP (result), 0);
4070 /* msb is 0x00 or 0xff depending on the sign */
4073 rmwWithReg ("lsl", hc08_reg_x);
4074 emitcode ("clra", "");
4075 emitcode ("sbc", "#0");
4077 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4079 else /* compiletimeSign */
4081 storeConstToAop ("#0xff", AOP (result), ++offset);
4086 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4089 hc08_freeReg (hc08_reg_a);
4090 hc08_freeReg (hc08_reg_x);
4091 hc08_freeReg (hc08_reg_h);
4094 /*-----------------------------------------------------------------*/
4095 /* genMod - generates code for division */
4096 /*-----------------------------------------------------------------*/
4100 operand *left = IC_LEFT (ic);
4101 operand *right = IC_RIGHT (ic);
4102 operand *result = IC_RESULT (ic);
4104 D(emitcode ("; genMod",""));
4106 /* assign the amsops */
4107 aopOp (left, ic, FALSE);
4108 aopOp (right, ic, FALSE);
4109 aopOp (result, ic, TRUE);
4111 /* special cases first */
4112 /* if both are of size == 1 */
4113 if (AOP_SIZE (left) <= 2 &&
4114 AOP_SIZE (right) == 1)
4116 genModOneByte (left, right, result);
4120 /* should have been converted to function call */
4124 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4125 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4126 freeAsmop (result, NULL, ic, TRUE);
4129 /*-----------------------------------------------------------------*/
4130 /* genIfxJump :- will create a jump depending on the ifx */
4131 /*-----------------------------------------------------------------*/
4133 genIfxJump (iCode * ic, char *jval)
4136 symbol *tlbl = newiTempLabel (NULL);
4139 D(emitcode ("; genIfxJump",""));
4141 /* if true label then we jump if condition
4145 jlbl = IC_TRUE (ic);
4146 if (!strcmp (jval, "a"))
4148 else if (!strcmp (jval, "c"))
4155 /* false label is present */
4156 jlbl = IC_FALSE (ic);
4157 if (!strcmp (jval, "a"))
4159 else if (!strcmp (jval, "c"))
4164 emitBranch (inst, tlbl);
4165 emitBranch ("jmp", jlbl);
4168 /* mark the icode as generated */
4173 /*-----------------------------------------------------------------*/
4174 /* exchangedCmp : returns the opcode need if the two operands are */
4175 /* exchanged in a comparison */
4176 /*-----------------------------------------------------------------*/
4178 exchangedCmp (int opcode)
4195 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4196 "opcode not a comparison");
4198 return EQ_OP; /* shouldn't happen, but need to return something */
4201 /*------------------------------------------------------------------*/
4202 /* negatedCmp : returns the equivalent opcode for when a comparison */
4204 /*------------------------------------------------------------------*/
4206 negatedCmp (int opcode)
4223 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4224 "opcode not a comparison");
4226 return EQ_OP; /* shouldn't happen, but need to return something */
4229 /*------------------------------------------------------------------*/
4230 /* nameCmp : helper function for human readable debug output */
4231 /*------------------------------------------------------------------*/
4233 nameCmp (int opcode)
4254 /*------------------------------------------------------------------*/
4255 /* branchInstCmp : returns the conditional branch instruction that */
4256 /* will branch if the comparison is true */
4257 /*------------------------------------------------------------------*/
4259 branchInstCmp (int opcode, int sign)
4267 return "bcs"; /* same as blo */
4282 return "bcc"; /* same as bhs */
4288 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4289 "opcode not a comparison");
4295 /*------------------------------------------------------------------*/
4296 /* genCmp :- greater or less than (and maybe with equal) comparison */
4297 /*------------------------------------------------------------------*/
4299 genCmp (iCode * ic, iCode * ifx)
4301 operand *left, *right, *result;
4302 sym_link *letype, *retype;
4304 int size, offset = 0;
4305 unsigned long lit = 0L;
4307 symbol *jlbl = NULL;
4311 D(emitcode ("; genCmp", "(%s)",nameCmp (opcode)));
4313 result = IC_RESULT (ic);
4314 left = IC_LEFT (ic);
4315 right = IC_RIGHT (ic);
4317 letype = getSpec (operandType (left));
4318 retype = getSpec (operandType (right));
4319 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4320 /* assign the amsops */
4321 aopOp (left, ic, FALSE);
4322 aopOp (right, ic, FALSE);
4323 aopOp (result, ic, TRUE);
4325 /* need register operand on left, prefer literal operand on right */
4326 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4328 operand *temp = left;
4331 opcode = exchangedCmp (opcode);
4338 jlbl = IC_TRUE (ifx);
4339 opcode = negatedCmp (opcode);
4343 /* false label is present */
4344 jlbl = IC_FALSE (ifx);
4348 size = max (AOP_SIZE (left), AOP_SIZE (right));
4351 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4352 && ((AOP_TYPE (right) == AOP_LIT) ||
4353 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4354 && hc08_reg_hx->isFree)
4356 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4357 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4358 hc08_freeReg (hc08_reg_hx);
4369 /* These conditions depend on the Z flag bit, but Z is */
4370 /* only valid for the last byte of the comparison, not */
4371 /* the whole value. So exchange the operands to get a */
4372 /* comparison that doesn't depend on Z. (This is safe */
4373 /* to do here since ralloc won't assign multi-byte */
4374 /* operands to registers for comparisons) */
4375 if ((opcode == '>') || (opcode == LE_OP))
4377 operand *temp = left;
4380 opcode = exchangedCmp (opcode);
4383 if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
4385 lit = ulFromVal (AOP (right)->aopu.aop_lit);
4386 while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
4395 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4396 accopWithAop (sub, AOP (right), offset);
4397 hc08_freeReg (hc08_reg_a);
4402 freeAsmop (right, NULL, ic, FALSE);
4403 freeAsmop (left, NULL, ic, FALSE);
4407 symbol *tlbl = newiTempLabel (NULL);
4410 freeAsmop (result, NULL, ic, TRUE);
4412 inst = branchInstCmp (opcode, sign);
4413 emitBranch (inst, tlbl);
4414 emitBranch ("jmp", jlbl);
4417 /* mark the icode as generated */
4422 symbol *tlbl1 = newiTempLabel (NULL);
4423 symbol *tlbl2 = newiTempLabel (NULL);
4425 emitBranch (branchInstCmp (opcode, sign), tlbl1);
4426 loadRegFromConst (hc08_reg_a, zero);
4427 emitBranch ("bra", tlbl2);
4429 loadRegFromConst (hc08_reg_a, one);
4431 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4432 freeAsmop (result, NULL, ic, TRUE);
4437 /*-----------------------------------------------------------------*/
4438 /* genCmpEQorNE - equal or not equal comparison */
4439 /*-----------------------------------------------------------------*/
4441 genCmpEQorNE (iCode * ic, iCode * ifx)
4443 operand *left, *right, *result;
4444 sym_link *letype, *retype;
4446 int size, offset = 0;
4448 symbol *jlbl = NULL;
4449 symbol *tlbl_NE = NULL;
4450 symbol *tlbl_EQ = NULL;
4454 D(emitcode ("; genCmpEQorNE", "(%s)",nameCmp (opcode)));
4456 result = IC_RESULT (ic);
4457 left = IC_LEFT (ic);
4458 right = IC_RIGHT (ic);
4460 letype = getSpec (operandType (left));
4461 retype = getSpec (operandType (right));
4462 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4463 /* assign the amsops */
4464 aopOp (left, ic, FALSE);
4465 aopOp (right, ic, FALSE);
4466 aopOp (result, ic, TRUE);
4468 /* need register operand on left, prefer literal operand on right */
4469 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4471 operand *temp = left;
4474 opcode = exchangedCmp (opcode);
4481 jlbl = IC_TRUE (ifx);
4482 opcode = negatedCmp (opcode);
4486 /* false label is present */
4487 jlbl = IC_FALSE (ifx);
4491 size = max (AOP_SIZE (left), AOP_SIZE (right));
4494 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4495 && ((AOP_TYPE (right) == AOP_LIT) ||
4496 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4497 && hc08_reg_hx->isFree)
4499 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4500 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4501 hc08_freeReg (hc08_reg_hx);
4509 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4510 accopWithAop (sub, AOP (right), offset);
4514 tlbl_NE = newiTempLabel (NULL);
4515 emitBranch ("bne", tlbl_NE);
4517 hc08_freeReg (hc08_reg_a);
4521 freeAsmop (right, NULL, ic, FALSE);
4522 freeAsmop (left, NULL, ic, FALSE);
4526 freeAsmop (result, NULL, ic, TRUE);
4528 if (opcode == EQ_OP)
4531 tlbl_EQ = newiTempLabel (NULL);
4532 emitBranch ("beq", tlbl_EQ);
4534 emitLabel (tlbl_NE);
4535 emitBranch ("jmp", jlbl);
4536 emitLabel (tlbl_EQ);
4541 tlbl_NE = newiTempLabel (NULL);
4542 emitBranch ("bne", tlbl_NE);
4543 emitBranch ("jmp", jlbl);
4544 emitLabel (tlbl_NE);
4547 /* mark the icode as generated */
4552 symbol *tlbl = newiTempLabel (NULL);
4554 if (opcode == EQ_OP)
4557 tlbl_EQ = newiTempLabel (NULL);
4558 emitBranch ("beq", tlbl_EQ);
4560 emitLabel (tlbl_NE);
4561 loadRegFromConst (hc08_reg_a, zero);
4562 emitBranch ("bra", tlbl);
4563 emitLabel (tlbl_EQ);
4564 loadRegFromConst (hc08_reg_a, one);
4569 tlbl_NE = newiTempLabel (NULL);
4570 emitBranch ("bne", tlbl_NE);
4571 loadRegFromConst (hc08_reg_a, zero);
4572 emitBranch ("bra", tlbl);
4573 emitLabel (tlbl_NE);
4574 loadRegFromConst (hc08_reg_a, one);
4578 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4579 freeAsmop (result, NULL, ic, TRUE);
4585 /*-----------------------------------------------------------------*/
4586 /* ifxForOp - returns the icode containing the ifx for operand */
4587 /*-----------------------------------------------------------------*/
4589 ifxForOp (operand * op, iCode * ic)
4591 /* if true symbol then needs to be assigned */
4592 if (IS_TRUE_SYMOP (op))
4595 /* if this has register type condition and
4596 the next instruction is ifx with the same operand
4597 and live to of the operand is upto the ifx only then */
4599 ic->next->op == IFX &&
4600 IC_COND (ic->next)->key == op->key &&
4601 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4608 genPointerGetSetOfs (iCode *ic)
4610 iCode *lic = ic->next;
4616 /* Make sure we have a next iCode */
4617 DD(emitcode("","; checking lic"));
4621 /* Make sure the result of the addition is an iCode */
4622 DD(emitcode("","; checking IS_ITEMP"));
4623 if (!IS_ITEMP (IC_RESULT (ic)))
4626 /* Make sure the next iCode is a pointer set or get */
4627 pset = POINTER_SET(lic);
4628 pget = POINTER_GET(lic);
4629 DD(emitcode("","; pset=%d, pget=%d",pset,pget));
4633 /* Make sure this is the only use of the pointer */
4634 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4637 DD(emitcode("", "; checking pset operandsEqu"));
4638 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4641 DD(emitcode("", "; checking pget operandsEqu"));
4642 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4645 DD(emitcode("", "; checking IS_SYMOP"));
4646 if (!IS_SYMOP (IC_LEFT (ic)))
4649 DD(emitcode("", "; checking !IS_TRUE_SYMOP"));
4650 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4653 sym = OP_SYMBOL (IC_LEFT (ic));
4655 DD(emitcode("", "; checking remat"));
4662 D(emitcode ("; genPointerGetOfs",""));
4663 aopOp (IC_LEFT(ic), ic, FALSE);
4664 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4665 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4667 aopOp (IC_RIGHT(ic), ic, FALSE);
4668 aopOp (IC_RESULT(lic), lic, FALSE);
4670 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4672 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4674 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4675 loadRegFromConst (hc08_reg_h, zero);
4679 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4680 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4681 emitcode ("rola","");
4682 emitcode ("clra","");
4683 emitcode ("sbc", "#0");
4684 hc08_useReg (hc08_reg_a);
4685 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4689 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4690 size = AOP_SIZE (IC_RESULT(lic));
4691 derefaop->size = size;
4695 emitcode ("lda", "%s,x",
4696 aopAdrStr (derefaop, size, TRUE));
4697 hc08_useReg (hc08_reg_a);
4698 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
4699 hc08_freeReg (hc08_reg_a);
4703 hc08_freeReg (hc08_reg_hx);
4705 freeAsmop (NULL, derefaop, ic, TRUE);
4706 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4707 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4714 D(emitcode ("; genPointerSetOfs",""));
4715 aopOp (IC_LEFT(ic), ic, FALSE);
4716 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4717 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4719 aopOp (IC_RIGHT(ic), ic, FALSE);
4720 aopOp (IC_RIGHT(lic), lic, FALSE);
4722 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4724 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4726 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4727 loadRegFromConst (hc08_reg_h, zero);
4731 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4732 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4733 emitcode ("rola","");
4734 emitcode ("clra","");
4735 emitcode ("sbc", "#0");
4736 hc08_useReg (hc08_reg_a);
4737 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4741 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4742 size = AOP_SIZE (IC_RIGHT(lic));
4743 derefaop->size = size;
4747 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
4748 emitcode ("sta", "%s,x",
4749 aopAdrStr (derefaop, size, TRUE));
4750 hc08_freeReg (hc08_reg_a);
4754 hc08_freeReg (hc08_reg_hx);
4756 freeAsmop (NULL, derefaop, ic, TRUE);
4757 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4758 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4767 /*-----------------------------------------------------------------*/
4768 /* hasInc - operand is incremented before any other use */
4769 /*-----------------------------------------------------------------*/
4771 hasInc (operand *op, iCode *ic,int osize)
4773 sym_link *type = operandType(op);
4774 sym_link *retype = getSpec (type);
4775 iCode *lic = ic->next;
4778 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4779 if (!IS_SYMOP(op)) return NULL;
4781 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4782 if (IS_AGGREGATE(type->next)) return NULL;
4783 if (osize != (isize = getSize(type->next))) return NULL;
4786 /* if operand of the form op = op + <sizeof *op> */
4787 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4788 isOperandEqual(IC_RESULT(lic),op) &&
4789 isOperandLiteral(IC_RIGHT(lic)) &&
4790 operandLitValue(IC_RIGHT(lic)) == isize) {
4793 /* if the operand used or deffed */
4794 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
4797 /* if GOTO or IFX */
4798 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4804 /*-----------------------------------------------------------------*/
4805 /* genAndOp - for && operation */
4806 /*-----------------------------------------------------------------*/
4808 genAndOp (iCode * ic)
4810 operand *left, *right, *result;
4811 symbol *tlbl, *tlbl0;
4813 D(emitcode ("; genAndOp",""));
4815 /* note here that && operations that are in an
4816 if statement are taken away by backPatchLabels
4817 only those used in arthmetic operations remain */
4818 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4819 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4820 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4822 tlbl = newiTempLabel (NULL);
4823 tlbl0 = newiTempLabel (NULL);
4825 asmopToBool (AOP (left), FALSE);
4826 emitBranch ("beq", tlbl0);
4827 asmopToBool (AOP (right), FALSE);
4828 emitBranch ("beq", tlbl0);
4829 loadRegFromConst (hc08_reg_a,one);
4830 emitBranch ("bra", tlbl);
4832 loadRegFromConst (hc08_reg_a,zero);
4835 hc08_useReg (hc08_reg_a);
4836 hc08_freeReg (hc08_reg_a);
4838 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4840 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4841 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4842 freeAsmop (result, NULL, ic, TRUE);
4846 /*-----------------------------------------------------------------*/
4847 /* genOrOp - for || operation */
4848 /*-----------------------------------------------------------------*/
4850 genOrOp (iCode * ic)
4852 operand *left, *right, *result;
4853 symbol *tlbl, *tlbl0;
4855 D(emitcode ("; genOrOp",""));
4857 /* note here that || operations that are in an
4858 if statement are taken away by backPatchLabels
4859 only those used in arthmetic operations remain */
4860 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4861 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4862 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4864 tlbl = newiTempLabel (NULL);
4865 tlbl0 = newiTempLabel (NULL);
4867 asmopToBool (AOP (left), FALSE);
4868 emitBranch ("bne", tlbl0);
4869 asmopToBool (AOP (right), FALSE);
4870 emitBranch ("bne", tlbl0);
4871 loadRegFromConst (hc08_reg_a,zero);
4872 emitBranch ("bra", tlbl);
4874 loadRegFromConst (hc08_reg_a,one);
4877 hc08_useReg (hc08_reg_a);
4878 hc08_freeReg (hc08_reg_a);
4880 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4883 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4884 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4885 freeAsmop (result, NULL, ic, TRUE);
4888 /*-----------------------------------------------------------------*/
4889 /* isLiteralBit - test if lit == 2^n */
4890 /*-----------------------------------------------------------------*/
4892 isLiteralBit (unsigned long lit)
4894 unsigned long pw[32] =
4895 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4896 0x100L, 0x200L, 0x400L, 0x800L,
4897 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4898 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4899 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4900 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4901 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4904 for (idx = 0; idx < 32; idx++)
4911 /*-----------------------------------------------------------------*/
4912 /* continueIfTrue - */
4913 /*-----------------------------------------------------------------*/
4915 continueIfTrue (iCode * ic)
4918 emitBranch ("jmp", IC_TRUE (ic));
4922 /*-----------------------------------------------------------------*/
4924 /*-----------------------------------------------------------------*/
4926 jumpIfTrue (iCode * ic)
4929 emitBranch ("jmp", IC_FALSE (ic));
4933 /*-----------------------------------------------------------------*/
4934 /* jmpTrueOrFalse - */
4935 /*-----------------------------------------------------------------*/
4937 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4939 // ugly but optimized by peephole
4942 symbol *nlbl = newiTempLabel (NULL);
4943 emitBranch ("bra", nlbl);
4945 emitBranch ("jmp", IC_TRUE (ic));
4950 emitBranch ("jmp", IC_FALSE (ic));
4957 /*-----------------------------------------------------------------*/
4958 /* genAnd - code for and */
4959 /*-----------------------------------------------------------------*/
4961 genAnd (iCode * ic, iCode * ifx)
4963 operand *left, *right, *result;
4964 int size, offset = 0;
4965 unsigned long lit = 0L;
4966 unsigned long litinv;
4967 unsigned char bytemask;
4973 D(emitcode ("; genAnd",""));
4975 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4976 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4977 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4980 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4982 AOP_TYPE (left), AOP_TYPE (right)));
4983 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4985 AOP_SIZE (left), AOP_SIZE (right)));
4988 /* if left is a literal & right is not then exchange them */
4989 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4991 operand *tmp = right;
4996 /* if right is accumulator & left is not then exchange them */
4997 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4999 operand *tmp = right;
5004 if (AOP_TYPE (right) == AOP_LIT)
5005 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5007 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5009 if (AOP_TYPE (result) == AOP_CRY
5011 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5013 /* this generates ugly code, but meets volatility requirements */
5014 loadRegFromConst (hc08_reg_a, zero);
5015 pushReg (hc08_reg_a, TRUE);
5020 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5021 accopWithAop ("and", AOP (right), offset);
5022 emitcode ("ora", "1,s");
5023 emitcode ("sta", "1,s");
5027 pullReg (hc08_reg_a);
5028 emitcode ("tsta", "");
5029 genIfxJump (ifx, "a");
5033 if (AOP_TYPE (result) == AOP_CRY)
5035 symbol *tlbl = NULL;
5036 wassertl (ifx, "AOP_CRY result without ifx");
5041 bytemask = (lit >> (offset*8)) & 0xff;
5043 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5047 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5049 rmwWithAop ("tst", AOP (left), offset);
5053 tlbl = newiTempLabel (NULL);
5054 emitBranch ("bne", tlbl);
5059 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5060 accopWithAop ("and", AOP (right), offset);
5061 hc08_freeReg( hc08_reg_a);
5065 tlbl = newiTempLabel (NULL);
5066 emitBranch ("bne", tlbl);
5073 genIfxJump (ifx, "a");
5077 size = AOP_SIZE (result);
5079 if (AOP_TYPE (right) == AOP_LIT)
5081 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
5082 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5083 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
5085 int bitpos = isLiteralBit(litinv)-1;
5086 emitcode ("bclr","#%d,%s",bitpos & 7,
5087 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5095 bytemask = (lit >> (offset*8)) & 0xff;
5097 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5099 if (isOperandVolatile (left, FALSE))
5101 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5102 hc08_freeReg( hc08_reg_a);
5104 storeConstToAop (zero, AOP (result), offset);
5106 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5108 transferAopAop (AOP (left), offset, AOP (result), offset);
5112 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5113 accopWithAop ("and", AOP (right), offset);
5114 storeRegToAop (hc08_reg_a, AOP (result), offset);
5115 hc08_freeReg (hc08_reg_a);
5121 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5122 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5123 freeAsmop (result, NULL, ic, TRUE);
5126 /*-----------------------------------------------------------------*/
5127 /* genOr - code for or */
5128 /*-----------------------------------------------------------------*/
5130 genOr (iCode * ic, iCode * ifx)
5132 operand *left, *right, *result;
5133 int size, offset = 0;
5134 unsigned long lit = 0L;
5135 unsigned char bytemask;
5137 D(emitcode ("; genOr",""));
5139 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5140 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5141 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5144 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5146 AOP_TYPE (left), AOP_TYPE (right)));
5147 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5149 AOP_SIZE (left), AOP_SIZE (right)));
5152 /* if left is a literal & right is not then exchange them */
5153 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5155 operand *tmp = right;
5160 /* if left is accumulator & right is not then exchange them */
5161 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5163 operand *tmp = right;
5168 if (AOP_TYPE (right) == AOP_LIT)
5169 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5171 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5173 if (AOP_TYPE (result) == AOP_CRY
5175 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5177 /* this generates ugly code, but meets volatility requirements */
5178 loadRegFromConst (hc08_reg_a, zero);
5179 pushReg (hc08_reg_a, TRUE);
5184 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5185 accopWithAop ("ora", AOP (right), offset);
5186 emitcode ("ora", "1,s");
5187 emitcode ("sta", "1,s");
5191 pullReg (hc08_reg_a);
5192 emitcode ("tsta", "");
5193 genIfxJump (ifx, "a");
5197 if (AOP_TYPE (result) == AOP_CRY)
5199 symbol *tlbl = NULL;
5200 wassertl (ifx, "AOP_CRY result without ifx");
5205 bytemask = (lit >> (offset*8)) & 0xff;
5207 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5209 rmwWithAop ("tst", AOP (left), offset);
5213 tlbl = newiTempLabel (NULL);
5214 emitBranch ("bne", tlbl);
5219 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5220 accopWithAop ("ora", AOP (right), offset);
5221 hc08_freeReg( hc08_reg_a);
5225 tlbl = newiTempLabel (NULL);
5226 emitBranch ("bne", tlbl);
5233 genIfxJump (ifx, "a");
5236 if (AOP_TYPE (right) == AOP_LIT)
5237 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5239 size = AOP_SIZE (result);
5241 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5242 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5243 (AOP_TYPE (left) == AOP_DIR))
5245 int bitpos = isLiteralBit(lit)-1;
5246 emitcode ("bset","#%d,%s",bitpos & 7,
5247 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5254 bytemask = (lit >> (offset*8)) & 0xff;
5256 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5258 if (isOperandVolatile (left, FALSE))
5260 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5261 hc08_freeReg( hc08_reg_a);
5263 transferAopAop (AOP (right), offset, AOP (result), offset);
5265 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5267 transferAopAop (AOP (left), offset, AOP (result), offset);
5271 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5272 accopWithAop ("ora", AOP (right), offset);
5273 storeRegToAop (hc08_reg_a, AOP (result), offset);
5274 hc08_freeReg (hc08_reg_a);
5281 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5282 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5283 freeAsmop (result, NULL, ic, TRUE);
5286 /*-----------------------------------------------------------------*/
5287 /* genXor - code for xclusive or */
5288 /*-----------------------------------------------------------------*/
5290 genXor (iCode * ic, iCode * ifx)
5292 operand *left, *right, *result;
5293 int size, offset = 0;
5294 unsigned long lit = 0L;
5296 D(emitcode ("; genXor",""));
5298 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5299 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5300 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5303 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5305 AOP_TYPE (left), AOP_TYPE (right)));
5306 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5308 AOP_SIZE (left), AOP_SIZE (right)));
5311 /* if left is a literal & right is not ||
5312 if left needs acc & right does not */
5313 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5315 operand *tmp = right;
5320 /* if left is accumulator & right is not then exchange them */
5321 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5323 operand *tmp = right;
5328 if (AOP_TYPE (result) == AOP_CRY)
5331 wassertl (ifx, "AOP_CPY result without ifx");
5333 tlbl = newiTempLabel (NULL);
5334 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5338 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5339 if ((AOP_TYPE (right) == AOP_LIT)
5340 && (((lit >> (offset*8)) & 0xff) == 0))
5341 emitcode ("tsta","");
5343 accopWithAop ("eor", AOP (right), offset);
5344 hc08_freeReg( hc08_reg_a);
5346 emitBranch ("bne", tlbl);
5350 genIfxJump (ifx, "a");
5356 if (AOP_TYPE (right) == AOP_LIT)
5357 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5359 size = AOP_SIZE (result);
5363 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5364 accopWithAop ("eor", AOP (right), offset);
5365 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5366 hc08_freeReg( hc08_reg_a);
5370 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5371 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5372 freeAsmop (result, NULL, ic, TRUE);
5376 emitinline (iCode * ic, char *inlin)
5382 symbol *sym, *tempsym;
5391 while (isalnum((unsigned char)*inlin) || (*inlin == '_'))
5395 //printf("Found possible symbol '%s'\n",symname);
5396 tempsym = newSymbol (symname, ic->level);
5397 tempsym->block = ic->block;
5398 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5407 aop = aopForSym (ic, sym, FALSE);
5408 l = aopAdrStr (aop, aop->size - 1, TRUE);
5412 if (sym->level && !sym->allocreq && !sym->ismyparm)
5414 werror (E_ID_UNDEF, sym->name);
5416 " Add 'volatile' to the variable declaration so that it\n"
5417 " can be referenced within inline assembly");
5419 //printf("Replacing with '%s'\n",l);
5423 if ((2+bp-buffer)>sizeof(buffer))
5432 if ((2+bp-buffer)>sizeof(buffer))
5439 if ((2+bp-buffer)>sizeof(buffer))
5440 fprintf(stderr, "Inline assembly buffer overflow\n");
5442 //printf("%s\n",buffer);
5443 emitcode (buffer,"");
5447 /*-----------------------------------------------------------------*/
5448 /* genInline - write the inline code out */
5449 /*-----------------------------------------------------------------*/
5451 genInline (iCode * ic)
5453 char *buffer, *bp, *bp1;
5454 bool inComment = FALSE;
5456 D(emitcode ("; genInline",""));
5458 _G.inLine += (!options.asmpeep);
5460 buffer = bp = bp1 = Safe_strdup (IC_INLINE(ic));
5462 /* emit each line as a code */
5475 emitinline (ic, bp1);
5480 /* Add \n for labels, not dirs such as c:\mydir */
5481 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
5495 emitinline (ic, bp1);
5499 _G.inLine -= (!options.asmpeep);
5502 /*-----------------------------------------------------------------*/
5503 /* genRRC - rotate right with carry */
5504 /*-----------------------------------------------------------------*/
5508 operand *left, *result;
5509 int size, offset = 0;
5510 bool needpula = FALSE;
5511 bool resultInA = FALSE;
5514 D(emitcode ("; genRRC",""));
5516 /* rotate right with carry */
5517 left = IC_LEFT (ic);
5518 result = IC_RESULT (ic);
5519 aopOp (left, ic, FALSE);
5520 aopOp (result, ic, FALSE);
5522 if ((AOP_TYPE (result) == AOP_REG)
5523 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5526 size = AOP_SIZE (result);
5530 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5534 rmwWithAop (shift, AOP (result), offset--);
5542 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5543 rmwWithReg (shift, hc08_reg_a);
5544 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5545 hc08_freeReg (hc08_reg_a);
5550 if ((!hc08_reg_a->isFree) || resultInA)
5552 pushReg (hc08_reg_a, TRUE);
5556 /* now we need to put the carry into the
5557 highest order byte of the result */
5558 offset = AOP_SIZE (result) - 1;
5559 emitcode ("clra","");
5560 emitcode ("rora","");
5561 hc08_dirtyReg (hc08_reg_a, FALSE);
5564 emitcode ("ora", "1,s");
5565 emitcode ("ais", "#1");
5566 hc08_dirtyReg (hc08_reg_a, FALSE);
5570 accopWithAop ("ora", AOP (result), offset);
5571 storeRegToAop (hc08_reg_a, AOP (result), offset);
5573 pullOrFreeReg (hc08_reg_a, needpula);
5575 freeAsmop (left, NULL, ic, TRUE);
5576 freeAsmop (result, NULL, ic, TRUE);
5579 /*-----------------------------------------------------------------*/
5580 /* genRLC - generate code for rotate left with carry */
5581 /*-----------------------------------------------------------------*/
5585 operand *left, *result;
5586 int size, offset = 0;
5588 bool resultInA = FALSE;
5589 bool needpula = FALSE;
5591 D(emitcode ("; genRLC",""));
5593 /* rotate right with carry */
5594 left = IC_LEFT (ic);
5595 result = IC_RESULT (ic);
5596 aopOp (left, ic, FALSE);
5597 aopOp (result, ic, FALSE);
5599 if ((AOP_TYPE (result) == AOP_REG)
5600 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5603 size = AOP_SIZE (result);
5607 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5611 rmwWithAop (shift, AOP (result), offset--);
5619 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5620 rmwWithReg (shift, hc08_reg_a);
5621 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5622 hc08_freeReg (hc08_reg_a);
5627 if ((!hc08_reg_a->isFree) || resultInA)
5629 pushReg (hc08_reg_a, TRUE);
5633 /* now we need to put the carry into the
5634 lowest order byte of the result */
5636 emitcode ("clra","");
5637 emitcode ("rola","");
5638 hc08_dirtyReg (hc08_reg_a, FALSE);
5641 emitcode ("ora", "1,s");
5642 emitcode ("ais", "#1");
5643 hc08_dirtyReg (hc08_reg_a, FALSE);
5647 accopWithAop ("ora", AOP (result), offset);
5648 storeRegToAop (hc08_reg_a, AOP (result), offset);
5650 pullOrFreeReg (hc08_reg_a, needpula);
5652 freeAsmop (left, NULL, ic, TRUE);
5653 freeAsmop (result, NULL, ic, TRUE);
5656 /*-----------------------------------------------------------------*/
5657 /* genGetHbit - generates code get highest order bit */
5658 /*-----------------------------------------------------------------*/
5660 genGetHbit (iCode * ic)
5662 operand *left, *result;
5664 D(emitcode ("; genGetHbit",""));
5666 left = IC_LEFT (ic);
5667 result = IC_RESULT (ic);
5668 aopOp (left, ic, FALSE);
5669 aopOp (result, ic, FALSE);
5671 /* get the highest order byte into a */
5672 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5673 emitcode ("rola", "");
5674 emitcode ("clra", "");
5675 emitcode ("rola", "");
5676 hc08_dirtyReg (hc08_reg_a, FALSE);
5677 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5678 hc08_freeReg (hc08_reg_a);
5680 freeAsmop (left, NULL, ic, TRUE);
5681 freeAsmop (result, NULL, ic, TRUE);
5684 /*-----------------------------------------------------------------*/
5685 /* genSwap - generates code to swap nibbles or bytes */
5686 /*-----------------------------------------------------------------*/
5688 genSwap (iCode * ic)
5690 operand *left, *result;
5692 D(emitcode ("; genSwap",""));
5694 left = IC_LEFT (ic);
5695 result = IC_RESULT (ic);
5696 aopOp (left, ic, FALSE);
5697 aopOp (result, ic, FALSE);
5699 switch (AOP_SIZE (left))
5701 case 1: /* swap nibbles in byte */
5702 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5703 emitcode ("nsa", "");
5704 hc08_dirtyReg (hc08_reg_a, FALSE);
5705 storeRegToAop (hc08_reg_a, AOP (result), 0);
5706 hc08_freeReg (hc08_reg_a);
5708 case 2: /* swap bytes in a word */
5709 if (operandsEqu (left, result) || sameRegs (AOP (left), AOP (result)))
5711 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5712 hc08_useReg (hc08_reg_a);
5713 transferAopAop (AOP (left), 1, AOP (result), 0);
5714 storeRegToAop (hc08_reg_a, AOP (result), 1);
5715 hc08_freeReg (hc08_reg_a);
5719 transferAopAop (AOP (left), 0, AOP (result), 1);
5720 transferAopAop (AOP (left), 1, AOP (result), 0);
5724 wassertl(FALSE, "unsupported SWAP operand size");
5727 freeAsmop (left, NULL, ic, TRUE);
5728 freeAsmop (result, NULL, ic, TRUE);
5732 /*-----------------------------------------------------------------*/
5733 /* AccRol - rotate left accumulator by known count */
5734 /*-----------------------------------------------------------------*/
5736 AccRol (int shCount)
5738 shCount &= 0x0007; // shCount : 0..7
5745 emitcode ("rola", ""); /* 1 cycle */
5748 emitcode ("rola", ""); /* 1 cycle */
5749 emitcode ("rola", ""); /* 1 cycle */
5752 emitcode ("nsa", "");
5753 emitcode ("rora", "");
5756 emitcode ("nsa", ""); /* 3 cycles */
5759 emitcode ("nsa", ""); /* 3 cycles */
5760 emitcode ("rola", ""); /* 1 cycle */
5763 emitcode ("nsa", ""); /* 3 cycles */
5764 emitcode ("rola", ""); /* 1 cycle */
5765 emitcode ("rola", ""); /* 1 cycle */
5768 emitcode ("nsa", ""); /* 3 cycles */
5769 emitcode ("rola", ""); /* 1 cycle */
5770 emitcode ("rola", ""); /* 1 cycle */
5771 emitcode ("rola", ""); /* 1 cycle */
5778 /*-----------------------------------------------------------------*/
5779 /* AccLsh - left shift accumulator by known count */
5780 /*-----------------------------------------------------------------*/
5782 AccLsh (int shCount)
5786 shCount &= 0x0007; // shCount : 0..7
5788 /* Shift counts of 4 and 5 are currently optimized for code size. */
5789 /* Falling through to the unrolled loop would be optimal for code speed. */
5790 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5794 if (optimize.codeSpeed)
5796 accopWithMisc ("nsa", "");
5797 accopWithMisc ("and", "#0xf0");
5798 /* total: 5 cycles, 3 bytes */
5801 if (optimize.codeSpeed)
5803 accopWithMisc ("nsa", "");
5804 accopWithMisc ("and", "#0xf0");
5805 accopWithMisc ("lsla", "");
5806 /* total: 6 cycles, 4 bytes */
5809 accopWithMisc ("rora", "");
5810 accopWithMisc ("rora", "");
5811 accopWithMisc ("rora", "");
5812 accopWithMisc ("and", "#0xc0");
5813 /* total: 5 cycles, 5 bytes */
5816 accopWithMisc ("rora", "");
5817 accopWithMisc ("clra", "");
5818 accopWithMisc ("rora", "");
5819 /* total: 3 cycles, 3 bytes */
5823 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5824 /* the fastest (shCount<6) and shortest (shCount<4). */
5825 for (i=0;i<shCount;i++)
5826 accopWithMisc ("lsla", "");
5830 /*-----------------------------------------------------------------*/
5831 /* AccSRsh - signed right shift accumulator by known count */
5832 /*-----------------------------------------------------------------*/
5834 AccSRsh (int shCount)
5838 shCount &= 0x0007; // shCount : 0..7
5842 accopWithMisc ("rola", "");
5843 accopWithMisc ("clra", "");
5844 accopWithMisc ("sbc", zero);
5845 /* total: 4 cycles, 4 bytes */
5849 for (i=0;i<shCount;i++)
5850 accopWithMisc ("asra", "");
5853 /*-----------------------------------------------------------------*/
5854 /* AccRsh - right shift accumulator by known count */
5855 /*-----------------------------------------------------------------*/
5857 AccRsh (int shCount, bool sign)
5867 shCount &= 0x0007; // shCount : 0..7
5869 /* Shift counts of 4 and 5 are currently optimized for code size. */
5870 /* Falling through to the unrolled loop would be optimal for code speed. */
5871 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5875 if (optimize.codeSpeed)
5877 accopWithMisc ("nsa", "");
5878 accopWithMisc ("and", "#0x0f");
5879 /* total: 5 cycles, 3 bytes */
5882 if (optimize.codeSpeed)
5884 accopWithMisc ("nsa", "");
5885 accopWithMisc ("and", "#0x0f");
5886 accopWithMisc ("lsra", "");
5887 /* total: 6 cycles, 4 bytes */
5890 accopWithMisc ("rola", "");
5891 accopWithMisc ("rola", "");
5892 accopWithMisc ("rola", "");
5893 accopWithMisc ("and", "#0x03");
5894 /* total: 5 cycles, 5 bytes */
5897 accopWithMisc ("rola", "");
5898 accopWithMisc ("clra", "");
5899 accopWithMisc ("rola", "");
5900 /* total: 3 cycles, 3 bytes */
5904 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5905 /* the fastest (shCount<6) and shortest (shCount<4). */
5906 for (i=0;i<shCount;i++)
5907 accopWithMisc ("lsra", "");
5911 /*-----------------------------------------------------------------*/
5912 /* XAccLsh - left shift register pair XA by known count */
5913 /*-----------------------------------------------------------------*/
5915 XAccLsh (int shCount)
5919 shCount &= 0x000f; // shCount : 0..15
5924 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5925 loadRegFromConst (hc08_reg_a, zero);
5929 /* if we can beat 2n cycles or bytes for some special case, do it here */
5933 /* bytes cycles reg x reg a carry
5934 ** abcd efgh ijkl mnop ?
5935 ** lsrx 1 1 0abc defg ijkl mnop h
5936 ** rora 1 1 0abc defg hijk lmno p
5937 ** tax 1 1 hijk lmno hijk lmno p
5938 ** clra 1 1 hijk lmno 0000 0000 p
5939 ** rora 1 1 hijk lmno p000 0000 0
5940 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5942 rmwWithReg ("lsr", hc08_reg_x);
5943 rmwWithReg ("ror", hc08_reg_a);
5944 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5945 loadRegFromConst (hc08_reg_a, zero);
5946 rmwWithReg ("ror", hc08_reg_a);
5953 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5954 /* the fastest and shortest. */
5955 for (i=0;i<shCount;i++)
5957 rmwWithReg ("lsl", hc08_reg_a);
5958 rmwWithReg ("rol", hc08_reg_x);
5962 /*-----------------------------------------------------------------*/
5963 /* XAccSRsh - signed right shift register pair XA by known count */
5964 /*-----------------------------------------------------------------*/
5966 XAccSRsh (int shCount)
5970 shCount &= 0x000f; // shCount : 0..7
5972 /* if we can beat 2n cycles or bytes for some special case, do it here */
5976 /* bytes cycles reg x reg a carry
5977 ** abcd efgh ijkl mnop ?
5978 ** lslx 1 1 bcde fgh0 ijkl mnop a
5979 ** clra 1 1 bcde fgh0 0000 0000 a
5980 ** rola 1 1 bcde fgh0 0000 000a 0
5981 ** nega 1 1 bcde fgh0 aaaa aaaa a
5982 ** tax 1 1 aaaa aaaa aaaa aaaa a
5983 ** total: 5 cycles, 5 bytes
5985 rmwWithReg ("lsl", hc08_reg_x);
5986 loadRegFromConst (hc08_reg_a, zero);
5987 rmwWithReg ("rol", hc08_reg_a);
5988 rmwWithReg ("neg", hc08_reg_a);
5989 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5999 /* bytes cycles reg x reg a carry
6000 ** abcd efgh ijkl mnop ?
6001 ** txa 1 1 abcd efgh abcd efgh ?
6002 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
6003 ** lsla 1 1 abcd efgh ???? ???? a
6004 ** clrx 1 1 0000 0000 ???? ???? a
6005 ** rolx 1 1 0000 000a ???? ???? 0
6006 ** negx 1 1 aaaa aaaa ???? ???? a
6007 ** rora 1 1 aaaa aaaa LSBresult 0
6008 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
6010 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6011 AccSRsh (shCount-8);
6012 rmwWithReg ("lsl", hc08_reg_a);
6013 loadRegFromConst (hc08_reg_x, zero);
6014 rmwWithReg ("rol", hc08_reg_x);
6015 rmwWithReg ("neg", hc08_reg_x);
6016 rmwWithReg ("ror", hc08_reg_a);
6023 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6024 /* the fastest and shortest. */
6025 for (i=0;i<shCount;i++)
6027 rmwWithReg ("asr", hc08_reg_x);
6028 rmwWithReg ("ror", hc08_reg_a);
6032 /*-----------------------------------------------------------------*/
6033 /* XAccRsh - right shift register pair XA by known count */
6034 /*-----------------------------------------------------------------*/
6036 XAccRsh (int shCount, bool sign)
6046 shCount &= 0x000f; // shCount : 0..f
6048 /* if we can beat 2n cycles or bytes for some special case, do it here */
6052 /* bytes cycles reg x reg a carry
6053 ** abcd efgh ijkl mnop ?
6054 ** clra 1 1 abcd efgh 0000 0000 a
6055 ** lslx 1 1 bcde fgh0 0000 0000 a
6056 ** rola 1 1 bcde fgh0 0000 000a 0
6057 ** clrx 1 1 0000 0000 0000 000a 0
6058 ** total: 4 cycles, 4 bytes
6060 loadRegFromConst (hc08_reg_x, zero);
6061 rmwWithReg ("lsl", hc08_reg_x);
6062 rmwWithReg ("rol", hc08_reg_a);
6063 loadRegFromConst (hc08_reg_a, zero);
6067 /* bytes cycles reg x reg a carry
6068 ** abcd efgh ijkl mnop ?
6069 ** clra 1 1 abcd efgh 0000 0000 a
6070 ** lslx 1 1 bcde fgh0 0000 0000 a
6071 ** rola 1 1 bcde fgh0 0000 000a 0
6072 ** lslx 1 1 cdef gh00 0000 000a b
6073 ** rola 1 1 cdef gh00 0000 00ab 0
6074 ** clrx 1 1 0000 0000 0000 00ab 0
6075 ** total: 6 cycles, 6 bytes
6077 loadRegFromConst (hc08_reg_x, zero);
6078 rmwWithReg ("lsl", hc08_reg_x);
6079 rmwWithReg ("rol", hc08_reg_a);
6080 rmwWithReg ("lsl", hc08_reg_x);
6081 rmwWithReg ("rol", hc08_reg_a);
6082 loadRegFromConst (hc08_reg_a, zero);
6091 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6092 AccRsh (shCount-8, FALSE);
6093 loadRegFromConst (hc08_reg_x, zero);
6097 /* bytes cycles reg x reg a carry
6098 ** abcd efgh ijkl mnop ?
6099 ** lsla 1 1 abcd efgh jklm nop0 i
6100 ** txa 1 1 abcd efgh abcd efgh i
6101 ** rola 1 1 abcd efgh bcde fghi a
6102 ** clrx 1 1 0000 0000 bcde fghi a
6103 ** rolx 1 1 0000 000a bcde fghi 0
6104 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
6106 rmwWithReg ("lsl", hc08_reg_a);
6107 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6108 rmwWithReg ("rol", hc08_reg_a);
6109 loadRegFromConst (hc08_reg_x, zero);
6110 rmwWithReg ("rol", hc08_reg_x);
6113 /* bytes cycles reg x reg a carry
6114 ** abcd efgh ijkl mnop ?
6115 ** lsla 1 1 abcd efgh jklm nop0 i
6116 ** rolx 1 1 bcde fghi jklm nop0 a
6117 ** rola 1 1 bcde fghi klmn op0a j
6118 ** rolx 1 1 cdef ghij klmn op0a b
6119 ** rola 1 1 cdef ghij lmno p0ab k
6120 ** and #3 2 2 cdef ghij 0000 00ab k
6121 ** psha 1 2 cdef ghij 0000 00ab k
6122 ** txa 1 1 cdef ghij cdef ghij k
6123 ** pula 1 2 0000 00ab cdef ghij k
6124 ** total: 12 cycles, 10 bytes (beats 12 bytes)
6130 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6131 /* the fastest and shortest. */
6132 for (i=0;i<shCount;i++)
6134 rmwWithReg ("lsr", hc08_reg_x);
6135 rmwWithReg ("ror", hc08_reg_a);
6142 /*-----------------------------------------------------------------*/
6143 /* shiftR1Left2Result - shift right one byte from left to result */
6144 /*-----------------------------------------------------------------*/
6146 shiftR1Left2Result (operand * left, int offl,
6147 operand * result, int offr,
6148 int shCount, int sign)
6150 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6151 /* shift right accumulator */
6152 AccRsh (shCount, sign);
6153 storeRegToAop (hc08_reg_a, AOP (result), offr);
6157 /*-----------------------------------------------------------------*/
6158 /* shiftL1Left2Result - shift left one byte from left to result */
6159 /*-----------------------------------------------------------------*/
6161 shiftL1Left2Result (operand * left, int offl,
6162 operand * result, int offr, int shCount)
6164 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6165 /* shift left accumulator */
6167 storeRegToAop (hc08_reg_a, AOP (result), offr);
6170 /*-----------------------------------------------------------------*/
6171 /* movLeft2Result - move byte from left to result */
6172 /*-----------------------------------------------------------------*/
6174 movLeft2Result (operand * left, int offl,
6175 operand * result, int offr, int sign)
6177 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6179 transferAopAop (AOP (left), offl, AOP (result), offr);
6184 /*-----------------------------------------------------------------*/
6185 /* shiftL2Left2Result - shift left two bytes from left to result */
6186 /*-----------------------------------------------------------------*/
6188 shiftL2Left2Result (operand * left, int offl,
6189 operand * result, int offr, int shCount)
6192 bool needpula = FALSE;
6193 bool needpulx = FALSE;
6195 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6196 needpula = pushRegIfUsed (hc08_reg_a);
6199 if (!IS_AOP_XA (AOP (left)))
6200 needpulx = pushRegIfUsed (hc08_reg_x);
6204 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6209 rmwWithReg ("lsr", hc08_reg_x);
6210 rmwWithReg ("ror", hc08_reg_a);
6211 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6212 rmwWithReg ("clr", hc08_reg_a);
6213 rmwWithReg ("ror", hc08_reg_a);
6216 for (i=0; i<shCount; i++)
6218 rmwWithReg ("lsl", hc08_reg_a);
6219 rmwWithReg ("rol", hc08_reg_x);
6222 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6224 pullOrFreeReg (hc08_reg_x, needpulx);
6225 pullOrFreeReg (hc08_reg_a, needpula);
6231 /*-----------------------------------------------------------------*/
6232 /* shiftR2Left2Result - shift right two bytes from left to result */
6233 /*-----------------------------------------------------------------*/
6235 shiftR2Left2Result (operand * left, int offl,
6236 operand * result, int offr,
6237 int shCount, int sign)
6240 bool needpula = FALSE;
6241 bool needpulx = FALSE;
6243 needpula = pushRegIfUsed (hc08_reg_a);
6244 needpulx = pushRegIfUsed (hc08_reg_x);
6246 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6247 for (i=0; i<shCount; i++)
6250 rmwWithReg ("asr", hc08_reg_x);
6252 rmwWithReg ("lsr", hc08_reg_x);
6253 rmwWithReg ("ror", hc08_reg_a);
6255 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6257 pullOrFreeReg (hc08_reg_x, needpulx);
6258 pullOrFreeReg (hc08_reg_a, needpula);
6263 /*-----------------------------------------------------------------*/
6264 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6265 /*-----------------------------------------------------------------*/
6267 shiftLLeftOrResult (operand * left, int offl,
6268 operand * result, int offr, int shCount)
6270 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6271 /* shift left accumulator */
6273 /* or with result */
6274 accopWithAop ("ora", AOP (result), offr);
6275 /* back to result */
6276 storeRegToAop (hc08_reg_a, AOP (result), offr);
6277 hc08_freeReg (hc08_reg_a);
6281 /*-----------------------------------------------------------------*/
6282 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6283 /*-----------------------------------------------------------------*/
6285 shiftRLeftOrResult (operand * left, int offl,
6286 operand * result, int offr, int shCount)
6288 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6289 /* shift left accumulator */
6290 AccRsh (shCount, FALSE);
6291 /* or with result */
6292 accopWithAop ("ora", AOP (result), offr);
6293 /* back to result */
6294 storeRegToAop (hc08_reg_a, AOP (result), offr);
6295 hc08_freeReg (hc08_reg_a);
6298 /*-----------------------------------------------------------------*/
6299 /* genlshOne - left shift a one byte quantity by known count */
6300 /*-----------------------------------------------------------------*/
6302 genlshOne (operand * result, operand * left, int shCount)
6304 D(emitcode ("; genlshOne",""));
6306 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6309 /*-----------------------------------------------------------------*/
6310 /* genlshTwo - left shift two bytes by known amount != 0 */
6311 /*-----------------------------------------------------------------*/
6313 genlshTwo (operand * result, operand * left, int shCount)
6317 D(emitcode ("; genlshTwo",""));
6320 size = getDataSize (result);
6322 /* if shCount >= 8 */
6329 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6331 storeRegToAop (hc08_reg_a, AOP (result), 1);
6333 storeConstToAop(zero, AOP (result), LSB);
6336 /* 1 <= shCount <= 7 */
6339 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6341 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6345 /*-----------------------------------------------------------------*/
6346 /* shiftLLong - shift left one long from left to result */
6347 /* offr = LSB or MSB16 */
6348 /*-----------------------------------------------------------------*/
6350 shiftLLong (operand * left, operand * result, int offr)
6353 // int size = AOP_SIZE (result);
6355 bool needpula = FALSE;
6356 bool needpulx = FALSE;
6358 needpula = pushRegIfUsed (hc08_reg_a);
6359 needpulx = pushRegIfUsed (hc08_reg_x);
6361 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6362 rmwWithReg ("lsl", hc08_reg_a);
6363 rmwWithReg ("rol", hc08_reg_x);
6367 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6368 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6369 rmwWithReg ("rol", hc08_reg_a);
6370 rmwWithReg ("rol", hc08_reg_x);
6371 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6373 else if (offr==MSB16)
6375 storeRegToAop (hc08_reg_a, AOP (result), offr);
6376 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6377 storeRegToAop (hc08_reg_x, AOP (result), offr+1);
6378 rmwWithReg ("rol", hc08_reg_a);
6379 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6380 storeConstToAop (zero, AOP (result), 0);
6383 pullOrFreeReg (hc08_reg_x, needpulx);
6384 pullOrFreeReg (hc08_reg_a, needpula);
6387 /*-----------------------------------------------------------------*/
6388 /* genlshFour - shift four byte by a known amount != 0 */
6389 /*-----------------------------------------------------------------*/
6391 genlshFour (operand * result, operand * left, int shCount)
6395 D(emitcode ("; genlshFour",""));
6397 size = AOP_SIZE (result);
6399 /* TODO: deal with the &result == &left case */
6401 /* if shifting more that 3 bytes */
6406 /* lowest order of left goes to the highest
6407 order of the destination */
6408 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6410 movLeft2Result (left, LSB, result, MSB32, 0);
6411 storeConstToAop (zero, AOP (result), LSB);
6412 storeConstToAop (zero, AOP (result), MSB16);
6413 storeConstToAop (zero, AOP (result), MSB24);
6417 /* more than two bytes */
6418 else if (shCount >= 16)
6420 /* lower order two bytes goes to higher order two bytes */
6422 /* if some more remaining */
6424 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6427 movLeft2Result (left, MSB16, result, MSB32, 0);
6428 movLeft2Result (left, LSB, result, MSB24, 0);
6430 storeConstToAop (zero, AOP (result), LSB);
6431 storeConstToAop (zero, AOP (result), MSB16);
6435 /* if more than 1 byte */
6436 else if (shCount >= 8)
6438 /* lower order three bytes goes to higher order three bytes */
6443 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6445 movLeft2Result (left, LSB, result, MSB16, 0);
6451 movLeft2Result (left, MSB24, result, MSB32, 0);
6452 movLeft2Result (left, MSB16, result, MSB24, 0);
6453 movLeft2Result (left, LSB, result, MSB16, 0);
6454 storeConstToAop (zero, AOP (result), LSB);
6456 else if (shCount == 1)
6457 shiftLLong (left, result, MSB16);
6460 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6461 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6462 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6463 storeConstToAop (zero, AOP (result), LSB);
6468 /* 1 <= shCount <= 7 */
6469 else if (shCount <= 2)
6471 shiftLLong (left, result, LSB);
6473 shiftLLong (result, result, LSB);
6475 /* 3 <= shCount <= 7, optimize */
6478 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6479 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6480 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6484 /*-----------------------------------------------------------------*/
6485 /* genLeftShiftLiteral - left shifting by known count */
6486 /*-----------------------------------------------------------------*/
6488 genLeftShiftLiteral (operand * left,
6493 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
6496 D(emitcode ("; genLeftShiftLiteral",""));
6498 freeAsmop (right, NULL, ic, TRUE);
6500 aopOp (left, ic, FALSE);
6501 aopOp (result, ic, FALSE);
6503 // size = getSize (operandType (result));
6504 size = AOP_SIZE (result);
6507 DD(emitcode ("; shift left ", "result %d, left %d", size,
6514 transferAopAop( AOP(left), size, AOP(result), size);
6516 else if (shCount >= (size * 8))
6519 storeConstToAop (zero, AOP (result), size);
6526 genlshOne (result, left, shCount);
6530 genlshTwo (result, left, shCount);
6534 genlshFour (result, left, shCount);
6537 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6538 "*** ack! mystery literal shift!\n");
6542 freeAsmop (left, NULL, ic, TRUE);
6543 freeAsmop (result, NULL, ic, TRUE);
6546 /*-----------------------------------------------------------------*/
6547 /* genLeftShift - generates code for left shifting */
6548 /*-----------------------------------------------------------------*/
6550 genLeftShift (iCode * ic)
6552 operand *left, *right, *result;
6554 symbol *tlbl, *tlbl1;
6558 D(emitcode ("; genLeftShift",""));
6560 right = IC_RIGHT (ic);
6561 left = IC_LEFT (ic);
6562 result = IC_RESULT (ic);
6564 aopOp (right, ic, FALSE);
6566 /* if the shift count is known then do it
6567 as efficiently as possible */
6568 if (AOP_TYPE (right) == AOP_LIT)
6570 genLeftShiftLiteral (left, right, result, ic);
6574 /* shift count is unknown then we have to form
6575 a loop get the loop count in X : Note: we take
6576 only the lower order byte since shifting
6577 more that 32 bits make no sense anyway, ( the
6578 largest size of an object can be only 32 bits ) */
6580 aopOp (result, ic, FALSE);
6581 aopOp (left, ic, FALSE);
6582 aopResult = AOP (result);
6584 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result))
6585 || isOperandVolatile (result, FALSE))
6586 aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result)));
6588 /* now move the left to the result if they are not the
6590 if (!sameRegs (AOP (left), aopResult))
6592 size = AOP_SIZE (result);
6596 transferAopAop (AOP (left), offset, aopResult, offset);
6600 freeAsmop (left, NULL, ic, TRUE);
6601 AOP (result) = aopResult;
6603 tlbl = newiTempLabel (NULL);
6604 size = AOP_SIZE (result);
6606 tlbl1 = newiTempLabel (NULL);
6608 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6609 emitcode ("tstx", "");
6610 emitBranch ("beq", tlbl1);
6614 for (offset=0;offset<size;offset++)
6616 rmwWithAop (shift, AOP (result), offset);
6619 rmwWithReg ("dec", hc08_reg_x);
6620 emitBranch ("bne", tlbl);
6622 hc08_freeReg (hc08_reg_x);
6624 freeAsmop (result, NULL, ic, TRUE);
6625 freeAsmop (right, NULL, ic, TRUE);
6628 /*-----------------------------------------------------------------*/
6629 /* genrshOne - right shift a one byte quantity by known count */
6630 /*-----------------------------------------------------------------*/
6632 genrshOne (operand * result, operand * left,
6633 int shCount, int sign)
6635 D(emitcode ("; genrshOne",""));
6637 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6638 AccRsh (shCount, sign);
6639 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6642 /*-----------------------------------------------------------------*/
6643 /* genrshTwo - right shift two bytes by known amount != 0 */
6644 /*-----------------------------------------------------------------*/
6646 genrshTwo (operand * result, operand * left,
6647 int shCount, int sign)
6649 D(emitcode ("; genrshTwo",""));
6651 /* if shCount >= 8 */
6654 if (shCount || sign)
6656 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6657 AccRsh (shCount-8, sign);
6658 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6662 transferAopAop (AOP (left), 1, AOP (result), 0);
6663 storeConstToAop (zero, AOP (result), 1);
6667 /* 1 <= shCount <= 7 */
6670 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6671 XAccRsh (shCount, sign);
6672 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6676 /*-----------------------------------------------------------------*/
6677 /* shiftRLong - shift right one long from left to result */
6678 /* offl = LSB or MSB16 */
6679 /*-----------------------------------------------------------------*/
6681 shiftRLong (operand * left, int offl,
6682 operand * result, int sign)
6685 // int size = AOP_SIZE (result);
6687 bool needpula = FALSE;
6688 bool needpulx = FALSE;
6690 needpula = pushRegIfUsed (hc08_reg_a);
6691 needpulx = pushRegIfUsed (hc08_reg_x);
6695 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6697 rmwWithReg ("asr", hc08_reg_x);
6699 rmwWithReg ("lsr", hc08_reg_x);
6700 rmwWithReg ("ror", hc08_reg_a);
6701 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6702 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6704 else if (offl==MSB16)
6706 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6708 rmwWithReg ("asr", hc08_reg_a);
6710 rmwWithReg ("lsr", hc08_reg_a);
6711 loadRegFromAop (hc08_reg_x, AOP (left), MSB24);
6712 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6713 loadRegFromAop (hc08_reg_a, AOP (left), MSB16);
6716 rmwWithReg ("ror", hc08_reg_x);
6717 rmwWithReg ("ror", hc08_reg_a);
6718 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6724 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6725 storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
6729 storeConstToAop (zero, AOP (result), MSB32);
6733 pullOrFreeReg (hc08_reg_x, needpulx);
6734 pullOrFreeReg (hc08_reg_a, needpula);
6737 /*-----------------------------------------------------------------*/
6738 /* genrshFour - shift four byte by a known amount != 0 */
6739 /*-----------------------------------------------------------------*/
6741 genrshFour (operand * result, operand * left,
6742 int shCount, int sign)
6744 /* TODO: handle cases where left == result */
6746 D(emitcode ("; genrshFour",""));
6748 /* if shifting more that 3 bytes */
6751 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6752 AccRsh (shCount-24, sign);
6753 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6756 else if (shCount >= 16)
6758 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6759 XAccRsh (shCount-16, sign);
6760 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6763 else if (shCount >= 8)
6766 shiftRLong (left, MSB16, result, sign);
6767 else if (shCount == 8)
6769 transferAopAop (AOP (left), 1, AOP (result), 0);
6770 transferAopAop (AOP (left), 2, AOP (result), 1);
6771 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6772 storeRegToAop (hc08_reg_a, AOP (result), 2);
6773 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6775 else if (shCount == 9)
6777 shiftRLong (left, MSB16, result, sign);
6781 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6782 XAccRsh (shCount-8, FALSE);
6783 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6784 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6785 loadRegFromConst (hc08_reg_a, zero);
6786 XAccRsh (shCount-8, sign);
6787 accopWithAop ("ora", AOP (result), 1);
6788 storeRegToAop (hc08_reg_xa, AOP (result), 1);
6789 storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
6793 { /* 1 <= shCount <= 7 */
6796 shiftRLong (left, LSB, result, sign);
6800 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6801 XAccRsh (shCount, FALSE);
6802 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6803 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6805 accopWithAop ("ora", AOP (result), 1);
6806 storeRegToAop (hc08_reg_a, AOP (result), 1);
6807 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6808 XAccRsh (shCount, sign);
6809 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6814 /*-----------------------------------------------------------------*/
6815 /* genRightShiftLiteral - right shifting by known count */
6816 /*-----------------------------------------------------------------*/
6818 genRightShiftLiteral (operand * left,
6824 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
6827 D(emitcode ("; genRightShiftLiteral",""));
6829 freeAsmop (right, NULL, ic, TRUE);
6831 aopOp (left, ic, FALSE);
6832 aopOp (result, ic, FALSE);
6835 DD(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6839 size = getDataSize (left);
6840 /* test the LEFT size !!! */
6842 /* I suppose that the left size >= result size */
6845 size = getDataSize (result);
6847 transferAopAop (AOP (left), size, AOP(result), size);
6849 else if (shCount >= (size * 8))
6852 /* get sign in acc.7 */
6853 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6855 addSign (result, LSB, sign);
6862 genrshOne (result, left, shCount, sign);
6866 genrshTwo (result, left, shCount, sign);
6870 genrshFour (result, left, shCount, sign);
6876 freeAsmop (left, NULL, ic, TRUE);
6877 freeAsmop (result, NULL, ic, TRUE);
6881 /*-----------------------------------------------------------------*/
6882 /* genRightShift - generate code for right shifting */
6883 /*-----------------------------------------------------------------*/
6885 genRightShift (iCode * ic)
6887 operand *right, *left, *result;
6890 symbol *tlbl, *tlbl1;
6895 D(emitcode ("; genRightShift",""));
6897 /* if signed then we do it the hard way preserve the
6898 sign bit moving it inwards */
6899 retype = getSpec (operandType (IC_RESULT (ic)));
6900 sign = !SPEC_USIGN (retype);
6902 /* signed & unsigned types are treated the same : i.e. the
6903 signed is NOT propagated inwards : quoting from the
6904 ANSI - standard : "for E1 >> E2, is equivalent to division
6905 by 2**E2 if unsigned or if it has a non-negative value,
6906 otherwise the result is implementation defined ", MY definition
6907 is that the sign does not get propagated */
6909 right = IC_RIGHT (ic);
6910 left = IC_LEFT (ic);
6911 result = IC_RESULT (ic);
6913 aopOp (right, ic, FALSE);
6915 /* if the shift count is known then do it
6916 as efficiently as possible */
6917 if (AOP_TYPE (right) == AOP_LIT)
6919 genRightShiftLiteral (left, right, result, ic, sign);
6923 /* shift count is unknown then we have to form
6924 a loop get the loop count in X : Note: we take
6925 only the lower order byte since shifting
6926 more that 32 bits make no sense anyway, ( the
6927 largest size of an object can be only 32 bits ) */
6929 aopOp (result, ic, FALSE);
6930 aopOp (left, ic, FALSE);
6931 aopResult = AOP (result);
6933 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result))
6934 || isOperandVolatile (result, FALSE))
6935 aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result)));
6937 /* now move the left to the result if they are not the
6939 if (!sameRegs (AOP (left), aopResult))
6941 size = AOP_SIZE (result);
6945 transferAopAop (AOP (left), offset, aopResult, offset);
6949 freeAsmop (left, NULL, ic, TRUE);
6950 AOP (result) = aopResult;
6952 tlbl = newiTempLabel (NULL);
6953 size = AOP_SIZE (result);
6955 tlbl1 = newiTempLabel (NULL);
6957 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6958 emitcode ("tstx", "");
6959 emitBranch ("beq", tlbl1);
6962 shift= sign ? "asr" : "lsr";
6963 for (offset=size-1;offset>=0;offset--)
6965 rmwWithAop (shift, AOP (result), offset);
6968 rmwWithReg ("dec", hc08_reg_x);
6969 emitBranch ("bne", tlbl);
6971 hc08_freeReg (hc08_reg_x);
6973 freeAsmop (result, NULL, ic, TRUE);
6974 freeAsmop (right, NULL, ic, TRUE);
6978 /*-----------------------------------------------------------------*/
6979 /* genUnpackBits - generates code for unpacking bits */
6980 /*-----------------------------------------------------------------*/
6982 genUnpackBits (operand * result, iCode *ifx)
6984 int offset = 0; /* result byte offset */
6985 int rsize; /* result size */
6986 int rlen = 0; /* remaining bitfield length */
6987 sym_link *etype; /* bitfield type information */
6988 int blen; /* bitfield length */
6989 int bstr; /* bitfield starting bit within byte */
6991 D(emitcode ("; genUnpackBits",""));
6993 etype = getSpec (operandType (result));
6994 rsize = getSize (operandType (result));
6995 blen = SPEC_BLEN (etype);
6996 bstr = SPEC_BSTR (etype);
6998 if (ifx && blen <= 8)
7000 emitcode ("lda", ",x");
7001 hc08_dirtyReg (hc08_reg_a, FALSE);
7004 emitcode ("and", "#0x%02x",
7005 (((unsigned char) -1) >> (8 - blen)) << bstr);
7007 genIfxJump (ifx, "a");
7012 /* If the bitfield length is less than a byte */
7015 emitcode ("lda", ",x");
7016 hc08_dirtyReg (hc08_reg_a, FALSE);
7017 AccRsh (bstr, FALSE);
7018 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7019 if (!SPEC_USIGN (etype))
7021 /* signed bitfield */
7022 symbol *tlbl = newiTempLabel (NULL);
7024 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7025 emitcode ("beq", "%05d$", tlbl->key + 100);
7026 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7029 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7033 /* Bit field did not fit in a byte. Copy all
7034 but the partial byte at the end. */
7035 for (rlen=blen;rlen>=8;rlen-=8)
7037 emitcode ("lda", ",x");
7038 hc08_dirtyReg (hc08_reg_a, FALSE);
7039 storeRegToAop (hc08_reg_a, AOP (result), offset);
7042 emitcode ("aix", "#1");
7045 /* Handle the partial byte at the end */
7048 emitcode ("lda", ",x");
7049 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7050 if (!SPEC_USIGN (etype))
7052 /* signed bitfield */
7053 symbol *tlbl = newiTempLabel (NULL);
7055 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7056 emitcode ("beq", "%05d$", tlbl->key + 100);
7057 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7060 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7067 if (SPEC_USIGN (etype))
7070 storeConstToAop (zero, AOP (result), offset++);
7074 /* signed bitfield: sign extension with 0x00 or 0xff */
7075 emitcode ("rola", "");
7076 emitcode ("clra", "");
7077 emitcode ("sbc", zero);
7080 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7086 /*-----------------------------------------------------------------*/
7087 /* genUnpackBitsImmed - generates code for unpacking bits */
7088 /*-----------------------------------------------------------------*/
7090 genUnpackBitsImmed (operand * left,
7096 int offset = 0; /* result byte offset */
7097 int rsize; /* result size */
7098 int rlen = 0; /* remaining bitfield length */
7099 sym_link *etype; /* bitfield type information */
7100 int blen; /* bitfield length */
7101 int bstr; /* bitfield starting bit within byte */
7104 D(emitcode ("; genUnpackBitsImmed",""));
7106 aopOp (result, ic, TRUE);
7107 size = AOP_SIZE (result);
7109 derefaop = aopDerefAop (AOP (left));
7110 freeAsmop (left, NULL, ic, TRUE);
7111 derefaop->size = size;
7113 etype = getSpec (operandType (result));
7114 rsize = getSize (operandType (result));
7115 blen = SPEC_BLEN (etype);
7116 bstr = SPEC_BSTR (etype);
7118 /* if the bitfield is a single bit in the direct page */
7119 if (blen == 1 && derefaop->type == AOP_DIR)
7123 symbol *tlbl = newiTempLabel (NULL);
7125 loadRegFromConst (hc08_reg_a, zero);
7126 emitcode ("brclr", "#%d,%s,%05d$",
7127 bstr, aopAdrStr (derefaop, 0, FALSE),
7129 if (SPEC_USIGN (etype))
7130 rmwWithReg ("inc", hc08_reg_a);
7132 rmwWithReg ("dec", hc08_reg_a);
7134 storeRegToAop (hc08_reg_a, AOP (result), offset);
7135 hc08_freeReg (hc08_reg_a);
7141 symbol *tlbl = newiTempLabel (NULL);
7147 jlbl = IC_TRUE (ifx);
7152 jlbl = IC_FALSE (ifx);
7155 emitcode (inst, "#%d,%s,%05d$",
7156 bstr, aopAdrStr (derefaop, 0, FALSE),
7158 emitBranch ("jmp", jlbl);
7166 /* If the bitfield length is less than a byte */
7169 loadRegFromAop (hc08_reg_a, derefaop, 0);
7172 AccRsh (bstr, FALSE);
7173 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7174 hc08_dirtyReg (hc08_reg_a, FALSE);
7175 if (!SPEC_USIGN (etype))
7177 /* signed bitfield */
7178 symbol *tlbl = newiTempLabel (NULL);
7180 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7181 emitcode ("beq", "%05d$", tlbl->key + 100);
7182 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7185 storeRegToAop (hc08_reg_a, AOP (result), offset);
7189 emitcode ("and", "#0x%02x",
7190 (((unsigned char) -1) >> (8 - blen)) << bstr);
7191 hc08_dirtyReg (hc08_reg_a, FALSE);
7197 /* Bit field did not fit in a byte. Copy all
7198 but the partial byte at the end. */
7199 for (rlen=blen;rlen>=8;rlen-=8)
7201 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7203 storeRegToAop (hc08_reg_a, AOP (result), offset);
7205 emitcode ("tsta", "");
7209 /* Handle the partial byte at the end */
7212 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7213 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7214 if (!SPEC_USIGN (etype))
7216 /* signed bitfield */
7217 symbol *tlbl = newiTempLabel (NULL);
7219 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7220 emitcode ("beq", "%05d$", tlbl->key + 100);
7221 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7224 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7231 if (SPEC_USIGN (etype))
7234 storeConstToAop (zero, AOP (result), offset++);
7238 /* signed bitfield: sign extension with 0x00 or 0xff */
7239 emitcode ("rola", "");
7240 emitcode ("clra", "");
7241 emitcode ("sbc", zero);
7244 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7248 freeAsmop (NULL, derefaop, ic, TRUE);
7249 freeAsmop (result, NULL, ic, TRUE);
7251 if (ifx && !ifx->generated)
7253 genIfxJump (ifx, "a");
7258 /*-----------------------------------------------------------------*/
7259 /* genDataPointerGet - generates code when ptr offset is known */
7260 /*-----------------------------------------------------------------*/
7262 genDataPointerGet (operand * left,
7270 D(emitcode ("; genDataPointerGet",""));
7272 aopOp (result, ic, TRUE);
7273 size = AOP_SIZE (result);
7275 derefaop = aopDerefAop (AOP (left));
7276 freeAsmop (left, NULL, ic, TRUE);
7277 derefaop->size = size;
7282 transferAopAop (derefaop, size, AOP (result), size);
7284 loadRegFromAop (hc08_reg_a, derefaop, size);
7287 freeAsmop (NULL, derefaop, ic, TRUE);
7288 freeAsmop (result, NULL, ic, TRUE);
7290 if (ifx && !ifx->generated)
7292 genIfxJump (ifx, "a");
7297 /*-----------------------------------------------------------------*/
7298 /* genPointerGet - generate code for pointer get */
7299 /*-----------------------------------------------------------------*/
7301 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7303 operand *left = IC_LEFT (ic);
7304 operand *result = IC_RESULT (ic);
7306 sym_link *retype = getSpec (operandType (result));
7308 D(emitcode ("; genPointerGet",""));
7310 if (getSize (operandType (result))>1)
7313 aopOp (left, ic, FALSE);
7315 /* if left is rematerialisable and
7316 result is not bit variable type */
7317 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7319 if (!IS_BITVAR (retype))
7321 genDataPointerGet (left, result, ic, ifx);
7326 genUnpackBitsImmed (left, result, ic, ifx);
7331 /* if the operand is already in hx
7332 then we do nothing else we move the value to hx */
7333 if (AOP_TYPE (left) != AOP_STR)
7335 /* if this is remateriazable */
7336 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7339 /* so hx now contains the address */
7340 aopOp (result, ic, FALSE);
7342 /* if bit then unpack */
7343 if (IS_BITVAR (retype))
7344 genUnpackBits (result, ifx);
7347 size = AOP_SIZE (result);
7352 accopWithMisc ("lda", ",x");
7355 emitcode ("aix", "#1");
7356 hc08_dirtyReg (hc08_reg_hx, FALSE);
7359 storeRegToAop (hc08_reg_a, AOP (result), offset);
7361 hc08_freeReg (hc08_reg_a);
7365 freeAsmop (left, NULL, ic, TRUE);
7366 freeAsmop (result, NULL, ic, TRUE);
7369 aopOp (IC_RESULT (pi), pi, FALSE);
7370 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7371 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7375 if (ifx && !ifx->generated)
7377 genIfxJump (ifx, "a");
7380 hc08_freeReg (hc08_reg_hx);
7384 /*-----------------------------------------------------------------*/
7385 /* genPackBits - generates code for packed bit storage */
7386 /*-----------------------------------------------------------------*/
7388 genPackBits (sym_link * etype,
7391 int offset = 0; /* source byte offset */
7392 int rlen = 0; /* remaining bitfield length */
7393 int blen; /* bitfield length */
7394 int bstr; /* bitfield starting bit within byte */
7395 int litval; /* source literal value (if AOP_LIT) */
7396 unsigned char mask; /* bitmask within current byte */
7399 D(emitcode ("; genPackBits",""));
7401 blen = SPEC_BLEN (etype);
7402 bstr = SPEC_BSTR (etype);
7404 /* If the bitfield length is less than a byte */
7407 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7408 (unsigned char) (0xFF >> (8 - bstr)));
7410 if (AOP_TYPE (right) == AOP_LIT)
7412 /* Case with a bitfield length <8 and literal source
7414 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
7416 litval &= (~mask) & 0xff;
7418 emitcode ("lda", ",x");
7419 if ((mask|litval)!=0xff)
7420 emitcode ("and","#0x%02x", mask);
7422 emitcode ("ora","#0x%02x", litval);
7423 hc08_dirtyReg (hc08_reg_a, FALSE);
7424 emitcode ("sta", ",x");
7426 hc08_freeReg (hc08_reg_a);
7430 /* Case with a bitfield length < 8 and arbitrary source
7432 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7433 /* shift and mask source value */
7435 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7436 hc08_dirtyReg (hc08_reg_a, FALSE);
7437 pushReg (hc08_reg_a, TRUE);
7439 emitcode ("lda", ",x");
7440 emitcode ("and", "#0x%02x", mask);
7441 emitcode ("ora", "1,s");
7442 emitcode ("sta", ",x");
7443 pullReg (hc08_reg_a);
7445 hc08_freeReg (hc08_reg_a);
7449 /* Bit length is greater than 7 bits. In this case, copy */
7450 /* all except the partial byte at the end */
7451 for (rlen=blen;rlen>=8;rlen-=8)
7453 if (AOP (right)->type == AOP_DIR)
7455 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7460 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7461 emitcode ("sta", "%d,x", offset);
7466 /* If there was a partial byte at the end */
7469 mask = (((unsigned char) -1 << rlen) & 0xff);
7471 if (AOP_TYPE (right) == AOP_LIT)
7473 /* Case with partial byte and literal source
7475 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
7476 litval >>= (blen-rlen);
7477 litval &= (~mask) & 0xff;
7478 emitcode ("lda", "%d,x", offset - xoffset);
7479 hc08_dirtyReg (hc08_reg_a, FALSE);
7480 if ((mask|litval)!=0xff)
7481 emitcode ("and","#0x%02x", mask);
7483 emitcode ("ora","#0x%02x", litval);
7484 emitcode ("sta", "%d,x", offset - xoffset);
7485 hc08_dirtyReg (hc08_reg_a, FALSE);
7486 hc08_freeReg (hc08_reg_a);
7490 /* Case with partial byte and arbitrary source
7492 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7493 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7494 hc08_dirtyReg (hc08_reg_a, FALSE);
7495 pushReg (hc08_reg_a, TRUE);
7497 emitcode ("lda", "%d,x", offset - xoffset);
7498 emitcode ("and", "#0x%02x", mask);
7499 emitcode ("ora", "1,s");
7500 emitcode ("sta", "%d,x", offset - xoffset);
7501 pullReg (hc08_reg_a);
7504 hc08_freeReg (hc08_reg_a);
7507 /*-----------------------------------------------------------------*/
7508 /* genPackBitsImmed - generates code for packed bit storage */
7509 /*-----------------------------------------------------------------*/
7511 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7515 int offset = 0; /* source byte offset */
7516 int rlen = 0; /* remaining bitfield length */
7517 int blen; /* bitfield length */
7518 int bstr; /* bitfield starting bit within byte */
7519 int litval; /* source literal value (if AOP_LIT) */
7520 unsigned char mask; /* bitmask within current byte */
7522 D(emitcode ("; genPackBitsImmed",""));
7524 blen = SPEC_BLEN (etype);
7525 bstr = SPEC_BSTR (etype);
7527 aopOp (right, ic, FALSE);
7528 size = AOP_SIZE (right);
7530 derefaop = aopDerefAop (AOP (result));
7531 freeAsmop (result, NULL, ic, TRUE);
7532 derefaop->size = size;
7534 /* if the bitfield is a single bit in the direct page */
7535 if (blen == 1 && derefaop->type == AOP_DIR)
7537 if (AOP_TYPE (right) == AOP_LIT)
7539 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
7541 emitcode ((litval & 1) ? "bset" : "bclr",
7542 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7546 symbol *tlbl1 = newiTempLabel (NULL);
7547 symbol *tlbl2 = newiTempLabel (NULL);
7549 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7550 emitcode ("bit", "#1");
7551 emitBranch ("bne", tlbl1);
7552 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7553 emitBranch ("bra", tlbl2);
7555 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7557 hc08_freeReg (hc08_reg_a);
7562 /* If the bitfield length is less than a byte */
7565 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7566 (unsigned char) (0xFF >> (8 - bstr)));
7568 if (AOP_TYPE (right) == AOP_LIT)
7570 /* Case with a bitfield length <8 and literal source
7572 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
7574 litval &= (~mask) & 0xff;
7576 loadRegFromAop (hc08_reg_a, derefaop, 0);
7577 if ((mask|litval)!=0xff)
7578 emitcode ("and","#0x%02x", mask);
7580 emitcode ("ora","#0x%02x", litval);
7581 hc08_dirtyReg (hc08_reg_a, FALSE);
7582 storeRegToAop (hc08_reg_a, derefaop, 0);
7584 hc08_freeReg (hc08_reg_a);
7588 /* Case with a bitfield length < 8 and arbitrary source
7590 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7591 /* shift and mask source value */
7593 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7594 hc08_dirtyReg (hc08_reg_a, FALSE);
7595 pushReg (hc08_reg_a, TRUE);
7597 loadRegFromAop (hc08_reg_a, derefaop, 0);
7598 emitcode ("and", "#0x%02x", mask);
7599 emitcode ("ora", "1,s");
7600 storeRegToAop (hc08_reg_a, derefaop, 0);
7601 pullReg (hc08_reg_a);
7603 hc08_freeReg (hc08_reg_a);
7607 /* Bit length is greater than 7 bits. In this case, copy */
7608 /* all except the partial byte at the end */
7609 for (rlen=blen;rlen>=8;rlen-=8)
7611 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7615 /* If there was a partial byte at the end */
7618 mask = (((unsigned char) -1 << rlen) & 0xff);
7620 if (AOP_TYPE (right) == AOP_LIT)
7622 /* Case with partial byte and literal source
7624 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
7625 litval >>= (blen-rlen);
7626 litval &= (~mask) & 0xff;
7627 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7628 if ((mask|litval)!=0xff)
7629 emitcode ("and","#0x%02x", mask);
7631 emitcode ("ora","#0x%02x", litval);
7632 hc08_dirtyReg (hc08_reg_a, FALSE);
7633 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7634 hc08_dirtyReg (hc08_reg_a, FALSE);
7635 hc08_freeReg (hc08_reg_a);
7639 /* Case with partial byte and arbitrary source
7641 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7642 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7643 hc08_dirtyReg (hc08_reg_a, FALSE);
7644 pushReg (hc08_reg_a, TRUE);
7646 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7647 emitcode ("and", "#0x%02x", mask);
7648 emitcode ("ora", "1,s");
7649 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7650 pullReg (hc08_reg_a);
7653 hc08_freeReg (hc08_reg_a);
7656 freeAsmop (right, NULL, ic, TRUE);
7657 freeAsmop (NULL, derefaop, ic, TRUE);
7660 /*-----------------------------------------------------------------*/
7661 /* genDataPointerSet - remat pointer to data space */
7662 /*-----------------------------------------------------------------*/
7664 genDataPointerSet (operand * right,
7671 D(emitcode ("; genDataPointerSet",""));
7673 aopOp (right, ic, FALSE);
7674 size = AOP_SIZE (right);
7676 derefaop = aopDerefAop (AOP (result));
7677 freeAsmop (result, NULL, ic, TRUE);
7678 derefaop->size = size;
7682 transferAopAop (AOP (right), size, derefaop, size);
7685 freeAsmop (right, NULL, ic, TRUE);
7686 freeAsmop (NULL, derefaop, ic, TRUE);
7690 /*-----------------------------------------------------------------*/
7691 /* genPointerSet - stores the value into a pointer location */
7692 /*-----------------------------------------------------------------*/
7694 genPointerSet (iCode * ic, iCode *pi)
7696 operand *right = IC_RIGHT (ic);
7697 operand *result = IC_RESULT (ic);
7698 sym_link *type, *etype;
7700 sym_link *retype = getSpec (operandType (right));
7701 sym_link *letype = getSpec (operandType (result));
7703 D(emitcode ("; genPointerSet",""));
7705 type = operandType (result);
7706 etype = getSpec (type);
7708 aopOp (result, ic, FALSE);
7710 /* if the result is rematerializable */
7711 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7713 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7715 genDataPointerSet (right, result, ic);
7720 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7725 /* if the operand is already in hx
7726 then we do nothing else we move the value to hx */
7727 if (AOP_TYPE (result) != AOP_STR)
7729 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7731 /* so hx now contains the address */
7732 aopOp (right, ic, FALSE);
7734 /* if bit then unpack */
7735 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7736 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7739 size = AOP_SIZE (right);
7744 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7745 accopWithMisc ("sta", ",x");
7748 emitcode ("aix", "#1");
7750 hc08_freeReg (hc08_reg_a);
7754 freeAsmop (result, NULL, ic, TRUE);
7755 freeAsmop (right, NULL, ic, TRUE);
7758 aopOp (IC_RESULT (pi), pi, FALSE);
7759 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7760 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7764 hc08_freeReg (hc08_reg_hx);
7768 /*-----------------------------------------------------------------*/
7769 /* genIfx - generate code for Ifx statement */
7770 /*-----------------------------------------------------------------*/
7772 genIfx (iCode * ic, iCode * popIc)
7774 operand *cond = IC_COND (ic);
7777 D(emitcode ("; genIfx",""));
7779 aopOp (cond, ic, FALSE);
7781 /* If the condition is a literal, we can just do an unconditional */
7782 /* branch or no branch */
7783 if (AOP_TYPE (cond) == AOP_LIT)
7785 unsigned long lit = ulFromVal (AOP (cond)->aopu.aop_lit);
7786 freeAsmop (cond, NULL, ic, TRUE);
7788 /* if there was something to be popped then do it */
7794 emitBranch ("jmp", IC_TRUE (ic));
7799 emitBranch ("jmp", IC_FALSE (ic));
7805 /* get the value into acc */
7806 if (AOP_TYPE (cond) != AOP_CRY)
7807 asmopToBool (AOP (cond), FALSE);
7810 /* the result is now in the accumulator */
7811 freeAsmop (cond, NULL, ic, TRUE);
7813 /* if there was something to be popped then do it */
7817 /* if the condition is a bit variable */
7818 if (isbit && IS_ITEMP (cond) &&
7820 genIfxJump (ic, SPIL_LOC (cond)->rname);
7821 else if (isbit && !IS_ITEMP (cond))
7822 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7824 genIfxJump (ic, "a");
7829 /*-----------------------------------------------------------------*/
7830 /* genAddrOf - generates code for address of */
7831 /*-----------------------------------------------------------------*/
7833 genAddrOf (iCode * ic)
7835 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7838 D(emitcode ("; genAddrOf",""));
7840 aopOp (IC_RESULT (ic), ic, FALSE);
7842 /* if the operand is on the stack then we
7843 need to get the stack offset of this
7847 /* if it has an offset then we need to compute it */
7848 offset = _G.stackOfs + _G.stackPushes + sym->stack;
7849 hc08_useReg (hc08_reg_hx);
7850 emitcode ("tsx", "");
7851 while (offset > 127)
7853 emitcode ("aix", "#127");
7856 while (offset < -128)
7858 emitcode ("aix", "#-128");
7861 emitcode ("aix", "#%d", offset);
7862 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7863 hc08_freeReg (hc08_reg_hx);
7868 /* object not on stack then we need the name */
7869 size = AOP_SIZE (IC_RESULT (ic));
7874 char s[SDCC_NAME_MAX+10];
7877 sprintf (s, "#%s", sym->rname);
7880 sprintf (s, "#>%s", sym->rname);
7883 sprintf (s, "#(%s >> %d)",
7887 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7891 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7895 /*-----------------------------------------------------------------*/
7896 /* genAssign - generate code for assignment */
7897 /*-----------------------------------------------------------------*/
7899 genAssign (iCode * ic)
7901 operand *result, *right;
7903 // unsigned long lit = 0L;
7905 D(emitcode("; genAssign",""));
7907 result = IC_RESULT (ic);
7908 right = IC_RIGHT (ic);
7910 /* if they are the same */
7911 if (operandsEqu (result, right)) {
7915 aopOp (right, ic, FALSE);
7916 aopOp (result, ic, TRUE);
7918 /* if they are the same registers */
7919 if (sameRegs (AOP (right), AOP (result)))
7922 if ((AOP_TYPE (right) == AOP_LIT)
7923 && (IS_AOP_HX(AOP(result))))
7925 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7930 size = AOP_SIZE (result);
7933 transferAopAop (AOP (right), size, AOP (result), size);
7937 freeAsmop (right, NULL, ic, TRUE);
7938 freeAsmop (result, NULL, ic, TRUE);
7941 /*-----------------------------------------------------------------*/
7942 /* genJumpTab - generates code for jump table */
7943 /*-----------------------------------------------------------------*/
7945 genJumpTab (iCode * ic)
7948 symbol *jtablo = newiTempLabel (NULL);
7949 symbol *jtabhi = newiTempLabel (NULL);
7951 D(emitcode ("; genJumpTab",""));
7953 aopOp (IC_JTCOND (ic), ic, FALSE);
7955 if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7957 /* get the condition into x */
7958 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7959 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7960 loadRegFromConst (hc08_reg_h, zero);
7962 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7963 emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7964 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7965 emitcode ("jmp", ",x");
7967 hc08_dirtyReg (hc08_reg_a, TRUE);
7968 hc08_dirtyReg (hc08_reg_hx, TRUE);
7973 pushReg(hc08_reg_hx, TRUE);
7975 /* get the condition into x */
7976 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7977 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7978 loadRegFromConst (hc08_reg_h, zero);
7980 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7981 emitcode ("sta", "3,s");
7982 emitcode ("lda", "%05d$,x", jtablo->key + 100);
7983 emitcode ("sta", "4,s");
7985 pullReg(hc08_reg_hx);
7986 emitcode ("rts", "");
7987 _G.stackPushes += 2;
7991 /* now generate the jump labels */
7993 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7994 jtab = setNextItem (IC_JTLABELS (ic)))
7995 emitcode (".db", "%05d$", jtab->key + 100);
7997 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7998 jtab = setNextItem (IC_JTLABELS (ic)))
7999 emitcode (".db", ">%05d$", jtab->key + 100);
8003 /*-----------------------------------------------------------------*/
8004 /* genCast - gen code for casting */
8005 /*-----------------------------------------------------------------*/
8007 genCast (iCode * ic)
8009 operand *result = IC_RESULT (ic);
8010 sym_link *ctype = operandType (IC_LEFT (ic));
8011 sym_link *rtype = operandType (IC_RIGHT (ic));
8012 operand *right = IC_RIGHT (ic);
8015 D(emitcode("; genCast",""));
8017 /* if they are equivalent then do nothing */
8018 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8021 aopOp (right, ic, FALSE);
8022 aopOp (result, ic, FALSE);
8025 /* if they are the same size : or less */
8026 if (AOP_SIZE (result) <= AOP_SIZE (right))
8029 /* if they are in the same place */
8031 if (sameRegs (AOP (right), AOP (result)))
8035 /* if they in different places then copy */
8036 size = AOP_SIZE (result);
8040 transferAopAop(AOP (right), offset, AOP (result), offset);
8047 /* if the result is of type pointer */
8052 sym_link *type = operandType (right);
8053 sym_link *etype = getSpec (type);
8055 /* pointer to generic pointer */
8056 if (IS_GENPTR (ctype))
8059 p_type = DCL_TYPE (type);
8062 if (SPEC_SCLS(etype)==S_REGISTER) {
8063 // let's assume it is a generic pointer
8066 /* we have to go by the storage class */
8067 p_type = PTR_TYPE (SPEC_OCLS (etype));
8071 /* the first two bytes are known */
8072 size = GPTRSIZE - 1;
8076 transferAopAop(AOP (right), offset, AOP (result), offset);
8079 /* the last byte depending on type */
8082 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8087 // pointerTypeToGPByte will have bitched.
8091 sprintf(gpValStr, "#0x%x", gpVal);
8092 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8098 /* just copy the pointers */
8099 size = AOP_SIZE (result);
8103 transferAopAop(AOP (right), offset, AOP (result), offset);
8109 /* so we now know that the size of destination is greater
8110 than the size of the source */
8111 /* we move to result for the size of source */
8112 size = AOP_SIZE (right);
8116 transferAopAop(AOP (right), offset, AOP (result), offset);
8120 /* now depending on the sign of the source && destination */
8121 size = AOP_SIZE (result) - AOP_SIZE (right);
8122 /* if unsigned or not an integral type */
8123 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8126 storeConstToAop (zero, AOP (result), offset++);
8130 /* we need to extend the sign :{ */
8131 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
8132 accopWithMisc ("rola", "");
8133 accopWithMisc ("clra", "");
8134 accopWithMisc ("sbc", zero);
8136 storeRegToAop (hc08_reg_a, AOP (result), offset++);
8139 /* we are done hurray !!!! */
8142 freeAsmop (right, NULL, ic, TRUE);
8143 freeAsmop (result, NULL, ic, TRUE);
8147 /*-----------------------------------------------------------------*/
8148 /* genDjnz - generate decrement & jump if not zero instrucion */
8149 /*-----------------------------------------------------------------*/
8151 genDjnz (iCode * ic, iCode * ifx)
8157 D(emitcode ("; genDjnz",""));
8159 /* if the if condition has a false label
8160 then we cannot save */
8164 /* if the minus is not of the form
8166 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8167 !IS_OP_LITERAL (IC_RIGHT (ic)))
8170 if (operandLitValue (IC_RIGHT (ic)) != 1)
8173 /* dbnz doesn't support extended mode */
8174 if (isOperandInFarSpace (IC_RESULT (ic)))
8177 /* if the size of this greater than one then no
8179 // if (getSize (operandType (IC_RESULT (ic))) > 1)
8181 aopOp (IC_RESULT (ic), ic, FALSE);
8182 if (AOP_SIZE (IC_RESULT (ic))>1)
8184 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8188 /* otherwise we can save BIG */
8189 lbl = newiTempLabel (NULL);
8190 lbl1 = newiTempLabel (NULL);
8193 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
8196 emitBranch ("bra", lbl1);
8198 emitBranch ("jmp", IC_TRUE (ifx));
8201 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8206 /*-----------------------------------------------------------------*/
8207 /* genReceive - generate code for a receive iCode */
8208 /*-----------------------------------------------------------------*/
8210 genReceive (iCode * ic)
8214 D(emitcode ("; genReceive",""));
8216 aopOp (IC_RESULT (ic), ic, FALSE);
8217 size = AOP_SIZE (IC_RESULT (ic));
8222 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
8223 AOP (IC_RESULT (ic)), offset);
8224 if (hc08_aop_pass[offset]->type == AOP_REG)
8225 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
8230 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8233 /*-----------------------------------------------------------------*/
8234 /* genDummyRead - generate code for dummy read of volatiles */
8235 /*-----------------------------------------------------------------*/
8237 genDummyRead (iCode * ic)
8242 D(emitcode("; genDummyRead",""));
8245 if (op && IS_SYMOP (op))
8248 aopOp (op, ic, FALSE);
8250 size = AOP_SIZE (op);
8255 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8256 hc08_freeReg (hc08_reg_a);
8260 freeAsmop (op, NULL, ic, TRUE);
8263 if (op && IS_SYMOP (op))
8266 aopOp (op, ic, FALSE);
8268 size = AOP_SIZE (op);
8273 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8274 hc08_freeReg (hc08_reg_a);
8278 freeAsmop (op, NULL, ic, TRUE);
8282 /*-----------------------------------------------------------------*/
8283 /* genCritical - generate code for start of a critical sequence */
8284 /*-----------------------------------------------------------------*/
8286 genCritical (iCode *ic)
8288 D(emitcode("; genCritical",""));
8291 aopOp (IC_RESULT (ic), ic, TRUE);
8293 emitcode ("tpa", "");
8294 hc08_dirtyReg (hc08_reg_a, FALSE);
8295 emitcode ("sei", "");
8298 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8300 pushReg (hc08_reg_a, FALSE);
8302 hc08_freeReg (hc08_reg_a);
8304 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8307 /*-----------------------------------------------------------------*/
8308 /* genEndCritical - generate code for end of a critical sequence */
8309 /*-----------------------------------------------------------------*/
8311 genEndCritical (iCode *ic)
8313 D(emitcode("; genEndCritical",""));
8317 aopOp (IC_RIGHT (ic), ic, FALSE);
8318 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8319 emitcode ("tap", "");
8320 hc08_freeReg (hc08_reg_a);
8321 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8325 pullReg (hc08_reg_a);
8326 emitcode ("tap", "");
8332 /*-----------------------------------------------------------------*/
8333 /* genhc08Code - generate code for HC08 based controllers */
8334 /*-----------------------------------------------------------------*/
8336 genhc08Code (iCode * lic)
8343 lineHead = lineCurr = NULL;
8345 /* print the allocation information */
8346 if (allocInfo && currFunc)
8347 printAllocInfo (currFunc, codeOutBuf);
8348 /* if debug information required */
8349 if (options.debug && currFunc)
8351 debugFile->writeFunction (currFunc, lic);
8354 if (IS_STATIC (currFunc->etype))
8355 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8357 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8361 /* stack pointer name */
8362 if (options.useXstack)
8367 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8369 hc08_aop_pass[0] = newAsmop (AOP_REG);
8370 hc08_aop_pass[0]->size=1;
8371 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8372 hc08_aop_pass[1] = newAsmop (AOP_REG);
8373 hc08_aop_pass[1]->size=1;
8374 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8375 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8376 hc08_aop_pass[2]->size=1;
8377 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8378 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8379 hc08_aop_pass[3]->size=1;
8380 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8382 for (ic = lic; ic; ic = ic->next)
8385 _G.current_iCode = ic;
8387 if (ic->level != clevel || ic->block != cblock)
8391 debugFile->writeScope(ic);
8397 if (ic->lineno && cln != ic->lineno)
8401 debugFile->writeCLine(ic);
8404 emitcode ("", "C$%s$%d$%d$%d ==.",
8405 FileBaseName (ic->filename), ic->lineno,
8406 ic->level, ic->block);
8410 if (!options.noCcodeInAsm) {
8411 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8412 printCLine(ic->filename, ic->lineno));
8416 if (options.iCodeInAsm) {
8421 for (i=0; i<6; i++) {
8422 sprintf (®sInUse[i],
8423 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8426 iLine = printILine(ic);
8427 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8430 /* if the result is marked as
8431 spilt and rematerializable or code for
8432 this has already been generated then
8434 if (resultRemat (ic) || ic->generated)
8442 for (i=A_IDX;i<=XA_IDX;i++)
8444 reg = hc08_regWithIdx(i);
8446 emitcode("","; %s = %s offset %d", reg->name,
8447 aopName(reg->aop), reg->aopofs);
8450 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8452 sym = OP_SYMBOL (IC_LEFT (ic));
8453 if (sym->accuse == ACCUSE_HX)
8455 hc08_reg_h->isFree = FALSE;
8456 hc08_reg_x->isFree = FALSE;
8458 else if (sym->accuse == ACCUSE_XA)
8460 hc08_reg_a->isFree = FALSE;
8462 hc08_reg_x->isFree = FALSE;
8465 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8467 sym = OP_SYMBOL (IC_RIGHT (ic));
8468 if (sym->accuse == ACCUSE_HX)
8470 hc08_reg_h->isFree = FALSE;
8471 hc08_reg_x->isFree = FALSE;
8473 else if (sym->accuse == ACCUSE_XA)
8475 hc08_reg_a->isFree = FALSE;
8477 hc08_reg_x->isFree = FALSE;
8482 /* depending on the operation */
8502 /* IPOP happens only when trying to restore a
8503 spilt live range, if there is an ifx statement
8504 following this pop then the if statement might
8505 be using some of the registers being popped which
8506 would destory the contents of the register so
8507 we need to check for this condition and handle it */
8509 ic->next->op == IFX &&
8510 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8511 genIfx (ic->next, ic);
8529 genEndFunction (ic);
8545 if (!genPointerGetSetOfs (ic))
8550 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8570 genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
8575 genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
8587 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8591 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8595 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8622 case GET_VALUE_AT_ADDRESS:
8624 hasInc (IC_LEFT (ic), ic,
8625 getSize (operandType (IC_RESULT (ic)))),
8626 ifxForOp (IC_RESULT (ic), ic) );
8630 if (POINTER_SET (ic))
8631 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8657 addSet (&_G.sendSet, ic);
8660 case DUMMY_READ_VOLATILE:
8669 genEndCritical (ic);
8680 if (!hc08_reg_a->isFree)
8681 DD(emitcode("","; forgot to free a"));
8682 if (!hc08_reg_x->isFree)
8683 DD(emitcode("","; forgot to free x"));
8684 if (!hc08_reg_h->isFree)
8685 DD(emitcode("","; forgot to free h"));
8686 if (!hc08_reg_hx->isFree)
8687 DD(emitcode("","; forgot to free hx"));
8688 if (!hc08_reg_xa->isFree)
8689 DD(emitcode("","; forgot to free xa"));
8692 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8695 /* now we are ready to call the
8696 peep hole optimizer */
8697 if (!options.nopeep)
8698 peepHole (&lineHead);
8700 /* now do the actual printing */
8701 printLine (lineHead, codeOutBuf);