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 - rematerializes 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))
1509 sym_link *from_type = operandType(IC_RIGHT(ic));
1510 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1511 ptr_type = DCL_TYPE(from_type);
1512 if (ptr_type == IPOINTER)
1520 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1523 if (ic->op == ADDRESS_OF)
1527 SNPRINTF (buffer, sizeof(buffer),
1529 OP_SYMBOL (IC_LEFT (ic))->rname,
1530 val >= 0 ? '+' : '-',
1531 abs (val) & 0xffff);
1535 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
1538 aop = newAsmop (AOP_IMMD);
1539 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
1540 /* set immd2 field if required */
1542 else if (ic->op == '=')
1544 val += (int) operandLitValue (IC_RIGHT (ic));
1546 SNPRINTF (buffer, sizeof(buffer), "0x%04x", val);
1547 aop = newAsmop (AOP_LIT);
1548 aop->aopu.aop_lit = constVal (buffer);
1552 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1553 "unexpected rematerialization");
1559 /*-----------------------------------------------------------------*/
1560 /* regsInCommon - two operands have some registers in common */
1561 /*-----------------------------------------------------------------*/
1563 regsInCommon (operand * op1, operand * op2)
1565 symbol *sym1, *sym2;
1568 /* if they have registers in common */
1569 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1572 sym1 = OP_SYMBOL (op1);
1573 sym2 = OP_SYMBOL (op2);
1575 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1578 for (i = 0; i < sym1->nRegs; i++)
1584 for (j = 0; j < sym2->nRegs; j++)
1589 if (sym2->regs[j] == sym1->regs[i])
1597 /*-----------------------------------------------------------------*/
1598 /* operandsEqu - equivalent */
1599 /*-----------------------------------------------------------------*/
1601 operandsEqu (operand * op1, operand * op2)
1603 symbol *sym1, *sym2;
1605 /* if they not symbols */
1606 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1609 sym1 = OP_SYMBOL (op1);
1610 sym2 = OP_SYMBOL (op2);
1612 /* if both are itemps & one is spilt
1613 and the other is not then false */
1614 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1615 sym1->isspilt != sym2->isspilt)
1618 /* if they are the same */
1622 /* if they have the same rname */
1623 if (sym1->rname[0] && sym2->rname[0]
1624 && strcmp (sym1->rname, sym2->rname) == 0)
1627 /* if left is a tmp & right is not */
1628 if (IS_ITEMP (op1) &&
1631 (sym1->usl.spillLoc == sym2))
1634 if (IS_ITEMP (op2) &&
1638 (sym2->usl.spillLoc == sym1))
1644 /*-----------------------------------------------------------------*/
1645 /* sameRegs - two asmops have the same registers */
1646 /*-----------------------------------------------------------------*/
1648 sameRegs (asmop * aop1, asmop * aop2)
1655 // if (aop1->size != aop2->size)
1658 if (aop1->type == aop2->type)
1663 for (i = 0; i < aop1->size; i++)
1664 if (aop1->aopu.aop_reg[i] !=
1665 aop2->aopu.aop_reg[i])
1669 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1672 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1679 /*-----------------------------------------------------------------*/
1680 /* aopOp - allocates an asmop for an operand : */
1681 /*-----------------------------------------------------------------*/
1683 aopOp (operand * op, iCode * ic, bool result)
1692 // Is this a pointer set result?
1694 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1698 // printf("checking literal\n");
1699 /* if this a literal */
1700 if (IS_OP_LITERAL (op))
1702 op->aop = aop = newAsmop (AOP_LIT);
1703 aop->aopu.aop_lit = op->operand.valOperand;
1704 aop->size = getSize (operandType (op));
1706 aop->isaddr = op->isaddr;
1710 // printf("checking pre-existing\n");
1711 /* if already has a asmop then continue */
1715 op->aop->isaddr = op->isaddr;
1719 // printf("checking underlying sym\n");
1720 /* if the underlying symbol has a aop */
1721 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1723 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1724 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1725 //op->aop = aop = OP_SYMBOL (op)->aop;
1726 aop->size = getSize( operandType (op));
1727 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1728 //printf (" with size = %d\n", aop->size);
1731 aop->isaddr = op->isaddr;
1732 /* if (aop->isaddr & IS_ITEMP (op))
1734 aop->psize=aop->size;
1735 aop->size = getSize( operandType (op)->next);
1740 // printf("checking true sym\n");
1741 /* if this is a true symbol */
1742 if (IS_TRUE_SYMOP (op))
1744 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1746 aop->isaddr = op->isaddr;
1747 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1748 //printf (" with size = %d\n", aop->size);
1752 /* this is a temporary : this has
1758 e) can be a return use only */
1760 sym = OP_SYMBOL (op);
1762 // printf("checking conditional\n");
1763 /* if the type is a conditional */
1764 if (sym->regType == REG_CND)
1766 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1769 aop->isaddr = op->isaddr;
1773 // printf("checking spilt\n");
1774 /* if it is spilt then two situations
1776 b) has a spill location */
1777 if (sym->isspilt || sym->nRegs == 0)
1780 // printf("checking remat\n");
1781 /* rematerialize it NOW */
1784 sym->aop = op->aop = aop = aopForRemat (sym);
1785 aop->size = getSize (sym->type);
1787 aop->isaddr = op->isaddr;
1788 /* if (aop->isaddr & IS_ITEMP (op))
1790 aop->psize=aop->size;
1791 aop->size = getSize( operandType (op)->next);
1796 // printf("checking accuse\n");
1799 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1800 aop->size = getSize (sym->type);
1801 switch (sym->accuse)
1804 aop->aopu.aop_reg[0] = hc08_reg_a;
1805 aop->aopu.aop_reg[1] = hc08_reg_x;
1808 aop->aopu.aop_reg[0] = hc08_reg_x;
1809 aop->aopu.aop_reg[1] = hc08_reg_h;
1813 aop->isaddr = op->isaddr;
1817 // printf("checking ruonly\n");
1823 sym->aop = op->aop = aop = newAsmop (AOP_STR);
1824 aop->size = getSize (sym->type);
1825 for (i = 0; i < fReturnSizeHC08; i++)
1826 aop->aopu.aop_str[i] = fReturn2[i];
1828 aop->isaddr = op->isaddr;
1832 /* else spill location */
1833 if (sym->usl.spillLoc)
1835 asmop *oldAsmOp = NULL;
1837 if (sym->usl.spillLoc->aop
1838 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1840 /* force a new aop if sizes differ */
1841 oldAsmOp = sym->usl.spillLoc->aop;
1842 sym->usl.spillLoc->aop = NULL;
1843 //printf ("forcing new aop\n");
1845 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1846 if (sym->usl.spillLoc->aop->size != getSize (sym->type))
1848 /* Don't reuse the new aop, go with the last one */
1849 sym->usl.spillLoc->aop = oldAsmOp;
1851 aop->size = getSize (sym->type);
1853 aop->isaddr = op->isaddr;
1854 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1855 //printf (" with size = %d\n", aop->size);
1859 /* else must be a dummy iTemp */
1860 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1861 aop->size = getSize (sym->type);
1865 // printf("assuming register\n");
1866 /* must be in a register */
1867 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1868 aop->size = sym->nRegs;
1869 for (i = 0; i < sym->nRegs; i++)
1870 aop->aopu.aop_reg[i] = sym->regs[i];
1872 aop->isaddr = op->isaddr;
1876 /*-----------------------------------------------------------------*/
1877 /* freeAsmop - free up the asmop given to an operand */
1878 /*----------------------------------------------------------------*/
1880 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1902 DD(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1905 for (loffset=0; loffset<aop->size; loffset++)
1906 if (aop->stk_aop[loffset])
1908 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1911 pullNull (stackAdjust);
1915 /* all other cases just dealloc */
1921 OP_SYMBOL (op)->aop = NULL;
1922 /* if the symbol has a spill */
1924 SPIL_LOC (op)->aop = NULL;
1930 /*-----------------------------------------------------------------*/
1931 /* aopDerefAop - treating the aop parameter as a pointer, return */
1932 /* an asmop for the object it references */
1933 /*-----------------------------------------------------------------*/
1935 aopDerefAop (asmop *aop)
1940 asmop *newaop = NULL;
1941 sym_link *type, *etype;
1944 DD(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1948 type = operandType (aop->op);
1949 etype = getSpec (type);
1950 /* if op is of type of pointer then it is simple */
1951 if (IS_PTR (type) && !IS_FUNC (type->next))
1952 p_type = DCL_TYPE (type);
1955 /* we have to go by the storage class */
1956 p_type = PTR_TYPE (SPEC_OCLS (etype));
1965 if (p_type == POINTER)
1966 newaop = newAsmop (AOP_DIR);
1968 newaop = newAsmop (AOP_EXT);
1969 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1972 adr = (int) ulFromVal (aop->aopu.aop_lit);
1973 if (p_type == POINTER)
1978 newaop = newAsmop (AOP_DIR);
1979 sprintf (s, "0x%02x",adr);
1983 newaop = newAsmop (AOP_EXT);
1984 sprintf (s, "0x%04x",adr);
1986 rs = Safe_calloc (1, strlen (s) + 1);
1988 newaop->aopu.aop_dir = rs;
1991 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1992 "unsupported asmop");
2002 /*-----------------------------------------------------------------*/
2003 /* aopAdrStr - for referencing the address of the aop */
2004 /*-----------------------------------------------------------------*/
2006 aopAdrStr (asmop * aop, int loffset, bool bit16)
2010 int offset = aop->size - 1 - loffset;
2013 /* offset is greater than
2015 if (loffset > (aop->size - 1) &&
2016 aop->type != AOP_LIT)
2019 /* depending on type */
2027 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1)))
2029 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
2033 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
2038 sprintf (s, "#(%s >> %d)",
2039 aop->aopu.aop_immd.aop_immd1,
2043 aop->aopu.aop_immd.aop_immd1);
2047 aop->aopu.aop_immd.aop_immd1);
2048 rs = Safe_calloc (1, strlen (s) + 1);
2054 sprintf (s, "*(%s + %d)",
2058 sprintf (s, "*%s", aop->aopu.aop_dir);
2059 rs = Safe_calloc (1, strlen (s) + 1);
2065 sprintf (s, "(%s + %d)",
2069 sprintf (s, "%s", aop->aopu.aop_dir);
2070 rs = Safe_calloc (1, strlen (s) + 1);
2075 return aop->aopu.aop_reg[loffset]->name;
2079 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
2081 return aopLiteral (aop->aopu.aop_lit, loffset);
2085 return aop->aopu.aop_str[loffset];
2088 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2090 rs = Safe_calloc (1, strlen (s) + 1);
2096 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2097 "aopAdrStr got unsupported aop->type");
2106 /*-----------------------------------------------------------------*/
2107 /* opIsGptr: returns non-zero if the passed operand is */
2108 /* a generic pointer type. */
2109 /*-----------------------------------------------------------------*/
2111 opIsGptr (operand * op)
2113 sym_link *type = operandType (op);
2115 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2123 /*-----------------------------------------------------------------*/
2124 /* getDataSize - get the operand data size */
2125 /*-----------------------------------------------------------------*/
2127 getDataSize (operand * op)
2130 size = AOP_SIZE (op);
2135 /*-----------------------------------------------------------------*/
2136 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2137 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2138 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2139 /*-----------------------------------------------------------------*/
2141 asmopToBool (asmop *aop, bool resultInA)
2143 symbol *tlbl, *tlbl1;
2144 int size = aop->size;
2145 bool needpula = FALSE;
2146 bool flagsonly = TRUE;
2151 hc08_freeReg(hc08_reg_a);
2158 emitcode ("tsta", "");
2161 else if (IS_AOP_X(aop))
2162 emitcode ("tstx", "");
2163 else if (IS_AOP_H(aop))
2165 if (hc08_reg_a->isFree)
2167 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2168 emitcode ("tsta", "");
2170 hc08_freeReg(hc08_reg_a);
2172 else if (hc08_reg_x->isFree)
2174 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2175 emitcode ("tstx", "");
2176 hc08_freeReg(hc08_reg_x);
2180 emitcode ("pshh", "");
2181 emitcode ("tst", "1,s");
2182 emitcode ("ais", "#1");
2185 else if (IS_AOP_HX(aop))
2186 emitcode ("cphx", zero);
2187 else if (IS_AOP_XA(aop))
2189 symbol *tlbl = newiTempLabel (NULL);
2190 emitcode ("tsta", "");
2191 emitcode ("bne", "%05d$", (tlbl->key + 100));
2192 emitcode ("tstx", "");
2197 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2198 "Bad rIdx in asmToBool");
2206 needpula = pushRegIfUsed (hc08_reg_a);
2207 loadRegFromAop (hc08_reg_a, aop, 0);
2208 for (offset=1; offset<size; offset++)
2209 accopWithAop ("ora", aop, offset);
2211 pullReg (hc08_reg_a);
2214 hc08_freeReg (hc08_reg_a);
2219 /* Higher levels should optimize this case away but let's be safe */
2220 if (ulFromVal (aop->aopu.aop_lit))
2221 loadRegFromConst (hc08_reg_a, one);
2223 loadRegFromConst (hc08_reg_a, zero);
2224 hc08_freeReg(hc08_reg_a);
2231 loadRegFromAop (hc08_reg_a, aop, 0);
2232 hc08_freeReg (hc08_reg_a);
2236 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2241 if (hc08_reg_a->isFree)
2243 loadRegFromAop (hc08_reg_a, aop, 0);
2244 accopWithAop ("ora", aop, 1);
2245 hc08_freeReg (hc08_reg_a);
2250 tlbl = newiTempLabel (NULL);
2251 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2252 emitcode ("bne", "%05d$", (tlbl->key + 100));
2253 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2260 needpula = pushRegIfUsed (hc08_reg_a);
2261 loadRegFromAop (hc08_reg_a, aop, 0);
2262 for (offset=1; offset<size; offset++)
2263 accopWithAop ("ora", aop, offset);
2265 pullReg (hc08_reg_a);
2268 hc08_freeReg (hc08_reg_a);
2276 tlbl = newiTempLabel (NULL);
2280 tlbl1 = newiTempLabel (NULL);
2281 emitBranch ("bne", tlbl1);
2282 loadRegFromConst (hc08_reg_a, zero);
2283 emitBranch ("bra", tlbl);
2285 loadRegFromConst (hc08_reg_a, one);
2289 emitBranch ("beq", tlbl);
2290 loadRegFromConst (hc08_reg_a, one);
2293 hc08_useReg (hc08_reg_a);
2299 /*-----------------------------------------------------------------*/
2300 /* genNot - generate code for ! operation */
2301 /*-----------------------------------------------------------------*/
2305 D(emitcode ("; genNot",""));
2307 /* assign asmOps to operand & result */
2308 aopOp (IC_LEFT (ic), ic, FALSE);
2309 aopOp (IC_RESULT (ic), ic, TRUE);
2311 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2312 emitcode ("eor", one);
2313 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2315 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2316 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2320 /*-----------------------------------------------------------------*/
2321 /* genCpl - generate code for complement */
2322 /*-----------------------------------------------------------------*/
2328 regs* reg = hc08_reg_a;
2330 D(emitcode ("; genCpl",""));
2332 /* assign asmOps to operand & result */
2333 aopOp (IC_LEFT (ic), ic, FALSE);
2334 aopOp (IC_RESULT (ic), ic, TRUE);
2336 size = AOP_SIZE (IC_RESULT (ic));
2339 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2340 rmwWithReg ("com", reg);
2342 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2347 /* release the aops */
2348 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2349 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2352 /*-----------------------------------------------------------------*/
2353 /* genUminusFloat - unary minus for floating points */
2354 /*-----------------------------------------------------------------*/
2356 genUminusFloat (operand * op, operand * result)
2358 int size, offset = 0;
2361 D(emitcode ("; genUminusFloat",""));
2363 /* for this we just copy and then flip the bit */
2365 size = AOP_SIZE (op) - 1;
2369 transferAopAop (AOP (op), offset, AOP (result), offset);
2373 needpula = pushRegIfUsed (hc08_reg_a);
2374 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2375 emitcode ("eor", "#0x80");
2376 hc08_useReg (hc08_reg_a);
2377 storeRegToAop (hc08_reg_a, AOP (result), offset);
2378 pullOrFreeReg (hc08_reg_a, needpula);
2381 /*-----------------------------------------------------------------*/
2382 /* genUminus - unary minus code generation */
2383 /*-----------------------------------------------------------------*/
2385 genUminus (iCode * ic)
2388 sym_link *optype, *rtype;
2393 D(emitcode ("; genUminus",""));
2396 aopOp (IC_LEFT (ic), ic, FALSE);
2397 aopOp (IC_RESULT (ic), ic, TRUE);
2399 optype = operandType (IC_LEFT (ic));
2400 rtype = operandType (IC_RESULT (ic));
2402 /* if float then do float stuff */
2403 if (IS_FLOAT (optype))
2405 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2409 /* otherwise subtract from zero */
2410 size = AOP_SIZE (IC_LEFT (ic));
2415 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2416 needpula = pushRegIfUsed (hc08_reg_a);
2419 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2420 emitcode ("nega", "");
2421 hc08_freeReg (hc08_reg_a);
2422 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2423 SPEC_USIGN (operandType (IC_LEFT (ic))));
2424 pullOrFreeReg (hc08_reg_a, needpula);
2428 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2429 result = forceStackedAop (AOP (IC_RESULT (ic)), FALSE);
2431 result = AOP (IC_RESULT (ic));
2433 needpula = pushRegIfUsed (hc08_reg_a);
2437 loadRegFromConst (hc08_reg_a, zero);
2438 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2439 storeRegToAop (hc08_reg_a, result, offset++);
2442 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2443 SPEC_USIGN (operandType (IC_LEFT (ic))));
2444 pullOrFreeReg (hc08_reg_a, needpula);
2446 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2447 freeAsmop (NULL, result, ic, TRUE);
2453 /* release the aops */
2454 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2455 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2458 /*-----------------------------------------------------------------*/
2459 /* saveRegisters - will look for a call and save the registers */
2460 /*-----------------------------------------------------------------*/
2462 saveRegisters (iCode * lic)
2469 for (ic = lic; ic; ic = ic->next)
2470 if (ic->op == CALL || ic->op == PCALL)
2475 fprintf (stderr, "found parameter push with no function call\n");
2479 /* if the registers have been saved already or don't need to be then
2483 if (IS_SYMOP(IC_LEFT(ic)) &&
2484 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2485 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2488 /* safe the registers in use at this time but skip the
2489 ones for the result */
2490 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2491 hc08_rUmaskForOp (IC_RESULT(ic)));
2494 for (i = 0; i < hc08_nRegs; i++)
2496 if (bitVectBitValue (rsave, i))
2497 pushReg ( hc08_regWithIdx (i), FALSE);
2501 /*-----------------------------------------------------------------*/
2502 /* unsaveRegisters - pop the pushed registers */
2503 /*-----------------------------------------------------------------*/
2505 unsaveRegisters (iCode * ic)
2510 /* restore the registers in use at this time but skip the
2511 ones for the result */
2512 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2513 hc08_rUmaskForOp (IC_RESULT(ic)));
2515 for (i = hc08_nRegs; i >= 0; i--)
2517 if (bitVectBitValue (rsave, i))
2518 pullReg ( hc08_regWithIdx (i));
2524 /*-----------------------------------------------------------------*/
2526 /*-----------------------------------------------------------------*/
2528 pushSide (operand * oper, int size, iCode * ic)
2532 aopOp (oper, ic, FALSE);
2536 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2537 pushReg ( hc08_reg_a, TRUE);
2540 freeAsmop (oper, NULL, ic, TRUE);
2543 /*-----------------------------------------------------------------*/
2544 /* assignResultValue - */
2545 /*-----------------------------------------------------------------*/
2547 assignResultValue (operand * oper)
2549 int size = AOP_SIZE (oper);
2553 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2554 if (hc08_aop_pass[offset]->type == AOP_REG)
2555 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2562 /*-----------------------------------------------------------------*/
2563 /* genIpush - genrate code for pushing this gets a little complex */
2564 /*-----------------------------------------------------------------*/
2566 genIpush (iCode * ic)
2568 int size, offset = 0;
2570 D(emitcode ("; genIpush",""));
2572 /* if this is not a parm push : ie. it is spill push
2573 and spill push is always done on the local stack */
2577 /* and the item is spilt then do nothing */
2578 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2581 aopOp (IC_LEFT (ic), ic, FALSE);
2582 size = AOP_SIZE (IC_LEFT (ic));
2584 /* push it on the stack */
2587 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2588 pushReg ( hc08_reg_a, TRUE);
2594 /* this is a paramter push: in this case we call
2595 the routine to find the call and save those
2596 registers that need to be saved */
2599 /* then do the push */
2600 aopOp (IC_LEFT (ic), ic, FALSE);
2603 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2604 size = AOP_SIZE (IC_LEFT (ic));
2607 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2608 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2610 if ((size==2) && hc08_reg_hx->isFree)
2612 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2613 pushReg (hc08_reg_hx, TRUE);
2620 // printf("loading %d\n", offset);
2621 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2622 // printf("pushing \n");
2623 pushReg (hc08_reg_a, TRUE);
2627 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2630 /*-----------------------------------------------------------------*/
2631 /* genIpop - recover the registers: can happen only for spilling */
2632 /*-----------------------------------------------------------------*/
2634 genIpop (iCode * ic)
2638 D(emitcode ("; genIpop",""));
2640 /* if the temp was not pushed then */
2641 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2644 aopOp (IC_LEFT (ic), ic, FALSE);
2645 size = AOP_SIZE (IC_LEFT (ic));
2649 pullReg (hc08_reg_a);
2650 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2652 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2656 /*-----------------------------------------------------------------*/
2657 /* genSend - gen code for SEND */
2658 /*-----------------------------------------------------------------*/
2659 static void genSend(set *sendSet)
2663 for (sic = setFirstItem (sendSet); sic;
2664 sic = setNextItem (sendSet)) {
2665 int size, offset = 0;
2666 aopOp (IC_LEFT (sic), sic, FALSE);
2667 size = AOP_SIZE (IC_LEFT (sic));
2672 transferAopAop( AOP (IC_LEFT (sic)), offset,
2673 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2677 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2681 /*-----------------------------------------------------------------*/
2682 /* genCall - generates a call statement */
2683 /*-----------------------------------------------------------------*/
2685 genCall (iCode * ic)
2688 // bool restoreBank = FALSE;
2689 // bool swapBanks = FALSE;
2691 D(emitcode("; genCall",""));
2693 dtype = operandType (IC_LEFT (ic));
2694 /* if send set is not empty then assign */
2697 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2698 genSend(reverseSet(_G.sendSet));
2700 genSend(_G.sendSet);
2706 /* if caller saves & we have not saved then */
2712 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2713 OP_SYMBOL (IC_LEFT (ic))->rname :
2714 OP_SYMBOL (IC_LEFT (ic))->name));
2717 /* if we need assign a result value */
2718 if ((IS_ITEMP (IC_RESULT (ic)) &&
2719 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2720 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2721 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2722 IS_TRUE_SYMOP (IC_RESULT (ic)))
2726 aopOp (IC_RESULT (ic), ic, FALSE);
2729 assignResultValue (IC_RESULT (ic));
2731 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2734 /* adjust the stack for parameters if
2738 pullNull (ic->parmBytes);
2741 /* if we had saved some registers then unsave them */
2742 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2743 unsaveRegisters (ic);
2747 /*-----------------------------------------------------------------*/
2748 /* -10l - generates a call by pointer statement */
2749 /*-----------------------------------------------------------------*/
2751 genPcall (iCode * ic)
2754 symbol *rlbl = newiTempLabel (NULL);
2755 symbol *tlbl = newiTempLabel (NULL);
2756 // bool restoreBank=FALSE;
2757 // bool swapBanks = FALSE;
2759 D (emitcode (";", "genPcall"));
2761 /* if caller saves & we have not saved then */
2765 /* if we are calling a not _naked function that is not using
2766 the same register bank then we need to save the
2767 destination registers on the stack */
2768 dtype = operandType (IC_LEFT (ic))->next;
2770 /* push the return address on to the stack */
2771 emitBranch ("bsr", tlbl);
2772 emitBranch ("bra", rlbl);
2774 _G.stackPushes += 2; /* account for the bsr return address now on stack */
2777 /* now push the function address */
2778 pushSide (IC_LEFT (ic), FPTRSIZE, ic);
2780 /* if send set is not empty then assign */
2783 genSend(reverseSet(_G.sendSet));
2789 emitcode ("rts", "");
2792 _G.stackPushes -= 4; /* account for rts here & in called function */
2796 /* if we need assign a result value */
2797 if ((IS_ITEMP (IC_RESULT (ic)) &&
2798 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2799 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2800 IS_TRUE_SYMOP (IC_RESULT (ic)))
2804 aopOp (IC_RESULT (ic), ic, FALSE);
2807 assignResultValue (IC_RESULT (ic));
2809 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2812 /* adjust the stack for parameters if
2816 pullNull (ic->parmBytes);
2819 /* if we hade saved some registers then
2821 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2822 unsaveRegisters (ic);
2825 /*-----------------------------------------------------------------*/
2826 /* resultRemat - result is rematerializable */
2827 /*-----------------------------------------------------------------*/
2829 resultRemat (iCode * ic)
2831 if (SKIP_IC (ic) || ic->op == IFX)
2834 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2836 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2837 if (sym->remat && !POINTER_SET (ic))
2844 /*-----------------------------------------------------------------*/
2845 /* inExcludeList - return 1 if the string is in exclude Reg list */
2846 /*-----------------------------------------------------------------*/
2848 regsCmp(void *p1, void *p2)
2850 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2854 inExcludeList (char *s)
2856 const char *p = setFirstItem(options.excludeRegsSet);
2858 if (p == NULL || STRCASECMP(p, "none") == 0)
2862 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2865 /*-----------------------------------------------------------------*/
2866 /* genFunction - generated code for function entry */
2867 /*-----------------------------------------------------------------*/
2869 genFunction (iCode * ic)
2871 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2873 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2874 int stackAdjust = sym->stack;
2875 int accIsFree = sym->recvSize == 0;
2879 /* create the function header */
2880 emitcode (";", "-----------------------------------------");
2881 emitcode (";", " function %s", sym->name);
2882 emitcode (";", "-----------------------------------------");
2884 emitcode ("", "%s:", sym->rname);
2885 lineCurr->isLabel = 1;
2886 ftype = operandType (IC_LEFT (ic));
2890 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2892 if (IFFUNC_ISNAKED(ftype))
2894 emitcode(";", "naked function: no prologue.");
2898 /* if this is an interrupt service routine then
2900 if (IFFUNC_ISISR (sym->type))
2903 if (!inExcludeList ("h"))
2904 pushReg (hc08_reg_h, FALSE);
2907 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2908 /* before setting up the stack frame completely. */
2909 while (ric && ric->next && ric->next->op == RECEIVE)
2911 while (ric && IC_RESULT (ric))
2913 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2914 int rsymSize = rsym ? getSize(rsym->type) : 0;
2918 if (rsym && rsym->regType == REG_CND)
2920 if (rsym && (rsym->accuse || rsym->ruonly))
2922 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2923 rsym = rsym->usl.spillLoc;
2926 /* If the RECEIVE operand immediately spills to the first entry on the */
2927 /* stack, we can push it directly rather than use an sp relative store. */
2928 if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize)
2932 _G.current_iCode = ric;
2933 D(emitcode ("; genReceive",""));
2934 for (ofs=0; ofs < rsymSize; ofs++)
2936 regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
2937 pushReg (reg, TRUE);
2938 if (reg->rIdx == A_IDX)
2942 _G.current_iCode = ic;
2945 ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
2948 /* adjust the stack for the function */
2951 adjustStack (-stackAdjust);
2953 _G.stackOfs = sym->stack;
2956 /* if critical function then turn interrupts off */
2957 if (IFFUNC_ISCRITICAL (ftype))
2961 /* Function was passed parameters, so make sure A is preserved */
2962 pushReg (hc08_reg_a, FALSE);
2963 pushReg (hc08_reg_a, FALSE);
2964 emitcode ("tpa", "");
2965 emitcode ("sta", "2,s");
2966 emitcode ("sei", "");
2967 pullReg (hc08_reg_a);
2971 /* No passed parameters, so A can be freely modified */
2972 emitcode ("tpa", "");
2973 pushReg (hc08_reg_a, TRUE);
2974 emitcode ("sei", "");
2980 /*-----------------------------------------------------------------*/
2981 /* genEndFunction - generates epilogue for functions */
2982 /*-----------------------------------------------------------------*/
2984 genEndFunction (iCode * ic)
2986 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2988 if (IFFUNC_ISNAKED(sym->type))
2990 emitcode(";", "naked function: no epilogue.");
2991 if (options.debug && currFunc)
2992 debugFile->writeEndFunction (currFunc, ic, 0);
2996 if (IFFUNC_ISCRITICAL (sym->type))
2998 if (!IS_VOID(sym->type->next))
3000 /* Function has return value, so make sure A is preserved */
3001 pushReg (hc08_reg_a, FALSE);
3002 emitcode ("lda", "2,s");
3003 emitcode ("tap", "");
3004 pullReg (hc08_reg_a);
3009 /* Function returns void, so A can be freely modified */
3010 pullReg (hc08_reg_a);
3011 emitcode ("tap", "");
3015 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
3021 _G.stackPushes += sym->stack;
3022 adjustStack (sym->stack);
3026 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3030 if (IFFUNC_ISISR (sym->type))
3033 if (!inExcludeList ("h"))
3034 pullReg (hc08_reg_h);
3037 /* if debug then send end of function */
3038 if (options.debug && currFunc)
3040 debugFile->writeEndFunction (currFunc, ic, 1);
3043 emitcode ("rti", "");
3047 if (IFFUNC_CALLEESAVES(sym->type))
3051 /* if any registers used */
3054 /* save the registers used */
3055 for (i = sym->regsUsed->size; i >= 0; i--)
3057 if (bitVectBitValue (sym->regsUsed, i) ||
3058 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3059 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3065 /* if debug then send end of function */
3066 if (options.debug && currFunc)
3068 debugFile->writeEndFunction (currFunc, ic, 1);
3071 emitcode ("rts", "");
3076 /*-----------------------------------------------------------------*/
3077 /* genRet - generate code for return statement */
3078 /*-----------------------------------------------------------------*/
3082 int size, offset = 0;
3085 D(emitcode ("; genRet",""));
3087 /* if we have no return value then
3088 just generate the "ret" */
3092 /* we have something to return then
3093 move the return value into place */
3094 aopOp (IC_LEFT (ic), ic, FALSE);
3095 size = AOP_SIZE (IC_LEFT (ic));
3101 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3108 /* 4 byte return: store value in the global return variable */
3112 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3113 STA (fReturn2[offset--], FALSE);
3114 hc08_freeReg (hc08_reg_a);
3118 /* 2 byte return: store value in x:a */
3119 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3120 hc08_freeReg (hc08_reg_xa);
3123 /* 1 byte return: store value in a */
3124 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3125 hc08_freeReg (hc08_reg_a);
3130 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3133 /* generate a jump to the return label
3134 if the next is not the return statement */
3135 if (!(ic->next && ic->next->op == LABEL &&
3136 IC_LABEL (ic->next) == returnLabel))
3138 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3142 /*-----------------------------------------------------------------*/
3143 /* genLabel - generates a label */
3144 /*-----------------------------------------------------------------*/
3146 genLabel (iCode * ic)
3151 /* For the high level labels we cannot depend on any */
3152 /* register's contents. Amnesia time. */
3153 for (i=A_IDX;i<=XA_IDX;i++)
3155 reg = hc08_regWithIdx(i);
3160 /* special case never generate */
3161 if (IC_LABEL (ic) == entryLabel)
3164 debugFile->writeLabel(IC_LABEL (ic), ic);
3166 emitLabel (IC_LABEL (ic));
3170 /*-----------------------------------------------------------------*/
3171 /* genGoto - generates a jmp */
3172 /*-----------------------------------------------------------------*/
3174 genGoto (iCode * ic)
3176 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3180 /*-----------------------------------------------------------------*/
3181 /* findLabelBackwards: walks back through the iCode chain looking */
3182 /* for the given label. Returns number of iCode instructions */
3183 /* between that label and given ic. */
3184 /* Returns zero if label not found. */
3185 /*-----------------------------------------------------------------*/
3187 findLabelBackwards (iCode * ic, int key)
3196 /* If we have any pushes or pops, we cannot predict the distance.
3197 I don't like this at all, this should be dealt with in the
3199 if (ic->op == IPUSH || ic->op == IPOP) {
3203 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3213 /*-----------------------------------------------------------------*/
3214 /* genPlusIncr :- does addition with increment if possible */
3215 /*-----------------------------------------------------------------*/
3217 genPlusIncr (iCode * ic)
3225 unsigned int size = getDataSize (IC_RESULT (ic));
3226 unsigned int offset;
3227 symbol *tlbl = NULL;
3229 left = IC_LEFT (ic);
3230 result = IC_RESULT (ic);
3232 /* will try to generate an increment */
3233 /* if the right side is not a literal
3235 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3238 icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3240 DD(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3242 if ((IS_AOP_HX (AOP (left)) ||
3243 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3245 && (icount>=-128) && (icount<=127) && (size==2))
3247 if (!IS_AOP_HX (AOP (left)))
3249 needpulx = pushRegIfUsed (hc08_reg_x);
3250 needpulh = pushRegIfUsed (hc08_reg_h);
3257 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3258 emitcode ("aix","#%d", icount);
3259 hc08_dirtyReg (hc08_reg_hx, FALSE);
3260 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3261 pullOrFreeReg (hc08_reg_h, needpulh);
3262 pullOrFreeReg (hc08_reg_x, needpulx);
3266 DD(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3267 sameRegs (AOP (left), AOP (result))));
3269 if ((icount > 255) || (icount<0))
3272 if (!sameRegs (AOP (left), AOP (result)))
3275 D(emitcode ("; genPlusIncr",""));
3278 tlbl = newiTempLabel (NULL);
3283 rmwWithAop ("inc", AOP (result), 0);
3285 emitBranch ("bne", tlbl);
3289 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3290 needpula = pushRegIfUsed (hc08_reg_a);
3293 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3294 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3295 hc08_useReg (hc08_reg_a);
3296 storeRegToAop (hc08_reg_a, AOP (result), 0);
3297 hc08_freeReg (hc08_reg_a);
3299 emitBranch ("bcc", tlbl);
3301 for (offset=1; offset<size; offset++)
3303 rmwWithAop ("inc", AOP (result), offset);
3304 if ((offset+1)<size)
3305 emitBranch ("bne", tlbl);
3311 pullOrFreeReg (hc08_reg_a, needpula);
3318 /*-----------------------------------------------------------------*/
3319 /* genPlus - generates code for addition */
3320 /*-----------------------------------------------------------------*/
3322 genPlus (iCode * ic)
3324 int size, offset = 0;
3326 asmop *leftOp, *rightOp;
3328 /* special cases :- */
3330 D(emitcode ("; genPlus",""));
3332 aopOp (IC_LEFT (ic), ic, FALSE);
3333 aopOp (IC_RIGHT (ic), ic, FALSE);
3334 aopOp (IC_RESULT (ic), ic, TRUE);
3336 /* we want registers on the left and literals on the right */
3337 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3338 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3340 operand *t = IC_RIGHT (ic);
3341 IC_RIGHT (ic) = IC_LEFT (ic);
3346 /* if I can do an increment instead
3347 of add then GOOD for ME */
3348 if (genPlusIncr (ic) == TRUE)
3351 DD(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3352 DD(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3353 DD(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3355 size = getDataSize (IC_RESULT (ic));
3357 leftOp = AOP(IC_LEFT(ic));
3358 rightOp = AOP(IC_RIGHT(ic));
3364 loadRegFromAop (hc08_reg_a, leftOp, offset);
3365 accopWithAop(add, rightOp, offset);
3366 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3367 hc08_freeReg (hc08_reg_a);
3368 add = "adc"; /* further adds must propagate carry */
3372 // adjustArithmeticResult (ic);
3375 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3376 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3377 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3380 /*-----------------------------------------------------------------*/
3381 /* genMinusDec :- does subtraction with decrement if possible */
3382 /*-----------------------------------------------------------------*/
3384 genMinusDec (iCode * ic)
3386 unsigned int icount;
3391 unsigned int size = getDataSize (IC_RESULT (ic));
3395 left = IC_LEFT (ic);
3396 result = IC_RESULT (ic);
3398 /* will try to generate an increment */
3399 /* if the right side is not a literal
3401 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3404 icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3406 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3407 && (icount>=-127) && (icount<=128) && (size==2))
3409 if (!IS_AOP_HX (AOP (left)))
3411 needpulx = pushRegIfUsed (hc08_reg_x);
3412 needpulh = pushRegIfUsed (hc08_reg_h);
3419 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3420 emitcode ("aix","#%d", -(int) icount);
3421 hc08_dirtyReg (hc08_reg_hx, FALSE);
3422 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3423 pullOrFreeReg (hc08_reg_h, needpulh);
3424 pullOrFreeReg (hc08_reg_x, needpulx);
3428 if ((icount > 1) || (icount<0))
3431 if (!sameRegs (AOP (left), AOP (result)))
3437 D(emitcode ("; genMinusDec",""));
3439 rmwWithAop ("dec", AOP (result), 0);
3444 /*-----------------------------------------------------------------*/
3445 /* addSign - complete with sign */
3446 /*-----------------------------------------------------------------*/
3448 addSign (operand * result, int offset, int sign)
3450 int size = (getDataSize (result) - offset);
3455 emitcode ("rola", "");
3456 emitcode ("clra", "");
3457 emitcode ("sbc", zero);
3459 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3463 storeConstToAop (zero, AOP (result), offset++);
3468 /*-----------------------------------------------------------------*/
3469 /* genMinus - generates code for subtraction */
3470 /*-----------------------------------------------------------------*/
3472 genMinus (iCode * ic)
3475 int size, offset = 0;
3477 asmop *leftOp, *rightOp;
3479 D(emitcode ("; genMinus",""));
3481 aopOp (IC_LEFT (ic), ic, FALSE);
3482 aopOp (IC_RIGHT (ic), ic, FALSE);
3483 aopOp (IC_RESULT (ic), ic, TRUE);
3485 /* special cases :- */
3486 /* if I can do an decrement instead
3487 of subtract then GOOD for ME */
3488 if (genMinusDec (ic) == TRUE)
3491 size = getDataSize (IC_RESULT (ic));
3494 leftOp = AOP(IC_LEFT(ic));
3495 rightOp = AOP(IC_RIGHT(ic));
3499 if (IS_AOP_A (rightOp))
3501 loadRegFromAop ( hc08_reg_a, rightOp, offset);
3502 accopWithAop (sub, leftOp, offset);
3503 accopWithMisc ("nega", "");
3504 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3510 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3511 accopWithAop (sub, rightOp, offset);
3512 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3517 // adjustArithmeticResult (ic);
3520 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3521 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3522 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3527 /*-----------------------------------------------------------------*/
3528 /* genMultOneByte : 8*8=8/16 bit multiplication */
3529 /*-----------------------------------------------------------------*/
3531 genMultOneByte (operand * left,
3535 /* sym_link *opetype = operandType (result); */
3536 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3537 int size=AOP_SIZE(result);
3538 bool negLiteral = FALSE;
3539 bool lUnsigned, rUnsigned;
3541 D(emitcode ("; genMultOneByte",""));
3543 if (size<1 || size>2) {
3544 // this should never happen
3545 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3546 AOP_SIZE(result), __FILE__, lineno);
3550 /* (if two literals: the value is computed before) */
3551 /* if one literal, literal on the right */
3552 if (AOP_TYPE (left) == AOP_LIT)
3558 /* if an operand is in A, make sure it is on the left */
3559 if (IS_AOP_A (AOP (right)))
3566 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3567 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3569 /* lUnsigned rUnsigned negLiteral negate case */
3570 /* false false false odd 3 */
3571 /* false false true even 3 */
3572 /* false true false odd 3 */
3573 /* false true true impossible */
3574 /* true false false odd 3 */
3575 /* true false true always 2 */
3576 /* true true false never 1 */
3577 /* true true true impossible */
3581 || (lUnsigned && rUnsigned))
3583 // just an unsigned 8*8=8/16 multiply
3584 //DD(emitcode (";","unsigned"));
3586 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3587 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3588 emitcode ("mul", "");
3589 hc08_dirtyReg (hc08_reg_xa, FALSE);
3590 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3591 hc08_freeReg (hc08_reg_xa);
3596 // we have to do a signed multiply
3599 /* left unsigned, right signed literal -- literal determines sign handling */
3600 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3602 signed char val=(signed char) ulFromVal (AOP (right)->aopu.aop_lit);
3604 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3606 emitcode ("ldx", "#0x%02x", -val);
3608 emitcode ("ldx", "#0x%02x", val);
3610 emitcode ("mul", "");
3614 rmwWithReg ("neg", hc08_reg_a);
3615 tlbl4 = newiTempLabel (NULL);
3616 emitBranch ("bcc", tlbl4);
3617 rmwWithReg ("inc", hc08_reg_x);
3619 rmwWithReg ("neg", hc08_reg_x);
3622 hc08_dirtyReg (hc08_reg_xa, FALSE);
3623 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3624 hc08_freeReg (hc08_reg_xa);
3631 emitcode ("clr", "1,s");
3633 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3636 tlbl1 = newiTempLabel (NULL);
3637 emitcode ("tsta","");
3638 emitBranch ("bpl", tlbl1);
3639 emitcode ("inc", "1,s");
3640 rmwWithReg ("neg", hc08_reg_a);
3644 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3646 signed char val=(signed char) ulFromVal (AOP (right)->aopu.aop_lit);
3647 /* AND literal negative */
3649 emitcode ("ldx", "#0x%02x", -val);
3652 emitcode ("ldx", "#0x%02x", val);
3654 hc08_useReg (hc08_reg_x);
3658 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3661 tlbl2 = newiTempLabel (NULL);
3662 emitcode ("tstx", "");
3663 emitBranch ("bpl", tlbl2);
3664 emitcode ("inc", "1,s");
3665 rmwWithReg ("neg", hc08_reg_x);
3670 emitcode ("mul", "");
3671 hc08_dirtyReg (hc08_reg_xa, FALSE);
3673 tlbl3 = newiTempLabel (NULL);
3674 emitcode ("dec", "1,s");
3675 if (!lUnsigned && !rUnsigned && negLiteral)
3676 emitBranch ("beq", tlbl3);
3678 emitBranch ("bne", tlbl3);
3680 rmwWithReg ("neg", hc08_reg_a);
3681 tlbl4 = newiTempLabel (NULL);
3682 emitBranch ("bcc", tlbl4);
3683 rmwWithReg ("inc", hc08_reg_x);
3685 rmwWithReg ("neg", hc08_reg_x);
3689 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3690 hc08_freeReg (hc08_reg_xa);
3694 /*-----------------------------------------------------------------*/
3695 /* genMult - generates code for multiplication */
3696 /*-----------------------------------------------------------------*/
3698 genMult (iCode * ic)
3700 operand *left = IC_LEFT (ic);
3701 operand *right = IC_RIGHT (ic);
3702 operand *result = IC_RESULT (ic);
3704 D(emitcode ("; genMult",""));
3706 /* assign the amsops */
3707 aopOp (left, ic, FALSE);
3708 aopOp (right, ic, FALSE);
3709 aopOp (result, ic, TRUE);
3711 /* special cases first */
3712 /* if both are of size == 1 */
3713 // if (getSize(operandType(left)) == 1 &&
3714 // getSize(operandType(right)) == 1)
3715 if (AOP_SIZE (left) == 1 &&
3716 AOP_SIZE (right) == 1)
3718 genMultOneByte (left, right, result);
3722 /* should have been converted to function call */
3723 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3724 getSize(OP_SYMBOL(right)->type));
3725 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3730 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3731 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3732 freeAsmop (result, NULL, ic, TRUE);
3735 /*-----------------------------------------------------------------*/
3736 /* genDivOneByte : 8 bit division */
3737 /*-----------------------------------------------------------------*/
3739 genDivOneByte (operand * left,
3743 symbol *tlbl1, *tlbl2, *tlbl3;
3746 bool lUnsigned, rUnsigned;
3747 bool runtimeSign, compiletimeSign;
3749 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3750 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3752 D(emitcode ("; genDivOneByte",""));
3754 size = AOP_SIZE (result);
3755 /* signed or unsigned */
3756 if (lUnsigned && rUnsigned)
3758 /* unsigned is easy */
3759 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3760 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3761 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3762 emitcode ("div", "");
3763 hc08_dirtyReg (hc08_reg_a, FALSE);
3764 hc08_dirtyReg (hc08_reg_h, FALSE);
3765 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3766 hc08_freeReg (hc08_reg_a);
3767 hc08_freeReg (hc08_reg_x);
3768 hc08_freeReg (hc08_reg_h);
3772 /* signed is a little bit more difficult */
3774 /* now sign adjust for both left & right */
3776 /* let's see what's needed: */
3777 /* apply negative sign during runtime */
3778 runtimeSign = FALSE;
3779 /* negative sign from literals */
3780 compiletimeSign = FALSE;
3784 if (AOP_TYPE(left) == AOP_LIT)
3786 /* signed literal */
3787 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
3789 compiletimeSign = TRUE;
3792 /* signed but not literal */
3798 if (AOP_TYPE(right) == AOP_LIT)
3800 /* signed literal */
3801 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
3803 compiletimeSign ^= TRUE;
3806 /* signed but not literal */
3810 /* initialize the runtime sign */
3813 if (compiletimeSign)
3814 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3816 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3817 pushReg (hc08_reg_x, TRUE);
3820 /* save the signs of the operands */
3821 if (AOP_TYPE(right) == AOP_LIT)
3823 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
3825 if (!rUnsigned && val < 0)
3826 emitcode ("ldx", "#0x%02x", -val);
3828 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3830 else /* ! literal */
3832 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3835 tlbl1 = newiTempLabel (NULL);
3836 emitcode ("tstx", "");
3837 emitBranch ("bpl", tlbl1);
3838 emitcode ("inc", "1,s");
3839 rmwWithReg ("neg", hc08_reg_x);
3844 if (AOP_TYPE(left) == AOP_LIT)
3846 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
3848 if (!lUnsigned && val < 0)
3849 emitcode ("lda", "#0x%02x", -val);
3851 emitcode ("lda", "#0x%02x", (unsigned char) val);
3853 else /* ! literal */
3855 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3858 tlbl2 = newiTempLabel (NULL);
3859 emitcode ("tsta", "");
3860 emitBranch ("bpl", tlbl2);
3861 emitcode ("inc", "1,s");
3862 rmwWithReg ("neg", hc08_reg_a);
3867 loadRegFromConst (hc08_reg_h, zero);
3868 emitcode ("div", "");
3869 hc08_dirtyReg (hc08_reg_x, FALSE);
3870 hc08_dirtyReg (hc08_reg_a, FALSE);
3871 hc08_dirtyReg (hc08_reg_h, FALSE);
3873 if (runtimeSign || compiletimeSign)
3875 tlbl3 = newiTempLabel (NULL);
3878 pullReg (hc08_reg_x);
3879 rmwWithReg ("lsr", hc08_reg_x);
3880 rmwWithReg ("ror", hc08_reg_x);
3881 emitBranch ("bpl", tlbl3);
3884 rmwWithReg ("neg", hc08_reg_a);
3888 storeRegToAop (hc08_reg_a, AOP (result), 0);
3892 /* msb is 0x00 or 0xff depending on the sign */
3895 rmwWithReg ("lsl", hc08_reg_x);
3896 emitcode ("clra", "");
3897 emitcode ("sbc", "#0");
3899 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3901 else /* compiletimeSign */
3903 storeConstToAop ("#0xff", AOP (result), ++offset);
3908 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3911 hc08_freeReg (hc08_reg_a);
3912 hc08_freeReg (hc08_reg_x);
3913 hc08_freeReg (hc08_reg_h);
3916 /*-----------------------------------------------------------------*/
3917 /* genDiv - generates code for division */
3918 /*-----------------------------------------------------------------*/
3922 operand *left = IC_LEFT (ic);
3923 operand *right = IC_RIGHT (ic);
3924 operand *result = IC_RESULT (ic);
3926 D(emitcode ("; genDiv",""));
3928 /* assign the amsops */
3929 aopOp (left, ic, FALSE);
3930 aopOp (right, ic, FALSE);
3931 aopOp (result, ic, TRUE);
3933 /* special cases first */
3934 /* if both are of size == 1 */
3935 if (AOP_SIZE (left) <= 2 &&
3936 AOP_SIZE (right) == 1)
3938 genDivOneByte (left, right, result);
3942 /* should have been converted to function call */
3945 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3946 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3947 freeAsmop (result, NULL, ic, TRUE);
3950 /*-----------------------------------------------------------------*/
3951 /* genModOneByte : 8 bit modulus */
3952 /*-----------------------------------------------------------------*/
3954 genModOneByte (operand * left,
3958 symbol *tlbl1, *tlbl2, *tlbl3;
3961 bool lUnsigned, rUnsigned;
3962 bool runtimeSign, compiletimeSign;
3964 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3965 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3967 D(emitcode ("; genModOneByte",""));
3969 size = AOP_SIZE (result);
3971 if (lUnsigned && rUnsigned)
3973 /* unsigned is easy */
3974 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3975 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3976 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3977 emitcode ("div", "");
3978 hc08_freeReg (hc08_reg_a);
3979 hc08_freeReg (hc08_reg_x);
3980 hc08_dirtyReg (hc08_reg_h, FALSE);
3981 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3982 hc08_freeReg (hc08_reg_h);
3986 /* signed is a little bit more difficult */
3988 if (AOP_TYPE(right) == AOP_LIT)
3990 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
3992 if (!rUnsigned && val < 0)
3993 emitcode ("ldx", "#0x%02x", -val);
3995 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3997 else /* ! literal */
3999 loadRegFromAop (hc08_reg_x, AOP (right), 0);
4002 tlbl1 = newiTempLabel (NULL);
4003 emitcode ("tstx", "");
4004 emitBranch ("bpl", tlbl1);
4005 rmwWithReg ("neg", hc08_reg_x);
4010 /* let's see what's needed: */
4011 /* apply negative sign during runtime */
4012 runtimeSign = FALSE;
4013 /* negative sign from literals */
4014 compiletimeSign = FALSE;
4016 /* sign adjust left side */
4017 if (AOP_TYPE(left) == AOP_LIT)
4019 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
4021 if (!lUnsigned && val < 0)
4023 compiletimeSign = TRUE; /* set sign flag */
4024 emitcode ("lda", "#0x%02x", -val);
4027 emitcode ("lda", "#0x%02x", (unsigned char) val);
4029 else /* ! literal */
4032 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4037 emitcode ("clr", "1,s");
4039 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4040 tlbl2 = newiTempLabel (NULL);
4041 emitcode ("tsta", "");
4042 emitBranch ("bpl", tlbl2);
4043 emitcode ("inc", "1,s");
4044 rmwWithReg ("neg", hc08_reg_a);
4049 loadRegFromConst (hc08_reg_h, zero);
4050 emitcode ("div", "");
4051 hc08_freeReg (hc08_reg_a);
4052 hc08_freeReg (hc08_reg_x);
4053 hc08_dirtyReg (hc08_reg_h, FALSE);
4055 if (runtimeSign || compiletimeSign)
4057 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4058 tlbl3 = newiTempLabel (NULL);
4061 pullReg (hc08_reg_x);
4062 rmwWithReg ("lsr", hc08_reg_x);
4063 rmwWithReg ("ror", hc08_reg_x);
4064 emitBranch ("bpl", tlbl3);
4067 rmwWithReg ("neg", hc08_reg_a);
4071 storeRegToAop (hc08_reg_a, AOP (result), 0);
4075 /* msb is 0x00 or 0xff depending on the sign */
4078 rmwWithReg ("lsl", hc08_reg_x);
4079 emitcode ("clra", "");
4080 emitcode ("sbc", "#0");
4082 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4084 else /* compiletimeSign */
4086 storeConstToAop ("#0xff", AOP (result), ++offset);
4091 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4094 hc08_freeReg (hc08_reg_a);
4095 hc08_freeReg (hc08_reg_x);
4096 hc08_freeReg (hc08_reg_h);
4099 /*-----------------------------------------------------------------*/
4100 /* genMod - generates code for division */
4101 /*-----------------------------------------------------------------*/
4105 operand *left = IC_LEFT (ic);
4106 operand *right = IC_RIGHT (ic);
4107 operand *result = IC_RESULT (ic);
4109 D(emitcode ("; genMod",""));
4111 /* assign the amsops */
4112 aopOp (left, ic, FALSE);
4113 aopOp (right, ic, FALSE);
4114 aopOp (result, ic, TRUE);
4116 /* special cases first */
4117 /* if both are of size == 1 */
4118 if (AOP_SIZE (left) <= 2 &&
4119 AOP_SIZE (right) == 1)
4121 genModOneByte (left, right, result);
4125 /* should have been converted to function call */
4129 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4130 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4131 freeAsmop (result, NULL, ic, TRUE);
4134 /*-----------------------------------------------------------------*/
4135 /* genIfxJump :- will create a jump depending on the ifx */
4136 /*-----------------------------------------------------------------*/
4138 genIfxJump (iCode * ic, char *jval)
4141 symbol *tlbl = newiTempLabel (NULL);
4144 D(emitcode ("; genIfxJump",""));
4146 /* if true label then we jump if condition
4150 jlbl = IC_TRUE (ic);
4151 if (!strcmp (jval, "a"))
4153 else if (!strcmp (jval, "c"))
4160 /* false label is present */
4161 jlbl = IC_FALSE (ic);
4162 if (!strcmp (jval, "a"))
4164 else if (!strcmp (jval, "c"))
4169 emitBranch (inst, tlbl);
4170 emitBranch ("jmp", jlbl);
4173 /* mark the icode as generated */
4178 /*-----------------------------------------------------------------*/
4179 /* exchangedCmp : returns the opcode need if the two operands are */
4180 /* exchanged in a comparison */
4181 /*-----------------------------------------------------------------*/
4183 exchangedCmp (int opcode)
4200 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4201 "opcode not a comparison");
4203 return EQ_OP; /* shouldn't happen, but need to return something */
4206 /*------------------------------------------------------------------*/
4207 /* negatedCmp : returns the equivalent opcode for when a comparison */
4209 /*------------------------------------------------------------------*/
4211 negatedCmp (int opcode)
4228 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4229 "opcode not a comparison");
4231 return EQ_OP; /* shouldn't happen, but need to return something */
4234 /*------------------------------------------------------------------*/
4235 /* nameCmp : helper function for human readable debug output */
4236 /*------------------------------------------------------------------*/
4238 nameCmp (int opcode)
4259 /*------------------------------------------------------------------*/
4260 /* branchInstCmp : returns the conditional branch instruction that */
4261 /* will branch if the comparison is true */
4262 /*------------------------------------------------------------------*/
4264 branchInstCmp (int opcode, int sign)
4272 return "bcs"; /* same as blo */
4287 return "bcc"; /* same as bhs */
4293 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4294 "opcode not a comparison");
4300 /*------------------------------------------------------------------*/
4301 /* genCmp :- greater or less than (and maybe with equal) comparison */
4302 /*------------------------------------------------------------------*/
4304 genCmp (iCode * ic, iCode * ifx)
4306 operand *left, *right, *result;
4307 sym_link *letype, *retype;
4309 int size, offset = 0;
4310 unsigned long lit = 0L;
4312 symbol *jlbl = NULL;
4316 D(emitcode ("; genCmp", "(%s)",nameCmp (opcode)));
4318 result = IC_RESULT (ic);
4319 left = IC_LEFT (ic);
4320 right = IC_RIGHT (ic);
4322 letype = getSpec (operandType (left));
4323 retype = getSpec (operandType (right));
4324 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4325 /* assign the amsops */
4326 aopOp (left, ic, FALSE);
4327 aopOp (right, ic, FALSE);
4328 aopOp (result, ic, TRUE);
4330 /* need register operand on left, prefer literal operand on right */
4331 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4333 operand *temp = left;
4336 opcode = exchangedCmp (opcode);
4343 jlbl = IC_TRUE (ifx);
4344 opcode = negatedCmp (opcode);
4348 /* false label is present */
4349 jlbl = IC_FALSE (ifx);
4353 size = max (AOP_SIZE (left), AOP_SIZE (right));
4356 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4357 && ((AOP_TYPE (right) == AOP_LIT) ||
4358 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4359 && hc08_reg_hx->isFree)
4361 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4362 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4363 hc08_freeReg (hc08_reg_hx);
4374 /* These conditions depend on the Z flag bit, but Z is */
4375 /* only valid for the last byte of the comparison, not */
4376 /* the whole value. So exchange the operands to get a */
4377 /* comparison that doesn't depend on Z. (This is safe */
4378 /* to do here since ralloc won't assign multi-byte */
4379 /* operands to registers for comparisons) */
4380 if ((opcode == '>') || (opcode == LE_OP))
4382 operand *temp = left;
4385 opcode = exchangedCmp (opcode);
4388 if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
4390 lit = ulFromVal (AOP (right)->aopu.aop_lit);
4391 while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
4400 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4401 accopWithAop (sub, AOP (right), offset);
4402 hc08_freeReg (hc08_reg_a);
4407 freeAsmop (right, NULL, ic, FALSE);
4408 freeAsmop (left, NULL, ic, FALSE);
4412 symbol *tlbl = newiTempLabel (NULL);
4415 freeAsmop (result, NULL, ic, TRUE);
4417 inst = branchInstCmp (opcode, sign);
4418 emitBranch (inst, tlbl);
4419 emitBranch ("jmp", jlbl);
4422 /* mark the icode as generated */
4427 symbol *tlbl1 = newiTempLabel (NULL);
4428 symbol *tlbl2 = newiTempLabel (NULL);
4430 emitBranch (branchInstCmp (opcode, sign), tlbl1);
4431 loadRegFromConst (hc08_reg_a, zero);
4432 emitBranch ("bra", tlbl2);
4434 loadRegFromConst (hc08_reg_a, one);
4436 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4437 freeAsmop (result, NULL, ic, TRUE);
4442 /*-----------------------------------------------------------------*/
4443 /* genCmpEQorNE - equal or not equal comparison */
4444 /*-----------------------------------------------------------------*/
4446 genCmpEQorNE (iCode * ic, iCode * ifx)
4448 operand *left, *right, *result;
4449 sym_link *letype, *retype;
4451 int size, offset = 0;
4453 symbol *jlbl = NULL;
4454 symbol *tlbl_NE = NULL;
4455 symbol *tlbl_EQ = NULL;
4459 D(emitcode ("; genCmpEQorNE", "(%s)",nameCmp (opcode)));
4461 result = IC_RESULT (ic);
4462 left = IC_LEFT (ic);
4463 right = IC_RIGHT (ic);
4465 letype = getSpec (operandType (left));
4466 retype = getSpec (operandType (right));
4467 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4468 /* assign the amsops */
4469 aopOp (left, ic, FALSE);
4470 aopOp (right, ic, FALSE);
4471 aopOp (result, ic, TRUE);
4473 /* need register operand on left, prefer literal operand on right */
4474 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4476 operand *temp = left;
4479 opcode = exchangedCmp (opcode);
4486 jlbl = IC_TRUE (ifx);
4487 opcode = negatedCmp (opcode);
4491 /* false label is present */
4492 jlbl = IC_FALSE (ifx);
4496 size = max (AOP_SIZE (left), AOP_SIZE (right));
4499 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4500 && ((AOP_TYPE (right) == AOP_LIT) ||
4501 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4502 && hc08_reg_hx->isFree)
4504 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4505 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4506 hc08_freeReg (hc08_reg_hx);
4514 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4515 accopWithAop (sub, AOP (right), offset);
4519 tlbl_NE = newiTempLabel (NULL);
4520 emitBranch ("bne", tlbl_NE);
4522 hc08_freeReg (hc08_reg_a);
4526 freeAsmop (right, NULL, ic, FALSE);
4527 freeAsmop (left, NULL, ic, FALSE);
4531 freeAsmop (result, NULL, ic, TRUE);
4533 if (opcode == EQ_OP)
4536 tlbl_EQ = newiTempLabel (NULL);
4537 emitBranch ("beq", tlbl_EQ);
4539 emitLabel (tlbl_NE);
4540 emitBranch ("jmp", jlbl);
4541 emitLabel (tlbl_EQ);
4546 tlbl_NE = newiTempLabel (NULL);
4547 emitBranch ("bne", tlbl_NE);
4548 emitBranch ("jmp", jlbl);
4549 emitLabel (tlbl_NE);
4552 /* mark the icode as generated */
4557 symbol *tlbl = newiTempLabel (NULL);
4559 if (opcode == EQ_OP)
4562 tlbl_EQ = newiTempLabel (NULL);
4563 emitBranch ("beq", tlbl_EQ);
4565 emitLabel (tlbl_NE);
4566 loadRegFromConst (hc08_reg_a, zero);
4567 emitBranch ("bra", tlbl);
4568 emitLabel (tlbl_EQ);
4569 loadRegFromConst (hc08_reg_a, one);
4574 tlbl_NE = newiTempLabel (NULL);
4575 emitBranch ("bne", tlbl_NE);
4576 loadRegFromConst (hc08_reg_a, zero);
4577 emitBranch ("bra", tlbl);
4578 emitLabel (tlbl_NE);
4579 loadRegFromConst (hc08_reg_a, one);
4583 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4584 freeAsmop (result, NULL, ic, TRUE);
4590 /*-----------------------------------------------------------------*/
4591 /* ifxForOp - returns the icode containing the ifx for operand */
4592 /*-----------------------------------------------------------------*/
4594 ifxForOp (operand * op, iCode * ic)
4596 /* if true symbol then needs to be assigned */
4597 if (IS_TRUE_SYMOP (op))
4600 /* if this has register type condition and
4601 the next instruction is ifx with the same operand
4602 and live to of the operand is upto the ifx only then */
4604 ic->next->op == IFX &&
4605 IC_COND (ic->next)->key == op->key &&
4606 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4613 genPointerGetSetOfs (iCode *ic)
4615 iCode *lic = ic->next;
4621 /* Make sure we have a next iCode */
4622 DD(emitcode("","; checking lic"));
4626 /* Make sure the result of the addition is an iCode */
4627 DD(emitcode("","; checking IS_ITEMP"));
4628 if (!IS_ITEMP (IC_RESULT (ic)))
4631 /* Make sure the next iCode is a pointer set or get */
4632 pset = POINTER_SET(lic);
4633 pget = POINTER_GET(lic);
4634 DD(emitcode("","; pset=%d, pget=%d",pset,pget));
4638 /* Make sure this is the only use of the pointer */
4639 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4642 DD(emitcode("", "; checking pset operandsEqu"));
4643 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4646 DD(emitcode("", "; checking pget operandsEqu"));
4647 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4650 DD(emitcode("", "; checking IS_SYMOP"));
4651 if (!IS_SYMOP (IC_LEFT (ic)))
4654 DD(emitcode("", "; checking !IS_TRUE_SYMOP"));
4655 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4658 sym = OP_SYMBOL (IC_LEFT (ic));
4660 DD(emitcode("", "; checking remat"));
4667 D(emitcode ("; genPointerGetOfs",""));
4668 aopOp (IC_LEFT(ic), ic, FALSE);
4669 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4670 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4672 aopOp (IC_RIGHT(ic), ic, FALSE);
4673 aopOp (IC_RESULT(lic), lic, FALSE);
4675 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4677 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4679 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4680 loadRegFromConst (hc08_reg_h, zero);
4684 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4685 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4686 emitcode ("rola","");
4687 emitcode ("clra","");
4688 emitcode ("sbc", "#0");
4689 hc08_useReg (hc08_reg_a);
4690 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4694 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4695 size = AOP_SIZE (IC_RESULT(lic));
4696 derefaop->size = size;
4700 emitcode ("lda", "%s,x",
4701 aopAdrStr (derefaop, size, TRUE));
4702 hc08_useReg (hc08_reg_a);
4703 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
4704 hc08_freeReg (hc08_reg_a);
4708 hc08_freeReg (hc08_reg_hx);
4710 freeAsmop (NULL, derefaop, ic, TRUE);
4711 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4712 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4719 D(emitcode ("; genPointerSetOfs",""));
4720 aopOp (IC_LEFT(ic), ic, FALSE);
4721 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4722 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4724 aopOp (IC_RIGHT(ic), ic, FALSE);
4725 aopOp (IC_RIGHT(lic), lic, FALSE);
4727 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4729 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4731 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4732 loadRegFromConst (hc08_reg_h, zero);
4736 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4737 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4738 emitcode ("rola","");
4739 emitcode ("clra","");
4740 emitcode ("sbc", "#0");
4741 hc08_useReg (hc08_reg_a);
4742 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4746 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4747 size = AOP_SIZE (IC_RIGHT(lic));
4748 derefaop->size = size;
4752 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
4753 emitcode ("sta", "%s,x",
4754 aopAdrStr (derefaop, size, TRUE));
4755 hc08_freeReg (hc08_reg_a);
4759 hc08_freeReg (hc08_reg_hx);
4761 freeAsmop (NULL, derefaop, ic, TRUE);
4762 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4763 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4772 /*-----------------------------------------------------------------*/
4773 /* hasInc - operand is incremented before any other use */
4774 /*-----------------------------------------------------------------*/
4776 hasInc (operand *op, iCode *ic,int osize)
4778 sym_link *type = operandType(op);
4779 sym_link *retype = getSpec (type);
4780 iCode *lic = ic->next;
4783 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4784 if (!IS_SYMOP(op)) return NULL;
4786 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4787 if (IS_AGGREGATE(type->next)) return NULL;
4788 if (osize != (isize = getSize(type->next))) return NULL;
4791 /* if operand of the form op = op + <sizeof *op> */
4792 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4793 isOperandEqual(IC_RESULT(lic),op) &&
4794 isOperandLiteral(IC_RIGHT(lic)) &&
4795 operandLitValue(IC_RIGHT(lic)) == isize) {
4798 /* if the operand used or deffed */
4799 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
4802 /* if GOTO or IFX */
4803 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4809 /*-----------------------------------------------------------------*/
4810 /* genAndOp - for && operation */
4811 /*-----------------------------------------------------------------*/
4813 genAndOp (iCode * ic)
4815 operand *left, *right, *result;
4816 symbol *tlbl, *tlbl0;
4818 D(emitcode ("; genAndOp",""));
4820 /* note here that && operations that are in an
4821 if statement are taken away by backPatchLabels
4822 only those used in arthmetic operations remain */
4823 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4824 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4825 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4827 tlbl = newiTempLabel (NULL);
4828 tlbl0 = newiTempLabel (NULL);
4830 asmopToBool (AOP (left), FALSE);
4831 emitBranch ("beq", tlbl0);
4832 asmopToBool (AOP (right), FALSE);
4833 emitBranch ("beq", tlbl0);
4834 loadRegFromConst (hc08_reg_a,one);
4835 emitBranch ("bra", tlbl);
4837 loadRegFromConst (hc08_reg_a,zero);
4840 hc08_useReg (hc08_reg_a);
4841 hc08_freeReg (hc08_reg_a);
4843 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4845 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4846 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4847 freeAsmop (result, NULL, ic, TRUE);
4851 /*-----------------------------------------------------------------*/
4852 /* genOrOp - for || operation */
4853 /*-----------------------------------------------------------------*/
4855 genOrOp (iCode * ic)
4857 operand *left, *right, *result;
4858 symbol *tlbl, *tlbl0;
4860 D(emitcode ("; genOrOp",""));
4862 /* note here that || operations that are in an
4863 if statement are taken away by backPatchLabels
4864 only those used in arthmetic operations remain */
4865 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4866 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4867 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4869 tlbl = newiTempLabel (NULL);
4870 tlbl0 = newiTempLabel (NULL);
4872 asmopToBool (AOP (left), FALSE);
4873 emitBranch ("bne", tlbl0);
4874 asmopToBool (AOP (right), FALSE);
4875 emitBranch ("bne", tlbl0);
4876 loadRegFromConst (hc08_reg_a,zero);
4877 emitBranch ("bra", tlbl);
4879 loadRegFromConst (hc08_reg_a,one);
4882 hc08_useReg (hc08_reg_a);
4883 hc08_freeReg (hc08_reg_a);
4885 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4888 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4889 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4890 freeAsmop (result, NULL, ic, TRUE);
4893 /*-----------------------------------------------------------------*/
4894 /* isLiteralBit - test if lit == 2^n */
4895 /*-----------------------------------------------------------------*/
4897 isLiteralBit (unsigned long lit)
4899 unsigned long pw[32] =
4900 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4901 0x100L, 0x200L, 0x400L, 0x800L,
4902 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4903 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4904 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4905 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4906 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4909 for (idx = 0; idx < 32; idx++)
4916 /*-----------------------------------------------------------------*/
4917 /* continueIfTrue - */
4918 /*-----------------------------------------------------------------*/
4920 continueIfTrue (iCode * ic)
4923 emitBranch ("jmp", IC_TRUE (ic));
4927 /*-----------------------------------------------------------------*/
4929 /*-----------------------------------------------------------------*/
4931 jumpIfTrue (iCode * ic)
4934 emitBranch ("jmp", IC_FALSE (ic));
4938 /*-----------------------------------------------------------------*/
4939 /* jmpTrueOrFalse - */
4940 /*-----------------------------------------------------------------*/
4942 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4944 // ugly but optimized by peephole
4947 symbol *nlbl = newiTempLabel (NULL);
4948 emitBranch ("bra", nlbl);
4950 emitBranch ("jmp", IC_TRUE (ic));
4955 emitBranch ("jmp", IC_FALSE (ic));
4962 /*-----------------------------------------------------------------*/
4963 /* genAnd - code for and */
4964 /*-----------------------------------------------------------------*/
4966 genAnd (iCode * ic, iCode * ifx)
4968 operand *left, *right, *result;
4969 int size, offset = 0;
4970 unsigned long lit = 0L;
4971 unsigned long litinv;
4972 unsigned char bytemask;
4978 D(emitcode ("; genAnd",""));
4980 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4981 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4982 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4985 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4987 AOP_TYPE (left), AOP_TYPE (right)));
4988 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4990 AOP_SIZE (left), AOP_SIZE (right)));
4993 /* if left is a literal & right is not then exchange them */
4994 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4996 operand *tmp = right;
5001 /* if right is accumulator & left is not then exchange them */
5002 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5004 operand *tmp = right;
5009 if (AOP_TYPE (right) == AOP_LIT)
5010 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5012 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5014 if (AOP_TYPE (result) == AOP_CRY
5016 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5018 /* this generates ugly code, but meets volatility requirements */
5019 loadRegFromConst (hc08_reg_a, zero);
5020 pushReg (hc08_reg_a, TRUE);
5025 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5026 accopWithAop ("and", AOP (right), offset);
5027 emitcode ("ora", "1,s");
5028 emitcode ("sta", "1,s");
5032 pullReg (hc08_reg_a);
5033 emitcode ("tsta", "");
5034 genIfxJump (ifx, "a");
5038 if (AOP_TYPE (result) == AOP_CRY)
5040 symbol *tlbl = NULL;
5041 wassertl (ifx, "AOP_CRY result without ifx");
5046 bytemask = (lit >> (offset*8)) & 0xff;
5048 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5052 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5054 rmwWithAop ("tst", AOP (left), offset);
5058 tlbl = newiTempLabel (NULL);
5059 emitBranch ("bne", tlbl);
5064 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5065 accopWithAop ("and", AOP (right), offset);
5066 hc08_freeReg( hc08_reg_a);
5070 tlbl = newiTempLabel (NULL);
5071 emitBranch ("bne", tlbl);
5078 genIfxJump (ifx, "a");
5082 size = AOP_SIZE (result);
5084 if (AOP_TYPE (right) == AOP_LIT)
5086 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
5087 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5088 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
5090 int bitpos = isLiteralBit(litinv)-1;
5091 emitcode ("bclr","#%d,%s",bitpos & 7,
5092 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5100 bytemask = (lit >> (offset*8)) & 0xff;
5102 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5104 if (isOperandVolatile (left, FALSE))
5106 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5107 hc08_freeReg( hc08_reg_a);
5109 storeConstToAop (zero, AOP (result), offset);
5111 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5113 transferAopAop (AOP (left), offset, AOP (result), offset);
5117 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5118 accopWithAop ("and", AOP (right), offset);
5119 storeRegToAop (hc08_reg_a, AOP (result), offset);
5120 hc08_freeReg (hc08_reg_a);
5126 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5127 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5128 freeAsmop (result, NULL, ic, TRUE);
5131 /*-----------------------------------------------------------------*/
5132 /* genOr - code for or */
5133 /*-----------------------------------------------------------------*/
5135 genOr (iCode * ic, iCode * ifx)
5137 operand *left, *right, *result;
5138 int size, offset = 0;
5139 unsigned long lit = 0L;
5140 unsigned char bytemask;
5142 D(emitcode ("; genOr",""));
5144 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5145 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5146 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5149 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5151 AOP_TYPE (left), AOP_TYPE (right)));
5152 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5154 AOP_SIZE (left), AOP_SIZE (right)));
5157 /* if left is a literal & right is not then exchange them */
5158 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5160 operand *tmp = right;
5165 /* if left is accumulator & right is not then exchange them */
5166 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5168 operand *tmp = right;
5173 if (AOP_TYPE (right) == AOP_LIT)
5174 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5176 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5178 if (AOP_TYPE (result) == AOP_CRY
5180 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5182 /* this generates ugly code, but meets volatility requirements */
5183 loadRegFromConst (hc08_reg_a, zero);
5184 pushReg (hc08_reg_a, TRUE);
5189 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5190 accopWithAop ("ora", AOP (right), offset);
5191 emitcode ("ora", "1,s");
5192 emitcode ("sta", "1,s");
5196 pullReg (hc08_reg_a);
5197 emitcode ("tsta", "");
5198 genIfxJump (ifx, "a");
5202 if (AOP_TYPE (result) == AOP_CRY)
5204 symbol *tlbl = NULL;
5205 wassertl (ifx, "AOP_CRY result without ifx");
5210 bytemask = (lit >> (offset*8)) & 0xff;
5212 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5214 rmwWithAop ("tst", AOP (left), offset);
5218 tlbl = newiTempLabel (NULL);
5219 emitBranch ("bne", tlbl);
5224 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5225 accopWithAop ("ora", AOP (right), offset);
5226 hc08_freeReg( hc08_reg_a);
5230 tlbl = newiTempLabel (NULL);
5231 emitBranch ("bne", tlbl);
5238 genIfxJump (ifx, "a");
5241 if (AOP_TYPE (right) == AOP_LIT)
5242 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5244 size = AOP_SIZE (result);
5246 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5247 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5248 (AOP_TYPE (left) == AOP_DIR))
5250 int bitpos = isLiteralBit(lit)-1;
5251 emitcode ("bset","#%d,%s",bitpos & 7,
5252 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5259 bytemask = (lit >> (offset*8)) & 0xff;
5261 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5263 if (isOperandVolatile (left, FALSE))
5265 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5266 hc08_freeReg( hc08_reg_a);
5268 transferAopAop (AOP (right), offset, AOP (result), offset);
5270 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5272 transferAopAop (AOP (left), offset, AOP (result), offset);
5276 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5277 accopWithAop ("ora", AOP (right), offset);
5278 storeRegToAop (hc08_reg_a, AOP (result), offset);
5279 hc08_freeReg (hc08_reg_a);
5286 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5287 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5288 freeAsmop (result, NULL, ic, TRUE);
5291 /*-----------------------------------------------------------------*/
5292 /* genXor - code for xclusive or */
5293 /*-----------------------------------------------------------------*/
5295 genXor (iCode * ic, iCode * ifx)
5297 operand *left, *right, *result;
5298 int size, offset = 0;
5299 unsigned long lit = 0L;
5301 D(emitcode ("; genXor",""));
5303 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5304 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5305 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5308 DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5310 AOP_TYPE (left), AOP_TYPE (right)));
5311 DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5313 AOP_SIZE (left), AOP_SIZE (right)));
5316 /* if left is a literal & right is not ||
5317 if left needs acc & right does not */
5318 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5320 operand *tmp = right;
5325 /* if left is accumulator & right is not then exchange them */
5326 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5328 operand *tmp = right;
5333 if (AOP_TYPE (result) == AOP_CRY)
5336 wassertl (ifx, "AOP_CPY result without ifx");
5338 tlbl = newiTempLabel (NULL);
5339 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5343 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5344 if ((AOP_TYPE (right) == AOP_LIT)
5345 && (((lit >> (offset*8)) & 0xff) == 0))
5346 emitcode ("tsta","");
5348 accopWithAop ("eor", AOP (right), offset);
5349 hc08_freeReg( hc08_reg_a);
5351 emitBranch ("bne", tlbl);
5355 genIfxJump (ifx, "a");
5361 if (AOP_TYPE (right) == AOP_LIT)
5362 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5364 size = AOP_SIZE (result);
5368 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5369 accopWithAop ("eor", AOP (right), offset);
5370 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5371 hc08_freeReg( hc08_reg_a);
5375 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5376 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5377 freeAsmop (result, NULL, ic, TRUE);
5381 emitinline (iCode * ic, char *inlin)
5387 symbol *sym, *tempsym;
5396 while (isalnum((unsigned char)*inlin) || (*inlin == '_'))
5400 //printf("Found possible symbol '%s'\n",symname);
5401 tempsym = newSymbol (symname, ic->level);
5402 tempsym->block = ic->block;
5403 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5412 aop = aopForSym (ic, sym, FALSE);
5413 l = aopAdrStr (aop, aop->size - 1, TRUE);
5417 if (sym->level && !sym->allocreq && !sym->ismyparm)
5419 werror (E_ID_UNDEF, sym->name);
5421 " Add 'volatile' to the variable declaration so that it\n"
5422 " can be referenced within inline assembly");
5424 //printf("Replacing with '%s'\n",l);
5428 if ((2+bp-buffer)>sizeof(buffer))
5437 if ((2+bp-buffer)>sizeof(buffer))
5444 if ((2+bp-buffer)>sizeof(buffer))
5445 fprintf(stderr, "Inline assembly buffer overflow\n");
5447 //printf("%s\n",buffer);
5448 emitcode (buffer,"");
5452 /*-----------------------------------------------------------------*/
5453 /* genInline - write the inline code out */
5454 /*-----------------------------------------------------------------*/
5456 genInline (iCode * ic)
5458 char *buffer, *bp, *bp1;
5459 bool inComment = FALSE;
5461 D(emitcode ("; genInline",""));
5463 _G.inLine += (!options.asmpeep);
5465 buffer = bp = bp1 = Safe_strdup (IC_INLINE(ic));
5467 /* emit each line as a code */
5480 emitinline (ic, bp1);
5485 /* Add \n for labels, not dirs such as c:\mydir */
5486 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
5500 emitinline (ic, bp1);
5504 _G.inLine -= (!options.asmpeep);
5507 /*-----------------------------------------------------------------*/
5508 /* genRRC - rotate right with carry */
5509 /*-----------------------------------------------------------------*/
5513 operand *left, *result;
5514 int size, offset = 0;
5515 bool needpula = FALSE;
5516 bool resultInA = FALSE;
5519 D(emitcode ("; genRRC",""));
5521 /* rotate right with carry */
5522 left = IC_LEFT (ic);
5523 result = IC_RESULT (ic);
5524 aopOp (left, ic, FALSE);
5525 aopOp (result, ic, FALSE);
5527 if ((AOP_TYPE (result) == AOP_REG)
5528 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5531 size = AOP_SIZE (result);
5535 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5539 rmwWithAop (shift, AOP (result), offset--);
5547 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5548 rmwWithReg (shift, hc08_reg_a);
5549 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5550 hc08_freeReg (hc08_reg_a);
5555 if ((!hc08_reg_a->isFree) || resultInA)
5557 pushReg (hc08_reg_a, TRUE);
5561 /* now we need to put the carry into the
5562 highest order byte of the result */
5563 offset = AOP_SIZE (result) - 1;
5564 emitcode ("clra","");
5565 emitcode ("rora","");
5566 hc08_dirtyReg (hc08_reg_a, FALSE);
5569 emitcode ("ora", "1,s");
5570 emitcode ("ais", "#1");
5571 hc08_dirtyReg (hc08_reg_a, FALSE);
5575 accopWithAop ("ora", AOP (result), offset);
5576 storeRegToAop (hc08_reg_a, AOP (result), offset);
5578 pullOrFreeReg (hc08_reg_a, needpula);
5580 freeAsmop (left, NULL, ic, TRUE);
5581 freeAsmop (result, NULL, ic, TRUE);
5584 /*-----------------------------------------------------------------*/
5585 /* genRLC - generate code for rotate left with carry */
5586 /*-----------------------------------------------------------------*/
5590 operand *left, *result;
5591 int size, offset = 0;
5593 bool resultInA = FALSE;
5594 bool needpula = FALSE;
5596 D(emitcode ("; genRLC",""));
5598 /* rotate right with carry */
5599 left = IC_LEFT (ic);
5600 result = IC_RESULT (ic);
5601 aopOp (left, ic, FALSE);
5602 aopOp (result, ic, FALSE);
5604 if ((AOP_TYPE (result) == AOP_REG)
5605 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5608 size = AOP_SIZE (result);
5612 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5616 rmwWithAop (shift, AOP (result), offset--);
5624 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5625 rmwWithReg (shift, hc08_reg_a);
5626 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5627 hc08_freeReg (hc08_reg_a);
5632 if ((!hc08_reg_a->isFree) || resultInA)
5634 pushReg (hc08_reg_a, TRUE);
5638 /* now we need to put the carry into the
5639 lowest order byte of the result */
5641 emitcode ("clra","");
5642 emitcode ("rola","");
5643 hc08_dirtyReg (hc08_reg_a, FALSE);
5646 emitcode ("ora", "1,s");
5647 emitcode ("ais", "#1");
5648 hc08_dirtyReg (hc08_reg_a, FALSE);
5652 accopWithAop ("ora", AOP (result), offset);
5653 storeRegToAop (hc08_reg_a, AOP (result), offset);
5655 pullOrFreeReg (hc08_reg_a, needpula);
5657 freeAsmop (left, NULL, ic, TRUE);
5658 freeAsmop (result, NULL, ic, TRUE);
5661 /*-----------------------------------------------------------------*/
5662 /* genGetHbit - generates code get highest order bit */
5663 /*-----------------------------------------------------------------*/
5665 genGetHbit (iCode * ic)
5667 operand *left, *result;
5669 D(emitcode ("; genGetHbit",""));
5671 left = IC_LEFT (ic);
5672 result = IC_RESULT (ic);
5673 aopOp (left, ic, FALSE);
5674 aopOp (result, ic, FALSE);
5676 /* get the highest order byte into a */
5677 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5678 emitcode ("rola", "");
5679 emitcode ("clra", "");
5680 emitcode ("rola", "");
5681 hc08_dirtyReg (hc08_reg_a, FALSE);
5682 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5683 hc08_freeReg (hc08_reg_a);
5685 freeAsmop (left, NULL, ic, TRUE);
5686 freeAsmop (result, NULL, ic, TRUE);
5689 /*-----------------------------------------------------------------*/
5690 /* genSwap - generates code to swap nibbles or bytes */
5691 /*-----------------------------------------------------------------*/
5693 genSwap (iCode * ic)
5695 operand *left, *result;
5697 D(emitcode ("; genSwap",""));
5699 left = IC_LEFT (ic);
5700 result = IC_RESULT (ic);
5701 aopOp (left, ic, FALSE);
5702 aopOp (result, ic, FALSE);
5704 switch (AOP_SIZE (left))
5706 case 1: /* swap nibbles in byte */
5707 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5708 emitcode ("nsa", "");
5709 hc08_dirtyReg (hc08_reg_a, FALSE);
5710 storeRegToAop (hc08_reg_a, AOP (result), 0);
5711 hc08_freeReg (hc08_reg_a);
5713 case 2: /* swap bytes in a word */
5714 if (operandsEqu (left, result) || sameRegs (AOP (left), AOP (result)))
5716 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5717 hc08_useReg (hc08_reg_a);
5718 transferAopAop (AOP (left), 1, AOP (result), 0);
5719 storeRegToAop (hc08_reg_a, AOP (result), 1);
5720 hc08_freeReg (hc08_reg_a);
5724 transferAopAop (AOP (left), 0, AOP (result), 1);
5725 transferAopAop (AOP (left), 1, AOP (result), 0);
5729 wassertl(FALSE, "unsupported SWAP operand size");
5732 freeAsmop (left, NULL, ic, TRUE);
5733 freeAsmop (result, NULL, ic, TRUE);
5737 /*-----------------------------------------------------------------*/
5738 /* AccRol - rotate left accumulator by known count */
5739 /*-----------------------------------------------------------------*/
5741 AccRol (int shCount)
5743 shCount &= 0x0007; // shCount : 0..7
5750 emitcode ("rola", ""); /* 1 cycle */
5753 emitcode ("rola", ""); /* 1 cycle */
5754 emitcode ("rola", ""); /* 1 cycle */
5757 emitcode ("nsa", "");
5758 emitcode ("rora", "");
5761 emitcode ("nsa", ""); /* 3 cycles */
5764 emitcode ("nsa", ""); /* 3 cycles */
5765 emitcode ("rola", ""); /* 1 cycle */
5768 emitcode ("nsa", ""); /* 3 cycles */
5769 emitcode ("rola", ""); /* 1 cycle */
5770 emitcode ("rola", ""); /* 1 cycle */
5773 emitcode ("nsa", ""); /* 3 cycles */
5774 emitcode ("rola", ""); /* 1 cycle */
5775 emitcode ("rola", ""); /* 1 cycle */
5776 emitcode ("rola", ""); /* 1 cycle */
5783 /*-----------------------------------------------------------------*/
5784 /* AccLsh - left shift accumulator by known count */
5785 /*-----------------------------------------------------------------*/
5787 AccLsh (int shCount)
5791 shCount &= 0x0007; // shCount : 0..7
5793 /* Shift counts of 4 and 5 are currently optimized for code size. */
5794 /* Falling through to the unrolled loop would be optimal for code speed. */
5795 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5799 if (optimize.codeSpeed)
5801 accopWithMisc ("nsa", "");
5802 accopWithMisc ("and", "#0xf0");
5803 /* total: 5 cycles, 3 bytes */
5806 if (optimize.codeSpeed)
5808 accopWithMisc ("nsa", "");
5809 accopWithMisc ("and", "#0xf0");
5810 accopWithMisc ("lsla", "");
5811 /* total: 6 cycles, 4 bytes */
5814 accopWithMisc ("rora", "");
5815 accopWithMisc ("rora", "");
5816 accopWithMisc ("rora", "");
5817 accopWithMisc ("and", "#0xc0");
5818 /* total: 5 cycles, 5 bytes */
5821 accopWithMisc ("rora", "");
5822 accopWithMisc ("clra", "");
5823 accopWithMisc ("rora", "");
5824 /* total: 3 cycles, 3 bytes */
5828 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5829 /* the fastest (shCount<6) and shortest (shCount<4). */
5830 for (i=0;i<shCount;i++)
5831 accopWithMisc ("lsla", "");
5835 /*-----------------------------------------------------------------*/
5836 /* AccSRsh - signed right shift accumulator by known count */
5837 /*-----------------------------------------------------------------*/
5839 AccSRsh (int shCount)
5843 shCount &= 0x0007; // shCount : 0..7
5847 accopWithMisc ("rola", "");
5848 accopWithMisc ("clra", "");
5849 accopWithMisc ("sbc", zero);
5850 /* total: 4 cycles, 4 bytes */
5854 for (i=0;i<shCount;i++)
5855 accopWithMisc ("asra", "");
5858 /*-----------------------------------------------------------------*/
5859 /* AccRsh - right shift accumulator by known count */
5860 /*-----------------------------------------------------------------*/
5862 AccRsh (int shCount, bool sign)
5872 shCount &= 0x0007; // shCount : 0..7
5874 /* Shift counts of 4 and 5 are currently optimized for code size. */
5875 /* Falling through to the unrolled loop would be optimal for code speed. */
5876 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5880 if (optimize.codeSpeed)
5882 accopWithMisc ("nsa", "");
5883 accopWithMisc ("and", "#0x0f");
5884 /* total: 5 cycles, 3 bytes */
5887 if (optimize.codeSpeed)
5889 accopWithMisc ("nsa", "");
5890 accopWithMisc ("and", "#0x0f");
5891 accopWithMisc ("lsra", "");
5892 /* total: 6 cycles, 4 bytes */
5895 accopWithMisc ("rola", "");
5896 accopWithMisc ("rola", "");
5897 accopWithMisc ("rola", "");
5898 accopWithMisc ("and", "#0x03");
5899 /* total: 5 cycles, 5 bytes */
5902 accopWithMisc ("rola", "");
5903 accopWithMisc ("clra", "");
5904 accopWithMisc ("rola", "");
5905 /* total: 3 cycles, 3 bytes */
5909 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5910 /* the fastest (shCount<6) and shortest (shCount<4). */
5911 for (i=0;i<shCount;i++)
5912 accopWithMisc ("lsra", "");
5916 /*-----------------------------------------------------------------*/
5917 /* XAccLsh - left shift register pair XA by known count */
5918 /*-----------------------------------------------------------------*/
5920 XAccLsh (int shCount)
5924 shCount &= 0x000f; // shCount : 0..15
5929 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5930 loadRegFromConst (hc08_reg_a, zero);
5934 /* if we can beat 2n cycles or bytes for some special case, do it here */
5938 /* bytes cycles reg x reg a carry
5939 ** abcd efgh ijkl mnop ?
5940 ** lsrx 1 1 0abc defg ijkl mnop h
5941 ** rora 1 1 0abc defg hijk lmno p
5942 ** tax 1 1 hijk lmno hijk lmno p
5943 ** clra 1 1 hijk lmno 0000 0000 p
5944 ** rora 1 1 hijk lmno p000 0000 0
5945 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5947 rmwWithReg ("lsr", hc08_reg_x);
5948 rmwWithReg ("ror", hc08_reg_a);
5949 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5950 loadRegFromConst (hc08_reg_a, zero);
5951 rmwWithReg ("ror", hc08_reg_a);
5958 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5959 /* the fastest and shortest. */
5960 for (i=0;i<shCount;i++)
5962 rmwWithReg ("lsl", hc08_reg_a);
5963 rmwWithReg ("rol", hc08_reg_x);
5967 /*-----------------------------------------------------------------*/
5968 /* XAccSRsh - signed right shift register pair XA by known count */
5969 /*-----------------------------------------------------------------*/
5971 XAccSRsh (int shCount)
5975 shCount &= 0x000f; // shCount : 0..7
5977 /* if we can beat 2n cycles or bytes for some special case, do it here */
5981 /* bytes cycles reg x reg a carry
5982 ** abcd efgh ijkl mnop ?
5983 ** lslx 1 1 bcde fgh0 ijkl mnop a
5984 ** clra 1 1 bcde fgh0 0000 0000 a
5985 ** rola 1 1 bcde fgh0 0000 000a 0
5986 ** nega 1 1 bcde fgh0 aaaa aaaa a
5987 ** tax 1 1 aaaa aaaa aaaa aaaa a
5988 ** total: 5 cycles, 5 bytes
5990 rmwWithReg ("lsl", hc08_reg_x);
5991 loadRegFromConst (hc08_reg_a, zero);
5992 rmwWithReg ("rol", hc08_reg_a);
5993 rmwWithReg ("neg", hc08_reg_a);
5994 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6004 /* bytes cycles reg x reg a carry
6005 ** abcd efgh ijkl mnop ?
6006 ** txa 1 1 abcd efgh abcd efgh ?
6007 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
6008 ** lsla 1 1 abcd efgh ???? ???? a
6009 ** clrx 1 1 0000 0000 ???? ???? a
6010 ** rolx 1 1 0000 000a ???? ???? 0
6011 ** negx 1 1 aaaa aaaa ???? ???? a
6012 ** rora 1 1 aaaa aaaa LSBresult 0
6013 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
6015 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6016 AccSRsh (shCount-8);
6017 rmwWithReg ("lsl", hc08_reg_a);
6018 loadRegFromConst (hc08_reg_x, zero);
6019 rmwWithReg ("rol", hc08_reg_x);
6020 rmwWithReg ("neg", hc08_reg_x);
6021 rmwWithReg ("ror", hc08_reg_a);
6028 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6029 /* the fastest and shortest. */
6030 for (i=0;i<shCount;i++)
6032 rmwWithReg ("asr", hc08_reg_x);
6033 rmwWithReg ("ror", hc08_reg_a);
6037 /*-----------------------------------------------------------------*/
6038 /* XAccRsh - right shift register pair XA by known count */
6039 /*-----------------------------------------------------------------*/
6041 XAccRsh (int shCount, bool sign)
6051 shCount &= 0x000f; // shCount : 0..f
6053 /* if we can beat 2n cycles or bytes for some special case, do it here */
6057 /* bytes cycles reg x reg a carry
6058 ** abcd efgh ijkl mnop ?
6059 ** clra 1 1 abcd efgh 0000 0000 a
6060 ** lslx 1 1 bcde fgh0 0000 0000 a
6061 ** rola 1 1 bcde fgh0 0000 000a 0
6062 ** clrx 1 1 0000 0000 0000 000a 0
6063 ** total: 4 cycles, 4 bytes
6065 loadRegFromConst (hc08_reg_x, zero);
6066 rmwWithReg ("lsl", hc08_reg_x);
6067 rmwWithReg ("rol", hc08_reg_a);
6068 loadRegFromConst (hc08_reg_a, zero);
6072 /* bytes cycles reg x reg a carry
6073 ** abcd efgh ijkl mnop ?
6074 ** clra 1 1 abcd efgh 0000 0000 a
6075 ** lslx 1 1 bcde fgh0 0000 0000 a
6076 ** rola 1 1 bcde fgh0 0000 000a 0
6077 ** lslx 1 1 cdef gh00 0000 000a b
6078 ** rola 1 1 cdef gh00 0000 00ab 0
6079 ** clrx 1 1 0000 0000 0000 00ab 0
6080 ** total: 6 cycles, 6 bytes
6082 loadRegFromConst (hc08_reg_x, zero);
6083 rmwWithReg ("lsl", hc08_reg_x);
6084 rmwWithReg ("rol", hc08_reg_a);
6085 rmwWithReg ("lsl", hc08_reg_x);
6086 rmwWithReg ("rol", hc08_reg_a);
6087 loadRegFromConst (hc08_reg_a, zero);
6096 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6097 AccRsh (shCount-8, FALSE);
6098 loadRegFromConst (hc08_reg_x, zero);
6102 /* bytes cycles reg x reg a carry
6103 ** abcd efgh ijkl mnop ?
6104 ** lsla 1 1 abcd efgh jklm nop0 i
6105 ** txa 1 1 abcd efgh abcd efgh i
6106 ** rola 1 1 abcd efgh bcde fghi a
6107 ** clrx 1 1 0000 0000 bcde fghi a
6108 ** rolx 1 1 0000 000a bcde fghi 0
6109 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
6111 rmwWithReg ("lsl", hc08_reg_a);
6112 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6113 rmwWithReg ("rol", hc08_reg_a);
6114 loadRegFromConst (hc08_reg_x, zero);
6115 rmwWithReg ("rol", hc08_reg_x);
6118 /* bytes cycles reg x reg a carry
6119 ** abcd efgh ijkl mnop ?
6120 ** lsla 1 1 abcd efgh jklm nop0 i
6121 ** rolx 1 1 bcde fghi jklm nop0 a
6122 ** rola 1 1 bcde fghi klmn op0a j
6123 ** rolx 1 1 cdef ghij klmn op0a b
6124 ** rola 1 1 cdef ghij lmno p0ab k
6125 ** and #3 2 2 cdef ghij 0000 00ab k
6126 ** psha 1 2 cdef ghij 0000 00ab k
6127 ** txa 1 1 cdef ghij cdef ghij k
6128 ** pula 1 2 0000 00ab cdef ghij k
6129 ** total: 12 cycles, 10 bytes (beats 12 bytes)
6135 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6136 /* the fastest and shortest. */
6137 for (i=0;i<shCount;i++)
6139 rmwWithReg ("lsr", hc08_reg_x);
6140 rmwWithReg ("ror", hc08_reg_a);
6147 /*-----------------------------------------------------------------*/
6148 /* shiftR1Left2Result - shift right one byte from left to result */
6149 /*-----------------------------------------------------------------*/
6151 shiftR1Left2Result (operand * left, int offl,
6152 operand * result, int offr,
6153 int shCount, int sign)
6155 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6156 /* shift right accumulator */
6157 AccRsh (shCount, sign);
6158 storeRegToAop (hc08_reg_a, AOP (result), offr);
6162 /*-----------------------------------------------------------------*/
6163 /* shiftL1Left2Result - shift left one byte from left to result */
6164 /*-----------------------------------------------------------------*/
6166 shiftL1Left2Result (operand * left, int offl,
6167 operand * result, int offr, int shCount)
6169 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6170 /* shift left accumulator */
6172 storeRegToAop (hc08_reg_a, AOP (result), offr);
6175 /*-----------------------------------------------------------------*/
6176 /* movLeft2Result - move byte from left to result */
6177 /*-----------------------------------------------------------------*/
6179 movLeft2Result (operand * left, int offl,
6180 operand * result, int offr, int sign)
6182 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6184 transferAopAop (AOP (left), offl, AOP (result), offr);
6189 /*-----------------------------------------------------------------*/
6190 /* shiftL2Left2Result - shift left two bytes from left to result */
6191 /*-----------------------------------------------------------------*/
6193 shiftL2Left2Result (operand * left, int offl,
6194 operand * result, int offr, int shCount)
6197 bool needpula = FALSE;
6198 bool needpulx = FALSE;
6200 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6201 needpula = pushRegIfUsed (hc08_reg_a);
6204 if (!IS_AOP_XA (AOP (left)))
6205 needpulx = pushRegIfUsed (hc08_reg_x);
6209 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6214 rmwWithReg ("lsr", hc08_reg_x);
6215 rmwWithReg ("ror", hc08_reg_a);
6216 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6217 rmwWithReg ("clr", hc08_reg_a);
6218 rmwWithReg ("ror", hc08_reg_a);
6221 for (i=0; i<shCount; i++)
6223 rmwWithReg ("lsl", hc08_reg_a);
6224 rmwWithReg ("rol", hc08_reg_x);
6227 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6229 pullOrFreeReg (hc08_reg_x, needpulx);
6230 pullOrFreeReg (hc08_reg_a, needpula);
6236 /*-----------------------------------------------------------------*/
6237 /* shiftR2Left2Result - shift right two bytes from left to result */
6238 /*-----------------------------------------------------------------*/
6240 shiftR2Left2Result (operand * left, int offl,
6241 operand * result, int offr,
6242 int shCount, int sign)
6245 bool needpula = FALSE;
6246 bool needpulx = FALSE;
6248 needpula = pushRegIfUsed (hc08_reg_a);
6249 needpulx = pushRegIfUsed (hc08_reg_x);
6251 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6252 for (i=0; i<shCount; i++)
6255 rmwWithReg ("asr", hc08_reg_x);
6257 rmwWithReg ("lsr", hc08_reg_x);
6258 rmwWithReg ("ror", hc08_reg_a);
6260 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6262 pullOrFreeReg (hc08_reg_x, needpulx);
6263 pullOrFreeReg (hc08_reg_a, needpula);
6268 /*-----------------------------------------------------------------*/
6269 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6270 /*-----------------------------------------------------------------*/
6272 shiftLLeftOrResult (operand * left, int offl,
6273 operand * result, int offr, int shCount)
6275 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6276 /* shift left accumulator */
6278 /* or with result */
6279 accopWithAop ("ora", AOP (result), offr);
6280 /* back to result */
6281 storeRegToAop (hc08_reg_a, AOP (result), offr);
6282 hc08_freeReg (hc08_reg_a);
6286 /*-----------------------------------------------------------------*/
6287 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6288 /*-----------------------------------------------------------------*/
6290 shiftRLeftOrResult (operand * left, int offl,
6291 operand * result, int offr, int shCount)
6293 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6294 /* shift left accumulator */
6295 AccRsh (shCount, FALSE);
6296 /* or with result */
6297 accopWithAop ("ora", AOP (result), offr);
6298 /* back to result */
6299 storeRegToAop (hc08_reg_a, AOP (result), offr);
6300 hc08_freeReg (hc08_reg_a);
6303 /*-----------------------------------------------------------------*/
6304 /* genlshOne - left shift a one byte quantity by known count */
6305 /*-----------------------------------------------------------------*/
6307 genlshOne (operand * result, operand * left, int shCount)
6309 D(emitcode ("; genlshOne",""));
6311 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6314 /*-----------------------------------------------------------------*/
6315 /* genlshTwo - left shift two bytes by known amount != 0 */
6316 /*-----------------------------------------------------------------*/
6318 genlshTwo (operand * result, operand * left, int shCount)
6322 D(emitcode ("; genlshTwo",""));
6325 size = getDataSize (result);
6327 /* if shCount >= 8 */
6334 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6336 storeRegToAop (hc08_reg_a, AOP (result), 1);
6338 storeConstToAop(zero, AOP (result), LSB);
6341 /* 1 <= shCount <= 7 */
6344 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6346 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6350 /*-----------------------------------------------------------------*/
6351 /* shiftLLong - shift left one long from left to result */
6352 /* offr = LSB or MSB16 */
6353 /*-----------------------------------------------------------------*/
6355 shiftLLong (operand * left, operand * result, int offr)
6358 // int size = AOP_SIZE (result);
6360 bool needpula = FALSE;
6361 bool needpulx = FALSE;
6363 needpula = pushRegIfUsed (hc08_reg_a);
6364 needpulx = pushRegIfUsed (hc08_reg_x);
6366 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6367 rmwWithReg ("lsl", hc08_reg_a);
6368 rmwWithReg ("rol", hc08_reg_x);
6372 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6373 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6374 rmwWithReg ("rol", hc08_reg_a);
6375 rmwWithReg ("rol", hc08_reg_x);
6376 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6378 else if (offr==MSB16)
6380 storeRegToAop (hc08_reg_a, AOP (result), offr);
6381 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6382 storeRegToAop (hc08_reg_x, AOP (result), offr+1);
6383 rmwWithReg ("rol", hc08_reg_a);
6384 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6385 storeConstToAop (zero, AOP (result), 0);
6388 pullOrFreeReg (hc08_reg_x, needpulx);
6389 pullOrFreeReg (hc08_reg_a, needpula);
6392 /*-----------------------------------------------------------------*/
6393 /* genlshFour - shift four byte by a known amount != 0 */
6394 /*-----------------------------------------------------------------*/
6396 genlshFour (operand * result, operand * left, int shCount)
6400 D(emitcode ("; genlshFour",""));
6402 size = AOP_SIZE (result);
6404 /* TODO: deal with the &result == &left case */
6406 /* if shifting more that 3 bytes */
6411 /* lowest order of left goes to the highest
6412 order of the destination */
6413 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6415 movLeft2Result (left, LSB, result, MSB32, 0);
6416 storeConstToAop (zero, AOP (result), LSB);
6417 storeConstToAop (zero, AOP (result), MSB16);
6418 storeConstToAop (zero, AOP (result), MSB24);
6422 /* more than two bytes */
6423 else if (shCount >= 16)
6425 /* lower order two bytes goes to higher order two bytes */
6427 /* if some more remaining */
6429 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6432 movLeft2Result (left, MSB16, result, MSB32, 0);
6433 movLeft2Result (left, LSB, result, MSB24, 0);
6435 storeConstToAop (zero, AOP (result), LSB);
6436 storeConstToAop (zero, AOP (result), MSB16);
6440 /* if more than 1 byte */
6441 else if (shCount >= 8)
6443 /* lower order three bytes goes to higher order three bytes */
6448 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6450 movLeft2Result (left, LSB, result, MSB16, 0);
6456 movLeft2Result (left, MSB24, result, MSB32, 0);
6457 movLeft2Result (left, MSB16, result, MSB24, 0);
6458 movLeft2Result (left, LSB, result, MSB16, 0);
6459 storeConstToAop (zero, AOP (result), LSB);
6461 else if (shCount == 1)
6462 shiftLLong (left, result, MSB16);
6465 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6466 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6467 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6468 storeConstToAop (zero, AOP (result), LSB);
6473 /* 1 <= shCount <= 7 */
6474 else if (shCount <= 2)
6476 shiftLLong (left, result, LSB);
6478 shiftLLong (result, result, LSB);
6480 /* 3 <= shCount <= 7, optimize */
6483 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6484 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6485 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6489 /*-----------------------------------------------------------------*/
6490 /* genLeftShiftLiteral - left shifting by known count */
6491 /*-----------------------------------------------------------------*/
6493 genLeftShiftLiteral (operand * left,
6498 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
6501 D(emitcode ("; genLeftShiftLiteral",""));
6503 freeAsmop (right, NULL, ic, TRUE);
6505 aopOp (left, ic, FALSE);
6506 aopOp (result, ic, FALSE);
6508 // size = getSize (operandType (result));
6509 size = AOP_SIZE (result);
6512 DD(emitcode ("; shift left ", "result %d, left %d", size,
6519 transferAopAop( AOP(left), size, AOP(result), size);
6521 else if (shCount >= (size * 8))
6524 storeConstToAop (zero, AOP (result), size);
6531 genlshOne (result, left, shCount);
6535 genlshTwo (result, left, shCount);
6539 genlshFour (result, left, shCount);
6542 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6543 "*** ack! mystery literal shift!\n");
6547 freeAsmop (left, NULL, ic, TRUE);
6548 freeAsmop (result, NULL, ic, TRUE);
6551 /*-----------------------------------------------------------------*/
6552 /* genLeftShift - generates code for left shifting */
6553 /*-----------------------------------------------------------------*/
6555 genLeftShift (iCode * ic)
6557 operand *left, *right, *result;
6559 symbol *tlbl, *tlbl1;
6563 D(emitcode ("; genLeftShift",""));
6565 right = IC_RIGHT (ic);
6566 left = IC_LEFT (ic);
6567 result = IC_RESULT (ic);
6569 aopOp (right, ic, FALSE);
6571 /* if the shift count is known then do it
6572 as efficiently as possible */
6573 if (AOP_TYPE (right) == AOP_LIT)
6575 genLeftShiftLiteral (left, right, result, ic);
6579 /* shift count is unknown then we have to form
6580 a loop get the loop count in X : Note: we take
6581 only the lower order byte since shifting
6582 more that 32 bits make no sense anyway, ( the
6583 largest size of an object can be only 32 bits ) */
6585 aopOp (result, ic, FALSE);
6586 aopOp (left, ic, FALSE);
6587 aopResult = AOP (result);
6589 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result))
6590 || isOperandVolatile (result, FALSE))
6591 aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result)));
6593 /* now move the left to the result if they are not the
6595 if (!sameRegs (AOP (left), aopResult))
6597 size = AOP_SIZE (result);
6601 transferAopAop (AOP (left), offset, aopResult, offset);
6605 freeAsmop (left, NULL, ic, TRUE);
6606 AOP (result) = aopResult;
6608 tlbl = newiTempLabel (NULL);
6609 size = AOP_SIZE (result);
6611 tlbl1 = newiTempLabel (NULL);
6613 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6614 emitcode ("tstx", "");
6615 emitBranch ("beq", tlbl1);
6619 for (offset=0;offset<size;offset++)
6621 rmwWithAop (shift, AOP (result), offset);
6624 rmwWithReg ("dec", hc08_reg_x);
6625 emitBranch ("bne", tlbl);
6627 hc08_freeReg (hc08_reg_x);
6629 freeAsmop (result, NULL, ic, TRUE);
6630 freeAsmop (right, NULL, ic, TRUE);
6633 /*-----------------------------------------------------------------*/
6634 /* genrshOne - right shift a one byte quantity by known count */
6635 /*-----------------------------------------------------------------*/
6637 genrshOne (operand * result, operand * left,
6638 int shCount, int sign)
6640 D(emitcode ("; genrshOne",""));
6642 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6643 AccRsh (shCount, sign);
6644 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6647 /*-----------------------------------------------------------------*/
6648 /* genrshTwo - right shift two bytes by known amount != 0 */
6649 /*-----------------------------------------------------------------*/
6651 genrshTwo (operand * result, operand * left,
6652 int shCount, int sign)
6654 D(emitcode ("; genrshTwo",""));
6656 /* if shCount >= 8 */
6659 if (shCount || sign)
6661 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6662 AccRsh (shCount-8, sign);
6663 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6667 transferAopAop (AOP (left), 1, AOP (result), 0);
6668 storeConstToAop (zero, AOP (result), 1);
6672 /* 1 <= shCount <= 7 */
6675 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6676 XAccRsh (shCount, sign);
6677 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6681 /*-----------------------------------------------------------------*/
6682 /* shiftRLong - shift right one long from left to result */
6683 /* offl = LSB or MSB16 */
6684 /*-----------------------------------------------------------------*/
6686 shiftRLong (operand * left, int offl,
6687 operand * result, int sign)
6690 // int size = AOP_SIZE (result);
6692 bool needpula = FALSE;
6693 bool needpulx = FALSE;
6695 needpula = pushRegIfUsed (hc08_reg_a);
6696 needpulx = pushRegIfUsed (hc08_reg_x);
6700 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6702 rmwWithReg ("asr", hc08_reg_x);
6704 rmwWithReg ("lsr", hc08_reg_x);
6705 rmwWithReg ("ror", hc08_reg_a);
6706 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6707 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6709 else if (offl==MSB16)
6711 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6713 rmwWithReg ("asr", hc08_reg_a);
6715 rmwWithReg ("lsr", hc08_reg_a);
6716 loadRegFromAop (hc08_reg_x, AOP (left), MSB24);
6717 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6718 loadRegFromAop (hc08_reg_a, AOP (left), MSB16);
6721 rmwWithReg ("ror", hc08_reg_x);
6722 rmwWithReg ("ror", hc08_reg_a);
6723 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6729 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6730 storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
6734 storeConstToAop (zero, AOP (result), MSB32);
6738 pullOrFreeReg (hc08_reg_x, needpulx);
6739 pullOrFreeReg (hc08_reg_a, needpula);
6742 /*-----------------------------------------------------------------*/
6743 /* genrshFour - shift four byte by a known amount != 0 */
6744 /*-----------------------------------------------------------------*/
6746 genrshFour (operand * result, operand * left,
6747 int shCount, int sign)
6749 /* TODO: handle cases where left == result */
6751 D(emitcode ("; genrshFour",""));
6753 /* if shifting more that 3 bytes */
6756 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6757 AccRsh (shCount-24, sign);
6758 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6761 else if (shCount >= 16)
6763 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6764 XAccRsh (shCount-16, sign);
6765 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6768 else if (shCount >= 8)
6771 shiftRLong (left, MSB16, result, sign);
6772 else if (shCount == 8)
6774 transferAopAop (AOP (left), 1, AOP (result), 0);
6775 transferAopAop (AOP (left), 2, AOP (result), 1);
6776 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6777 storeRegToAop (hc08_reg_a, AOP (result), 2);
6778 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6780 else if (shCount == 9)
6782 shiftRLong (left, MSB16, result, sign);
6786 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6787 XAccRsh (shCount-8, FALSE);
6788 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6789 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6790 loadRegFromConst (hc08_reg_a, zero);
6791 XAccRsh (shCount-8, sign);
6792 accopWithAop ("ora", AOP (result), 1);
6793 storeRegToAop (hc08_reg_xa, AOP (result), 1);
6794 storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
6798 { /* 1 <= shCount <= 7 */
6801 shiftRLong (left, LSB, result, sign);
6805 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6806 XAccRsh (shCount, FALSE);
6807 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6808 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6810 accopWithAop ("ora", AOP (result), 1);
6811 storeRegToAop (hc08_reg_a, AOP (result), 1);
6812 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6813 XAccRsh (shCount, sign);
6814 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6819 /*-----------------------------------------------------------------*/
6820 /* genRightShiftLiteral - right shifting by known count */
6821 /*-----------------------------------------------------------------*/
6823 genRightShiftLiteral (operand * left,
6829 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
6832 D(emitcode ("; genRightShiftLiteral",""));
6834 freeAsmop (right, NULL, ic, TRUE);
6836 aopOp (left, ic, FALSE);
6837 aopOp (result, ic, FALSE);
6840 DD(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6844 size = getDataSize (left);
6845 /* test the LEFT size !!! */
6847 /* I suppose that the left size >= result size */
6850 size = getDataSize (result);
6852 transferAopAop (AOP (left), size, AOP(result), size);
6854 else if (shCount >= (size * 8))
6857 /* get sign in acc.7 */
6858 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6860 addSign (result, LSB, sign);
6867 genrshOne (result, left, shCount, sign);
6871 genrshTwo (result, left, shCount, sign);
6875 genrshFour (result, left, shCount, sign);
6881 freeAsmop (left, NULL, ic, TRUE);
6882 freeAsmop (result, NULL, ic, TRUE);
6886 /*-----------------------------------------------------------------*/
6887 /* genRightShift - generate code for right shifting */
6888 /*-----------------------------------------------------------------*/
6890 genRightShift (iCode * ic)
6892 operand *right, *left, *result;
6895 symbol *tlbl, *tlbl1;
6900 D(emitcode ("; genRightShift",""));
6902 /* if signed then we do it the hard way preserve the
6903 sign bit moving it inwards */
6904 retype = getSpec (operandType (IC_RESULT (ic)));
6905 sign = !SPEC_USIGN (retype);
6907 /* signed & unsigned types are treated the same : i.e. the
6908 signed is NOT propagated inwards : quoting from the
6909 ANSI - standard : "for E1 >> E2, is equivalent to division
6910 by 2**E2 if unsigned or if it has a non-negative value,
6911 otherwise the result is implementation defined ", MY definition
6912 is that the sign does not get propagated */
6914 right = IC_RIGHT (ic);
6915 left = IC_LEFT (ic);
6916 result = IC_RESULT (ic);
6918 aopOp (right, ic, FALSE);
6920 /* if the shift count is known then do it
6921 as efficiently as possible */
6922 if (AOP_TYPE (right) == AOP_LIT)
6924 genRightShiftLiteral (left, right, result, ic, sign);
6928 /* shift count is unknown then we have to form
6929 a loop get the loop count in X : Note: we take
6930 only the lower order byte since shifting
6931 more that 32 bits make no sense anyway, ( the
6932 largest size of an object can be only 32 bits ) */
6934 aopOp (result, ic, FALSE);
6935 aopOp (left, ic, FALSE);
6936 aopResult = AOP (result);
6938 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result))
6939 || isOperandVolatile (result, FALSE))
6940 aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result)));
6942 /* now move the left to the result if they are not the
6944 if (!sameRegs (AOP (left), aopResult))
6946 size = AOP_SIZE (result);
6950 transferAopAop (AOP (left), offset, aopResult, offset);
6954 freeAsmop (left, NULL, ic, TRUE);
6955 AOP (result) = aopResult;
6957 tlbl = newiTempLabel (NULL);
6958 size = AOP_SIZE (result);
6960 tlbl1 = newiTempLabel (NULL);
6962 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6963 emitcode ("tstx", "");
6964 emitBranch ("beq", tlbl1);
6967 shift= sign ? "asr" : "lsr";
6968 for (offset=size-1;offset>=0;offset--)
6970 rmwWithAop (shift, AOP (result), offset);
6973 rmwWithReg ("dec", hc08_reg_x);
6974 emitBranch ("bne", tlbl);
6976 hc08_freeReg (hc08_reg_x);
6978 freeAsmop (result, NULL, ic, TRUE);
6979 freeAsmop (right, NULL, ic, TRUE);
6983 /*-----------------------------------------------------------------*/
6984 /* genUnpackBits - generates code for unpacking bits */
6985 /*-----------------------------------------------------------------*/
6987 genUnpackBits (operand * result, iCode *ifx)
6989 int offset = 0; /* result byte offset */
6990 int rsize; /* result size */
6991 int rlen = 0; /* remaining bitfield length */
6992 sym_link *etype; /* bitfield type information */
6993 int blen; /* bitfield length */
6994 int bstr; /* bitfield starting bit within byte */
6996 D(emitcode ("; genUnpackBits",""));
6998 etype = getSpec (operandType (result));
6999 rsize = getSize (operandType (result));
7000 blen = SPEC_BLEN (etype);
7001 bstr = SPEC_BSTR (etype);
7003 if (ifx && blen <= 8)
7005 emitcode ("lda", ",x");
7006 hc08_dirtyReg (hc08_reg_a, FALSE);
7009 emitcode ("and", "#0x%02x",
7010 (((unsigned char) -1) >> (8 - blen)) << bstr);
7012 genIfxJump (ifx, "a");
7017 /* If the bitfield length is less than a byte */
7020 emitcode ("lda", ",x");
7021 hc08_dirtyReg (hc08_reg_a, FALSE);
7022 AccRsh (bstr, FALSE);
7023 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7024 if (!SPEC_USIGN (etype))
7026 /* signed bitfield */
7027 symbol *tlbl = newiTempLabel (NULL);
7029 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7030 emitcode ("beq", "%05d$", tlbl->key + 100);
7031 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7034 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7038 /* Bit field did not fit in a byte. Copy all
7039 but the partial byte at the end. */
7040 for (rlen=blen;rlen>=8;rlen-=8)
7042 emitcode ("lda", ",x");
7043 hc08_dirtyReg (hc08_reg_a, FALSE);
7044 storeRegToAop (hc08_reg_a, AOP (result), offset);
7047 emitcode ("aix", "#1");
7050 /* Handle the partial byte at the end */
7053 emitcode ("lda", ",x");
7054 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7055 if (!SPEC_USIGN (etype))
7057 /* signed bitfield */
7058 symbol *tlbl = newiTempLabel (NULL);
7060 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7061 emitcode ("beq", "%05d$", tlbl->key + 100);
7062 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7065 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7072 if (SPEC_USIGN (etype))
7075 storeConstToAop (zero, AOP (result), offset++);
7079 /* signed bitfield: sign extension with 0x00 or 0xff */
7080 emitcode ("rola", "");
7081 emitcode ("clra", "");
7082 emitcode ("sbc", zero);
7085 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7091 /*-----------------------------------------------------------------*/
7092 /* genUnpackBitsImmed - generates code for unpacking bits */
7093 /*-----------------------------------------------------------------*/
7095 genUnpackBitsImmed (operand * left,
7101 int offset = 0; /* result byte offset */
7102 int rsize; /* result size */
7103 int rlen = 0; /* remaining bitfield length */
7104 sym_link *etype; /* bitfield type information */
7105 int blen; /* bitfield length */
7106 int bstr; /* bitfield starting bit within byte */
7109 D(emitcode ("; genUnpackBitsImmed",""));
7111 aopOp (result, ic, TRUE);
7112 size = AOP_SIZE (result);
7114 derefaop = aopDerefAop (AOP (left));
7115 freeAsmop (left, NULL, ic, TRUE);
7116 derefaop->size = size;
7118 etype = getSpec (operandType (result));
7119 rsize = getSize (operandType (result));
7120 blen = SPEC_BLEN (etype);
7121 bstr = SPEC_BSTR (etype);
7123 /* if the bitfield is a single bit in the direct page */
7124 if (blen == 1 && derefaop->type == AOP_DIR)
7128 symbol *tlbl = newiTempLabel (NULL);
7130 loadRegFromConst (hc08_reg_a, zero);
7131 emitcode ("brclr", "#%d,%s,%05d$",
7132 bstr, aopAdrStr (derefaop, 0, FALSE),
7134 if (SPEC_USIGN (etype))
7135 rmwWithReg ("inc", hc08_reg_a);
7137 rmwWithReg ("dec", hc08_reg_a);
7139 storeRegToAop (hc08_reg_a, AOP (result), offset);
7140 hc08_freeReg (hc08_reg_a);
7146 symbol *tlbl = newiTempLabel (NULL);
7152 jlbl = IC_TRUE (ifx);
7157 jlbl = IC_FALSE (ifx);
7160 emitcode (inst, "#%d,%s,%05d$",
7161 bstr, aopAdrStr (derefaop, 0, FALSE),
7163 emitBranch ("jmp", jlbl);
7171 /* If the bitfield length is less than a byte */
7174 loadRegFromAop (hc08_reg_a, derefaop, 0);
7177 AccRsh (bstr, FALSE);
7178 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7179 hc08_dirtyReg (hc08_reg_a, FALSE);
7180 if (!SPEC_USIGN (etype))
7182 /* signed bitfield */
7183 symbol *tlbl = newiTempLabel (NULL);
7185 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7186 emitcode ("beq", "%05d$", tlbl->key + 100);
7187 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7190 storeRegToAop (hc08_reg_a, AOP (result), offset);
7194 emitcode ("and", "#0x%02x",
7195 (((unsigned char) -1) >> (8 - blen)) << bstr);
7196 hc08_dirtyReg (hc08_reg_a, FALSE);
7202 /* Bit field did not fit in a byte. Copy all
7203 but the partial byte at the end. */
7204 for (rlen=blen;rlen>=8;rlen-=8)
7206 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7208 storeRegToAop (hc08_reg_a, AOP (result), offset);
7210 emitcode ("tsta", "");
7214 /* Handle the partial byte at the end */
7217 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7218 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7219 if (!SPEC_USIGN (etype))
7221 /* signed bitfield */
7222 symbol *tlbl = newiTempLabel (NULL);
7224 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7225 emitcode ("beq", "%05d$", tlbl->key + 100);
7226 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7229 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7236 if (SPEC_USIGN (etype))
7239 storeConstToAop (zero, AOP (result), offset++);
7243 /* signed bitfield: sign extension with 0x00 or 0xff */
7244 emitcode ("rola", "");
7245 emitcode ("clra", "");
7246 emitcode ("sbc", zero);
7249 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7253 freeAsmop (NULL, derefaop, ic, TRUE);
7254 freeAsmop (result, NULL, ic, TRUE);
7256 if (ifx && !ifx->generated)
7258 genIfxJump (ifx, "a");
7263 /*-----------------------------------------------------------------*/
7264 /* genDataPointerGet - generates code when ptr offset is known */
7265 /*-----------------------------------------------------------------*/
7267 genDataPointerGet (operand * left,
7275 D(emitcode ("; genDataPointerGet",""));
7277 aopOp (result, ic, TRUE);
7278 size = AOP_SIZE (result);
7280 derefaop = aopDerefAop (AOP (left));
7281 freeAsmop (left, NULL, ic, TRUE);
7282 derefaop->size = size;
7287 transferAopAop (derefaop, size, AOP (result), size);
7289 loadRegFromAop (hc08_reg_a, derefaop, size);
7292 freeAsmop (NULL, derefaop, ic, TRUE);
7293 freeAsmop (result, NULL, ic, TRUE);
7295 if (ifx && !ifx->generated)
7297 genIfxJump (ifx, "a");
7302 /*-----------------------------------------------------------------*/
7303 /* genPointerGet - generate code for pointer get */
7304 /*-----------------------------------------------------------------*/
7306 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7308 operand *left = IC_LEFT (ic);
7309 operand *result = IC_RESULT (ic);
7311 sym_link *retype = getSpec (operandType (result));
7313 D(emitcode ("; genPointerGet",""));
7315 if (getSize (operandType (result))>1)
7318 aopOp (left, ic, FALSE);
7320 /* if left is rematerialisable and
7321 result is not bit variable type */
7322 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7324 if (!IS_BITVAR (retype))
7326 genDataPointerGet (left, result, ic, ifx);
7331 genUnpackBitsImmed (left, result, ic, ifx);
7336 /* if the operand is already in hx
7337 then we do nothing else we move the value to hx */
7338 if (AOP_TYPE (left) != AOP_STR)
7340 /* if this is remateriazable */
7341 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7344 /* so hx now contains the address */
7345 aopOp (result, ic, FALSE);
7347 /* if bit then unpack */
7348 if (IS_BITVAR (retype))
7349 genUnpackBits (result, ifx);
7352 size = AOP_SIZE (result);
7357 accopWithMisc ("lda", ",x");
7360 emitcode ("aix", "#1");
7361 hc08_dirtyReg (hc08_reg_hx, FALSE);
7364 storeRegToAop (hc08_reg_a, AOP (result), offset);
7366 hc08_freeReg (hc08_reg_a);
7370 freeAsmop (left, NULL, ic, TRUE);
7371 freeAsmop (result, NULL, ic, TRUE);
7374 aopOp (IC_RESULT (pi), pi, FALSE);
7375 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7376 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7380 if (ifx && !ifx->generated)
7382 genIfxJump (ifx, "a");
7385 hc08_freeReg (hc08_reg_hx);
7389 /*-----------------------------------------------------------------*/
7390 /* genPackBits - generates code for packed bit storage */
7391 /*-----------------------------------------------------------------*/
7393 genPackBits (sym_link * etype,
7396 int offset = 0; /* source byte offset */
7397 int rlen = 0; /* remaining bitfield length */
7398 int blen; /* bitfield length */
7399 int bstr; /* bitfield starting bit within byte */
7400 int litval; /* source literal value (if AOP_LIT) */
7401 unsigned char mask; /* bitmask within current byte */
7404 D(emitcode ("; genPackBits",""));
7406 blen = SPEC_BLEN (etype);
7407 bstr = SPEC_BSTR (etype);
7409 /* If the bitfield length is less than a byte */
7412 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7413 (unsigned char) (0xFF >> (8 - bstr)));
7415 if (AOP_TYPE (right) == AOP_LIT)
7417 /* Case with a bitfield length <8 and literal source
7419 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
7421 litval &= (~mask) & 0xff;
7423 emitcode ("lda", ",x");
7424 if ((mask|litval)!=0xff)
7425 emitcode ("and","#0x%02x", mask);
7427 emitcode ("ora","#0x%02x", litval);
7428 hc08_dirtyReg (hc08_reg_a, FALSE);
7429 emitcode ("sta", ",x");
7431 hc08_freeReg (hc08_reg_a);
7435 /* Case with a bitfield length < 8 and arbitrary source
7437 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7438 /* shift and mask source value */
7440 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7441 hc08_dirtyReg (hc08_reg_a, FALSE);
7442 pushReg (hc08_reg_a, TRUE);
7444 emitcode ("lda", ",x");
7445 emitcode ("and", "#0x%02x", mask);
7446 emitcode ("ora", "1,s");
7447 emitcode ("sta", ",x");
7448 pullReg (hc08_reg_a);
7450 hc08_freeReg (hc08_reg_a);
7454 /* Bit length is greater than 7 bits. In this case, copy */
7455 /* all except the partial byte at the end */
7456 for (rlen=blen;rlen>=8;rlen-=8)
7458 if (AOP (right)->type == AOP_DIR)
7460 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7465 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7466 emitcode ("sta", "%d,x", offset);
7471 /* If there was a partial byte at the end */
7474 mask = (((unsigned char) -1 << rlen) & 0xff);
7476 if (AOP_TYPE (right) == AOP_LIT)
7478 /* Case with partial byte and literal source
7480 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
7481 litval >>= (blen-rlen);
7482 litval &= (~mask) & 0xff;
7483 emitcode ("lda", "%d,x", offset - xoffset);
7484 hc08_dirtyReg (hc08_reg_a, FALSE);
7485 if ((mask|litval)!=0xff)
7486 emitcode ("and","#0x%02x", mask);
7488 emitcode ("ora","#0x%02x", litval);
7489 emitcode ("sta", "%d,x", offset - xoffset);
7490 hc08_dirtyReg (hc08_reg_a, FALSE);
7491 hc08_freeReg (hc08_reg_a);
7495 /* Case with partial byte and arbitrary source
7497 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7498 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7499 hc08_dirtyReg (hc08_reg_a, FALSE);
7500 pushReg (hc08_reg_a, TRUE);
7502 emitcode ("lda", "%d,x", offset - xoffset);
7503 emitcode ("and", "#0x%02x", mask);
7504 emitcode ("ora", "1,s");
7505 emitcode ("sta", "%d,x", offset - xoffset);
7506 pullReg (hc08_reg_a);
7509 hc08_freeReg (hc08_reg_a);
7512 /*-----------------------------------------------------------------*/
7513 /* genPackBitsImmed - generates code for packed bit storage */
7514 /*-----------------------------------------------------------------*/
7516 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7520 int offset = 0; /* source byte offset */
7521 int rlen = 0; /* remaining bitfield length */
7522 int blen; /* bitfield length */
7523 int bstr; /* bitfield starting bit within byte */
7524 int litval; /* source literal value (if AOP_LIT) */
7525 unsigned char mask; /* bitmask within current byte */
7527 D(emitcode ("; genPackBitsImmed",""));
7529 blen = SPEC_BLEN (etype);
7530 bstr = SPEC_BSTR (etype);
7532 aopOp (right, ic, FALSE);
7533 size = AOP_SIZE (right);
7535 derefaop = aopDerefAop (AOP (result));
7536 freeAsmop (result, NULL, ic, TRUE);
7537 derefaop->size = size;
7539 /* if the bitfield is a single bit in the direct page */
7540 if (blen == 1 && derefaop->type == AOP_DIR)
7542 if (AOP_TYPE (right) == AOP_LIT)
7544 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
7546 emitcode ((litval & 1) ? "bset" : "bclr",
7547 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7551 symbol *tlbl1 = newiTempLabel (NULL);
7552 symbol *tlbl2 = newiTempLabel (NULL);
7554 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7555 emitcode ("bit", "#1");
7556 emitBranch ("bne", tlbl1);
7557 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7558 emitBranch ("bra", tlbl2);
7560 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7562 hc08_freeReg (hc08_reg_a);
7567 /* If the bitfield length is less than a byte */
7570 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7571 (unsigned char) (0xFF >> (8 - bstr)));
7573 if (AOP_TYPE (right) == AOP_LIT)
7575 /* Case with a bitfield length <8 and literal source
7577 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
7579 litval &= (~mask) & 0xff;
7581 loadRegFromAop (hc08_reg_a, derefaop, 0);
7582 if ((mask|litval)!=0xff)
7583 emitcode ("and","#0x%02x", mask);
7585 emitcode ("ora","#0x%02x", litval);
7586 hc08_dirtyReg (hc08_reg_a, FALSE);
7587 storeRegToAop (hc08_reg_a, derefaop, 0);
7589 hc08_freeReg (hc08_reg_a);
7593 /* Case with a bitfield length < 8 and arbitrary source
7595 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7596 /* shift and mask source value */
7598 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7599 hc08_dirtyReg (hc08_reg_a, FALSE);
7600 pushReg (hc08_reg_a, TRUE);
7602 loadRegFromAop (hc08_reg_a, derefaop, 0);
7603 emitcode ("and", "#0x%02x", mask);
7604 emitcode ("ora", "1,s");
7605 storeRegToAop (hc08_reg_a, derefaop, 0);
7606 pullReg (hc08_reg_a);
7608 hc08_freeReg (hc08_reg_a);
7612 /* Bit length is greater than 7 bits. In this case, copy */
7613 /* all except the partial byte at the end */
7614 for (rlen=blen;rlen>=8;rlen-=8)
7616 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7620 /* If there was a partial byte at the end */
7623 mask = (((unsigned char) -1 << rlen) & 0xff);
7625 if (AOP_TYPE (right) == AOP_LIT)
7627 /* Case with partial byte and literal source
7629 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
7630 litval >>= (blen-rlen);
7631 litval &= (~mask) & 0xff;
7632 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7633 if ((mask|litval)!=0xff)
7634 emitcode ("and","#0x%02x", mask);
7636 emitcode ("ora","#0x%02x", litval);
7637 hc08_dirtyReg (hc08_reg_a, FALSE);
7638 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7639 hc08_dirtyReg (hc08_reg_a, FALSE);
7640 hc08_freeReg (hc08_reg_a);
7644 /* Case with partial byte and arbitrary source
7646 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7647 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7648 hc08_dirtyReg (hc08_reg_a, FALSE);
7649 pushReg (hc08_reg_a, TRUE);
7651 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7652 emitcode ("and", "#0x%02x", mask);
7653 emitcode ("ora", "1,s");
7654 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7655 pullReg (hc08_reg_a);
7658 hc08_freeReg (hc08_reg_a);
7661 freeAsmop (right, NULL, ic, TRUE);
7662 freeAsmop (NULL, derefaop, ic, TRUE);
7665 /*-----------------------------------------------------------------*/
7666 /* genDataPointerSet - remat pointer to data space */
7667 /*-----------------------------------------------------------------*/
7669 genDataPointerSet (operand * right,
7676 D(emitcode ("; genDataPointerSet",""));
7678 aopOp (right, ic, FALSE);
7679 size = AOP_SIZE (right);
7681 derefaop = aopDerefAop (AOP (result));
7682 freeAsmop (result, NULL, ic, TRUE);
7683 derefaop->size = size;
7687 transferAopAop (AOP (right), size, derefaop, size);
7690 freeAsmop (right, NULL, ic, TRUE);
7691 freeAsmop (NULL, derefaop, ic, TRUE);
7695 /*-----------------------------------------------------------------*/
7696 /* genPointerSet - stores the value into a pointer location */
7697 /*-----------------------------------------------------------------*/
7699 genPointerSet (iCode * ic, iCode *pi)
7701 operand *right = IC_RIGHT (ic);
7702 operand *result = IC_RESULT (ic);
7703 sym_link *type, *etype;
7705 sym_link *retype = getSpec (operandType (right));
7706 sym_link *letype = getSpec (operandType (result));
7708 D(emitcode ("; genPointerSet",""));
7710 type = operandType (result);
7711 etype = getSpec (type);
7713 aopOp (result, ic, FALSE);
7715 /* if the result is rematerializable */
7716 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7718 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7720 genDataPointerSet (right, result, ic);
7725 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7730 /* if the operand is already in hx
7731 then we do nothing else we move the value to hx */
7732 if (AOP_TYPE (result) != AOP_STR)
7734 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7736 /* so hx now contains the address */
7737 aopOp (right, ic, FALSE);
7739 /* if bit then unpack */
7740 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7741 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7744 size = AOP_SIZE (right);
7749 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7750 accopWithMisc ("sta", ",x");
7753 emitcode ("aix", "#1");
7755 hc08_freeReg (hc08_reg_a);
7759 freeAsmop (result, NULL, ic, TRUE);
7760 freeAsmop (right, NULL, ic, TRUE);
7763 aopOp (IC_RESULT (pi), pi, FALSE);
7764 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7765 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7769 hc08_freeReg (hc08_reg_hx);
7773 /*-----------------------------------------------------------------*/
7774 /* genIfx - generate code for Ifx statement */
7775 /*-----------------------------------------------------------------*/
7777 genIfx (iCode * ic, iCode * popIc)
7779 operand *cond = IC_COND (ic);
7782 D(emitcode ("; genIfx",""));
7784 aopOp (cond, ic, FALSE);
7786 /* If the condition is a literal, we can just do an unconditional */
7787 /* branch or no branch */
7788 if (AOP_TYPE (cond) == AOP_LIT)
7790 unsigned long lit = ulFromVal (AOP (cond)->aopu.aop_lit);
7791 freeAsmop (cond, NULL, ic, TRUE);
7793 /* if there was something to be popped then do it */
7799 emitBranch ("jmp", IC_TRUE (ic));
7804 emitBranch ("jmp", IC_FALSE (ic));
7810 /* get the value into acc */
7811 if (AOP_TYPE (cond) != AOP_CRY)
7812 asmopToBool (AOP (cond), FALSE);
7815 /* the result is now in the accumulator */
7816 freeAsmop (cond, NULL, ic, TRUE);
7818 /* if there was something to be popped then do it */
7822 /* if the condition is a bit variable */
7823 if (isbit && IS_ITEMP (cond) &&
7825 genIfxJump (ic, SPIL_LOC (cond)->rname);
7826 else if (isbit && !IS_ITEMP (cond))
7827 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7829 genIfxJump (ic, "a");
7834 /*-----------------------------------------------------------------*/
7835 /* genAddrOf - generates code for address of */
7836 /*-----------------------------------------------------------------*/
7838 genAddrOf (iCode * ic)
7840 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7843 D(emitcode ("; genAddrOf",""));
7845 aopOp (IC_RESULT (ic), ic, FALSE);
7847 /* if the operand is on the stack then we
7848 need to get the stack offset of this
7852 /* if it has an offset then we need to compute it */
7853 offset = _G.stackOfs + _G.stackPushes + sym->stack;
7854 hc08_useReg (hc08_reg_hx);
7855 emitcode ("tsx", "");
7856 while (offset > 127)
7858 emitcode ("aix", "#127");
7861 while (offset < -128)
7863 emitcode ("aix", "#-128");
7866 emitcode ("aix", "#%d", offset);
7867 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7868 hc08_freeReg (hc08_reg_hx);
7873 /* object not on stack then we need the name */
7874 size = AOP_SIZE (IC_RESULT (ic));
7879 char s[SDCC_NAME_MAX+10];
7882 sprintf (s, "#%s", sym->rname);
7885 sprintf (s, "#>%s", sym->rname);
7888 sprintf (s, "#(%s >> %d)",
7892 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7896 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7900 /*-----------------------------------------------------------------*/
7901 /* genAssign - generate code for assignment */
7902 /*-----------------------------------------------------------------*/
7904 genAssign (iCode * ic)
7906 operand *result, *right;
7908 // unsigned long lit = 0L;
7910 D(emitcode("; genAssign",""));
7912 result = IC_RESULT (ic);
7913 right = IC_RIGHT (ic);
7915 /* if they are the same */
7916 if (operandsEqu (result, right)) {
7920 aopOp (right, ic, FALSE);
7921 aopOp (result, ic, TRUE);
7923 /* if they are the same registers */
7924 if (sameRegs (AOP (right), AOP (result)))
7927 if ((AOP_TYPE (right) == AOP_LIT)
7928 && (IS_AOP_HX(AOP(result))))
7930 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7935 size = AOP_SIZE (result);
7938 transferAopAop (AOP (right), size, AOP (result), size);
7942 freeAsmop (right, NULL, ic, TRUE);
7943 freeAsmop (result, NULL, ic, TRUE);
7946 /*-----------------------------------------------------------------*/
7947 /* genJumpTab - generates code for jump table */
7948 /*-----------------------------------------------------------------*/
7950 genJumpTab (iCode * ic)
7953 symbol *jtablo = newiTempLabel (NULL);
7954 symbol *jtabhi = newiTempLabel (NULL);
7956 D(emitcode ("; genJumpTab",""));
7958 aopOp (IC_JTCOND (ic), ic, FALSE);
7960 if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7962 /* get the condition into x */
7963 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7964 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7965 loadRegFromConst (hc08_reg_h, zero);
7967 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7968 emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7969 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7970 emitcode ("jmp", ",x");
7972 hc08_dirtyReg (hc08_reg_a, TRUE);
7973 hc08_dirtyReg (hc08_reg_hx, TRUE);
7978 pushReg(hc08_reg_hx, TRUE);
7980 /* get the condition into x */
7981 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7982 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7983 loadRegFromConst (hc08_reg_h, zero);
7985 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7986 emitcode ("sta", "3,s");
7987 emitcode ("lda", "%05d$,x", jtablo->key + 100);
7988 emitcode ("sta", "4,s");
7990 pullReg(hc08_reg_hx);
7991 emitcode ("rts", "");
7992 _G.stackPushes += 2;
7996 /* now generate the jump labels */
7998 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7999 jtab = setNextItem (IC_JTLABELS (ic)))
8000 emitcode (".db", "%05d$", jtab->key + 100);
8002 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8003 jtab = setNextItem (IC_JTLABELS (ic)))
8004 emitcode (".db", ">%05d$", jtab->key + 100);
8008 /*-----------------------------------------------------------------*/
8009 /* genCast - gen code for casting */
8010 /*-----------------------------------------------------------------*/
8012 genCast (iCode * ic)
8014 operand *result = IC_RESULT (ic);
8015 sym_link *ctype = operandType (IC_LEFT (ic));
8016 sym_link *rtype = operandType (IC_RIGHT (ic));
8017 operand *right = IC_RIGHT (ic);
8020 D(emitcode("; genCast",""));
8022 /* if they are equivalent then do nothing */
8023 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8026 aopOp (right, ic, FALSE);
8027 aopOp (result, ic, FALSE);
8030 /* if they are the same size : or less */
8031 if (AOP_SIZE (result) <= AOP_SIZE (right))
8034 /* if they are in the same place */
8036 if (sameRegs (AOP (right), AOP (result)))
8040 /* if they in different places then copy */
8041 size = AOP_SIZE (result);
8045 transferAopAop(AOP (right), offset, AOP (result), offset);
8052 /* if the result is of type pointer */
8057 sym_link *type = operandType (right);
8058 sym_link *etype = getSpec (type);
8060 /* pointer to generic pointer */
8061 if (IS_GENPTR (ctype))
8064 p_type = DCL_TYPE (type);
8067 if (SPEC_SCLS(etype)==S_REGISTER) {
8068 // let's assume it is a generic pointer
8071 /* we have to go by the storage class */
8072 p_type = PTR_TYPE (SPEC_OCLS (etype));
8076 /* the first two bytes are known */
8077 size = GPTRSIZE - 1;
8081 transferAopAop(AOP (right), offset, AOP (result), offset);
8084 /* the last byte depending on type */
8087 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8092 // pointerTypeToGPByte will have bitched.
8096 sprintf(gpValStr, "#0x%x", gpVal);
8097 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8103 /* just copy the pointers */
8104 size = AOP_SIZE (result);
8108 transferAopAop(AOP (right), offset, AOP (result), offset);
8114 /* so we now know that the size of destination is greater
8115 than the size of the source */
8116 /* we move to result for the size of source */
8117 size = AOP_SIZE (right);
8121 transferAopAop(AOP (right), offset, AOP (result), offset);
8125 /* now depending on the sign of the source && destination */
8126 size = AOP_SIZE (result) - AOP_SIZE (right);
8127 /* if unsigned or not an integral type */
8128 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8131 storeConstToAop (zero, AOP (result), offset++);
8135 /* we need to extend the sign :{ */
8136 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
8137 accopWithMisc ("rola", "");
8138 accopWithMisc ("clra", "");
8139 accopWithMisc ("sbc", zero);
8141 storeRegToAop (hc08_reg_a, AOP (result), offset++);
8144 /* we are done hurray !!!! */
8147 freeAsmop (right, NULL, ic, TRUE);
8148 freeAsmop (result, NULL, ic, TRUE);
8152 /*-----------------------------------------------------------------*/
8153 /* genDjnz - generate decrement & jump if not zero instrucion */
8154 /*-----------------------------------------------------------------*/
8156 genDjnz (iCode * ic, iCode * ifx)
8162 D(emitcode ("; genDjnz",""));
8164 /* if the if condition has a false label
8165 then we cannot save */
8169 /* if the minus is not of the form
8171 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8172 !IS_OP_LITERAL (IC_RIGHT (ic)))
8175 if (operandLitValue (IC_RIGHT (ic)) != 1)
8178 /* dbnz doesn't support extended mode */
8179 if (isOperandInFarSpace (IC_RESULT (ic)))
8182 /* if the size of this greater than one then no
8184 // if (getSize (operandType (IC_RESULT (ic))) > 1)
8186 aopOp (IC_RESULT (ic), ic, FALSE);
8187 if (AOP_SIZE (IC_RESULT (ic))>1)
8189 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8193 /* otherwise we can save BIG */
8194 lbl = newiTempLabel (NULL);
8195 lbl1 = newiTempLabel (NULL);
8198 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
8201 emitBranch ("bra", lbl1);
8203 emitBranch ("jmp", IC_TRUE (ifx));
8206 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8211 /*-----------------------------------------------------------------*/
8212 /* genReceive - generate code for a receive iCode */
8213 /*-----------------------------------------------------------------*/
8215 genReceive (iCode * ic)
8219 D(emitcode ("; genReceive",""));
8221 aopOp (IC_RESULT (ic), ic, FALSE);
8222 size = AOP_SIZE (IC_RESULT (ic));
8227 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
8228 AOP (IC_RESULT (ic)), offset);
8229 if (hc08_aop_pass[offset]->type == AOP_REG)
8230 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
8235 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8238 /*-----------------------------------------------------------------*/
8239 /* genDummyRead - generate code for dummy read of volatiles */
8240 /*-----------------------------------------------------------------*/
8242 genDummyRead (iCode * ic)
8247 D(emitcode("; genDummyRead",""));
8250 if (op && IS_SYMOP (op))
8253 aopOp (op, ic, FALSE);
8255 size = AOP_SIZE (op);
8260 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8261 hc08_freeReg (hc08_reg_a);
8265 freeAsmop (op, NULL, ic, TRUE);
8268 if (op && IS_SYMOP (op))
8271 aopOp (op, ic, FALSE);
8273 size = AOP_SIZE (op);
8278 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8279 hc08_freeReg (hc08_reg_a);
8283 freeAsmop (op, NULL, ic, TRUE);
8287 /*-----------------------------------------------------------------*/
8288 /* genCritical - generate code for start of a critical sequence */
8289 /*-----------------------------------------------------------------*/
8291 genCritical (iCode *ic)
8293 D(emitcode("; genCritical",""));
8296 aopOp (IC_RESULT (ic), ic, TRUE);
8298 emitcode ("tpa", "");
8299 hc08_dirtyReg (hc08_reg_a, FALSE);
8300 emitcode ("sei", "");
8303 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8305 pushReg (hc08_reg_a, FALSE);
8307 hc08_freeReg (hc08_reg_a);
8309 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8312 /*-----------------------------------------------------------------*/
8313 /* genEndCritical - generate code for end of a critical sequence */
8314 /*-----------------------------------------------------------------*/
8316 genEndCritical (iCode *ic)
8318 D(emitcode("; genEndCritical",""));
8322 aopOp (IC_RIGHT (ic), ic, FALSE);
8323 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8324 emitcode ("tap", "");
8325 hc08_freeReg (hc08_reg_a);
8326 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8330 pullReg (hc08_reg_a);
8331 emitcode ("tap", "");
8337 /*-----------------------------------------------------------------*/
8338 /* genhc08Code - generate code for HC08 based controllers */
8339 /*-----------------------------------------------------------------*/
8341 genhc08Code (iCode * lic)
8348 lineHead = lineCurr = NULL;
8350 /* print the allocation information */
8351 if (allocInfo && currFunc)
8352 printAllocInfo (currFunc, codeOutBuf);
8353 /* if debug information required */
8354 if (options.debug && currFunc)
8356 debugFile->writeFunction (currFunc, lic);
8359 if (IS_STATIC (currFunc->etype))
8360 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8362 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8366 /* stack pointer name */
8367 if (options.useXstack)
8372 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8374 hc08_aop_pass[0] = newAsmop (AOP_REG);
8375 hc08_aop_pass[0]->size=1;
8376 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8377 hc08_aop_pass[1] = newAsmop (AOP_REG);
8378 hc08_aop_pass[1]->size=1;
8379 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8380 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8381 hc08_aop_pass[2]->size=1;
8382 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8383 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8384 hc08_aop_pass[3]->size=1;
8385 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8387 for (ic = lic; ic; ic = ic->next)
8390 _G.current_iCode = ic;
8392 if (ic->level != clevel || ic->block != cblock)
8396 debugFile->writeScope(ic);
8402 if (ic->lineno && cln != ic->lineno)
8406 debugFile->writeCLine(ic);
8409 emitcode ("", "C$%s$%d$%d$%d ==.",
8410 FileBaseName (ic->filename), ic->lineno,
8411 ic->level, ic->block);
8415 if (!options.noCcodeInAsm) {
8416 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8417 printCLine(ic->filename, ic->lineno));
8421 if (options.iCodeInAsm) {
8426 for (i=0; i<6; i++) {
8427 sprintf (®sInUse[i],
8428 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8431 iLine = printILine(ic);
8432 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8435 /* if the result is marked as
8436 spilt and rematerializable or code for
8437 this has already been generated then
8439 if (resultRemat (ic) || ic->generated)
8447 for (i=A_IDX;i<=XA_IDX;i++)
8449 reg = hc08_regWithIdx(i);
8451 emitcode("","; %s = %s offset %d", reg->name,
8452 aopName(reg->aop), reg->aopofs);
8455 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8457 sym = OP_SYMBOL (IC_LEFT (ic));
8458 if (sym->accuse == ACCUSE_HX)
8460 hc08_reg_h->isFree = FALSE;
8461 hc08_reg_x->isFree = FALSE;
8463 else if (sym->accuse == ACCUSE_XA)
8465 hc08_reg_a->isFree = FALSE;
8467 hc08_reg_x->isFree = FALSE;
8470 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8472 sym = OP_SYMBOL (IC_RIGHT (ic));
8473 if (sym->accuse == ACCUSE_HX)
8475 hc08_reg_h->isFree = FALSE;
8476 hc08_reg_x->isFree = FALSE;
8478 else if (sym->accuse == ACCUSE_XA)
8480 hc08_reg_a->isFree = FALSE;
8482 hc08_reg_x->isFree = FALSE;
8487 /* depending on the operation */
8507 /* IPOP happens only when trying to restore a
8508 spilt live range, if there is an ifx statement
8509 following this pop then the if statement might
8510 be using some of the registers being popped which
8511 would destory the contents of the register so
8512 we need to check for this condition and handle it */
8514 ic->next->op == IFX &&
8515 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8516 genIfx (ic->next, ic);
8534 genEndFunction (ic);
8550 if (!genPointerGetSetOfs (ic))
8555 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8575 genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
8580 genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
8592 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8596 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8600 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8627 case GET_VALUE_AT_ADDRESS:
8629 hasInc (IC_LEFT (ic), ic,
8630 getSize (operandType (IC_RESULT (ic)))),
8631 ifxForOp (IC_RESULT (ic), ic) );
8635 if (POINTER_SET (ic))
8636 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8662 addSet (&_G.sendSet, ic);
8665 case DUMMY_READ_VOLATILE:
8674 genEndCritical (ic);
8685 if (!hc08_reg_a->isFree)
8686 DD(emitcode("","; forgot to free a"));
8687 if (!hc08_reg_x->isFree)
8688 DD(emitcode("","; forgot to free x"));
8689 if (!hc08_reg_h->isFree)
8690 DD(emitcode("","; forgot to free h"));
8691 if (!hc08_reg_hx->isFree)
8692 DD(emitcode("","; forgot to free hx"));
8693 if (!hc08_reg_xa->isFree)
8694 DD(emitcode("","; forgot to free xa"));
8697 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8700 /* now we are ready to call the
8701 peep hole optimizer */
8702 if (!options.nopeep)
8703 peepHole (&lineHead);
8705 /* now do the actual printing */
8706 printLine (lineHead, codeOutBuf);