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 -------------------------------------------------------------------------*/
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
45 char *aopLiteral (value * val, int offset);
46 char *aopLiteralLong (value * val, int offset, int size);
48 static int pushReg (regs *reg, bool freereg);
49 static void pullReg (regs *reg);
51 static char *zero = "#0x00";
52 static char *one = "#0x01";
56 {"a", "x", "_ret2", "_ret3"};
57 unsigned fReturnSizeHC08 = 4; /* shared with ralloc.c */
58 char **fReturn2 = fReturnhc08;
77 static asmop *hc08_aop_pass[4];
79 extern int hc08_ptrRegReq;
80 extern int hc08_nRegs;
81 extern FILE *codeOutFile;
82 //static void saveRBank (int, iCode *, bool);
83 static bool operandsEqu (operand * op1, operand * op2);
84 static void loadRegFromConst (regs *reg, char *c);
85 static char *aopName (asmop *aop);
86 static asmop * newAsmop (short type);
87 static char * aopAdrStr (asmop * aop, int loffset, bool bit16);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 #define IS_AOP_HX(x) \
93 (((x)->type == AOP_REG) \
94 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
95 && ((x)->aopu.aop_reg[1] == hc08_reg_h) )
97 #define IS_AOP_XA(x) \
98 (((x)->type == AOP_REG) \
99 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
100 && ((x)->aopu.aop_reg[1] == hc08_reg_x) )
102 #define IS_AOP_A(x) \
103 (((x)->type == AOP_REG) \
104 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
105 && ((x)->size == 1) )
107 #define IS_AOP_X(x) \
108 (((x)->type == AOP_REG) \
109 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
110 && ((x)->size == 1) )
112 #define IS_AOP_H(x) \
113 (((x)->type == AOP_REG) \
114 && ((x)->aopu.aop_reg[0] == hc08_reg_h) \
115 && ((x)->size == 1) )
117 #define CLRC emitcode("clc","")
119 static lineNode *lineHead = NULL;
120 static lineNode *lineCurr = NULL;
123 static unsigned char SLMask[] =
124 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
125 0xE0, 0xC0, 0x80, 0x00};
126 static unsigned char SRMask[] =
127 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
128 0x07, 0x03, 0x01, 0x00};
136 #define AOP(op) op->aop
137 #define AOP_TYPE(op) AOP(op)->type
138 #define AOP_SIZE(op) AOP(op)->size
139 #define AOP_OP(aop) aop->op
142 /*-----------------------------------------------------------------*/
143 /* emitcode - writes the code into a file : for now it is simple */
144 /*-----------------------------------------------------------------*/
146 emitcode (char *inst, char *fmt,...)
149 char lb[INITIAL_INLINEASM];
157 sprintf (lb, "%s\t", inst);
159 sprintf (lb, "%s", inst);
160 vsprintf (lb + (strlen (lb)), fmt, ap);
163 vsprintf (lb, fmt, ap);
165 while (isspace ((unsigned char)*lbp))
169 lineCurr = (lineCurr ?
170 connectLine (lineCurr, newLineNode (lb)) :
171 (lineHead = newLineNode (lb)));
172 lineCurr->isInline = _G.inLine;
173 lineCurr->isDebug = _G.debugLine;
174 lineCurr->ic = _G.current_iCode;
175 lineCurr->isComment = (*lbp==';');
177 //printf("%s\n", lb);
182 emitBranch (char *branchop, symbol *tlbl)
184 emitcode (branchop, "%05d$", (tlbl->key + 100));
188 emitLabel (symbol *tlbl)
190 emitcode ("", "%05d$:", (tlbl->key +100));
193 /*-----------------------------------------------------------------*/
194 /* hc08_emitDebuggerSymbol - associate the current code location */
195 /* with a debugger symbol */
196 /*-----------------------------------------------------------------*/
198 hc08_emitDebuggerSymbol (char * debugSym)
201 emitcode ("", "%s ==.", debugSym);
206 /*--------------------------------------------------------------------------*/
207 /* transferRegReg - Transfer from register(s) sreg to register(s) dreg. If */
208 /* freesrc is true, sreg is marked free and available for */
209 /* reuse. sreg and dreg must be of equal size */
210 /*--------------------------------------------------------------------------*/
212 transferRegReg (regs *sreg, regs *dreg, bool freesrc)
218 /* Nothing to do if no destination. */
222 /* But it's definately an error if there's no source. */
225 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
226 "NULL sreg in transferRegReg");
230 D(emitcode ("", "; transferRegReg(%s,%s)",
231 sreg->name, dreg->name));
244 case H_IDX: /* H to A */
245 pushReg (hc08_reg_h, FALSE);
246 pullReg (hc08_reg_a);
248 case X_IDX: /* X to A */
249 emitcode ("txa", "");
258 case A_IDX: /* A to H */
259 pushReg (hc08_reg_a, FALSE);
260 pullReg (hc08_reg_h);
262 case X_IDX: /* X to H */
263 pushReg (hc08_reg_x, FALSE);
264 pullReg (hc08_reg_h);
273 case A_IDX: /* A to X */
274 emitcode ("tax", "");
276 case H_IDX: /* H to X */
277 pushReg (hc08_reg_h, FALSE);
278 pullReg (hc08_reg_x);
287 case XA_IDX: /* XA to HX */
288 pushReg (hc08_reg_x, FALSE);
289 pullReg (hc08_reg_h);
290 emitcode ("tax", "");
299 case HX_IDX: /* HX to XA */
300 emitcode ("txa", "");
301 pushReg (hc08_reg_h, FALSE);
302 pullReg (hc08_reg_x);
312 wassertl (!error, "bad combo in transferRegReg");
317 dreg->aop = sreg->aop;
318 dreg->aopofs = sreg->aopofs;
319 dreg->isFree = FALSE;
323 /*--------------------------------------------------------------------------*/
324 /* updateCFA - update the debugger information to reflect the current */
325 /* connonical frame address relative to the stack pointer */
326 /*--------------------------------------------------------------------------*/
330 /* there is no frame unless there is a function */
334 debugFile->writeFrameAddress (NULL, hc08_reg_sp,
335 1 + _G.stackOfs + _G.stackPushes);
338 /*--------------------------------------------------------------------------*/
339 /* pushReg - Push register reg onto the stack. If freereg is true, reg is */
340 /* marked free and available for reuse. */
341 /*--------------------------------------------------------------------------*/
343 pushReg (regs *reg, bool freereg)
345 int regidx = reg->rIdx;
350 emitcode ("psha", "");
355 emitcode ("pshx", "");
360 emitcode ("pshh", "");
365 emitcode ("pshx", "");
368 emitcode ("pshh", "");
373 emitcode ("psha", "");
376 emitcode ("pshx", "");
385 return -_G.stackOfs-_G.stackPushes;
388 /*--------------------------------------------------------------------------*/
389 /* pullReg - Pull register reg off the stack. */
390 /*--------------------------------------------------------------------------*/
394 int regidx = reg->rIdx;
399 emitcode ("pula", "");
404 emitcode ("pulx", "");
409 emitcode ("pulh", "");
414 emitcode ("pulh", "");
417 emitcode ("pulx", "");
422 emitcode ("pulx", "");
425 emitcode ("pula", "");
433 hc08_dirtyReg(reg, FALSE);
436 /*--------------------------------------------------------------------------*/
437 /* pullNull - Discard n bytes off the top of the stack */
438 /*--------------------------------------------------------------------------*/
444 emitcode("ais","#%d",n);
450 /*--------------------------------------------------------------------------*/
451 /* pushRegIfUsed - Push register reg if marked in use. Returns true if the */
452 /* push was performed, false otherwise. */
453 /*--------------------------------------------------------------------------*/
455 pushRegIfUsed (regs *reg)
466 /*--------------------------------------------------------------------------*/
467 /* pullOrFreeReg - If needpull is true, register reg is pulled from the */
468 /* stack. Otherwise register reg is marked as free. */
469 /*--------------------------------------------------------------------------*/
471 pullOrFreeReg (regs *reg, bool needpull)
479 /*--------------------------------------------------------------------------*/
480 /* adjustStack - Adjust the stack pointer by n bytes. */
481 /*--------------------------------------------------------------------------*/
489 emitcode ("ais","#127");
491 _G.stackPushes -= 127;
496 emitcode ("ais","#-128");
498 _G.stackPushes += 128;
503 emitcode ("ais", "#%d", n);
512 /*--------------------------------------------------------------------------*/
513 /* aopName - Return a string with debugging information about an asmop. */
514 /*--------------------------------------------------------------------------*/
518 static char buffer[256];
522 return "(asmop*)NULL";
527 sprintf (buf,"IMMD(%s)", aop->aopu.aop_immd.aop_immd1);
530 sprintf (buf,"LIT(%s)", aopLiteral (aop->aopu.aop_lit, 0));
533 sprintf (buf,"DIR(%s)", aop->aopu.aop_dir);
536 sprintf (buf,"EXT(%s)", aop->aopu.aop_dir);
539 sprintf (buf,"SOF(%s)", OP_SYMBOL (aop->op)->name);
542 sprintf (buf, "REG(%s,%s,%s,%s)",
543 aop->aopu.aop_reg[3] ? aop->aopu.aop_reg[3]->name : "-",
544 aop->aopu.aop_reg[2] ? aop->aopu.aop_reg[2]->name : "-",
545 aop->aopu.aop_reg[1] ? aop->aopu.aop_reg[1]->name : "-",
546 aop->aopu.aop_reg[0] ? aop->aopu.aop_reg[0]->name : "-");
553 sprintf (buf,"?%d", aop->type);
561 /*--------------------------------------------------------------------------*/
562 /* loadRegFromAop - Load register reg from logical offset loffset of aop. */
563 /*--------------------------------------------------------------------------*/
565 loadRegFromAop (regs *reg, asmop *aop, int loffset)
567 int regidx = reg->rIdx;
569 if (aop->stacked && aop->stk_aop[loffset])
571 loadRegFromAop (reg, aop->stk_aop[loffset], 0);
576 printf("loadRegFromAop called\n");
579 printf(" reg = NULL\n");
582 printf(" reg = %s\n", reg->name);
585 printf(" aop = NULL\n");
588 printf(" aop->type = %d\n", aop->type);
589 printf(" loffset = %d\n", loffset);
592 printf(" aop has operand link\n");
594 printf(" aop missing operand link\n");
596 printf(" reg has operand link\n");
598 printf(" reg missing operand link\n");
601 D(emitcode ("", "; loadRegFromAop (%s, %s, %d)",
602 reg->name, aopName (aop), loffset));
604 /* If operand is volatile, we cannot optimize. */
605 if (!aop->op || isOperandVolatile (aop->op, FALSE))
609 /* If this register already has this offset of the operand
610 then we need only mark it as in use. */
611 if (reg->aop && reg->aop->op && aop->op
612 && operandsEqu(reg->aop->op,aop->op)
613 && (reg->aopofs == loffset))
616 D(emitcode ("","; already had correct value for %s", reg->name));
620 /* TODO: check to see if we can transfer from another register */
622 if (hc08_reg_h->aop && hc08_reg_h->aop->op && aop->op
623 && operandsEqu(hc08_reg_h->aop->op,aop->op)
624 && (hc08_reg_h->aopofs == loffset))
626 D(emitcode ("","; found correct value for %s in h", reg->name));
627 transferRegReg (hc08_reg_h, reg, FALSE);
633 if (hc08_reg_x->aop && hc08_reg_x->aop->op && aop->op
634 && operandsEqu(hc08_reg_x->aop->op,aop->op)
635 && (hc08_reg_x->aopofs == loffset))
637 D(emitcode ("","; found correct value for %s in x", reg->name));
638 transferRegReg (hc08_reg_x, reg, FALSE);
643 if (hc08_reg_a->aop && hc08_reg_a->aop->op && aop->op
644 && operandsEqu(hc08_reg_a->aop->op,aop->op)
645 && (hc08_reg_a->aopofs == loffset))
647 D(emitcode ("","; found correct value for %s in a", reg->name));
648 transferRegReg (hc08_reg_a, reg, FALSE);
658 if (aop->type == AOP_REG)
660 if (loffset < aop->size)
661 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
663 emitcode ("clra", ""); /* TODO: handle sign extension */
667 char * l = aopAdrStr (aop, loffset, FALSE);
668 if (!strcmp (l, zero))
669 emitcode ("clra", "");
671 emitcode ("lda", "%s", l);
675 if (aop->type == AOP_REG)
677 if (loffset < aop->size)
678 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
680 emitcode ("clrx", ""); /* TODO: handle sign extension */
684 char * l = aopAdrStr (aop, loffset, FALSE);
685 if (!strcmp (l, zero))
686 emitcode ("clrx", "");
688 emitcode ("ldx", "%s", l);
693 char * l = aopAdrStr (aop, loffset, FALSE);
694 if (!strcmp (l, zero))
696 emitcode ("clrh", "");
700 if (hc08_reg_a->isFree)
702 loadRegFromAop (hc08_reg_a, aop, loffset);
703 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
705 else if (hc08_reg_x->isFree)
707 loadRegFromAop (hc08_reg_x, aop, loffset);
708 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
712 pushReg (hc08_reg_a, TRUE);
713 loadRegFromAop (hc08_reg_a, aop, loffset);
714 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
715 pullReg (hc08_reg_a);
721 else if (IS_AOP_XA(aop))
722 transferRegReg (hc08_reg_xa, hc08_reg_hx, FALSE);
723 else if ((aop->type == AOP_DIR))
725 if (aop->size>(loffset+1))
726 emitcode ("ldhx","%s", aopAdrStr (aop, loffset+1, TRUE));
729 loadRegFromAop (hc08_reg_x, aop, loffset);
730 loadRegFromConst (hc08_reg_h, zero);
733 else if ((aop->type == AOP_LIT) || (aop->type == AOP_IMMD))
735 emitcode ("ldhx","%s", aopAdrStr (aop, loffset, TRUE));
740 needpula = pushRegIfUsed (hc08_reg_a);
741 loadRegFromAop (hc08_reg_a, aop, loffset+1);
742 loadRegFromAop (hc08_reg_x, aop, loffset);
743 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
744 pullOrFreeReg (hc08_reg_a, needpula);
750 else if (IS_AOP_HX(aop))
751 transferRegReg (hc08_reg_hx, hc08_reg_xa, FALSE);
754 loadRegFromAop (hc08_reg_a, aop, loffset);
755 loadRegFromAop (hc08_reg_x, aop, loffset+1);
760 // ignore caching for now
763 reg->aopofs = loffset;
768 /*--------------------------------------------------------------------------*/
769 /* forceStackedAop - Reserve space on the stack for asmop aop; when */
770 /* freeAsmop is called with aop, the stacked data will */
771 /* be copied to the original aop location and */
772 /*--------------------------------------------------------------------------*/
774 forceStackedAop (asmop *aop)
777 asmop *newaop = newAsmop (aop->type);
778 memcpy (newaop, aop, sizeof(*newaop));
780 D(emitcode("", "; forcedStackAop %s", aopName(aop)));
781 for (loffset=0; loffset < newaop->size; loffset++)
783 asmop *aopsof = newAsmop (AOP_SOF);
785 aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE);
786 aopsof->op = aop->op;
787 newaop->stk_aop[loffset] = aopsof;
794 /*--------------------------------------------------------------------------*/
795 /* storeRegToAop - Store register reg to logical offset loffset of aop. */
796 /*--------------------------------------------------------------------------*/
798 storeRegToAop (regs *reg, asmop *aop, int loffset)
800 int regidx = reg->rIdx;
806 D(emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
807 reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr));
809 if ((reg->rIdx == HX_IDX) && aop->stacked
810 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
812 storeRegToAop (hc08_reg_h, aop, loffset+1);
813 storeRegToAop (hc08_reg_x, aop, loffset);
817 if ((reg->rIdx == XA_IDX) && aop->stacked
818 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
820 storeRegToAop (hc08_reg_x, aop, loffset+1);
821 storeRegToAop (hc08_reg_a, aop, loffset);
825 if (aop->stacked && aop->stk_aop[loffset])
827 storeRegToAop (reg, aop->stk_aop[loffset], 0);
831 if (aop->type == AOP_STR)
834 transferRegReg (reg, hc08_reg_x, FALSE);
836 transferRegReg (reg, hc08_reg_h, FALSE);
840 if (aop->type == AOP_DUMMY)
843 if (aop->type == AOP_CRY) /* This can only happen if IFX was optimized */
844 return; /* away, so just toss the result */
849 if ((aop->type == AOP_REG) && (loffset < aop->size))
850 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
852 emitcode ("sta","%s", aopAdrStr (aop, loffset, FALSE));
855 if ((aop->type == AOP_REG) && (loffset < aop->size))
856 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
858 emitcode ("stx","%s", aopAdrStr (aop, loffset, FALSE));
861 if (hc08_reg_a->isFree)
863 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
864 storeRegToAop (hc08_reg_a, aop, loffset);
865 hc08_freeReg (hc08_reg_a);
867 else if (hc08_reg_x->isFree)
869 transferRegReg (hc08_reg_h, hc08_reg_x, FALSE);
870 storeRegToAop (hc08_reg_x, aop, loffset);
871 hc08_freeReg (hc08_reg_x);
875 pushReg (hc08_reg_a, TRUE);
876 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
877 storeRegToAop (hc08_reg_a, aop, loffset);
878 pullReg (hc08_reg_a);
882 if ((aop->type == AOP_DIR) )
884 emitcode("sthx","%s", aopAdrStr (aop, loffset+1, TRUE));
886 else if (IS_AOP_XA(aop))
887 transferRegReg(reg, hc08_reg_xa, FALSE);
888 else if (IS_AOP_HX(aop))
893 needpula = pushRegIfUsed (hc08_reg_a);
894 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
895 storeRegToAop (hc08_reg_a, aop, loffset+1);
896 storeRegToAop (hc08_reg_x, aop, loffset);
897 pullOrFreeReg (hc08_reg_a, needpula);
902 transferRegReg(reg, hc08_reg_hx, FALSE);
903 else if (IS_AOP_XA(aop))
907 storeRegToAop (hc08_reg_a, aop, loffset);
908 storeRegToAop (hc08_reg_x, aop, loffset+1);
913 /* Disable the register tracking for now */
915 //if (!reg->aop || (reg->aop && (reg->aop != aop)))
918 for (otheridx=0;otheridx<hc08_nRegs;otheridx++)
920 otherreg=hc08_regWithIdx(otheridx);
921 if (otherreg && otherreg->aop
922 && otherreg->aop->op && aop->op
923 && operandsEqu(otherreg->aop->op,aop->op)
924 && (otherreg->aopofs == loffset))
926 D(emitcode("","; marking %s stale", otherreg->name));
930 if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
932 hc08_reg_hx->aop = NULL;
933 D(emitcode("","; marking hx stale"));
935 if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
937 hc08_reg_xa->aop = NULL;
938 D(emitcode("","; marking xa stale"));
942 reg->aopofs = loffset;
947 /*--------------------------------------------------------------------------*/
948 /* loadRegFromConst - Load register reg from constant c. */
949 /*--------------------------------------------------------------------------*/
951 loadRegFromConst (regs *reg, char *c)
957 emitcode ("clra", "");
959 emitcode ("lda", "%s", c);
963 emitcode ("clrx", "");
965 emitcode ("ldx", "%s", c);
969 emitcode ("clrh", "");
970 else if (hc08_reg_a->isFree)
972 loadRegFromConst (hc08_reg_a, c);
973 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
975 else if (hc08_reg_x->isFree)
977 loadRegFromConst (hc08_reg_x, c);
978 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
982 pushReg (hc08_reg_a, TRUE);
983 loadRegFromConst (hc08_reg_a, c);
984 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
985 pullReg (hc08_reg_a);
989 emitcode ("ldhx", "%s", c);
992 emitcode ("lda", "%s", c);
993 emitcode ("ldx", "%s >> 8", c);
996 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
997 "Bad rIdx in loadRegFromConst");
1004 /*--------------------------------------------------------------------------*/
1005 /* storeConstToAop- Store constant c to logical offset loffset of asmop aop.*/
1006 /*--------------------------------------------------------------------------*/
1008 storeConstToAop (char *c, asmop *aop, int loffset)
1010 if (aop->stacked && aop->stk_aop[loffset])
1012 storeConstToAop (c, aop->stk_aop[loffset], 0);
1019 if (!strcmp(c,zero))
1020 emitcode ("clr", "%s", aopAdrStr (aop, loffset, FALSE));
1022 emitcode ("mov", "%s,%s", c, aopAdrStr (aop, loffset, FALSE));
1025 if (loffset>(aop->size-1))
1027 loadRegFromConst (aop->aopu.aop_reg[loffset], c);
1032 if (hc08_reg_a->isFree)
1034 loadRegFromConst (hc08_reg_a, c);
1035 storeRegToAop( hc08_reg_a, aop, loffset);
1036 hc08_freeReg (hc08_reg_a);
1038 else if (hc08_reg_x->isFree)
1040 loadRegFromConst (hc08_reg_x, c);
1041 storeRegToAop( hc08_reg_x, aop, loffset);
1042 hc08_freeReg (hc08_reg_x);
1046 pushReg (hc08_reg_a, TRUE);
1047 loadRegFromConst (hc08_reg_a, c);
1048 storeRegToAop( hc08_reg_a, aop, loffset);
1049 pullReg (hc08_reg_a);
1055 /*--------------------------------------------------------------------------*/
1056 /* storeRegSignToUpperAop - If isSigned is true, the sign bit of register */
1057 /* reg is extended to fill logical offsets loffset */
1058 /* and above of asmop aop. Otherwise, logical */
1059 /* offsets loffset and above of asmop aop are */
1060 /* zeroed. reg must be an 8-bit register. */
1061 /*--------------------------------------------------------------------------*/
1063 storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned)
1065 // int regidx = reg->rIdx;
1066 int size = aop->size;
1074 while (loffset<size)
1075 storeConstToAop(zero, aop, loffset++);
1080 transferRegReg (reg, hc08_reg_a, FALSE);
1081 emitcode ("rola","");
1082 emitcode ("clra","");
1083 emitcode ("sbc", "#0");
1084 hc08_useReg (hc08_reg_a);
1085 while (loffset<size)
1086 storeRegToAop (hc08_reg_a, aop, loffset++);
1087 hc08_freeReg (hc08_reg_a);
1091 /*--------------------------------------------------------------------------*/
1092 /* storeRegToFullAop - Store register reg to asmop aop with appropriate */
1093 /* padding and/or truncation as needed. If isSigned is */
1094 /* true, sign extension will take place in the padding. */
1095 /*--------------------------------------------------------------------------*/
1097 storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
1099 int regidx = reg->rIdx;
1100 int size = aop->size;
1107 storeRegToAop (reg, aop, 0);
1108 storeRegSignToUpperAop (reg, aop, 1, isSigned);
1113 storeRegToAop (hc08_reg_x, aop, 0);
1117 storeRegToAop (reg, aop, 0);
1118 storeRegSignToUpperAop (hc08_reg_h, aop, 2, isSigned);
1124 storeRegToAop (hc08_reg_a, aop, 0);
1128 storeRegToAop (reg, aop, 0);
1129 storeRegSignToUpperAop (hc08_reg_x, aop, 2, isSigned);
1135 /*--------------------------------------------------------------------------*/
1136 /* transferAopAop - Transfer the value at logical offset srcofs of asmop */
1137 /* srcaop to logical offset dstofs of asmop dstaop. */
1138 /*--------------------------------------------------------------------------*/
1140 transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
1142 bool needpula = FALSE;
1145 bool keepreg = FALSE;
1147 /* ignore transfers at the same byte, unless its volatile */
1148 if (srcaop->op && !isOperandVolatile (srcaop->op, FALSE)
1149 && dstaop->op && !isOperandVolatile (dstaop->op, FALSE)
1150 && operandsEqu(srcaop->op, dstaop->op) && srcofs == dstofs)
1153 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1155 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1159 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1161 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1165 // D(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1166 // aopName (srcaop), srcofs, aopName (dstaop), dstofs));
1167 // D(emitcode ("", "; srcaop->type = %d", srcaop->type));
1168 // D(emitcode ("", "; dstaop->type = %d", dstaop->type));
1170 if (dstofs >= dstaop->size)
1173 if ((dstaop->type == AOP_DIR)
1174 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1176 if (srcaop->type == AOP_LIT)
1179 unsigned long bytemask;
1181 lit = (unsigned long) floatFromVal (srcaop->aopu.aop_lit);
1182 bytemask = (lit >> (srcofs*8)) & 0xff;
1186 emitcode ("clr", "%s", aopAdrStr(dstaop, dstofs, FALSE));
1191 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1192 aopAdrStr(dstaop, dstofs, FALSE));
1196 if (dstaop->type == AOP_REG)
1198 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1199 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1201 reg = dstaop->aopu.aop_reg[dstofs];
1206 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1208 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1209 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1211 reg = srcaop->aopu.aop_reg[srcofs];
1218 if (hc08_reg_a->isFree)
1220 else if (hc08_reg_x->isFree)
1224 pushReg (hc08_reg_a, TRUE);
1230 loadRegFromAop (reg, srcaop, srcofs);
1231 storeRegToAop (reg, dstaop, dstofs);
1234 pullOrFreeReg (hc08_reg_a, needpula);
1238 /*--------------------------------------------------------------------------*/
1239 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1240 /* parameter param. */
1241 /*--------------------------------------------------------------------------*/
1243 accopWithMisc (char *accop, char *param)
1245 emitcode (accop, "%s", param);
1246 hc08_dirtyReg (hc08_reg_a, FALSE);
1249 /*--------------------------------------------------------------------------*/
1250 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1251 /* byte at logical offset loffset of asmop aop. */
1252 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1253 /*--------------------------------------------------------------------------*/
1255 accopWithAop (char *accop, asmop *aop, int loffset)
1257 if (aop->stacked && aop->stk_aop[loffset])
1259 accopWithAop (accop, aop->stk_aop[loffset], 0);
1263 if (aop->type == AOP_DUMMY)
1266 if (aop->type == AOP_REG)
1268 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1269 emitcode (accop, "1,s");
1273 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1275 hc08_dirtyReg (hc08_reg_a, FALSE);
1279 /*--------------------------------------------------------------------------*/
1280 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1281 /* byte at logical offset loffset of asmop aop. Register reg */
1282 /* must be 8-bit. */
1283 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1284 /*--------------------------------------------------------------------------*/
1286 rmwWithReg (char *rmwop, regs *reg)
1289 char *rmwaop = rmwbuf;
1291 if (reg->rIdx == A_IDX)
1293 sprintf(rmwaop,"%sa", rmwop);
1294 emitcode (rmwaop, "");
1295 hc08_dirtyReg (hc08_reg_a, FALSE);
1297 else if (reg->rIdx == X_IDX)
1299 sprintf(rmwaop,"%sx", rmwop);
1300 emitcode (rmwaop, "");
1301 hc08_dirtyReg (hc08_reg_a, FALSE);
1303 else if (hc08_reg_a->isFree)
1305 transferRegReg(reg, hc08_reg_a, FALSE);
1306 sprintf(rmwaop,"%sa", rmwop);
1307 emitcode (rmwaop, "");
1308 hc08_dirtyReg (hc08_reg_a, FALSE);
1309 transferRegReg(hc08_reg_a, reg, TRUE);
1313 pushReg (reg, FALSE);
1314 emitcode (rmwop, "1,s");
1316 hc08_dirtyReg (reg, FALSE);
1320 /*--------------------------------------------------------------------------*/
1321 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1322 /* logical offset loffset of asmop aop. */
1323 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror, tst */
1324 /*--------------------------------------------------------------------------*/
1326 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1328 bool needpula = FALSE;
1330 if (aop->stacked && aop->stk_aop[loffset])
1332 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1339 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1342 needpula = pushRegIfUsed (hc08_reg_a);
1343 loadRegFromAop (hc08_reg_a, aop, loffset);
1344 rmwWithReg (rmwop, hc08_reg_a);
1345 if (strcmp ("tst", rmwop))
1346 storeRegToAop (hc08_reg_a, aop, loffset);
1347 pullOrFreeReg (hc08_reg_a, needpula);
1352 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1358 /*-----------------------------------------------------------------*/
1359 /* newAsmop - creates a new asmOp */
1360 /*-----------------------------------------------------------------*/
1362 newAsmop (short type)
1366 aop = Safe_calloc (1, sizeof (asmop));
1373 /*-----------------------------------------------------------------*/
1374 /* pointerCode - returns the code for a pointer type */
1375 /*-----------------------------------------------------------------*/
1377 pointerCode (sym_link * etype)
1380 return PTR_TYPE (SPEC_OCLS (etype));
1385 /*-----------------------------------------------------------------*/
1386 /* aopForSym - for a true symbol */
1387 /*-----------------------------------------------------------------*/
1389 aopForSym (iCode * ic, symbol * sym, bool result)
1394 wassertl (ic != NULL, "Got a null iCode");
1395 wassertl (sym != NULL, "Got a null symbol");
1397 // printf("in aopForSym for symbol %s\n", sym->name);
1399 space = SPEC_OCLS (sym->etype);
1401 /* if already has one */
1407 /* special case for a function */
1408 if (IS_FUNC (sym->type))
1410 sym->aop = aop = newAsmop (AOP_IMMD);
1411 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1412 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1413 aop->size = FPTRSIZE;
1417 /* if it is in direct space */
1418 if (IN_DIRSPACE (space))
1420 sym->aop = aop = newAsmop (AOP_DIR);
1421 aop->aopu.aop_dir = sym->rname;
1422 aop->size = getSize (sym->type);
1426 /* if it is in far space */
1427 if (IN_FARSPACE (space))
1429 sym->aop = aop = newAsmop (AOP_EXT);
1430 aop->aopu.aop_dir = sym->rname;
1431 aop->size = getSize (sym->type);
1435 if (IN_STACK (sym->etype))
1437 sym->aop = aop = newAsmop (AOP_SOF);
1438 aop->aopu.aop_dir = sym->rname;
1439 aop->size = getSize (sym->type);
1440 aop->aopu.aop_stk = sym->stack;
1446 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1447 "aopForSym should never reach here");
1451 /* if it is in code space */
1452 if (IN_CODESPACE (space))
1458 /*-----------------------------------------------------------------*/
1459 /* aopForRemat - rematerialzes an object */
1460 /*-----------------------------------------------------------------*/
1462 aopForRemat (symbol * sym)
1464 iCode *ic = sym->rematiCode;
1472 val += (int) operandLitValue (IC_RIGHT (ic));
1473 else if (ic->op == '-')
1474 val -= (int) operandLitValue (IC_RIGHT (ic));
1475 else if (IS_CAST_ICODE(ic)) {
1476 sym_link *from_type = operandType(IC_RIGHT(ic));
1477 aop->aopu.aop_immd.from_cast_remat = 1;
1478 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1479 ptr_type = DCL_TYPE(from_type);
1480 if (ptr_type == IPOINTER) {
1487 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1490 if (ic->op == ADDRESS_OF)
1493 sprintf (buffer, "(%s %c 0x%04x)",
1494 OP_SYMBOL (IC_LEFT (ic))->rname,
1495 val >= 0 ? '+' : '-',
1496 abs (val) & 0xffff);
1498 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1500 aop = newAsmop (AOP_IMMD);
1501 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1502 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1503 /* set immd2 field if required */
1504 if (aop->aopu.aop_immd.from_cast_remat)
1506 sprintf(buffer,"#0x%02x",ptr_type);
1507 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1508 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1511 else if (ic->op == '=')
1513 val += (int) operandLitValue (IC_RIGHT (ic));
1515 sprintf (buffer, "0x%04x", val);
1516 aop = newAsmop (AOP_LIT);
1517 aop->aopu.aop_lit = constVal (buffer);
1520 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1521 "unexpected rematerialization");
1528 /*-----------------------------------------------------------------*/
1529 /* regsInCommon - two operands have some registers in common */
1530 /*-----------------------------------------------------------------*/
1532 regsInCommon (operand * op1, operand * op2)
1534 symbol *sym1, *sym2;
1537 /* if they have registers in common */
1538 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1541 sym1 = OP_SYMBOL (op1);
1542 sym2 = OP_SYMBOL (op2);
1544 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1547 for (i = 0; i < sym1->nRegs; i++)
1553 for (j = 0; j < sym2->nRegs; j++)
1558 if (sym2->regs[j] == sym1->regs[i])
1566 /*-----------------------------------------------------------------*/
1567 /* operandsEqu - equivalent */
1568 /*-----------------------------------------------------------------*/
1570 operandsEqu (operand * op1, operand * op2)
1572 symbol *sym1, *sym2;
1574 /* if they not symbols */
1575 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1578 sym1 = OP_SYMBOL (op1);
1579 sym2 = OP_SYMBOL (op2);
1581 /* if both are itemps & one is spilt
1582 and the other is not then false */
1583 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1584 sym1->isspilt != sym2->isspilt)
1587 /* if they are the same */
1591 if (sym1->rname[0] && sym2->rname[0]
1592 && strcmp (sym1->rname, sym2->rname) == 0)
1595 /* if left is a tmp & right is not */
1596 if (IS_ITEMP (op1) &&
1599 (sym1->usl.spillLoc == sym2))
1602 if (IS_ITEMP (op2) &&
1606 (sym2->usl.spillLoc == sym1))
1612 /*-----------------------------------------------------------------*/
1613 /* sameRegs - two asmops have the same registers */
1614 /*-----------------------------------------------------------------*/
1616 sameRegs (asmop * aop1, asmop * aop2)
1623 // if (aop1->size != aop2->size)
1626 if (aop1->type == aop2->type)
1631 for (i = 0; i < aop1->size; i++)
1632 if (aop1->aopu.aop_reg[i] !=
1633 aop2->aopu.aop_reg[i])
1637 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1640 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1647 /*-----------------------------------------------------------------*/
1648 /* aopOp - allocates an asmop for an operand : */
1649 /*-----------------------------------------------------------------*/
1651 aopOp (operand * op, iCode * ic, bool result)
1660 // Is this a pointer set result?
1662 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1666 // printf("checking literal\n");
1667 /* if this a literal */
1668 if (IS_OP_LITERAL (op))
1670 op->aop = aop = newAsmop (AOP_LIT);
1671 aop->aopu.aop_lit = op->operand.valOperand;
1672 aop->size = getSize (operandType (op));
1674 aop->isaddr = op->isaddr;
1678 // printf("checking pre-existing\n");
1679 /* if already has a asmop then continue */
1683 op->aop->isaddr = op->isaddr;
1687 // printf("checking underlying sym\n");
1688 /* if the underlying symbol has a aop */
1689 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1691 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1692 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1693 //op->aop = aop = OP_SYMBOL (op)->aop;
1694 aop->size = getSize( operandType (op));
1695 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1696 //printf (" with size = %d\n", aop->size);
1699 aop->isaddr = op->isaddr;
1700 /* if (aop->isaddr & IS_ITEMP (op))
1702 aop->psize=aop->size;
1703 aop->size = getSize( operandType (op)->next);
1708 // printf("checking true sym\n");
1709 /* if this is a true symbol */
1710 if (IS_TRUE_SYMOP (op))
1712 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1714 aop->isaddr = op->isaddr;
1715 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1716 //printf (" with size = %d\n", aop->size);
1720 /* this is a temporary : this has
1726 e) can be a return use only */
1728 sym = OP_SYMBOL (op);
1730 // printf("checking conditional\n");
1731 /* if the type is a conditional */
1732 if (sym->regType == REG_CND)
1734 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1737 aop->isaddr = op->isaddr;
1741 // printf("checking spilt\n");
1742 /* if it is spilt then two situations
1744 b) has a spill location */
1745 if (sym->isspilt || sym->nRegs == 0)
1748 // printf("checking remat\n");
1749 /* rematerialize it NOW */
1752 sym->aop = op->aop = aop =
1754 aop->size = getSize (sym->type);
1756 aop->isaddr = op->isaddr;
1757 /* if (aop->isaddr & IS_ITEMP (op))
1759 aop->psize=aop->size;
1760 aop->size = getSize( operandType (op)->next);
1765 // printf("checking accuse\n");
1768 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1769 aop->size = getSize (sym->type);
1770 switch (sym->accuse)
1773 aop->aopu.aop_reg[0] = hc08_reg_a;
1774 aop->aopu.aop_reg[1] = hc08_reg_x;
1777 aop->aopu.aop_reg[0] = hc08_reg_x;
1778 aop->aopu.aop_reg[1] = hc08_reg_h;
1782 aop->isaddr = op->isaddr;
1786 // printf("checking ruonly\n");
1792 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1793 aop->size = getSize (sym->type);
1794 for (i = 0; i < fReturnSizeHC08; i++)
1795 aop->aopu.aop_str[i] = fReturn2[i];
1797 aop->isaddr = op->isaddr;
1801 /* else spill location */
1802 if (sym->usl.spillLoc)
1804 asmop *oldAsmOp = NULL;
1806 if (sym->usl.spillLoc->aop
1807 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1809 /* force a new aop if sizes differ */
1810 oldAsmOp = sym->usl.spillLoc->aop;
1811 sym->usl.spillLoc->aop = NULL;
1812 //printf ("forcing new aop\n");
1814 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1815 if (sym->usl.spillLoc->aop->size != getSize (sym->type))
1817 /* Don't reuse the new aop, go with the last one */
1818 sym->usl.spillLoc->aop = oldAsmOp;
1820 aop->size = getSize (sym->type);
1822 aop->isaddr = op->isaddr;
1823 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1824 //printf (" with size = %d\n", aop->size);
1828 /* else must be a dummy iTemp */
1829 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1830 aop->size = getSize (sym->type);
1834 // printf("assuming register\n");
1835 /* must be in a register */
1836 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1837 aop->size = sym->nRegs;
1838 for (i = 0; i < sym->nRegs; i++)
1839 aop->aopu.aop_reg[i] = sym->regs[i];
1841 aop->isaddr = op->isaddr;
1845 /*-----------------------------------------------------------------*/
1846 /* freeAsmop - free up the asmop given to an operand */
1847 /*----------------------------------------------------------------*/
1849 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1871 D(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1874 for (loffset=0; loffset<aop->size; loffset++)
1875 if (aop->stk_aop[loffset])
1877 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1880 pullNull (stackAdjust);
1884 /* all other cases just dealloc */
1890 OP_SYMBOL (op)->aop = NULL;
1891 /* if the symbol has a spill */
1893 SPIL_LOC (op)->aop = NULL;
1899 /*-----------------------------------------------------------------*/
1900 /* aopDerefAop - treating the aop parameter as a pointer, return */
1901 /* an asmop for the object it references */
1902 /*-----------------------------------------------------------------*/
1904 aopDerefAop (asmop *aop)
1909 asmop *newaop = NULL;
1910 sym_link *type, *etype;
1913 D(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1917 type = operandType (aop->op);
1918 etype = getSpec (type);
1919 /* if op is of type of pointer then it is simple */
1920 if (IS_PTR (type) && !IS_FUNC (type->next))
1921 p_type = DCL_TYPE (type);
1924 /* we have to go by the storage class */
1925 p_type = PTR_TYPE (SPEC_OCLS (etype));
1934 if (p_type == POINTER)
1935 newaop = newAsmop (AOP_DIR);
1937 newaop = newAsmop (AOP_EXT);
1938 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1941 adr = (int) floatFromVal (aop->aopu.aop_lit);
1942 if (p_type == POINTER)
1947 newaop = newAsmop (AOP_DIR);
1948 sprintf (s, "0x%02x",adr);
1952 newaop = newAsmop (AOP_EXT);
1953 sprintf (s, "0x%04x",adr);
1955 rs = Safe_calloc (1, strlen (s) + 1);
1957 newaop->aopu.aop_dir = rs;
1960 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1961 "unsupported asmop");
1971 /*-----------------------------------------------------------------*/
1972 /* aopAdrStr - for referencing the address of the aop */
1973 /*-----------------------------------------------------------------*/
1975 aopAdrStr (asmop * aop, int loffset, bool bit16)
1979 int offset = aop->size - 1 - loffset;
1982 /* offset is greater than
1984 if (loffset > (aop->size - 1) &&
1985 aop->type != AOP_LIT)
1988 /* depending on type */
1996 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
1997 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1999 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
2003 sprintf (s, "#(%s >> %d)",
2004 aop->aopu.aop_immd.aop_immd1,
2008 aop->aopu.aop_immd.aop_immd1);
2012 aop->aopu.aop_immd.aop_immd1);
2013 rs = Safe_calloc (1, strlen (s) + 1);
2019 sprintf (s, "*(%s + %d)",
2023 sprintf (s, "*%s", aop->aopu.aop_dir);
2024 rs = Safe_calloc (1, strlen (s) + 1);
2030 sprintf (s, "(%s + %d)",
2034 sprintf (s, "%s", aop->aopu.aop_dir);
2035 rs = Safe_calloc (1, strlen (s) + 1);
2040 return aop->aopu.aop_reg[loffset]->name;
2044 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
2046 return aopLiteral (aop->aopu.aop_lit, loffset);
2050 return aop->aopu.aop_str[loffset];
2053 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2055 rs = Safe_calloc (1, strlen (s) + 1);
2061 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2062 "aopAdrStr got unsupported aop->type");
2071 /*-----------------------------------------------------------------*/
2072 /* opIsGptr: returns non-zero if the passed operand is */
2073 /* a generic pointer type. */
2074 /*-----------------------------------------------------------------*/
2076 opIsGptr (operand * op)
2078 sym_link *type = operandType (op);
2080 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2088 /*-----------------------------------------------------------------*/
2089 /* getDataSize - get the operand data size */
2090 /*-----------------------------------------------------------------*/
2092 getDataSize (operand * op)
2095 size = AOP_SIZE (op);
2100 /*-----------------------------------------------------------------*/
2101 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2102 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2103 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2104 /*-----------------------------------------------------------------*/
2106 asmopToBool (asmop *aop, bool resultInA)
2108 symbol *tlbl, *tlbl1;
2109 int size = aop->size;
2110 bool needpula = FALSE;
2111 bool flagsonly = TRUE;
2116 hc08_freeReg(hc08_reg_a);
2123 emitcode ("tsta", "");
2126 else if (IS_AOP_X(aop))
2127 emitcode ("tstx", "");
2128 else if (IS_AOP_H(aop))
2130 if (hc08_reg_a->isFree)
2132 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2133 emitcode ("tsta", "");
2135 hc08_freeReg(hc08_reg_a);
2137 else if (hc08_reg_x->isFree)
2139 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2140 emitcode ("tstx", "");
2141 hc08_freeReg(hc08_reg_x);
2145 emitcode ("pshh", "");
2146 emitcode ("tst", "1,s");
2147 emitcode ("ais", "#1");
2150 else if (IS_AOP_HX(aop))
2151 emitcode ("cphx", zero);
2152 else if (IS_AOP_XA(aop))
2154 symbol *tlbl = newiTempLabel (NULL);
2155 emitcode ("tsta", "");
2156 emitcode ("bne", "%05d$", (tlbl->key + 100));
2157 emitcode ("tstx", "");
2158 emitcode ("", "%05d$:", (tlbl->key + 100));
2162 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2163 "Bad rIdx in asmToBool");
2171 needpula = pushRegIfUsed (hc08_reg_a);
2172 loadRegFromAop (hc08_reg_a, aop, 0);
2173 for (offset=1; offset<size; offset++)
2174 accopWithAop ("ora", aop, offset);
2176 pullReg (hc08_reg_a);
2179 hc08_freeReg (hc08_reg_a);
2184 /* Higher levels should optimize this case away but let's be safe */
2185 if ((unsigned long) floatFromVal (aop->aopu.aop_lit))
2186 loadRegFromConst (hc08_reg_a, one);
2188 loadRegFromConst (hc08_reg_a, zero);
2189 hc08_freeReg(hc08_reg_a);
2196 loadRegFromAop (hc08_reg_a, aop, 0);
2197 hc08_freeReg (hc08_reg_a);
2201 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2206 if (hc08_reg_a->isFree)
2208 loadRegFromAop (hc08_reg_a, aop, 0);
2209 accopWithAop ("ora", aop, 1);
2210 hc08_freeReg (hc08_reg_a);
2215 tlbl = newiTempLabel (NULL);
2216 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2217 emitcode ("bne", "%05d$", (tlbl->key + 100));
2218 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2219 emitcode ("", "%05d$:", (tlbl->key + 100));
2225 needpula = pushRegIfUsed (hc08_reg_a);
2226 loadRegFromAop (hc08_reg_a, aop, 0);
2227 for (offset=1; offset<size; offset++)
2228 accopWithAop ("ora", aop, offset);
2230 pullReg (hc08_reg_a);
2233 hc08_freeReg (hc08_reg_a);
2241 tlbl = newiTempLabel (NULL);
2245 tlbl1 = newiTempLabel (NULL);
2246 emitBranch ("bne", tlbl1);
2247 loadRegFromConst (hc08_reg_a, zero);
2248 emitBranch ("bra", tlbl);
2250 loadRegFromConst (hc08_reg_a, one);
2254 emitBranch ("beq", tlbl);
2255 loadRegFromConst (hc08_reg_a, one);
2258 hc08_useReg (hc08_reg_a);
2264 /*-----------------------------------------------------------------*/
2265 /* genNot - generate code for ! operation */
2266 /*-----------------------------------------------------------------*/
2270 D(emitcode ("; genNot",""));
2272 /* assign asmOps to operand & result */
2273 aopOp (IC_LEFT (ic), ic, FALSE);
2274 aopOp (IC_RESULT (ic), ic, TRUE);
2276 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2277 emitcode ("eor", one);
2278 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2280 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2281 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2285 /*-----------------------------------------------------------------*/
2286 /* genCpl - generate code for complement */
2287 /*-----------------------------------------------------------------*/
2293 regs* reg = hc08_reg_a;
2297 D(emitcode ("; genCpl",""));
2299 /* assign asmOps to operand & result */
2300 aopOp (IC_LEFT (ic), ic, FALSE);
2301 aopOp (IC_RESULT (ic), ic, TRUE);
2303 size = AOP_SIZE (IC_RESULT (ic));
2306 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2307 rmwWithReg ("com", reg);
2309 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2314 /* release the aops */
2315 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2316 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2319 /*-----------------------------------------------------------------*/
2320 /* genUminusFloat - unary minus for floating points */
2321 /*-----------------------------------------------------------------*/
2323 genUminusFloat (operand * op, operand * result)
2325 int size, offset = 0;
2328 D(emitcode ("; genUminusFloat",""));
2330 /* for this we just copy and then flip the bit */
2332 size = AOP_SIZE (op) - 1;
2336 transferAopAop (AOP (op), offset, AOP (result), offset);
2340 needpula = pushRegIfUsed (hc08_reg_a);
2341 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2342 emitcode ("eor", "#0x80");
2343 hc08_useReg (hc08_reg_a);
2344 storeRegToAop (hc08_reg_a, AOP (result), offset);
2345 pullOrFreeReg (hc08_reg_a, needpula);
2348 /*-----------------------------------------------------------------*/
2349 /* genUminus - unary minus code generation */
2350 /*-----------------------------------------------------------------*/
2352 genUminus (iCode * ic)
2355 sym_link *optype, *rtype;
2360 D(emitcode ("; genUminus",""));
2363 aopOp (IC_LEFT (ic), ic, FALSE);
2364 aopOp (IC_RESULT (ic), ic, TRUE);
2366 optype = operandType (IC_LEFT (ic));
2367 rtype = operandType (IC_RESULT (ic));
2369 /* if float then do float stuff */
2370 if (IS_FLOAT (optype))
2372 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2376 /* otherwise subtract from zero */
2377 size = AOP_SIZE (IC_LEFT (ic));
2382 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2383 needpula = pushRegIfUsed (hc08_reg_a);
2386 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2387 emitcode ("nega", "");
2388 hc08_freeReg (hc08_reg_a);
2389 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2390 SPEC_USIGN (operandType (IC_LEFT (ic))));
2391 pullOrFreeReg (hc08_reg_a, needpula);
2395 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2396 result = forceStackedAop (AOP (IC_RESULT (ic)));
2398 result = AOP (IC_RESULT (ic));
2400 needpula = pushRegIfUsed (hc08_reg_a);
2404 loadRegFromConst (hc08_reg_a, zero);
2405 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2406 storeRegToAop (hc08_reg_a, result, offset++);
2409 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2410 SPEC_USIGN (operandType (IC_LEFT (ic))));
2411 pullOrFreeReg (hc08_reg_a, needpula);
2413 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2414 freeAsmop (NULL, result, ic, TRUE);
2420 /* release the aops */
2421 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2422 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2425 /*-----------------------------------------------------------------*/
2426 /* saveRegisters - will look for a call and save the registers */
2427 /*-----------------------------------------------------------------*/
2429 saveRegisters (iCode * lic)
2436 for (ic = lic; ic; ic = ic->next)
2437 if (ic->op == CALL || ic->op == PCALL)
2442 fprintf (stderr, "found parameter push with no function call\n");
2446 /* if the registers have been saved already or don't need to be then
2450 if (IS_SYMOP(IC_LEFT(ic)) &&
2451 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2452 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2455 /* safe the registers in use at this time but skip the
2456 ones for the result */
2457 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2458 hc08_rUmaskForOp (IC_RESULT(ic)));
2461 for (i = 0; i < hc08_nRegs; i++)
2463 if (bitVectBitValue (rsave, i))
2464 pushReg ( hc08_regWithIdx (i), FALSE);
2468 /*-----------------------------------------------------------------*/
2469 /* unsaveRegisters - pop the pushed registers */
2470 /*-----------------------------------------------------------------*/
2472 unsaveRegisters (iCode * ic)
2477 /* restore the registers in use at this time but skip the
2478 ones for the result */
2479 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2480 hc08_rUmaskForOp (IC_RESULT(ic)));
2482 for (i = hc08_nRegs; i >= 0; i--)
2484 if (bitVectBitValue (rsave, i))
2485 pullReg ( hc08_regWithIdx (i));
2491 /*-----------------------------------------------------------------*/
2493 /*-----------------------------------------------------------------*/
2495 pushSide (operand * oper, int size)
2500 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2501 pushReg ( hc08_reg_a, TRUE);
2505 /*-----------------------------------------------------------------*/
2506 /* assignResultValue - */
2507 /*-----------------------------------------------------------------*/
2509 assignResultValue (operand * oper)
2511 int size = AOP_SIZE (oper);
2515 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2516 if (hc08_aop_pass[offset]->type == AOP_REG)
2517 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2524 /*-----------------------------------------------------------------*/
2525 /* genIpush - genrate code for pushing this gets a little complex */
2526 /*-----------------------------------------------------------------*/
2528 genIpush (iCode * ic)
2530 int size, offset = 0;
2533 D(emitcode ("; genIpush",""));
2535 /* if this is not a parm push : ie. it is spill push
2536 and spill push is always done on the local stack */
2540 /* and the item is spilt then do nothing */
2541 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2544 aopOp (IC_LEFT (ic), ic, FALSE);
2545 size = AOP_SIZE (IC_LEFT (ic));
2547 /* push it on the stack */
2550 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2551 pushReg ( hc08_reg_a, TRUE);
2557 /* this is a paramter push: in this case we call
2558 the routine to find the call and save those
2559 registers that need to be saved */
2562 /* then do the push */
2563 aopOp (IC_LEFT (ic), ic, FALSE);
2566 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2567 size = AOP_SIZE (IC_LEFT (ic));
2570 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2571 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2573 if ((size==2) && hc08_reg_hx->isFree)
2575 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2576 pushReg (hc08_reg_hx, TRUE);
2583 // printf("loading %d\n", offset);
2584 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2585 // printf("pushing \n");
2586 pushReg (hc08_reg_a, TRUE);
2590 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2593 /*-----------------------------------------------------------------*/
2594 /* genIpop - recover the registers: can happen only for spilling */
2595 /*-----------------------------------------------------------------*/
2597 genIpop (iCode * ic)
2601 D(emitcode ("; genIpop",""));
2603 /* if the temp was not pushed then */
2604 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2607 aopOp (IC_LEFT (ic), ic, FALSE);
2608 size = AOP_SIZE (IC_LEFT (ic));
2612 pullReg (hc08_reg_a);
2613 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2615 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2619 /*-----------------------------------------------------------------*/
2620 /* genSend - gen code for SEND */
2621 /*-----------------------------------------------------------------*/
2622 static void genSend(set *sendSet)
2626 for (sic = setFirstItem (sendSet); sic;
2627 sic = setNextItem (sendSet)) {
2628 int size, offset = 0;
2629 aopOp (IC_LEFT (sic), sic, FALSE);
2630 size = AOP_SIZE (IC_LEFT (sic));
2635 transferAopAop( AOP (IC_LEFT (sic)), offset,
2636 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2640 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2644 /*-----------------------------------------------------------------*/
2645 /* genCall - generates a call statement */
2646 /*-----------------------------------------------------------------*/
2648 genCall (iCode * ic)
2651 // bool restoreBank = FALSE;
2652 // bool swapBanks = FALSE;
2654 D(emitcode("; genCall",""));
2656 dtype = operandType (IC_LEFT (ic));
2657 /* if send set is not empty then assign */
2660 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2661 genSend(reverseSet(_G.sendSet));
2663 genSend(_G.sendSet);
2669 /* if caller saves & we have not saved then */
2675 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2676 OP_SYMBOL (IC_LEFT (ic))->rname :
2677 OP_SYMBOL (IC_LEFT (ic))->name));
2680 /* if we need assign a result value */
2681 if ((IS_ITEMP (IC_RESULT (ic)) &&
2682 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2683 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2684 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2685 IS_TRUE_SYMOP (IC_RESULT (ic)))
2689 aopOp (IC_RESULT (ic), ic, FALSE);
2692 assignResultValue (IC_RESULT (ic));
2694 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2697 /* adjust the stack for parameters if
2701 pullNull (ic->parmBytes);
2704 /* if we had saved some registers then unsave them */
2705 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2706 unsaveRegisters (ic);
2710 /*-----------------------------------------------------------------*/
2711 /* -10l - generates a call by pointer statement */
2712 /*-----------------------------------------------------------------*/
2714 genPcall (iCode * ic)
2717 symbol *rlbl = newiTempLabel (NULL);
2718 symbol *tlbl = newiTempLabel (NULL);
2719 // bool restoreBank=FALSE;
2720 // bool swapBanks = FALSE;
2722 D(emitcode("; genPCall",""));
2724 /* if caller saves & we have not saved then */
2728 /* if we are calling a not _naked function that is not using
2729 the same register bank then we need to save the
2730 destination registers on the stack */
2731 dtype = operandType (IC_LEFT (ic))->next;
2733 /* now push the calling address */
2734 emitBranch ("bsr", tlbl);
2735 emitBranch ("bra", rlbl);
2738 /* Push the function's address */
2739 aopOp (IC_LEFT (ic), ic, FALSE);
2740 pushSide (IC_LEFT (ic), FPTRSIZE);
2741 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2743 /* if send set is not empty the assign */
2746 genSend(reverseSet(_G.sendSet));
2752 emitcode ("rts", "");
2757 /* if we need assign a result value */
2758 if ((IS_ITEMP (IC_RESULT (ic)) &&
2759 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2760 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2761 IS_TRUE_SYMOP (IC_RESULT (ic)))
2765 aopOp (IC_RESULT (ic), ic, FALSE);
2768 assignResultValue (IC_RESULT (ic));
2770 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2773 /* adjust the stack for parameters if
2777 pullNull (ic->parmBytes);
2780 /* if we hade saved some registers then
2782 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2783 unsaveRegisters (ic);
2786 /*-----------------------------------------------------------------*/
2787 /* resultRemat - result is rematerializable */
2788 /*-----------------------------------------------------------------*/
2790 resultRemat (iCode * ic)
2792 if (SKIP_IC (ic) || ic->op == IFX)
2795 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2797 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2798 if (sym->remat && !POINTER_SET (ic))
2805 #if defined(__BORLANDC__) || defined(_MSC_VER)
2806 #define STRCASECMP stricmp
2808 #define STRCASECMP strcasecmp
2811 /*-----------------------------------------------------------------*/
2812 /* inExcludeList - return 1 if the string is in exclude Reg list */
2813 /*-----------------------------------------------------------------*/
2815 regsCmp(void *p1, void *p2)
2817 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2821 inExcludeList (char *s)
2823 const char *p = setFirstItem(options.excludeRegsSet);
2825 if (p == NULL || STRCASECMP(p, "none") == 0)
2829 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2832 /*-----------------------------------------------------------------*/
2833 /* genFunction - generated code for function entry */
2834 /*-----------------------------------------------------------------*/
2836 genFunction (iCode * ic)
2838 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2840 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2841 int stackAdjust = sym->stack;
2842 int accIsFree = sym->recvSize == 0;
2846 /* create the function header */
2847 emitcode (";", "-----------------------------------------");
2848 emitcode (";", " function %s", sym->name);
2849 emitcode (";", "-----------------------------------------");
2851 emitcode ("", "%s:", sym->rname);
2852 ftype = operandType (IC_LEFT (ic));
2856 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2858 if (IFFUNC_ISNAKED(ftype))
2860 emitcode(";", "naked function: no prologue.");
2864 /* if this is an interrupt service routine then
2866 if (IFFUNC_ISISR (sym->type))
2869 if (!inExcludeList ("h"))
2870 pushReg (hc08_reg_h, FALSE);
2873 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2874 /* before setting up the stack frame completely. */
2875 while (ric && ric->next && ric->next->op == RECEIVE)
2877 while (ric && IC_RESULT (ric))
2879 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2880 int rsymSize = rsym ? getSize(rsym->type) : 0;
2884 if (rsym && rsym->regType == REG_CND)
2886 if (rsym && (rsym->accuse || rsym->ruonly))
2888 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2889 rsym = rsym->usl.spillLoc;
2892 /* If the RECEIVE operand immediately spills to the first entry on the */
2893 /* stack, we can push it directly rather than use an sp relative store. */
2894 if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize)
2898 _G.current_iCode = ric;
2899 D(emitcode ("; genReceive",""));
2900 for (ofs=0; ofs < rsymSize; ofs++)
2902 regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
2903 pushReg (reg, TRUE);
2904 if (reg->rIdx == A_IDX)
2908 _G.current_iCode = ic;
2911 ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
2914 /* adjust the stack for the function */
2917 adjustStack (-stackAdjust);
2919 _G.stackOfs = sym->stack;
2922 /* if critical function then turn interrupts off */
2923 if (IFFUNC_ISCRITICAL (ftype))
2927 /* Function was passed parameters, so make sure A is preserved */
2928 pushReg (hc08_reg_a, FALSE);
2929 pushReg (hc08_reg_a, FALSE);
2930 emitcode ("tpa", "");
2931 emitcode ("sta", "2,s");
2932 emitcode ("sei", "");
2933 pullReg (hc08_reg_a);
2937 /* No passed parameters, so A can be freely modified */
2938 emitcode ("tpa", "");
2939 pushReg (hc08_reg_a, TRUE);
2940 emitcode ("sei", "");
2946 /*-----------------------------------------------------------------*/
2947 /* genEndFunction - generates epilogue for functions */
2948 /*-----------------------------------------------------------------*/
2950 genEndFunction (iCode * ic)
2952 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2954 if (IFFUNC_ISNAKED(sym->type))
2956 emitcode(";", "naked function: no epilogue.");
2957 if (options.debug && currFunc)
2958 debugFile->writeEndFunction (currFunc, ic, 0);
2962 if (IFFUNC_ISCRITICAL (sym->type))
2964 if (!IS_VOID(sym->type->next))
2966 /* Function has return value, so make sure A is preserved */
2967 pushReg (hc08_reg_a, FALSE);
2968 emitcode ("lda", "2,s");
2969 emitcode ("tap", "");
2970 pullReg (hc08_reg_a);
2975 /* Function returns void, so A can be freely modified */
2976 pullReg (hc08_reg_a);
2977 emitcode ("tap", "");
2981 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2987 _G.stackPushes += sym->stack;
2988 adjustStack (sym->stack);
2992 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2996 if (IFFUNC_ISISR (sym->type))
2999 if (!inExcludeList ("h"))
3000 pullReg (hc08_reg_h);
3003 /* if debug then send end of function */
3004 if (options.debug && currFunc)
3006 debugFile->writeEndFunction (currFunc, ic, 1);
3009 emitcode ("rti", "");
3013 if (IFFUNC_CALLEESAVES(sym->type))
3017 /* if any registers used */
3020 /* save the registers used */
3021 for (i = sym->regsUsed->size; i >= 0; i--)
3023 if (bitVectBitValue (sym->regsUsed, i) ||
3024 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3025 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3031 /* if debug then send end of function */
3032 if (options.debug && currFunc)
3034 debugFile->writeEndFunction (currFunc, ic, 1);
3037 emitcode ("rts", "");
3042 /*-----------------------------------------------------------------*/
3043 /* genRet - generate code for return statement */
3044 /*-----------------------------------------------------------------*/
3048 int size, offset = 0;
3051 D(emitcode ("; genRet",""));
3053 /* if we have no return value then
3054 just generate the "ret" */
3058 /* we have something to return then
3059 move the return value into place */
3060 aopOp (IC_LEFT (ic), ic, FALSE);
3061 size = AOP_SIZE (IC_LEFT (ic));
3067 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3074 /* 4 byte return: store value in the global return variable */
3078 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3079 STA (fReturn2[offset--], FALSE);
3080 hc08_freeReg (hc08_reg_a);
3084 /* 2 byte return: store value in x:a */
3085 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3086 hc08_freeReg (hc08_reg_xa);
3089 /* 1 byte return: store value in a */
3090 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3091 hc08_freeReg (hc08_reg_a);
3096 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3099 /* generate a jump to the return label
3100 if the next is not the return statement */
3101 if (!(ic->next && ic->next->op == LABEL &&
3102 IC_LABEL (ic->next) == returnLabel))
3104 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3108 /*-----------------------------------------------------------------*/
3109 /* genLabel - generates a label */
3110 /*-----------------------------------------------------------------*/
3112 genLabel (iCode * ic)
3117 /* For the high level labels we cannot depend on any */
3118 /* register's contents. Amnesia time. */
3119 for (i=A_IDX;i<=XA_IDX;i++)
3121 reg = hc08_regWithIdx(i);
3126 /* special case never generate */
3127 if (IC_LABEL (ic) == entryLabel)
3130 debugFile->writeLabel(IC_LABEL (ic), ic);
3132 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3136 /*-----------------------------------------------------------------*/
3137 /* genGoto - generates a jmp */
3138 /*-----------------------------------------------------------------*/
3140 genGoto (iCode * ic)
3142 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3146 /*-----------------------------------------------------------------*/
3147 /* findLabelBackwards: walks back through the iCode chain looking */
3148 /* for the given label. Returns number of iCode instructions */
3149 /* between that label and given ic. */
3150 /* Returns zero if label not found. */
3151 /*-----------------------------------------------------------------*/
3153 findLabelBackwards (iCode * ic, int key)
3162 /* If we have any pushes or pops, we cannot predict the distance.
3163 I don't like this at all, this should be dealt with in the
3165 if (ic->op == IPUSH || ic->op == IPOP) {
3169 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3179 /*-----------------------------------------------------------------*/
3180 /* genPlusIncr :- does addition with increment if possible */
3181 /*-----------------------------------------------------------------*/
3183 genPlusIncr (iCode * ic)
3191 unsigned int size = getDataSize (IC_RESULT (ic));
3192 unsigned int offset;
3193 symbol *tlbl = NULL;
3195 left = IC_LEFT (ic);
3196 result = IC_RESULT (ic);
3198 /* will try to generate an increment */
3199 /* if the right side is not a literal
3201 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3204 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3206 D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3208 if ((IS_AOP_HX (AOP (left)) ||
3209 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3211 && (icount>=-128) && (icount<=127) && (size==2))
3213 if (!IS_AOP_HX (AOP (left)))
3215 needpulx = pushRegIfUsed (hc08_reg_x);
3216 needpulh = pushRegIfUsed (hc08_reg_h);
3223 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3224 emitcode ("aix","#%d", icount);
3225 hc08_dirtyReg (hc08_reg_hx, FALSE);
3226 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3227 pullOrFreeReg (hc08_reg_h, needpulh);
3228 pullOrFreeReg (hc08_reg_x, needpulx);
3232 D(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3233 sameRegs (AOP (left), AOP (result))));
3235 if ((icount > 255) || (icount<0))
3238 if (!sameRegs (AOP (left), AOP (result)))
3241 D(emitcode ("; genPlusIncr",""));
3244 tlbl = newiTempLabel (NULL);
3249 rmwWithAop ("inc", AOP (result), 0);
3251 emitBranch ("bne", tlbl);
3255 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3256 needpula = pushRegIfUsed (hc08_reg_a);
3259 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3260 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3261 hc08_useReg (hc08_reg_a);
3262 storeRegToAop (hc08_reg_a, AOP (result), 0);
3263 hc08_freeReg (hc08_reg_a);
3265 emitBranch ("bcc", tlbl);
3267 for (offset=1; offset<size; offset++)
3269 rmwWithAop ("inc", AOP (result), offset);
3270 if ((offset+1)<size)
3271 emitBranch ("bne", tlbl);
3277 pullOrFreeReg (hc08_reg_a, needpula);
3284 /*-----------------------------------------------------------------*/
3285 /* genPlus - generates code for addition */
3286 /*-----------------------------------------------------------------*/
3288 genPlus (iCode * ic)
3290 int size, offset = 0;
3292 asmop *leftOp, *rightOp;
3294 /* special cases :- */
3296 D(emitcode ("; genPlus",""));
3298 aopOp (IC_LEFT (ic), ic, FALSE);
3299 aopOp (IC_RIGHT (ic), ic, FALSE);
3300 aopOp (IC_RESULT (ic), ic, TRUE);
3302 /* we want registers on the left and literals on the right */
3303 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3304 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3306 operand *t = IC_RIGHT (ic);
3307 IC_RIGHT (ic) = IC_LEFT (ic);
3312 /* if I can do an increment instead
3313 of add then GOOD for ME */
3314 if (genPlusIncr (ic) == TRUE)
3317 D(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3318 D(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3319 D(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3321 size = getDataSize (IC_RESULT (ic));
3323 leftOp = AOP(IC_LEFT(ic));
3324 rightOp = AOP(IC_RIGHT(ic));
3330 loadRegFromAop (hc08_reg_a, leftOp, offset);
3331 accopWithAop(add, rightOp, offset);
3332 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3333 hc08_freeReg (hc08_reg_a);
3334 add = "adc"; /* further adds must propagate carry */
3338 // adjustArithmeticResult (ic);
3341 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3342 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3343 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3346 /*-----------------------------------------------------------------*/
3347 /* genMinusDec :- does subtraction with decrement if possible */
3348 /*-----------------------------------------------------------------*/
3350 genMinusDec (iCode * ic)
3352 unsigned int icount;
3357 unsigned int size = getDataSize (IC_RESULT (ic));
3361 left = IC_LEFT (ic);
3362 result = IC_RESULT (ic);
3364 /* will try to generate an increment */
3365 /* if the right side is not a literal
3367 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3370 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3372 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3373 && (icount>=-127) && (icount<=128) && (size==2))
3375 if (!IS_AOP_HX (AOP (left)))
3377 needpulx = pushRegIfUsed (hc08_reg_x);
3378 needpulh = pushRegIfUsed (hc08_reg_h);
3385 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3386 emitcode ("aix","#%d", -icount);
3387 hc08_dirtyReg (hc08_reg_hx, FALSE);
3388 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3389 pullOrFreeReg (hc08_reg_h, needpulh);
3390 pullOrFreeReg (hc08_reg_x, needpulx);
3394 if ((icount > 1) || (icount<0))
3397 if (!sameRegs (AOP (left), AOP (result)))
3403 D(emitcode ("; genMinusDec",""));
3405 rmwWithAop ("dec", AOP (result), 0);
3410 /*-----------------------------------------------------------------*/
3411 /* addSign - complete with sign */
3412 /*-----------------------------------------------------------------*/
3414 addSign (operand * result, int offset, int sign)
3416 int size = (getDataSize (result) - offset);
3421 emitcode ("rola", "");
3422 emitcode ("clra", "");
3423 emitcode ("sbc", zero);
3425 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3429 storeConstToAop (zero, AOP (result), offset++);
3434 /*-----------------------------------------------------------------*/
3435 /* genMinus - generates code for subtraction */
3436 /*-----------------------------------------------------------------*/
3438 genMinus (iCode * ic)
3441 int size, offset = 0;
3443 asmop *leftOp, *rightOp;
3445 D(emitcode ("; genMinus",""));
3447 aopOp (IC_LEFT (ic), ic, FALSE);
3448 aopOp (IC_RIGHT (ic), ic, FALSE);
3449 aopOp (IC_RESULT (ic), ic, TRUE);
3451 /* special cases :- */
3452 /* if I can do an decrement instead
3453 of subtract then GOOD for ME */
3454 if (genMinusDec (ic) == TRUE)
3457 size = getDataSize (IC_RESULT (ic));
3460 leftOp = AOP(IC_LEFT(ic));
3461 rightOp = AOP(IC_RIGHT(ic));
3465 if (IS_AOP_A (rightOp))
3467 loadRegFromAop ( hc08_reg_a, rightOp, offset);
3468 accopWithAop (sub, leftOp, offset);
3469 accopWithMisc ("nega", "");
3470 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3476 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3477 accopWithAop (sub, rightOp, offset);
3478 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3483 // adjustArithmeticResult (ic);
3486 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3487 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3488 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3493 /*-----------------------------------------------------------------*/
3494 /* genMultOneByte : 8*8=8/16 bit multiplication */
3495 /*-----------------------------------------------------------------*/
3497 genMultOneByte (operand * left,
3501 /* sym_link *opetype = operandType (result); */
3502 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3503 int size=AOP_SIZE(result);
3504 bool negLiteral = FALSE;
3505 bool lUnsigned, rUnsigned;
3507 D(emitcode ("; genMultOneByte",""));
3509 if (size<1 || size>2) {
3510 // this should never happen
3511 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3512 AOP_SIZE(result), __FILE__, lineno);
3516 /* (if two literals: the value is computed before) */
3517 /* if one literal, literal on the right */
3518 if (AOP_TYPE (left) == AOP_LIT)
3524 /* if an operand is in A, make sure it is on the left */
3525 if (IS_AOP_A (AOP (right)))
3532 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3533 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3535 /* lUnsigned rUnsigned negLiteral negate case */
3536 /* false false false odd 3 */
3537 /* false false true even 3 */
3538 /* false true false odd 3 */
3539 /* false true true impossible */
3540 /* true false false odd 3 */
3541 /* true false true always 2 */
3542 /* true true false never 1 */
3543 /* true true true impossible */
3547 || (lUnsigned && rUnsigned))
3549 // just an unsigned 8*8=8/16 multiply
3550 //D(emitcode (";","unsigned"));
3552 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3553 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3554 emitcode ("mul", "");
3555 hc08_dirtyReg (hc08_reg_xa, FALSE);
3556 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3557 hc08_freeReg (hc08_reg_xa);
3562 // we have to do a signed multiply
3565 /* left unsigned, right signed literal -- literal determines sign handling */
3566 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3568 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3570 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3572 emitcode ("ldx", "#0x%02x", -val);
3574 emitcode ("ldx", "#0x%02x", val);
3576 emitcode ("mul", "");
3580 rmwWithReg ("neg", hc08_reg_a);
3581 tlbl4 = newiTempLabel (NULL);
3582 emitBranch ("bcc", tlbl4);
3583 rmwWithReg ("inc", hc08_reg_x);
3585 rmwWithReg ("neg", hc08_reg_x);
3588 hc08_dirtyReg (hc08_reg_xa, FALSE);
3589 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3590 hc08_freeReg (hc08_reg_xa);
3597 emitcode ("clr", "1,s");
3599 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3602 tlbl1 = newiTempLabel (NULL);
3603 emitcode ("tsta","");
3604 emitBranch ("bpl", tlbl1);
3605 emitcode ("inc", "1,s");
3606 rmwWithReg ("neg", hc08_reg_a);
3610 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3612 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3613 /* AND literal negative */
3615 emitcode ("ldx", "#0x%02x", -val);
3618 emitcode ("ldx", "#0x%02x", val);
3620 hc08_useReg (hc08_reg_x);
3624 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3627 tlbl2 = newiTempLabel (NULL);
3628 emitcode ("tstx", "");
3629 emitBranch ("bpl", tlbl2);
3630 emitcode ("inc", "1,s");
3631 rmwWithReg ("neg", hc08_reg_x);
3636 emitcode ("mul", "");
3637 hc08_dirtyReg (hc08_reg_xa, FALSE);
3639 tlbl3 = newiTempLabel (NULL);
3640 emitcode ("dec", "1,s");
3641 if (!lUnsigned && !rUnsigned && negLiteral)
3642 emitBranch ("beq", tlbl3);
3644 emitBranch ("bne", tlbl3);
3646 rmwWithReg ("neg", hc08_reg_a);
3647 tlbl4 = newiTempLabel (NULL);
3648 emitBranch ("bcc", tlbl4);
3649 rmwWithReg ("inc", hc08_reg_x);
3651 rmwWithReg ("neg", hc08_reg_x);
3655 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3656 hc08_freeReg (hc08_reg_xa);
3660 /*-----------------------------------------------------------------*/
3661 /* genMult - generates code for multiplication */
3662 /*-----------------------------------------------------------------*/
3664 genMult (iCode * ic)
3666 operand *left = IC_LEFT (ic);
3667 operand *right = IC_RIGHT (ic);
3668 operand *result = IC_RESULT (ic);
3670 D(emitcode ("; genMult",""));
3672 /* assign the amsops */
3673 aopOp (left, ic, FALSE);
3674 aopOp (right, ic, FALSE);
3675 aopOp (result, ic, TRUE);
3677 /* special cases first */
3678 /* if both are of size == 1 */
3679 // if (getSize(operandType(left)) == 1 &&
3680 // getSize(operandType(right)) == 1)
3681 if (AOP_SIZE (left) == 1 &&
3682 AOP_SIZE (right) == 1)
3684 genMultOneByte (left, right, result);
3688 /* should have been converted to function call */
3689 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3690 getSize(OP_SYMBOL(right)->type));
3691 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3696 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3697 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3698 freeAsmop (result, NULL, ic, TRUE);
3701 /*-----------------------------------------------------------------*/
3702 /* genDivOneByte : 8 bit division */
3703 /*-----------------------------------------------------------------*/
3705 genDivOneByte (operand * left,
3709 symbol *tlbl1, *tlbl2, *tlbl3;
3712 bool lUnsigned, rUnsigned;
3713 bool runtimeSign, compiletimeSign;
3715 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3716 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3718 D(emitcode ("; genDivOneByte",""));
3720 size = AOP_SIZE (result);
3721 /* signed or unsigned */
3722 if (lUnsigned && rUnsigned)
3724 /* unsigned is easy */
3725 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3726 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3727 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3728 emitcode ("div", "");
3729 hc08_dirtyReg (hc08_reg_a, FALSE);
3730 hc08_dirtyReg (hc08_reg_h, FALSE);
3731 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3732 hc08_freeReg (hc08_reg_a);
3733 hc08_freeReg (hc08_reg_x);
3734 hc08_freeReg (hc08_reg_h);
3738 /* signed is a little bit more difficult */
3740 /* now sign adjust for both left & right */
3742 /* let's see what's needed: */
3743 /* apply negative sign during runtime */
3744 runtimeSign = FALSE;
3745 /* negative sign from literals */
3746 compiletimeSign = FALSE;
3750 if (AOP_TYPE(left) == AOP_LIT)
3752 /* signed literal */
3753 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3755 compiletimeSign = TRUE;
3758 /* signed but not literal */
3764 if (AOP_TYPE(right) == AOP_LIT)
3766 /* signed literal */
3767 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3769 compiletimeSign ^= TRUE;
3772 /* signed but not literal */
3776 /* initialize the runtime sign */
3779 if (compiletimeSign)
3780 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3782 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3783 pushReg (hc08_reg_x, TRUE);
3786 /* save the signs of the operands */
3787 if (AOP_TYPE(right) == AOP_LIT)
3789 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3791 if (!rUnsigned && val < 0)
3792 emitcode ("ldx", "#0x%02x", -val);
3794 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3796 else /* ! literal */
3798 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3801 tlbl1 = newiTempLabel (NULL);
3802 emitcode ("tstx", "");
3803 emitBranch ("bpl", tlbl1);
3804 emitcode ("inc", "1,s");
3805 rmwWithReg ("neg", hc08_reg_x);
3810 if (AOP_TYPE(left) == AOP_LIT)
3812 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3814 if (!lUnsigned && val < 0)
3815 emitcode ("lda", "#0x%02x", -val);
3817 emitcode ("lda", "#0x%02x", (unsigned char) val);
3819 else /* ! literal */
3821 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3824 tlbl2 = newiTempLabel (NULL);
3825 emitcode ("tsta", "");
3826 emitBranch ("bpl", tlbl2);
3827 emitcode ("inc", "1,s");
3828 rmwWithReg ("neg", hc08_reg_a);
3833 loadRegFromConst (hc08_reg_h, zero);
3834 emitcode ("div", "");
3835 hc08_dirtyReg (hc08_reg_x, FALSE);
3836 hc08_dirtyReg (hc08_reg_a, FALSE);
3837 hc08_dirtyReg (hc08_reg_h, FALSE);
3839 if (runtimeSign || compiletimeSign)
3841 tlbl3 = newiTempLabel (NULL);
3844 pullReg (hc08_reg_x);
3845 rmwWithReg ("lsr", hc08_reg_x);
3846 rmwWithReg ("ror", hc08_reg_x);
3847 emitBranch ("bpl", tlbl3);
3850 rmwWithReg ("neg", hc08_reg_a);
3854 storeRegToAop (hc08_reg_a, AOP (result), 0);
3858 /* msb is 0x00 or 0xff depending on the sign */
3861 rmwWithReg ("lsl", hc08_reg_x);
3862 emitcode ("clra", "");
3863 emitcode ("sbc", "#0");
3865 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3867 else /* compiletimeSign */
3869 storeConstToAop ("#0xff", AOP (result), ++offset);
3874 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3877 hc08_freeReg (hc08_reg_a);
3878 hc08_freeReg (hc08_reg_x);
3879 hc08_freeReg (hc08_reg_h);
3882 /*-----------------------------------------------------------------*/
3883 /* genDiv - generates code for division */
3884 /*-----------------------------------------------------------------*/
3888 operand *left = IC_LEFT (ic);
3889 operand *right = IC_RIGHT (ic);
3890 operand *result = IC_RESULT (ic);
3892 D(emitcode ("; genDiv",""));
3894 /* assign the amsops */
3895 aopOp (left, ic, FALSE);
3896 aopOp (right, ic, FALSE);
3897 aopOp (result, ic, TRUE);
3899 /* special cases first */
3900 /* if both are of size == 1 */
3901 if (AOP_SIZE (left) <= 2 &&
3902 AOP_SIZE (right) == 1)
3904 genDivOneByte (left, right, result);
3908 /* should have been converted to function call */
3911 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3912 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3913 freeAsmop (result, NULL, ic, TRUE);
3916 /*-----------------------------------------------------------------*/
3917 /* genModOneByte : 8 bit modulus */
3918 /*-----------------------------------------------------------------*/
3920 genModOneByte (operand * left,
3924 symbol *tlbl1, *tlbl2, *tlbl3;
3927 bool lUnsigned, rUnsigned;
3928 bool runtimeSign, compiletimeSign;
3930 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3931 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3933 D(emitcode ("; genModOneByte",""));
3935 size = AOP_SIZE (result);
3937 if (lUnsigned && rUnsigned)
3939 /* unsigned is easy */
3940 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3941 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3942 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3943 emitcode ("div", "");
3944 hc08_freeReg (hc08_reg_a);
3945 hc08_freeReg (hc08_reg_x);
3946 hc08_dirtyReg (hc08_reg_h, FALSE);
3947 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3948 hc08_freeReg (hc08_reg_h);
3952 /* signed is a little bit more difficult */
3954 if (AOP_TYPE(right) == AOP_LIT)
3956 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3958 if (!rUnsigned && val < 0)
3959 emitcode ("ldx", "#0x%02x", -val);
3961 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3963 else /* ! literal */
3965 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3968 tlbl1 = newiTempLabel (NULL);
3969 emitcode ("tstx", "");
3970 emitBranch ("bpl", tlbl1);
3971 rmwWithReg ("neg", hc08_reg_x);
3976 /* let's see what's needed: */
3977 /* apply negative sign during runtime */
3978 runtimeSign = FALSE;
3979 /* negative sign from literals */
3980 compiletimeSign = FALSE;
3982 /* sign adjust left side */
3983 if (AOP_TYPE(left) == AOP_LIT)
3985 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3987 if (!lUnsigned && val < 0)
3989 compiletimeSign = TRUE; /* set sign flag */
3990 emitcode ("lda", "#0x%02x", -val);
3993 emitcode ("lda", "#0x%02x", (unsigned char) val);
3995 else /* ! literal */
3998 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4003 emitcode ("clr", "1,s");
4005 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4006 tlbl2 = newiTempLabel (NULL);
4007 emitcode ("tsta", "");
4008 emitBranch ("bpl", tlbl2);
4009 emitcode ("inc", "1,s");
4010 rmwWithReg ("neg", hc08_reg_a);
4015 loadRegFromConst (hc08_reg_h, zero);
4016 emitcode ("div", "");
4017 hc08_freeReg (hc08_reg_a);
4018 hc08_freeReg (hc08_reg_x);
4019 hc08_dirtyReg (hc08_reg_h, FALSE);
4021 if (runtimeSign || compiletimeSign)
4023 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4024 tlbl3 = newiTempLabel (NULL);
4027 pullReg (hc08_reg_x);
4028 rmwWithReg ("lsr", hc08_reg_x);
4029 rmwWithReg ("ror", hc08_reg_x);
4030 emitBranch ("bpl", tlbl3);
4033 rmwWithReg ("neg", hc08_reg_a);
4037 storeRegToAop (hc08_reg_a, AOP (result), 0);
4041 /* msb is 0x00 or 0xff depending on the sign */
4044 rmwWithReg ("lsl", hc08_reg_x);
4045 emitcode ("clra", "");
4046 emitcode ("sbc", "#0");
4048 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4050 else /* compiletimeSign */
4052 storeConstToAop ("#0xff", AOP (result), ++offset);
4057 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4060 hc08_freeReg (hc08_reg_a);
4061 hc08_freeReg (hc08_reg_x);
4062 hc08_freeReg (hc08_reg_h);
4065 /*-----------------------------------------------------------------*/
4066 /* genMod - generates code for division */
4067 /*-----------------------------------------------------------------*/
4071 operand *left = IC_LEFT (ic);
4072 operand *right = IC_RIGHT (ic);
4073 operand *result = IC_RESULT (ic);
4075 D(emitcode ("; genMod",""));
4077 /* assign the amsops */
4078 aopOp (left, ic, FALSE);
4079 aopOp (right, ic, FALSE);
4080 aopOp (result, ic, TRUE);
4082 /* special cases first */
4083 /* if both are of size == 1 */
4084 if (AOP_SIZE (left) <= 2 &&
4085 AOP_SIZE (right) == 1)
4087 genModOneByte (left, right, result);
4091 /* should have been converted to function call */
4095 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4096 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4097 freeAsmop (result, NULL, ic, TRUE);
4100 /*-----------------------------------------------------------------*/
4101 /* genIfxJump :- will create a jump depending on the ifx */
4102 /*-----------------------------------------------------------------*/
4104 genIfxJump (iCode * ic, char *jval)
4107 symbol *tlbl = newiTempLabel (NULL);
4110 D(emitcode ("; genIfxJump",""));
4112 /* if true label then we jump if condition
4116 jlbl = IC_TRUE (ic);
4117 if (!strcmp (jval, "a"))
4119 else if (!strcmp (jval, "c"))
4126 /* false label is present */
4127 jlbl = IC_FALSE (ic);
4128 if (!strcmp (jval, "a"))
4130 else if (!strcmp (jval, "c"))
4135 emitBranch (inst, tlbl);
4136 emitBranch ("jmp", jlbl);
4139 /* mark the icode as generated */
4144 /*-----------------------------------------------------------------*/
4145 /* exchangedCmp : returns the opcode need if the two operands are */
4146 /* exchanged in a comparison */
4147 /*-----------------------------------------------------------------*/
4149 exchangedCmp (int opcode)
4166 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4167 "opcode not a comparison");
4169 return EQ_OP; /* shouldn't happen, but need to return something */
4172 /*------------------------------------------------------------------*/
4173 /* negatedCmp : returns the equivalent opcode for when a comparison */
4175 /*------------------------------------------------------------------*/
4177 negatedCmp (int opcode)
4194 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4195 "opcode not a comparison");
4197 return EQ_OP; /* shouldn't happen, but need to return something */
4200 /* compile only if the debugging macro D is enabled */
4203 nameCmp (int opcode)
4225 /*------------------------------------------------------------------*/
4226 /* branchInstCmp : returns the conditional branch instruction that */
4227 /* will branch if the comparison is true */
4228 /*------------------------------------------------------------------*/
4230 branchInstCmp (int opcode, int sign)
4238 return "bcs"; /* same as blo */
4253 return "bcc"; /* same as bhs */
4259 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4260 "opcode not a comparison");
4266 /*------------------------------------------------------------------*/
4267 /* genCmp :- greater or less than (and maybe with equal) comparison */
4268 /*------------------------------------------------------------------*/
4270 genCmp (iCode * ic, iCode * ifx)
4272 operand *left, *right, *result;
4273 sym_link *letype, *retype;
4275 int size, offset = 0;
4276 unsigned long lit = 0L;
4278 symbol *jlbl = NULL;
4282 D(emitcode ("; genCmp", "(%s)",nameCmp (opcode)));
4284 result = IC_RESULT (ic);
4285 left = IC_LEFT (ic);
4286 right = IC_RIGHT (ic);
4288 letype = getSpec (operandType (left));
4289 retype = getSpec (operandType (right));
4290 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4291 /* assign the amsops */
4292 aopOp (left, ic, FALSE);
4293 aopOp (right, ic, FALSE);
4294 aopOp (result, ic, TRUE);
4296 /* need register operand on left, prefer literal operand on right */
4297 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4299 operand *temp = left;
4302 opcode = exchangedCmp (opcode);
4309 jlbl = IC_TRUE (ifx);
4310 opcode = negatedCmp (opcode);
4314 /* false label is present */
4315 jlbl = IC_FALSE (ifx);
4319 size = max (AOP_SIZE (left), AOP_SIZE (right));
4322 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4323 && ((AOP_TYPE (right) == AOP_LIT) ||
4324 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4325 && hc08_reg_hx->isFree)
4327 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4328 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4329 hc08_freeReg (hc08_reg_hx);
4340 /* These conditions depend on the Z flag bit, but Z is */
4341 /* only valid for the last byte of the comparison, not */
4342 /* the whole value. So exchange the operands to get a */
4343 /* comparison that doesn't depend on Z. (This is safe */
4344 /* to do here since ralloc won't assign multi-byte */
4345 /* operands to registers for comparisons) */
4346 if ((opcode == '>') || (opcode == LE_OP))
4348 operand *temp = left;
4351 opcode = exchangedCmp (opcode);
4354 if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
4356 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4357 while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
4366 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4367 accopWithAop (sub, AOP (right), offset);
4368 hc08_freeReg (hc08_reg_a);
4373 freeAsmop (right, NULL, ic, FALSE);
4374 freeAsmop (left, NULL, ic, FALSE);
4378 symbol *tlbl = newiTempLabel (NULL);
4381 freeAsmop (result, NULL, ic, TRUE);
4383 inst = branchInstCmp (opcode, sign);
4384 emitBranch (inst, tlbl);
4385 emitBranch ("jmp", jlbl);
4388 /* mark the icode as generated */
4393 symbol *tlbl1 = newiTempLabel (NULL);
4394 symbol *tlbl2 = newiTempLabel (NULL);
4396 emitBranch (branchInstCmp (opcode, sign), tlbl1);
4397 loadRegFromConst (hc08_reg_a, zero);
4398 emitBranch ("bra", tlbl2);
4400 loadRegFromConst (hc08_reg_a, one);
4402 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4403 freeAsmop (result, NULL, ic, TRUE);
4408 /*-----------------------------------------------------------------*/
4409 /* genCmpEQorNE - equal or not equal comparison */
4410 /*-----------------------------------------------------------------*/
4412 genCmpEQorNE (iCode * ic, iCode * ifx)
4414 operand *left, *right, *result;
4415 sym_link *letype, *retype;
4417 int size, offset = 0;
4419 symbol *jlbl = NULL;
4420 symbol *tlbl_NE = NULL;
4421 symbol *tlbl_EQ = NULL;
4425 D(emitcode ("; genCmpEQorNE", "(%s)",nameCmp (opcode)));
4427 result = IC_RESULT (ic);
4428 left = IC_LEFT (ic);
4429 right = IC_RIGHT (ic);
4431 letype = getSpec (operandType (left));
4432 retype = getSpec (operandType (right));
4433 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4434 /* assign the amsops */
4435 aopOp (left, ic, FALSE);
4436 aopOp (right, ic, FALSE);
4437 aopOp (result, ic, TRUE);
4439 /* need register operand on left, prefer literal operand on right */
4440 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4442 operand *temp = left;
4445 opcode = exchangedCmp (opcode);
4452 jlbl = IC_TRUE (ifx);
4453 opcode = negatedCmp (opcode);
4457 /* false label is present */
4458 jlbl = IC_FALSE (ifx);
4462 size = max (AOP_SIZE (left), AOP_SIZE (right));
4465 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4466 && ((AOP_TYPE (right) == AOP_LIT) ||
4467 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4468 && hc08_reg_hx->isFree)
4470 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4471 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4472 hc08_freeReg (hc08_reg_hx);
4480 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4481 accopWithAop (sub, AOP (right), offset);
4485 tlbl_NE = newiTempLabel (NULL);
4486 emitBranch ("bne", tlbl_NE);
4488 hc08_freeReg (hc08_reg_a);
4492 freeAsmop (right, NULL, ic, FALSE);
4493 freeAsmop (left, NULL, ic, FALSE);
4497 freeAsmop (result, NULL, ic, TRUE);
4499 if (opcode == EQ_OP)
4502 tlbl_EQ = newiTempLabel (NULL);
4503 emitBranch ("beq", tlbl_EQ);
4505 emitLabel (tlbl_NE);
4506 emitBranch ("jmp", jlbl);
4507 emitLabel (tlbl_EQ);
4512 tlbl_NE = newiTempLabel (NULL);
4513 emitBranch ("bne", tlbl_NE);
4514 emitBranch ("jmp", jlbl);
4515 emitLabel (tlbl_NE);
4518 /* mark the icode as generated */
4523 symbol *tlbl = newiTempLabel (NULL);
4525 if (opcode == EQ_OP)
4528 tlbl_EQ = newiTempLabel (NULL);
4529 emitBranch ("beq", tlbl_EQ);
4531 emitLabel (tlbl_NE);
4532 loadRegFromConst (hc08_reg_a, zero);
4533 emitBranch ("bra", tlbl);
4534 emitLabel (tlbl_EQ);
4535 loadRegFromConst (hc08_reg_a, one);
4540 tlbl_NE = newiTempLabel (NULL);
4541 emitBranch ("bne", tlbl_NE);
4542 loadRegFromConst (hc08_reg_a, zero);
4543 emitBranch ("bra", tlbl);
4544 emitLabel (tlbl_NE);
4545 loadRegFromConst (hc08_reg_a, one);
4549 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4550 freeAsmop (result, NULL, ic, TRUE);
4556 /*-----------------------------------------------------------------*/
4557 /* ifxForOp - returns the icode containing the ifx for operand */
4558 /*-----------------------------------------------------------------*/
4560 ifxForOp (operand * op, iCode * ic)
4562 /* if true symbol then needs to be assigned */
4563 if (IS_TRUE_SYMOP (op))
4566 /* if this has register type condition and
4567 the next instruction is ifx with the same operand
4568 and live to of the operand is upto the ifx only then */
4570 ic->next->op == IFX &&
4571 IC_COND (ic->next)->key == op->key &&
4572 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4579 genPointerGetSetOfs (iCode *ic)
4581 iCode *lic = ic->next;
4587 /* Make sure we have a next iCode */
4588 D(emitcode("","; checking lic"));
4592 /* Make sure the result of the addition is an iCode */
4593 D(emitcode("","; checking IS_ITEMP"));
4594 if (!IS_ITEMP (IC_RESULT (ic)))
4597 /* Make sure the next iCode is a pointer set or get */
4598 pset = POINTER_SET(lic);
4599 pget = POINTER_GET(lic);
4600 D(emitcode("","; pset=%d, pget=%d",pset,pget));
4604 /* Make sure this is the only use of the pointer */
4605 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4608 D(emitcode("", "; checking pset operandsEqu"));
4609 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4612 D(emitcode("", "; checking pget operandsEqu"));
4613 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4616 D(emitcode("", "; checking IS_SYMOP"));
4617 if (!IS_SYMOP (IC_LEFT (ic)))
4620 D(emitcode("", "; checking !IS_TRUE_SYMOP"));
4621 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4624 sym = OP_SYMBOL (IC_LEFT (ic));
4626 D(emitcode("", "; checking remat"));
4633 D(emitcode ("; genPointerGetOfs",""));
4634 aopOp (IC_LEFT(ic), ic, FALSE);
4635 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4636 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4638 aopOp (IC_RIGHT(ic), ic, FALSE);
4639 aopOp (IC_RESULT(lic), lic, FALSE);
4641 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4643 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4645 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4646 loadRegFromConst (hc08_reg_h, zero);
4650 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4651 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4652 emitcode ("rola","");
4653 emitcode ("clra","");
4654 emitcode ("sbc", "#0");
4655 hc08_useReg (hc08_reg_a);
4656 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4660 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4661 size = AOP_SIZE (IC_RESULT(lic));
4662 derefaop->size = size;
4666 emitcode ("lda", "%s,x",
4667 aopAdrStr (derefaop, size, TRUE));
4668 hc08_useReg (hc08_reg_a);
4669 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
4670 hc08_freeReg (hc08_reg_a);
4674 hc08_freeReg (hc08_reg_hx);
4676 freeAsmop (NULL, derefaop, ic, TRUE);
4677 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4678 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4685 D(emitcode ("; genPointerSetOfs",""));
4686 aopOp (IC_LEFT(ic), ic, FALSE);
4687 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4688 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4690 aopOp (IC_RIGHT(ic), ic, FALSE);
4691 aopOp (IC_RIGHT(lic), lic, FALSE);
4693 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4695 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4697 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4698 loadRegFromConst (hc08_reg_h, zero);
4702 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4703 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4704 emitcode ("rola","");
4705 emitcode ("clra","");
4706 emitcode ("sbc", "#0");
4707 hc08_useReg (hc08_reg_a);
4708 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4712 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4713 size = AOP_SIZE (IC_RIGHT(lic));
4714 derefaop->size = size;
4718 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
4719 emitcode ("sta", "%s,x",
4720 aopAdrStr (derefaop, size, TRUE));
4721 hc08_freeReg (hc08_reg_a);
4725 hc08_freeReg (hc08_reg_hx);
4727 freeAsmop (NULL, derefaop, ic, TRUE);
4728 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4729 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4738 /*-----------------------------------------------------------------*/
4739 /* hasInc - operand is incremented before any other use */
4740 /*-----------------------------------------------------------------*/
4742 hasInc (operand *op, iCode *ic,int osize)
4744 sym_link *type = operandType(op);
4745 sym_link *retype = getSpec (type);
4746 iCode *lic = ic->next;
4749 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4750 if (!IS_SYMOP(op)) return NULL;
4752 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4753 if (IS_AGGREGATE(type->next)) return NULL;
4754 if (osize != (isize = getSize(type->next))) return NULL;
4757 /* if operand of the form op = op + <sizeof *op> */
4758 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4759 isOperandEqual(IC_RESULT(lic),op) &&
4760 isOperandLiteral(IC_RIGHT(lic)) &&
4761 operandLitValue(IC_RIGHT(lic)) == isize) {
4764 /* if the operand used or deffed */
4765 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
4768 /* if GOTO or IFX */
4769 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4775 /*-----------------------------------------------------------------*/
4776 /* genAndOp - for && operation */
4777 /*-----------------------------------------------------------------*/
4779 genAndOp (iCode * ic)
4781 operand *left, *right, *result;
4782 symbol *tlbl, *tlbl0;
4784 D(emitcode ("; genAndOp",""));
4786 /* note here that && operations that are in an
4787 if statement are taken away by backPatchLabels
4788 only those used in arthmetic operations remain */
4789 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4790 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4791 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4793 tlbl = newiTempLabel (NULL);
4794 tlbl0 = newiTempLabel (NULL);
4796 asmopToBool (AOP (left), FALSE);
4797 emitBranch ("beq", tlbl0);
4798 asmopToBool (AOP (right), FALSE);
4799 emitBranch ("beq", tlbl0);
4800 loadRegFromConst (hc08_reg_a,one);
4801 emitBranch ("bra", tlbl);
4803 loadRegFromConst (hc08_reg_a,zero);
4806 hc08_useReg (hc08_reg_a);
4807 hc08_freeReg (hc08_reg_a);
4809 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4811 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4812 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4813 freeAsmop (result, NULL, ic, TRUE);
4817 /*-----------------------------------------------------------------*/
4818 /* genOrOp - for || operation */
4819 /*-----------------------------------------------------------------*/
4821 genOrOp (iCode * ic)
4823 operand *left, *right, *result;
4824 symbol *tlbl, *tlbl0;
4826 D(emitcode ("; genOrOp",""));
4828 /* note here that || operations that are in an
4829 if statement are taken away by backPatchLabels
4830 only those used in arthmetic operations remain */
4831 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4832 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4833 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4835 tlbl = newiTempLabel (NULL);
4836 tlbl0 = newiTempLabel (NULL);
4838 asmopToBool (AOP (left), FALSE);
4839 emitBranch ("bne", tlbl0);
4840 asmopToBool (AOP (right), FALSE);
4841 emitBranch ("bne", tlbl0);
4842 loadRegFromConst (hc08_reg_a,zero);
4843 emitBranch ("bra", tlbl);
4845 loadRegFromConst (hc08_reg_a,one);
4848 hc08_useReg (hc08_reg_a);
4849 hc08_freeReg (hc08_reg_a);
4851 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4854 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4855 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4856 freeAsmop (result, NULL, ic, TRUE);
4859 /*-----------------------------------------------------------------*/
4860 /* isLiteralBit - test if lit == 2^n */
4861 /*-----------------------------------------------------------------*/
4863 isLiteralBit (unsigned long lit)
4865 unsigned long pw[32] =
4866 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4867 0x100L, 0x200L, 0x400L, 0x800L,
4868 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4869 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4870 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4871 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4872 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4875 for (idx = 0; idx < 32; idx++)
4882 /*-----------------------------------------------------------------*/
4883 /* continueIfTrue - */
4884 /*-----------------------------------------------------------------*/
4886 continueIfTrue (iCode * ic)
4889 emitBranch ("jmp", IC_TRUE (ic));
4893 /*-----------------------------------------------------------------*/
4895 /*-----------------------------------------------------------------*/
4897 jumpIfTrue (iCode * ic)
4900 emitBranch ("jmp", IC_FALSE (ic));
4904 /*-----------------------------------------------------------------*/
4905 /* jmpTrueOrFalse - */
4906 /*-----------------------------------------------------------------*/
4908 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4910 // ugly but optimized by peephole
4913 symbol *nlbl = newiTempLabel (NULL);
4914 emitBranch ("bra", nlbl);
4916 emitBranch ("jmp", IC_TRUE (ic));
4921 emitBranch ("jmp", IC_FALSE (ic));
4928 /*-----------------------------------------------------------------*/
4929 /* genAnd - code for and */
4930 /*-----------------------------------------------------------------*/
4932 genAnd (iCode * ic, iCode * ifx)
4934 operand *left, *right, *result;
4935 int size, offset = 0;
4936 unsigned long lit = 0L;
4937 unsigned long litinv;
4938 unsigned char bytemask;
4944 D(emitcode ("; genAnd",""));
4946 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4947 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4948 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4951 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4953 AOP_TYPE (left), AOP_TYPE (right)));
4954 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4956 AOP_SIZE (left), AOP_SIZE (right)));
4959 /* if left is a literal & right is not then exchange them */
4960 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4962 operand *tmp = right;
4967 /* if right is accumulator & left is not then exchange them */
4968 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4970 operand *tmp = right;
4975 if (AOP_TYPE (right) == AOP_LIT)
4976 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4978 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4980 if (AOP_TYPE (result) == AOP_CRY
4982 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
4984 /* this generates ugly code, but meets volatility requirements */
4985 loadRegFromConst (hc08_reg_a, zero);
4986 pushReg (hc08_reg_a, TRUE);
4991 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4992 accopWithAop ("and", AOP (right), offset);
4993 emitcode ("ora", "1,s");
4994 emitcode ("sta", "1,s");
4998 pullReg (hc08_reg_a);
4999 emitcode ("tsta", "");
5000 genIfxJump (ifx, "a");
5004 if (AOP_TYPE (result) == AOP_CRY)
5006 symbol *tlbl = NULL;
5007 wassertl (ifx, "AOP_CRY result without ifx");
5012 bytemask = (lit >> (offset*8)) & 0xff;
5014 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5018 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5020 rmwWithAop ("tst", AOP (left), offset);
5024 tlbl = newiTempLabel (NULL);
5025 emitBranch ("bne", tlbl);
5030 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5031 accopWithAop ("and", AOP (right), offset);
5032 hc08_freeReg( hc08_reg_a);
5036 tlbl = newiTempLabel (NULL);
5037 emitBranch ("bne", tlbl);
5044 genIfxJump (ifx, "a");
5048 size = AOP_SIZE (result);
5050 if (AOP_TYPE (right) == AOP_LIT)
5052 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
5053 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5054 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
5056 int bitpos = isLiteralBit(litinv)-1;
5057 emitcode ("bclr","#%d,%s",bitpos & 7,
5058 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5066 bytemask = (lit >> (offset*8)) & 0xff;
5068 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5070 if (isOperandVolatile (left, FALSE))
5072 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5073 hc08_freeReg( hc08_reg_a);
5075 storeConstToAop (zero, AOP (result), offset);
5077 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5079 transferAopAop (AOP (left), offset, AOP (result), offset);
5083 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5084 accopWithAop ("and", AOP (right), offset);
5085 storeRegToAop (hc08_reg_a, AOP (result), offset);
5086 hc08_freeReg (hc08_reg_a);
5092 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5093 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5094 freeAsmop (result, NULL, ic, TRUE);
5097 /*-----------------------------------------------------------------*/
5098 /* genOr - code for or */
5099 /*-----------------------------------------------------------------*/
5101 genOr (iCode * ic, iCode * ifx)
5103 operand *left, *right, *result;
5104 int size, offset = 0;
5105 unsigned long lit = 0L;
5106 unsigned char bytemask;
5108 D(emitcode ("; genOr",""));
5110 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5111 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5112 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5115 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5117 AOP_TYPE (left), AOP_TYPE (right)));
5118 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5120 AOP_SIZE (left), AOP_SIZE (right)));
5123 /* if left is a literal & right is not then exchange them */
5124 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5126 operand *tmp = right;
5131 /* if left is accumulator & right is not then exchange them */
5132 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5134 operand *tmp = right;
5139 if (AOP_TYPE (right) == AOP_LIT)
5140 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5142 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5144 if (AOP_TYPE (result) == AOP_CRY
5146 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5148 /* this generates ugly code, but meets volatility requirements */
5149 loadRegFromConst (hc08_reg_a, zero);
5150 pushReg (hc08_reg_a, TRUE);
5155 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5156 accopWithAop ("ora", AOP (right), offset);
5157 emitcode ("ora", "1,s");
5158 emitcode ("sta", "1,s");
5162 pullReg (hc08_reg_a);
5163 emitcode ("tsta", "");
5164 genIfxJump (ifx, "a");
5168 if (AOP_TYPE (result) == AOP_CRY)
5170 symbol *tlbl = NULL;
5171 wassertl (ifx, "AOP_CRY result without ifx");
5176 bytemask = (lit >> (offset*8)) & 0xff;
5178 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5180 rmwWithAop ("tst", AOP (left), offset);
5184 tlbl = newiTempLabel (NULL);
5185 emitBranch ("bne", tlbl);
5190 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5191 accopWithAop ("ora", AOP (right), offset);
5192 hc08_freeReg( hc08_reg_a);
5196 tlbl = newiTempLabel (NULL);
5197 emitBranch ("bne", tlbl);
5204 genIfxJump (ifx, "a");
5207 if (AOP_TYPE (right) == AOP_LIT)
5208 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5210 size = AOP_SIZE (result);
5212 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5213 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5214 (AOP_TYPE (left) == AOP_DIR))
5216 int bitpos = isLiteralBit(lit)-1;
5217 emitcode ("bset","#%d,%s",bitpos & 7,
5218 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5225 bytemask = (lit >> (offset*8)) & 0xff;
5227 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5229 if (isOperandVolatile (left, FALSE))
5231 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5232 hc08_freeReg( hc08_reg_a);
5234 transferAopAop (AOP (right), offset, AOP (result), offset);
5236 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5238 transferAopAop (AOP (left), offset, AOP (result), offset);
5242 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5243 accopWithAop ("ora", AOP (right), offset);
5244 storeRegToAop (hc08_reg_a, AOP (result), offset);
5245 hc08_freeReg (hc08_reg_a);
5252 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5253 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5254 freeAsmop (result, NULL, ic, TRUE);
5257 /*-----------------------------------------------------------------*/
5258 /* genXor - code for xclusive or */
5259 /*-----------------------------------------------------------------*/
5261 genXor (iCode * ic, iCode * ifx)
5263 operand *left, *right, *result;
5264 int size, offset = 0;
5265 unsigned long lit = 0L;
5267 D(emitcode ("; genXor",""));
5269 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5270 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5271 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5274 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5276 AOP_TYPE (left), AOP_TYPE (right)));
5277 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5279 AOP_SIZE (left), AOP_SIZE (right)));
5282 /* if left is a literal & right is not ||
5283 if left needs acc & right does not */
5284 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5286 operand *tmp = right;
5291 /* if left is accumulator & right is not then exchange them */
5292 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5294 operand *tmp = right;
5299 if (AOP_TYPE (result) == AOP_CRY)
5302 wassertl (ifx, "AOP_CPY result without ifx");
5304 tlbl = newiTempLabel (NULL);
5305 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5309 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5310 if ((AOP_TYPE (right) == AOP_LIT)
5311 && (((lit >> (offset*8)) & 0xff) == 0))
5312 emitcode ("tsta","");
5314 accopWithAop ("eor", AOP (right), offset);
5315 hc08_freeReg( hc08_reg_a);
5317 emitBranch ("bne", tlbl);
5321 genIfxJump (ifx, "a");
5327 if (AOP_TYPE (right) == AOP_LIT)
5328 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5330 size = AOP_SIZE (result);
5334 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5335 accopWithAop ("eor", AOP (right), offset);
5336 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5337 hc08_freeReg( hc08_reg_a);
5341 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5342 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5343 freeAsmop (result, NULL, ic, TRUE);
5347 emitinline (iCode * ic, char *inlin)
5353 symbol *sym, *tempsym;
5362 while (isalnum((unsigned char)*inlin) || (*inlin == '_'))
5366 //printf("Found possible symbol '%s'\n",symname);
5367 tempsym = newSymbol (symname, ic->level);
5368 tempsym->block = ic->block;
5369 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5378 aop = aopForSym (ic, sym, FALSE);
5379 l = aopAdrStr (aop, aop->size - 1, TRUE);
5383 if (sym->level && !sym->allocreq && !sym->ismyparm)
5385 werror (E_ID_UNDEF, sym->name);
5387 " Add 'volatile' to the variable declaration so that it\n"
5388 " can be referenced within inline assembly");
5390 //printf("Replacing with '%s'\n",l);
5394 if ((2+bp-buffer)>sizeof(buffer))
5403 if ((2+bp-buffer)>sizeof(buffer))
5410 if ((2+bp-buffer)>sizeof(buffer))
5411 fprintf(stderr, "Inline assembly buffer overflow\n");
5413 //printf("%s\n",buffer);
5414 emitcode (buffer,"");
5418 /*-----------------------------------------------------------------*/
5419 /* genInline - write the inline code out */
5420 /*-----------------------------------------------------------------*/
5422 genInline (iCode * ic)
5424 char *buffer, *bp, *bp1;
5426 D(emitcode ("; genInline",""));
5428 _G.inLine += (!options.asmpeep);
5430 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5431 strcpy (buffer, IC_INLINE (ic));
5433 /* emit each line as a code */
5439 /* emitcode (bp1, ""); */
5440 emitinline (ic, bp1);
5459 /* emitcode (bp1, ""); */
5460 emitinline (ic, bp1);
5462 /* emitcode("",buffer); */
5463 _G.inLine -= (!options.asmpeep);
5466 /*-----------------------------------------------------------------*/
5467 /* genRRC - rotate right with carry */
5468 /*-----------------------------------------------------------------*/
5472 operand *left, *result;
5473 int size, offset = 0;
5474 bool needpula = FALSE;
5475 bool resultInA = FALSE;
5478 D(emitcode ("; genRRC",""));
5480 /* rotate right with carry */
5481 left = IC_LEFT (ic);
5482 result = IC_RESULT (ic);
5483 aopOp (left, ic, FALSE);
5484 aopOp (result, ic, FALSE);
5486 if ((AOP_TYPE (result) == AOP_REG)
5487 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5490 size = AOP_SIZE (result);
5494 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5498 rmwWithAop (shift, AOP (result), offset--);
5506 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5507 rmwWithReg (shift, hc08_reg_a);
5508 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5509 hc08_freeReg (hc08_reg_a);
5514 if ((!hc08_reg_a->isFree) || resultInA)
5516 pushReg (hc08_reg_a, TRUE);
5520 /* now we need to put the carry into the
5521 highest order byte of the result */
5522 offset = AOP_SIZE (result) - 1;
5523 emitcode ("clra","");
5524 emitcode ("rora","");
5525 hc08_dirtyReg (hc08_reg_a, FALSE);
5528 emitcode ("ora", "1,s");
5529 emitcode ("ais", "#1");
5530 hc08_dirtyReg (hc08_reg_a, FALSE);
5534 accopWithAop ("ora", AOP (result), offset);
5535 storeRegToAop (hc08_reg_a, AOP (result), offset);
5537 pullOrFreeReg (hc08_reg_a, needpula);
5539 freeAsmop (left, NULL, ic, TRUE);
5540 freeAsmop (result, NULL, ic, TRUE);
5543 /*-----------------------------------------------------------------*/
5544 /* genRLC - generate code for rotate left with carry */
5545 /*-----------------------------------------------------------------*/
5549 operand *left, *result;
5550 int size, offset = 0;
5552 bool resultInA = FALSE;
5553 bool needpula = FALSE;
5555 D(emitcode ("; genRLC",""));
5557 /* rotate right with carry */
5558 left = IC_LEFT (ic);
5559 result = IC_RESULT (ic);
5560 aopOp (left, ic, FALSE);
5561 aopOp (result, ic, FALSE);
5563 if ((AOP_TYPE (result) == AOP_REG)
5564 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5567 size = AOP_SIZE (result);
5571 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5575 rmwWithAop (shift, AOP (result), offset--);
5583 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5584 rmwWithReg (shift, hc08_reg_a);
5585 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5586 hc08_freeReg (hc08_reg_a);
5591 if ((!hc08_reg_a->isFree) || resultInA)
5593 pushReg (hc08_reg_a, TRUE);
5597 /* now we need to put the carry into the
5598 lowest order byte of the result */
5600 emitcode ("clra","");
5601 emitcode ("rola","");
5602 hc08_dirtyReg (hc08_reg_a, FALSE);
5605 emitcode ("ora", "1,s");
5606 emitcode ("ais", "#1");
5607 hc08_dirtyReg (hc08_reg_a, FALSE);
5611 accopWithAop ("ora", AOP (result), offset);
5612 storeRegToAop (hc08_reg_a, AOP (result), offset);
5614 pullOrFreeReg (hc08_reg_a, needpula);
5616 freeAsmop (left, NULL, ic, TRUE);
5617 freeAsmop (result, NULL, ic, TRUE);
5620 /*-----------------------------------------------------------------*/
5621 /* genGetHbit - generates code get highest order bit */
5622 /*-----------------------------------------------------------------*/
5624 genGetHbit (iCode * ic)
5626 operand *left, *result;
5628 D(emitcode ("; genGetHbit",""));
5630 left = IC_LEFT (ic);
5631 result = IC_RESULT (ic);
5632 aopOp (left, ic, FALSE);
5633 aopOp (result, ic, FALSE);
5635 /* get the highest order byte into a */
5636 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5637 emitcode ("rola", "");
5638 emitcode ("clra", "");
5639 emitcode ("rola", "");
5640 hc08_dirtyReg (hc08_reg_a, FALSE);
5641 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5642 hc08_freeReg (hc08_reg_a);
5644 freeAsmop (left, NULL, ic, TRUE);
5645 freeAsmop (result, NULL, ic, TRUE);
5648 /*-----------------------------------------------------------------*/
5649 /* genSwap - generates code to swap nibbles or bytes */
5650 /*-----------------------------------------------------------------*/
5652 genSwap (iCode * ic)
5654 operand *left, *result;
5656 D(emitcode ("; genSwap",""));
5658 left = IC_LEFT (ic);
5659 result = IC_RESULT (ic);
5660 aopOp (left, ic, FALSE);
5661 aopOp (result, ic, FALSE);
5663 switch (AOP_SIZE (left))
5665 case 1: /* swap nibbles in byte */
5666 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5667 emitcode ("nsa", "");
5668 hc08_dirtyReg (hc08_reg_a, FALSE);
5669 storeRegToAop (hc08_reg_a, AOP (result), 0);
5670 hc08_freeReg (hc08_reg_a);
5672 case 2: /* swap bytes in a word */
5673 if (operandsEqu (left, result))
5675 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5676 hc08_useReg (hc08_reg_a);
5677 transferAopAop (AOP (left), 1, AOP (result), 0);
5678 storeRegToAop (hc08_reg_a, AOP (result), 1);
5679 hc08_freeReg (hc08_reg_a);
5683 transferAopAop (AOP (left), 0, AOP (result), 1);
5684 transferAopAop (AOP (left), 1, AOP (result), 0);
5688 wassertl(FALSE, "unsupported SWAP operand size");
5691 freeAsmop (left, NULL, ic, TRUE);
5692 freeAsmop (result, NULL, ic, TRUE);
5696 /*-----------------------------------------------------------------*/
5697 /* AccRol - rotate left accumulator by known count */
5698 /*-----------------------------------------------------------------*/
5700 AccRol (int shCount)
5702 shCount &= 0x0007; // shCount : 0..7
5709 emitcode ("rola", ""); /* 1 cycle */
5712 emitcode ("rola", ""); /* 1 cycle */
5713 emitcode ("rola", ""); /* 1 cycle */
5716 emitcode ("nsa", "");
5717 emitcode ("rora", "");
5720 emitcode ("nsa", ""); /* 3 cycles */
5723 emitcode ("nsa", ""); /* 3 cycles */
5724 emitcode ("rola", ""); /* 1 cycle */
5727 emitcode ("nsa", ""); /* 3 cycles */
5728 emitcode ("rola", ""); /* 1 cycle */
5729 emitcode ("rola", ""); /* 1 cycle */
5732 emitcode ("nsa", ""); /* 3 cycles */
5733 emitcode ("rola", ""); /* 1 cycle */
5734 emitcode ("rola", ""); /* 1 cycle */
5735 emitcode ("rola", ""); /* 1 cycle */
5742 /*-----------------------------------------------------------------*/
5743 /* AccLsh - left shift accumulator by known count */
5744 /*-----------------------------------------------------------------*/
5746 AccLsh (int shCount)
5750 shCount &= 0x0007; // shCount : 0..7
5752 /* Shift counts of 4 and 5 are currently optimized for code size. */
5753 /* Falling through to the unrolled loop would be optimal for code speed. */
5754 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5758 if (optimize.codeSpeed)
5760 accopWithMisc ("nsa", "");
5761 accopWithMisc ("and", "#0xf0");
5762 /* total: 5 cycles, 3 bytes */
5765 if (optimize.codeSpeed)
5767 accopWithMisc ("nsa", "");
5768 accopWithMisc ("and", "#0xf0");
5769 accopWithMisc ("lsla", "");
5770 /* total: 6 cycles, 4 bytes */
5773 accopWithMisc ("rora", "");
5774 accopWithMisc ("rora", "");
5775 accopWithMisc ("rora", "");
5776 accopWithMisc ("and", "#0xc0");
5777 /* total: 5 cycles, 5 bytes */
5780 accopWithMisc ("rora", "");
5781 accopWithMisc ("clra", "");
5782 accopWithMisc ("rora", "");
5783 /* total: 3 cycles, 3 bytes */
5787 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5788 /* the fastest (shCount<6) and shortest (shCount<4). */
5789 for (i=0;i<shCount;i++)
5790 accopWithMisc ("lsla", "");
5794 /*-----------------------------------------------------------------*/
5795 /* AccSRsh - signed right shift accumulator by known count */
5796 /*-----------------------------------------------------------------*/
5798 AccSRsh (int shCount)
5802 shCount &= 0x0007; // shCount : 0..7
5806 accopWithMisc ("rola", "");
5807 accopWithMisc ("clra", "");
5808 accopWithMisc ("sbc", zero);
5809 /* total: 4 cycles, 4 bytes */
5813 for (i=0;i<shCount;i++)
5814 accopWithMisc ("asra", "");
5817 /*-----------------------------------------------------------------*/
5818 /* AccRsh - right shift accumulator by known count */
5819 /*-----------------------------------------------------------------*/
5821 AccRsh (int shCount, bool sign)
5831 shCount &= 0x0007; // shCount : 0..7
5833 /* Shift counts of 4 and 5 are currently optimized for code size. */
5834 /* Falling through to the unrolled loop would be optimal for code speed. */
5835 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5839 if (optimize.codeSpeed)
5841 accopWithMisc ("nsa", "");
5842 accopWithMisc ("and", "#0x0f");
5843 /* total: 5 cycles, 3 bytes */
5846 if (optimize.codeSpeed)
5848 accopWithMisc ("nsa", "");
5849 accopWithMisc ("and", "#0x0f");
5850 accopWithMisc ("lsra", "");
5851 /* total: 6 cycles, 4 bytes */
5854 accopWithMisc ("rola", "");
5855 accopWithMisc ("rola", "");
5856 accopWithMisc ("rola", "");
5857 accopWithMisc ("and", "#0x03");
5858 /* total: 5 cycles, 5 bytes */
5861 accopWithMisc ("rola", "");
5862 accopWithMisc ("clra", "");
5863 accopWithMisc ("rola", "");
5864 /* total: 3 cycles, 3 bytes */
5868 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5869 /* the fastest (shCount<6) and shortest (shCount<4). */
5870 for (i=0;i<shCount;i++)
5871 accopWithMisc ("lsra", "");
5875 /*-----------------------------------------------------------------*/
5876 /* XAccLsh - left shift register pair XA by known count */
5877 /*-----------------------------------------------------------------*/
5879 XAccLsh (int shCount)
5883 shCount &= 0x000f; // shCount : 0..15
5888 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5889 loadRegFromConst (hc08_reg_a, zero);
5893 /* if we can beat 2n cycles or bytes for some special case, do it here */
5897 /* bytes cycles reg x reg a carry
5898 ** abcd efgh ijkl mnop ?
5899 ** lsrx 1 1 0abc defg ijkl mnop h
5900 ** rora 1 1 0abc defg hijk lmno p
5901 ** tax 1 1 hijk lmno hijk lmno p
5902 ** clra 1 1 hijk lmno 0000 0000 p
5903 ** rora 1 1 hijk lmno p000 0000 0
5904 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5906 rmwWithReg ("lsr", hc08_reg_x);
5907 rmwWithReg ("ror", hc08_reg_a);
5908 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5909 loadRegFromConst (hc08_reg_a, zero);
5910 rmwWithReg ("ror", hc08_reg_a);
5917 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5918 /* the fastest and shortest. */
5919 for (i=0;i<shCount;i++)
5921 rmwWithReg ("lsl", hc08_reg_a);
5922 rmwWithReg ("rol", hc08_reg_x);
5926 /*-----------------------------------------------------------------*/
5927 /* XAccSRsh - signed right shift register pair XA by known count */
5928 /*-----------------------------------------------------------------*/
5930 XAccSRsh (int shCount)
5934 shCount &= 0x000f; // shCount : 0..7
5936 /* if we can beat 2n cycles or bytes for some special case, do it here */
5940 /* bytes cycles reg x reg a carry
5941 ** abcd efgh ijkl mnop ?
5942 ** lslx 1 1 bcde fgh0 ijkl mnop a
5943 ** clra 1 1 bcde fgh0 0000 0000 a
5944 ** rola 1 1 bcde fgh0 0000 000a 0
5945 ** nega 1 1 bcde fgh0 aaaa aaaa a
5946 ** tax 1 1 aaaa aaaa aaaa aaaa a
5947 ** total: 5 cycles, 5 bytes
5949 rmwWithReg ("lsl", hc08_reg_x);
5950 loadRegFromConst (hc08_reg_a, zero);
5951 rmwWithReg ("rol", hc08_reg_a);
5952 rmwWithReg ("neg", hc08_reg_a);
5953 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5963 /* bytes cycles reg x reg a carry
5964 ** abcd efgh ijkl mnop ?
5965 ** txa 1 1 abcd efgh abcd efgh ?
5966 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5967 ** lsla 1 1 abcd efgh ???? ???? a
5968 ** clrx 1 1 0000 0000 ???? ???? a
5969 ** rolx 1 1 0000 000a ???? ???? 0
5970 ** negx 1 1 aaaa aaaa ???? ???? a
5971 ** rora 1 1 aaaa aaaa LSBresult 0
5972 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5974 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5975 AccSRsh (shCount-8);
5976 rmwWithReg ("lsl", hc08_reg_a);
5977 loadRegFromConst (hc08_reg_x, zero);
5978 rmwWithReg ("rol", hc08_reg_x);
5979 rmwWithReg ("neg", hc08_reg_x);
5980 rmwWithReg ("ror", hc08_reg_a);
5987 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5988 /* the fastest and shortest. */
5989 for (i=0;i<shCount;i++)
5991 rmwWithReg ("asr", hc08_reg_x);
5992 rmwWithReg ("ror", hc08_reg_a);
5996 /*-----------------------------------------------------------------*/
5997 /* XAccRsh - right shift register pair XA by known count */
5998 /*-----------------------------------------------------------------*/
6000 XAccRsh (int shCount, bool sign)
6010 shCount &= 0x000f; // shCount : 0..f
6012 /* if we can beat 2n cycles or bytes for some special case, do it here */
6016 /* bytes cycles reg x reg a carry
6017 ** abcd efgh ijkl mnop ?
6018 ** clra 1 1 abcd efgh 0000 0000 a
6019 ** lslx 1 1 bcde fgh0 0000 0000 a
6020 ** rola 1 1 bcde fgh0 0000 000a 0
6021 ** clrx 1 1 0000 0000 0000 000a 0
6022 ** total: 4 cycles, 4 bytes
6024 loadRegFromConst (hc08_reg_x, zero);
6025 rmwWithReg ("lsl", hc08_reg_x);
6026 rmwWithReg ("rol", hc08_reg_a);
6027 loadRegFromConst (hc08_reg_a, zero);
6031 /* bytes cycles reg x reg a carry
6032 ** abcd efgh ijkl mnop ?
6033 ** clra 1 1 abcd efgh 0000 0000 a
6034 ** lslx 1 1 bcde fgh0 0000 0000 a
6035 ** rola 1 1 bcde fgh0 0000 000a 0
6036 ** lslx 1 1 cdef gh00 0000 000a b
6037 ** rola 1 1 cdef gh00 0000 00ab 0
6038 ** clrx 1 1 0000 0000 0000 00ab 0
6039 ** total: 6 cycles, 6 bytes
6041 loadRegFromConst (hc08_reg_x, zero);
6042 rmwWithReg ("lsl", hc08_reg_x);
6043 rmwWithReg ("rol", hc08_reg_a);
6044 rmwWithReg ("lsl", hc08_reg_x);
6045 rmwWithReg ("rol", hc08_reg_a);
6046 loadRegFromConst (hc08_reg_a, zero);
6055 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6056 AccRsh (shCount-8, FALSE);
6057 loadRegFromConst (hc08_reg_x, zero);
6061 /* bytes cycles reg x reg a carry
6062 ** abcd efgh ijkl mnop ?
6063 ** lsla 1 1 abcd efgh jklm nop0 i
6064 ** txa 1 1 abcd efgh abcd efgh i
6065 ** rola 1 1 abcd efgh bcde fghi a
6066 ** clrx 1 1 0000 0000 bcde fghi a
6067 ** rolx 1 1 0000 000a bcde fghi 0
6068 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
6070 rmwWithReg ("lsl", hc08_reg_a);
6071 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6072 rmwWithReg ("rol", hc08_reg_a);
6073 loadRegFromConst (hc08_reg_x, zero);
6074 rmwWithReg ("rol", hc08_reg_x);
6077 /* bytes cycles reg x reg a carry
6078 ** abcd efgh ijkl mnop ?
6079 ** lsla 1 1 abcd efgh jklm nop0 i
6080 ** rolx 1 1 bcde fghi jklm nop0 a
6081 ** rola 1 1 bcde fghi klmn op0a j
6082 ** rolx 1 1 cdef ghij klmn op0a b
6083 ** rola 1 1 cdef ghij lmno p0ab k
6084 ** and #3 2 2 cdef ghij 0000 00ab k
6085 ** psha 1 2 cdef ghij 0000 00ab k
6086 ** txa 1 1 cdef ghij cdef ghij k
6087 ** pula 1 2 0000 00ab cdef ghij k
6088 ** total: 12 cycles, 10 bytes (beats 12 bytes)
6094 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6095 /* the fastest and shortest. */
6096 for (i=0;i<shCount;i++)
6098 rmwWithReg ("lsr", hc08_reg_x);
6099 rmwWithReg ("ror", hc08_reg_a);
6106 /*-----------------------------------------------------------------*/
6107 /* shiftR1Left2Result - shift right one byte from left to result */
6108 /*-----------------------------------------------------------------*/
6110 shiftR1Left2Result (operand * left, int offl,
6111 operand * result, int offr,
6112 int shCount, int sign)
6114 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6115 /* shift right accumulator */
6116 AccRsh (shCount, sign);
6117 storeRegToAop (hc08_reg_a, AOP (result), offr);
6121 /*-----------------------------------------------------------------*/
6122 /* shiftL1Left2Result - shift left one byte from left to result */
6123 /*-----------------------------------------------------------------*/
6125 shiftL1Left2Result (operand * left, int offl,
6126 operand * result, int offr, int shCount)
6128 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6129 /* shift left accumulator */
6131 storeRegToAop (hc08_reg_a, AOP (result), offr);
6134 /*-----------------------------------------------------------------*/
6135 /* movLeft2Result - move byte from left to result */
6136 /*-----------------------------------------------------------------*/
6138 movLeft2Result (operand * left, int offl,
6139 operand * result, int offr, int sign)
6141 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6143 transferAopAop (AOP (left), offl, AOP (result), offr);
6148 /*-----------------------------------------------------------------*/
6149 /* shiftL2Left2Result - shift left two bytes from left to result */
6150 /*-----------------------------------------------------------------*/
6152 shiftL2Left2Result (operand * left, int offl,
6153 operand * result, int offr, int shCount)
6156 bool needpula = FALSE;
6157 bool needpulx = FALSE;
6159 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6160 needpula = pushRegIfUsed (hc08_reg_a);
6163 if (!IS_AOP_XA (AOP (left)))
6164 needpulx = pushRegIfUsed (hc08_reg_x);
6168 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6173 rmwWithReg ("lsr", hc08_reg_x);
6174 rmwWithReg ("ror", hc08_reg_a);
6175 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6176 rmwWithReg ("clr", hc08_reg_a);
6177 rmwWithReg ("ror", hc08_reg_a);
6180 for (i=0; i<shCount; i++)
6182 rmwWithReg ("lsl", hc08_reg_a);
6183 rmwWithReg ("rol", hc08_reg_x);
6186 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6188 pullOrFreeReg (hc08_reg_x, needpulx);
6189 pullOrFreeReg (hc08_reg_a, needpula);
6195 /*-----------------------------------------------------------------*/
6196 /* shiftR2Left2Result - shift right two bytes from left to result */
6197 /*-----------------------------------------------------------------*/
6199 shiftR2Left2Result (operand * left, int offl,
6200 operand * result, int offr,
6201 int shCount, int sign)
6204 bool needpula = FALSE;
6205 bool needpulx = FALSE;
6207 needpula = pushRegIfUsed (hc08_reg_a);
6208 needpulx = pushRegIfUsed (hc08_reg_x);
6210 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6211 for (i=0; i<shCount; i++)
6214 rmwWithReg ("asr", hc08_reg_x);
6216 rmwWithReg ("lsr", hc08_reg_x);
6217 rmwWithReg ("ror", hc08_reg_a);
6219 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6221 pullOrFreeReg (hc08_reg_x, needpulx);
6222 pullOrFreeReg (hc08_reg_a, needpula);
6227 /*-----------------------------------------------------------------*/
6228 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6229 /*-----------------------------------------------------------------*/
6231 shiftLLeftOrResult (operand * left, int offl,
6232 operand * result, int offr, int shCount)
6234 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6235 /* shift left accumulator */
6237 /* or with result */
6238 accopWithAop ("ora", AOP (result), offr);
6239 /* back to result */
6240 storeRegToAop (hc08_reg_a, AOP (result), offr);
6241 hc08_freeReg (hc08_reg_a);
6245 /*-----------------------------------------------------------------*/
6246 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6247 /*-----------------------------------------------------------------*/
6249 shiftRLeftOrResult (operand * left, int offl,
6250 operand * result, int offr, int shCount)
6252 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6253 /* shift left accumulator */
6254 AccRsh (shCount, FALSE);
6255 /* or with result */
6256 accopWithAop ("ora", AOP (result), offr);
6257 /* back to result */
6258 storeRegToAop (hc08_reg_a, AOP (result), offr);
6259 hc08_freeReg (hc08_reg_a);
6262 /*-----------------------------------------------------------------*/
6263 /* genlshOne - left shift a one byte quantity by known count */
6264 /*-----------------------------------------------------------------*/
6266 genlshOne (operand * result, operand * left, int shCount)
6268 D(emitcode ("; genlshOne",""));
6270 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6273 /*-----------------------------------------------------------------*/
6274 /* genlshTwo - left shift two bytes by known amount != 0 */
6275 /*-----------------------------------------------------------------*/
6277 genlshTwo (operand * result, operand * left, int shCount)
6281 D(emitcode ("; genlshTwo",""));
6284 size = getDataSize (result);
6286 /* if shCount >= 8 */
6293 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6295 storeRegToAop (hc08_reg_a, AOP (result), 1);
6297 storeConstToAop(zero, AOP (result), LSB);
6300 /* 1 <= shCount <= 7 */
6303 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6305 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6309 /*-----------------------------------------------------------------*/
6310 /* shiftLLong - shift left one long from left to result */
6311 /* offl = LSB or MSB16 */
6312 /*-----------------------------------------------------------------*/
6314 shiftLLong (operand * left, operand * result, int offr)
6317 // int size = AOP_SIZE (result);
6319 bool needpula = FALSE;
6320 bool needpulx = FALSE;
6322 needpula = pushRegIfUsed (hc08_reg_a);
6323 needpulx = pushRegIfUsed (hc08_reg_x);
6325 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6326 rmwWithReg ("lsl", hc08_reg_a);
6327 rmwWithReg ("rol", hc08_reg_x);
6328 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6332 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6333 rmwWithReg ("rol", hc08_reg_a);
6334 rmwWithReg ("rol", hc08_reg_x);
6335 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6337 else if (offr==MSB16)
6339 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6340 rmwWithReg ("rol", hc08_reg_a);
6341 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6342 storeConstToAop (zero, AOP (result), 0);
6345 pullOrFreeReg (hc08_reg_x, needpulx);
6346 pullOrFreeReg (hc08_reg_a, needpula);
6349 /*-----------------------------------------------------------------*/
6350 /* genlshFour - shift four byte by a known amount != 0 */
6351 /*-----------------------------------------------------------------*/
6353 genlshFour (operand * result, operand * left, int shCount)
6357 D(emitcode ("; genlshFour",""));
6359 size = AOP_SIZE (result);
6361 /* TODO: deal with the &result == &left case */
6363 /* if shifting more that 3 bytes */
6368 /* lowest order of left goes to the highest
6369 order of the destination */
6370 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6372 movLeft2Result (left, LSB, result, MSB32, 0);
6373 storeConstToAop (zero, AOP (result), LSB);
6374 storeConstToAop (zero, AOP (result), MSB16);
6375 storeConstToAop (zero, AOP (result), MSB24);
6379 /* more than two bytes */
6380 else if (shCount >= 16)
6382 /* lower order two bytes goes to higher order two bytes */
6384 /* if some more remaining */
6386 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6389 movLeft2Result (left, MSB16, result, MSB32, 0);
6390 movLeft2Result (left, LSB, result, MSB24, 0);
6392 storeConstToAop (zero, AOP (result), LSB);
6393 storeConstToAop (zero, AOP (result), MSB16);
6397 /* if more than 1 byte */
6398 else if (shCount >= 8)
6400 /* lower order three bytes goes to higher order three bytes */
6405 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6407 movLeft2Result (left, LSB, result, MSB16, 0);
6413 movLeft2Result (left, MSB24, result, MSB32, 0);
6414 movLeft2Result (left, MSB16, result, MSB24, 0);
6415 movLeft2Result (left, LSB, result, MSB16, 0);
6416 storeConstToAop (zero, AOP (result), LSB);
6418 else if (shCount == 1)
6419 shiftLLong (left, result, MSB16);
6422 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6423 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6424 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6425 storeConstToAop (zero, AOP (result), LSB);
6430 /* 1 <= shCount <= 7 */
6431 else if (shCount <= 2)
6433 shiftLLong (left, result, LSB);
6435 shiftLLong (result, result, LSB);
6437 /* 3 <= shCount <= 7, optimize */
6440 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6441 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6442 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6446 /*-----------------------------------------------------------------*/
6447 /* genLeftShiftLiteral - left shifting by known count */
6448 /*-----------------------------------------------------------------*/
6450 genLeftShiftLiteral (operand * left,
6455 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6458 D(emitcode ("; genLeftShiftLiteral",""));
6460 freeAsmop (right, NULL, ic, TRUE);
6462 aopOp (left, ic, FALSE);
6463 aopOp (result, ic, FALSE);
6465 // size = getSize (operandType (result));
6466 size = AOP_SIZE (result);
6469 D(emitcode ("; shift left ", "result %d, left %d", size,
6476 transferAopAop( AOP(left), size, AOP(result), size);
6478 else if (shCount >= (size * 8))
6481 storeConstToAop (zero, AOP (result), size);
6488 genlshOne (result, left, shCount);
6492 genlshTwo (result, left, shCount);
6496 genlshFour (result, left, shCount);
6499 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6500 "*** ack! mystery literal shift!\n");
6504 freeAsmop (left, NULL, ic, TRUE);
6505 freeAsmop (result, NULL, ic, TRUE);
6508 /*-----------------------------------------------------------------*/
6509 /* genLeftShift - generates code for left shifting */
6510 /*-----------------------------------------------------------------*/
6512 genLeftShift (iCode * ic)
6514 operand *left, *right, *result;
6516 symbol *tlbl, *tlbl1;
6521 D(emitcode ("; genLeftShift",""));
6523 right = IC_RIGHT (ic);
6524 left = IC_LEFT (ic);
6525 result = IC_RESULT (ic);
6527 aopOp (right, ic, FALSE);
6529 /* if the shift count is known then do it
6530 as efficiently as possible */
6531 if (AOP_TYPE (right) == AOP_LIT)
6533 genLeftShiftLiteral (left, right, result, ic);
6537 /* shift count is unknown then we have to form
6538 a loop get the loop count in A : Note: we take
6539 only the lower order byte since shifting
6540 more that 32 bits make no sense anyway, ( the
6541 largest size of an object can be only 32 bits ) */
6543 aopOp (left, ic, FALSE);
6544 aopOp (result, ic, FALSE);
6546 /* now move the left to the result if they are not the
6548 if (!sameRegs (AOP (left), AOP (result)))
6551 size = AOP_SIZE (result);
6555 transferAopAop (AOP (left), offset, AOP (result), offset);
6559 freeAsmop (left, NULL, ic, TRUE);
6561 tlbl = newiTempLabel (NULL);
6562 size = AOP_SIZE (result);
6564 tlbl1 = newiTempLabel (NULL);
6568 loadRegFromAop (reg, AOP (right), 0);
6569 freeAsmop (right, NULL, ic, TRUE);
6570 emitBranch ("beq", tlbl1);
6574 for (offset=0;offset<size;offset++)
6576 rmwWithAop (shift, AOP (result), offset);
6579 rmwWithReg ("dec", reg);
6580 emitBranch ("bne", tlbl);
6584 freeAsmop (result, NULL, ic, TRUE);
6587 /*-----------------------------------------------------------------*/
6588 /* genrshOne - right shift a one byte quantity by known count */
6589 /*-----------------------------------------------------------------*/
6591 genrshOne (operand * result, operand * left,
6592 int shCount, int sign)
6594 D(emitcode ("; genrshOne",""));
6596 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6597 AccRsh (shCount, sign);
6598 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6601 /*-----------------------------------------------------------------*/
6602 /* genrshTwo - right shift two bytes by known amount != 0 */
6603 /*-----------------------------------------------------------------*/
6605 genrshTwo (operand * result, operand * left,
6606 int shCount, int sign)
6608 D(emitcode ("; genrshTwo",""));
6610 /* if shCount >= 8 */
6613 if (shCount || sign)
6615 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6616 AccRsh (shCount-8, sign);
6617 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6621 transferAopAop (AOP (left), 1, AOP (result), 0);
6622 storeConstToAop (zero, AOP (result), 1);
6626 /* 1 <= shCount <= 7 */
6629 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6630 XAccRsh (shCount, sign);
6631 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6635 /*-----------------------------------------------------------------*/
6636 /* shiftRLong - shift right one long from left to result */
6637 /* offl = LSB or MSB16 */
6638 /*-----------------------------------------------------------------*/
6640 shiftRLong (operand * left, int offl,
6641 operand * result, int sign)
6644 // int size = AOP_SIZE (result);
6646 bool needpula = FALSE;
6647 bool needpulx = FALSE;
6649 needpula = pushRegIfUsed (hc08_reg_a);
6650 needpulx = pushRegIfUsed (hc08_reg_x);
6654 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6656 rmwWithReg ("asr", hc08_reg_x);
6658 rmwWithReg ("lsr", hc08_reg_x);
6659 rmwWithReg ("ror", hc08_reg_a);
6660 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6662 else if (offl==MSB16)
6664 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6666 rmwWithReg ("asr", hc08_reg_a);
6668 rmwWithReg ("lsr", hc08_reg_a);
6669 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6670 storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
6673 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6674 rmwWithReg ("ror", hc08_reg_x);
6675 rmwWithReg ("ror", hc08_reg_a);
6676 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6679 pullOrFreeReg (hc08_reg_x, needpulx);
6680 pullOrFreeReg (hc08_reg_a, needpula);
6683 /*-----------------------------------------------------------------*/
6684 /* genrshFour - shift four byte by a known amount != 0 */
6685 /*-----------------------------------------------------------------*/
6687 genrshFour (operand * result, operand * left,
6688 int shCount, int sign)
6690 /* TODO: handle cases where left == result */
6692 D(emitcode ("; genrshFour",""));
6694 /* if shifting more that 3 bytes */
6697 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6698 AccRsh (shCount-24, sign);
6699 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6702 else if (shCount >= 16)
6704 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6705 XAccRsh (shCount-16, sign);
6706 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6709 else if (shCount >= 8)
6712 shiftRLong (left, MSB16, result, sign);
6713 else if (shCount == 8)
6715 transferAopAop (AOP (left), 1, AOP (result), 0);
6716 transferAopAop (AOP (left), 2, AOP (result), 1);
6717 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6718 storeRegToAop (hc08_reg_a, AOP (result), 2);
6719 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6721 else if (shCount == 9)
6723 shiftRLong (left, MSB16, result, sign);
6727 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6728 XAccRsh (shCount-8, FALSE);
6729 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6730 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6731 loadRegFromConst (hc08_reg_a, zero);
6732 XAccRsh (shCount-8, sign);
6733 accopWithAop ("ora", AOP (result), 1);
6734 storeRegToAop (hc08_reg_xa, AOP (result), 1);
6735 storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
6739 { /* 1 <= shCount <= 7 */
6742 shiftRLong (left, LSB, result, sign);
6746 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6747 XAccRsh (shCount, FALSE);
6748 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6749 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6751 accopWithAop ("ora", AOP (result), 1);
6752 storeRegToAop (hc08_reg_a, AOP (result), 1);
6753 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6754 XAccRsh (shCount, sign);
6755 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6760 /*-----------------------------------------------------------------*/
6761 /* genRightShiftLiteral - right shifting by known count */
6762 /*-----------------------------------------------------------------*/
6764 genRightShiftLiteral (operand * left,
6770 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6773 D(emitcode ("; genRightShiftLiteral",""));
6775 freeAsmop (right, NULL, ic, TRUE);
6777 aopOp (left, ic, FALSE);
6778 aopOp (result, ic, FALSE);
6781 D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6785 size = getDataSize (left);
6786 /* test the LEFT size !!! */
6788 /* I suppose that the left size >= result size */
6791 size = getDataSize (result);
6793 transferAopAop (AOP (left), size, AOP(result), size);
6795 else if (shCount >= (size * 8))
6798 /* get sign in acc.7 */
6799 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6801 addSign (result, LSB, sign);
6808 genrshOne (result, left, shCount, sign);
6812 genrshTwo (result, left, shCount, sign);
6816 genrshFour (result, left, shCount, sign);
6822 freeAsmop (left, NULL, ic, TRUE);
6823 freeAsmop (result, NULL, ic, TRUE);
6827 /*-----------------------------------------------------------------*/
6828 /* genRightShift - generate code for right shifting */
6829 /*-----------------------------------------------------------------*/
6831 genRightShift (iCode * ic)
6833 operand *right, *left, *result;
6837 symbol *tlbl, *tlbl1;
6841 D(emitcode ("; genRightShift",""));
6843 /* if signed then we do it the hard way preserve the
6844 sign bit moving it inwards */
6845 retype = getSpec (operandType (IC_RESULT (ic)));
6846 sign = !SPEC_USIGN (retype);
6848 /* signed & unsigned types are treated the same : i.e. the
6849 signed is NOT propagated inwards : quoting from the
6850 ANSI - standard : "for E1 >> E2, is equivalent to division
6851 by 2**E2 if unsigned or if it has a non-negative value,
6852 otherwise the result is implementation defined ", MY definition
6853 is that the sign does not get propagated */
6855 right = IC_RIGHT (ic);
6856 left = IC_LEFT (ic);
6857 result = IC_RESULT (ic);
6859 aopOp (right, ic, FALSE);
6861 /* if the shift count is known then do it
6862 as efficiently as possible */
6863 if (AOP_TYPE (right) == AOP_LIT)
6865 genRightShiftLiteral (left, right, result, ic, sign);
6869 /* shift count is unknown then we have to form
6870 a loop get the loop count in X : Note: we take
6871 only the lower order byte since shifting
6872 more that 32 bits make no sense anyway, ( the
6873 largest size of an object can be only 32 bits ) */
6875 aopOp (left, ic, FALSE);
6876 aopOp (result, ic, FALSE);
6878 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6879 AOP (result) = forceStackedAop (AOP (result));
6881 size = AOP_SIZE (result);
6885 transferAopAop (AOP (left), offset, AOP (result), offset);
6889 tlbl = newiTempLabel (NULL);
6890 size = AOP_SIZE (result);
6892 tlbl1 = newiTempLabel (NULL);
6894 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6895 emitcode ("tstx", "");
6896 emitcode ("beq", "%05d$", tlbl1->key + 100);
6897 emitcode ("", "%05d$:", tlbl->key + 100);
6898 shift= sign ? "asr" : "lsr";
6899 for (offset=size-1;offset>=0;offset--)
6901 rmwWithAop (shift, AOP (result), offset);
6904 rmwWithReg ("dec", hc08_reg_x);
6905 emitcode ("bne","%05d$", tlbl->key + 100);
6906 emitcode ("", "%05d$:", tlbl1->key + 100);
6908 freeAsmop (result, NULL, ic, TRUE);
6909 freeAsmop (left, NULL, ic, TRUE);
6910 freeAsmop (right, NULL, ic, TRUE);
6914 /*-----------------------------------------------------------------*/
6915 /* genUnpackBits - generates code for unpacking bits */
6916 /*-----------------------------------------------------------------*/
6918 genUnpackBits (operand * result, iCode *ifx)
6920 int offset = 0; /* result byte offset */
6921 int rsize; /* result size */
6922 int rlen = 0; /* remaining bitfield length */
6923 sym_link *etype; /* bitfield type information */
6924 int blen; /* bitfield length */
6925 int bstr; /* bitfield starting bit within byte */
6927 D(emitcode ("; genUnpackBits",""));
6929 etype = getSpec (operandType (result));
6930 rsize = getSize (operandType (result));
6931 blen = SPEC_BLEN (etype);
6932 bstr = SPEC_BSTR (etype);
6934 if (ifx && blen <= 8)
6936 emitcode ("lda", ",x");
6937 hc08_dirtyReg (hc08_reg_a, FALSE);
6940 emitcode ("and", "#0x%02x",
6941 (((unsigned char) -1) >> (8 - blen)) << bstr);
6943 genIfxJump (ifx, "a");
6948 /* If the bitfield length is less than a byte */
6951 emitcode ("lda", ",x");
6952 hc08_dirtyReg (hc08_reg_a, FALSE);
6953 AccRsh (bstr, FALSE);
6954 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6955 if (!SPEC_USIGN (etype))
6957 /* signed bitfield */
6958 symbol *tlbl = newiTempLabel (NULL);
6960 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
6961 emitcode ("beq", "%05d$", tlbl->key + 100);
6962 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
6965 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6969 /* Bit field did not fit in a byte. Copy all
6970 but the partial byte at the end. */
6971 for (rlen=blen;rlen>=8;rlen-=8)
6973 emitcode ("lda", ",x");
6974 hc08_dirtyReg (hc08_reg_a, FALSE);
6975 storeRegToAop (hc08_reg_a, AOP (result), offset);
6978 emitcode ("aix", "#1");
6981 /* Handle the partial byte at the end */
6984 emitcode ("lda", ",x");
6985 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6986 if (!SPEC_USIGN (etype))
6988 /* signed bitfield */
6989 symbol *tlbl = newiTempLabel (NULL);
6991 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
6992 emitcode ("beq", "%05d$", tlbl->key + 100);
6993 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
6996 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7003 if (SPEC_USIGN (etype))
7006 storeConstToAop (zero, AOP (result), offset++);
7010 /* signed bitfield: sign extension with 0x00 or 0xff */
7011 emitcode ("rola", "");
7012 emitcode ("clra", "");
7013 emitcode ("sbc", zero);
7016 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7022 /*-----------------------------------------------------------------*/
7023 /* genUnpackBitsImmed - generates code for unpacking bits */
7024 /*-----------------------------------------------------------------*/
7026 genUnpackBitsImmed (operand * left,
7032 int offset = 0; /* result byte offset */
7033 int rsize; /* result size */
7034 int rlen = 0; /* remaining bitfield length */
7035 sym_link *etype; /* bitfield type information */
7036 int blen; /* bitfield length */
7037 int bstr; /* bitfield starting bit within byte */
7040 D(emitcode ("; genUnpackBitsImmed",""));
7042 aopOp (result, ic, TRUE);
7043 size = AOP_SIZE (result);
7045 derefaop = aopDerefAop (AOP (left));
7046 freeAsmop (left, NULL, ic, TRUE);
7047 derefaop->size = size;
7049 etype = getSpec (operandType (result));
7050 rsize = getSize (operandType (result));
7051 blen = SPEC_BLEN (etype);
7052 bstr = SPEC_BSTR (etype);
7054 /* if the bitfield is a single bit in the direct page */
7055 if (blen == 1 && derefaop->type == AOP_DIR)
7059 symbol *tlbl = newiTempLabel (NULL);
7061 loadRegFromConst (hc08_reg_a, zero);
7062 emitcode ("brclr", "#%d,%s,%05d$",
7063 bstr, aopAdrStr (derefaop, 0, FALSE),
7065 if (SPEC_USIGN (etype))
7066 rmwWithReg ("inc", hc08_reg_a);
7068 rmwWithReg ("dec", hc08_reg_a);
7070 storeRegToAop (hc08_reg_a, AOP (result), offset);
7071 hc08_freeReg (hc08_reg_a);
7077 symbol *tlbl = newiTempLabel (NULL);
7083 jlbl = IC_TRUE (ifx);
7088 jlbl = IC_FALSE (ifx);
7091 emitcode (inst, "#%d,%s,%05d$",
7092 bstr, aopAdrStr (derefaop, 0, FALSE),
7094 emitBranch ("jmp", jlbl);
7102 /* If the bitfield length is less than a byte */
7105 loadRegFromAop (hc08_reg_a, derefaop, 0);
7108 AccRsh (bstr, FALSE);
7109 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7110 hc08_dirtyReg (hc08_reg_a, FALSE);
7111 if (!SPEC_USIGN (etype))
7113 /* signed bitfield */
7114 symbol *tlbl = newiTempLabel (NULL);
7116 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7117 emitcode ("beq", "%05d$", tlbl->key + 100);
7118 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7121 storeRegToAop (hc08_reg_a, AOP (result), offset);
7125 emitcode ("and", "#0x%02x",
7126 (((unsigned char) -1) >> (8 - blen)) << bstr);
7127 hc08_dirtyReg (hc08_reg_a, FALSE);
7133 /* Bit field did not fit in a byte. Copy all
7134 but the partial byte at the end. */
7135 for (rlen=blen;rlen>=8;rlen-=8)
7137 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7139 storeRegToAop (hc08_reg_a, AOP (result), offset);
7141 emitcode ("tsta", "");
7145 /* Handle the partial byte at the end */
7148 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7149 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7150 if (!SPEC_USIGN (etype))
7152 /* signed bitfield */
7153 symbol *tlbl = newiTempLabel (NULL);
7155 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7156 emitcode ("beq", "%05d$", tlbl->key + 100);
7157 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7160 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7167 if (SPEC_USIGN (etype))
7170 storeConstToAop (zero, AOP (result), offset++);
7174 /* signed bitfield: sign extension with 0x00 or 0xff */
7175 emitcode ("rola", "");
7176 emitcode ("clra", "");
7177 emitcode ("sbc", zero);
7180 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7184 freeAsmop (NULL, derefaop, ic, TRUE);
7185 freeAsmop (result, NULL, ic, TRUE);
7187 if (ifx && !ifx->generated)
7189 genIfxJump (ifx, "a");
7194 /*-----------------------------------------------------------------*/
7195 /* genDataPointerGet - generates code when ptr offset is known */
7196 /*-----------------------------------------------------------------*/
7198 genDataPointerGet (operand * left,
7206 D(emitcode ("; genDataPointerGet",""));
7208 aopOp (result, ic, TRUE);
7209 size = AOP_SIZE (result);
7211 derefaop = aopDerefAop (AOP (left));
7212 freeAsmop (left, NULL, ic, TRUE);
7213 derefaop->size = size;
7218 transferAopAop (derefaop, size, AOP (result), size);
7220 loadRegFromAop (hc08_reg_a, derefaop, size);
7223 freeAsmop (NULL, derefaop, ic, TRUE);
7224 freeAsmop (result, NULL, ic, TRUE);
7226 if (ifx && !ifx->generated)
7228 genIfxJump (ifx, "a");
7233 /*-----------------------------------------------------------------*/
7234 /* genPointerGet - generate code for pointer get */
7235 /*-----------------------------------------------------------------*/
7237 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7239 operand *left = IC_LEFT (ic);
7240 operand *result = IC_RESULT (ic);
7242 sym_link *retype = getSpec (operandType (result));
7244 D(emitcode ("; genPointerGet",""));
7246 if (getSize (operandType (result))>1)
7249 aopOp (left, ic, FALSE);
7251 /* if left is rematerialisable and
7252 result is not bit variable type */
7253 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7255 if (!IS_BITVAR (retype))
7257 genDataPointerGet (left, result, ic, ifx);
7262 genUnpackBitsImmed (left, result, ic, ifx);
7267 /* if the operand is already in hx
7268 then we do nothing else we move the value to hx */
7269 if (AOP_TYPE (left) != AOP_STR)
7271 /* if this is remateriazable */
7272 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7275 /* so hx now contains the address */
7276 aopOp (result, ic, FALSE);
7278 /* if bit then unpack */
7279 if (IS_BITVAR (retype))
7280 genUnpackBits (result, ifx);
7283 size = AOP_SIZE (result);
7288 accopWithMisc ("lda", ",x");
7291 emitcode ("aix", "#1");
7292 hc08_dirtyReg (hc08_reg_hx, FALSE);
7295 storeRegToAop (hc08_reg_a, AOP (result), offset);
7297 hc08_freeReg (hc08_reg_a);
7301 freeAsmop (left, NULL, ic, TRUE);
7302 freeAsmop (result, NULL, ic, TRUE);
7305 aopOp (IC_RESULT (pi), pi, FALSE);
7306 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7307 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7311 if (ifx && !ifx->generated)
7313 genIfxJump (ifx, "a");
7316 hc08_freeReg (hc08_reg_hx);
7320 /*-----------------------------------------------------------------*/
7321 /* genPackBits - generates code for packed bit storage */
7322 /*-----------------------------------------------------------------*/
7324 genPackBits (sym_link * etype,
7327 int offset = 0; /* source byte offset */
7328 int rlen = 0; /* remaining bitfield length */
7329 int blen; /* bitfield length */
7330 int bstr; /* bitfield starting bit within byte */
7331 int litval; /* source literal value (if AOP_LIT) */
7332 unsigned char mask; /* bitmask within current byte */
7335 D(emitcode ("; genPackBits",""));
7337 blen = SPEC_BLEN (etype);
7338 bstr = SPEC_BSTR (etype);
7340 /* If the bitfield length is less than a byte */
7343 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7344 (unsigned char) (0xFF >> (8 - bstr)));
7346 if (AOP_TYPE (right) == AOP_LIT)
7348 /* Case with a bitfield length <8 and literal source
7350 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7352 litval &= (~mask) & 0xff;
7354 emitcode ("lda", ",x");
7355 if ((mask|litval)!=0xff)
7356 emitcode ("and","#0x%02x", mask);
7358 emitcode ("ora","#0x%02x", litval);
7359 hc08_dirtyReg (hc08_reg_a, FALSE);
7360 emitcode ("sta", ",x");
7362 hc08_freeReg (hc08_reg_a);
7366 /* Case with a bitfield length < 8 and arbitrary source
7368 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7369 /* shift and mask source value */
7371 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7372 hc08_dirtyReg (hc08_reg_a, FALSE);
7373 pushReg (hc08_reg_a, TRUE);
7375 emitcode ("lda", ",x");
7376 emitcode ("and", "#0x%02x", mask);
7377 emitcode ("ora", "1,s");
7378 emitcode ("sta", ",x");
7379 pullReg (hc08_reg_a);
7381 hc08_freeReg (hc08_reg_a);
7385 /* Bit length is greater than 7 bits. In this case, copy */
7386 /* all except the partial byte at the end */
7387 for (rlen=blen;rlen>=8;rlen-=8)
7389 if (AOP (right)->type == AOP_DIR)
7391 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7396 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7397 emitcode ("sta", "%d,x", offset);
7402 /* If there was a partial byte at the end */
7405 mask = (((unsigned char) -1 << rlen) & 0xff);
7407 if (AOP_TYPE (right) == AOP_LIT)
7409 /* Case with partial byte and literal source
7411 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7412 litval >>= (blen-rlen);
7413 litval &= (~mask) & 0xff;
7414 emitcode ("lda", "%d,x", offset - xoffset);
7415 hc08_dirtyReg (hc08_reg_a, FALSE);
7416 if ((mask|litval)!=0xff)
7417 emitcode ("and","#0x%02x", mask);
7419 emitcode ("ora","#0x%02x", litval);
7420 emitcode ("sta", "%d,x", offset - xoffset);
7421 hc08_dirtyReg (hc08_reg_a, FALSE);
7422 hc08_freeReg (hc08_reg_a);
7426 /* Case with partial byte and arbitrary source
7428 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7429 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7430 hc08_dirtyReg (hc08_reg_a, FALSE);
7431 pushReg (hc08_reg_a, TRUE);
7433 emitcode ("lda", "%d,x", offset - xoffset);
7434 emitcode ("and", "#0x%02x", mask);
7435 emitcode ("ora", "1,s");
7436 emitcode ("sta", "%d,x", offset - xoffset);
7437 pullReg (hc08_reg_a);
7440 hc08_freeReg (hc08_reg_a);
7443 /*-----------------------------------------------------------------*/
7444 /* genPackBitsImmed - generates code for packed bit storage */
7445 /*-----------------------------------------------------------------*/
7447 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7451 int offset = 0; /* source byte offset */
7452 int rlen = 0; /* remaining bitfield length */
7453 int blen; /* bitfield length */
7454 int bstr; /* bitfield starting bit within byte */
7455 int litval; /* source literal value (if AOP_LIT) */
7456 unsigned char mask; /* bitmask within current byte */
7458 D(emitcode ("; genPackBitsImmed",""));
7460 blen = SPEC_BLEN (etype);
7461 bstr = SPEC_BSTR (etype);
7463 aopOp (right, ic, FALSE);
7464 size = AOP_SIZE (right);
7466 derefaop = aopDerefAop (AOP (result));
7467 freeAsmop (result, NULL, ic, TRUE);
7468 derefaop->size = size;
7470 /* if the bitfield is a single bit in the direct page */
7471 if (blen == 1 && derefaop->type == AOP_DIR)
7473 if (AOP_TYPE (right) == AOP_LIT)
7475 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7477 emitcode ((litval & 1) ? "bset" : "bclr",
7478 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7482 symbol *tlbl1 = newiTempLabel (NULL);
7483 symbol *tlbl2 = newiTempLabel (NULL);
7485 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7486 emitcode ("bit", "#1");
7487 emitBranch ("bne", tlbl1);
7488 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7489 emitBranch ("bra", tlbl2);
7491 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7493 hc08_freeReg (hc08_reg_a);
7498 /* If the bitfield length is less than a byte */
7501 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7502 (unsigned char) (0xFF >> (8 - bstr)));
7504 if (AOP_TYPE (right) == AOP_LIT)
7506 /* Case with a bitfield length <8 and literal source
7508 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7510 litval &= (~mask) & 0xff;
7512 loadRegFromAop (hc08_reg_a, derefaop, 0);
7513 if ((mask|litval)!=0xff)
7514 emitcode ("and","#0x%02x", mask);
7516 emitcode ("ora","#0x%02x", litval);
7517 hc08_dirtyReg (hc08_reg_a, FALSE);
7518 storeRegToAop (hc08_reg_a, derefaop, 0);
7520 hc08_freeReg (hc08_reg_a);
7524 /* Case with a bitfield length < 8 and arbitrary source
7526 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7527 /* shift and mask source value */
7529 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7530 hc08_dirtyReg (hc08_reg_a, FALSE);
7531 pushReg (hc08_reg_a, TRUE);
7533 loadRegFromAop (hc08_reg_a, derefaop, 0);
7534 emitcode ("and", "#0x%02x", mask);
7535 emitcode ("ora", "1,s");
7536 storeRegToAop (hc08_reg_a, derefaop, 0);
7537 pullReg (hc08_reg_a);
7539 hc08_freeReg (hc08_reg_a);
7543 /* Bit length is greater than 7 bits. In this case, copy */
7544 /* all except the partial byte at the end */
7545 for (rlen=blen;rlen>=8;rlen-=8)
7547 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7551 /* If there was a partial byte at the end */
7554 mask = (((unsigned char) -1 << rlen) & 0xff);
7556 if (AOP_TYPE (right) == AOP_LIT)
7558 /* Case with partial byte and literal source
7560 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7561 litval >>= (blen-rlen);
7562 litval &= (~mask) & 0xff;
7563 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7564 if ((mask|litval)!=0xff)
7565 emitcode ("and","#0x%02x", mask);
7567 emitcode ("ora","#0x%02x", litval);
7568 hc08_dirtyReg (hc08_reg_a, FALSE);
7569 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7570 hc08_dirtyReg (hc08_reg_a, FALSE);
7571 hc08_freeReg (hc08_reg_a);
7575 /* Case with partial byte and arbitrary source
7577 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7578 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7579 hc08_dirtyReg (hc08_reg_a, FALSE);
7580 pushReg (hc08_reg_a, TRUE);
7582 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7583 emitcode ("and", "#0x%02x", mask);
7584 emitcode ("ora", "1,s");
7585 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7586 pullReg (hc08_reg_a);
7589 hc08_freeReg (hc08_reg_a);
7592 freeAsmop (right, NULL, ic, TRUE);
7593 freeAsmop (NULL, derefaop, ic, TRUE);
7596 /*-----------------------------------------------------------------*/
7597 /* genDataPointerSet - remat pointer to data space */
7598 /*-----------------------------------------------------------------*/
7600 genDataPointerSet (operand * right,
7607 D(emitcode ("; genDataPointerSet",""));
7609 aopOp (right, ic, FALSE);
7610 size = AOP_SIZE (right);
7612 derefaop = aopDerefAop (AOP (result));
7613 freeAsmop (result, NULL, ic, TRUE);
7614 derefaop->size = size;
7618 transferAopAop (AOP (right), size, derefaop, size);
7621 freeAsmop (right, NULL, ic, TRUE);
7622 freeAsmop (NULL, derefaop, ic, TRUE);
7626 /*-----------------------------------------------------------------*/
7627 /* genPointerSet - stores the value into a pointer location */
7628 /*-----------------------------------------------------------------*/
7630 genPointerSet (iCode * ic, iCode *pi)
7632 operand *right = IC_RIGHT (ic);
7633 operand *result = IC_RESULT (ic);
7634 sym_link *type, *etype;
7636 sym_link *retype = getSpec (operandType (right));
7637 sym_link *letype = getSpec (operandType (result));
7639 D(emitcode ("; genPointerSet",""));
7641 type = operandType (result);
7642 etype = getSpec (type);
7644 aopOp (result, ic, FALSE);
7646 /* if the result is rematerializable */
7647 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7649 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7651 genDataPointerSet (right, result, ic);
7656 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7661 /* if the operand is already in hx
7662 then we do nothing else we move the value to hx */
7663 if (AOP_TYPE (result) != AOP_STR)
7665 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7667 /* so hx now contains the address */
7668 aopOp (right, ic, FALSE);
7670 /* if bit then unpack */
7671 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7672 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7675 size = AOP_SIZE (right);
7680 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7681 accopWithMisc ("sta", ",x");
7684 emitcode ("aix", "#1");
7686 hc08_freeReg (hc08_reg_a);
7690 freeAsmop (result, NULL, ic, TRUE);
7691 freeAsmop (right, NULL, ic, TRUE);
7694 aopOp (IC_RESULT (pi), pi, FALSE);
7695 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7696 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7700 hc08_freeReg (hc08_reg_hx);
7704 /*-----------------------------------------------------------------*/
7705 /* genIfx - generate code for Ifx statement */
7706 /*-----------------------------------------------------------------*/
7708 genIfx (iCode * ic, iCode * popIc)
7710 operand *cond = IC_COND (ic);
7713 D(emitcode ("; genIfx",""));
7715 aopOp (cond, ic, FALSE);
7717 /* If the condition is a literal, we can just do an unconditional */
7718 /* branch or no branch */
7719 if (AOP_TYPE (cond) == AOP_LIT)
7721 unsigned long lit = (unsigned long) floatFromVal (AOP (cond)->aopu.aop_lit);
7722 freeAsmop (cond, NULL, ic, TRUE);
7724 /* if there was something to be popped then do it */
7730 emitBranch ("jmp", IC_TRUE (ic));
7735 emitBranch ("jmp", IC_FALSE (ic));
7741 /* get the value into acc */
7742 if (AOP_TYPE (cond) != AOP_CRY)
7743 asmopToBool (AOP (cond), FALSE);
7746 /* the result is now in the accumulator */
7747 freeAsmop (cond, NULL, ic, TRUE);
7749 /* if there was something to be popped then do it */
7753 /* if the condition is a bit variable */
7754 if (isbit && IS_ITEMP (cond) &&
7756 genIfxJump (ic, SPIL_LOC (cond)->rname);
7757 else if (isbit && !IS_ITEMP (cond))
7758 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7760 genIfxJump (ic, "a");
7765 /*-----------------------------------------------------------------*/
7766 /* genAddrOf - generates code for address of */
7767 /*-----------------------------------------------------------------*/
7769 genAddrOf (iCode * ic)
7771 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7774 D(emitcode ("; genAddrOf",""));
7776 aopOp (IC_RESULT (ic), ic, FALSE);
7778 /* if the operand is on the stack then we
7779 need to get the stack offset of this
7783 /* if it has an offset then we need to compute
7785 hc08_useReg (hc08_reg_hx);
7786 emitcode ("tsx", "");
7787 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7788 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7789 hc08_freeReg (hc08_reg_hx);
7794 /* object not on stack then we need the name */
7795 size = AOP_SIZE (IC_RESULT (ic));
7800 char s[SDCC_NAME_MAX+10];
7803 sprintf (s, "#%s", sym->rname);
7806 sprintf (s, "#>%s", sym->rname);
7809 sprintf (s, "#(%s >> %d)",
7813 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7817 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7821 /*-----------------------------------------------------------------*/
7822 /* genAssign - generate code for assignment */
7823 /*-----------------------------------------------------------------*/
7825 genAssign (iCode * ic)
7827 operand *result, *right;
7829 // unsigned long lit = 0L;
7831 D(emitcode("; genAssign",""));
7833 result = IC_RESULT (ic);
7834 right = IC_RIGHT (ic);
7836 /* if they are the same */
7837 if (operandsEqu (result, right)) {
7841 aopOp (right, ic, FALSE);
7842 aopOp (result, ic, TRUE);
7844 /* if they are the same registers */
7845 if (sameRegs (AOP (right), AOP (result)))
7848 if ((AOP_TYPE (right) == AOP_LIT)
7849 && (IS_AOP_HX(AOP(result))))
7851 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7856 size = AOP_SIZE (result);
7859 transferAopAop (AOP (right), size, AOP (result), size);
7863 freeAsmop (right, NULL, ic, TRUE);
7864 freeAsmop (result, NULL, ic, TRUE);
7867 /*-----------------------------------------------------------------*/
7868 /* genJumpTab - generates code for jump table */
7869 /*-----------------------------------------------------------------*/
7871 genJumpTab (iCode * ic)
7874 symbol *jtablo = newiTempLabel (NULL);
7875 symbol *jtabhi = newiTempLabel (NULL);
7877 D(emitcode ("; genJumpTab",""));
7879 aopOp (IC_JTCOND (ic), ic, FALSE);
7881 if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7883 /* get the condition into x */
7884 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7885 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7886 loadRegFromConst (hc08_reg_h, zero);
7888 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7889 emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7890 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7891 emitcode ("jmp", ",x");
7893 hc08_dirtyReg (hc08_reg_a, TRUE);
7894 hc08_dirtyReg (hc08_reg_hx, TRUE);
7899 pushReg(hc08_reg_hx, TRUE);
7901 /* get the condition into x */
7902 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7903 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7904 loadRegFromConst (hc08_reg_h, zero);
7906 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7907 emitcode ("sta", "3,s");
7908 emitcode ("lda", "%05d$,x", jtablo->key + 100);
7909 emitcode ("sta", "4,s");
7911 pullReg(hc08_reg_hx);
7912 emitcode ("rts", "");
7913 _G.stackPushes += 2;
7917 /* now generate the jump labels */
7919 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7920 jtab = setNextItem (IC_JTLABELS (ic)))
7921 emitcode (".db", "%05d$", jtab->key + 100);
7923 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7924 jtab = setNextItem (IC_JTLABELS (ic)))
7925 emitcode (".db", ">%05d$", jtab->key + 100);
7929 /*-----------------------------------------------------------------*/
7930 /* genCast - gen code for casting */
7931 /*-----------------------------------------------------------------*/
7933 genCast (iCode * ic)
7935 operand *result = IC_RESULT (ic);
7936 sym_link *ctype = operandType (IC_LEFT (ic));
7937 sym_link *rtype = operandType (IC_RIGHT (ic));
7938 operand *right = IC_RIGHT (ic);
7941 D(emitcode("; genCast",""));
7943 /* if they are equivalent then do nothing */
7944 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7947 aopOp (right, ic, FALSE);
7948 aopOp (result, ic, FALSE);
7951 /* if they are the same size : or less */
7952 if (AOP_SIZE (result) <= AOP_SIZE (right))
7955 /* if they are in the same place */
7957 if (sameRegs (AOP (right), AOP (result)))
7961 /* if they in different places then copy */
7962 size = AOP_SIZE (result);
7966 transferAopAop(AOP (right), offset, AOP (result), offset);
7973 /* if the result is of type pointer */
7978 sym_link *type = operandType (right);
7979 sym_link *etype = getSpec (type);
7981 /* pointer to generic pointer */
7982 if (IS_GENPTR (ctype))
7985 p_type = DCL_TYPE (type);
7988 if (SPEC_SCLS(etype)==S_REGISTER) {
7989 // let's assume it is a generic pointer
7992 /* we have to go by the storage class */
7993 p_type = PTR_TYPE (SPEC_OCLS (etype));
7997 /* the first two bytes are known */
7998 size = GPTRSIZE - 1;
8002 transferAopAop(AOP (right), offset, AOP (result), offset);
8005 /* the last byte depending on type */
8008 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8013 // pointerTypeToGPByte will have bitched.
8017 sprintf(gpValStr, "#0x%x", gpVal);
8018 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8024 /* just copy the pointers */
8025 size = AOP_SIZE (result);
8029 transferAopAop(AOP (right), offset, AOP (result), offset);
8035 /* so we now know that the size of destination is greater
8036 than the size of the source */
8037 /* we move to result for the size of source */
8038 size = AOP_SIZE (right);
8042 transferAopAop(AOP (right), offset, AOP (result), offset);
8046 /* now depending on the sign of the source && destination */
8047 size = AOP_SIZE (result) - AOP_SIZE (right);
8048 /* if unsigned or not an integral type */
8049 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8052 storeConstToAop (zero, AOP (result), offset++);
8056 /* we need to extend the sign :{ */
8057 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
8058 accopWithMisc ("rola", "");
8059 accopWithMisc ("clra", "");
8060 accopWithMisc ("sbc", zero);
8062 storeRegToAop (hc08_reg_a, AOP (result), offset++);
8065 /* we are done hurray !!!! */
8068 freeAsmop (right, NULL, ic, TRUE);
8069 freeAsmop (result, NULL, ic, TRUE);
8073 /*-----------------------------------------------------------------*/
8074 /* genDjnz - generate decrement & jump if not zero instrucion */
8075 /*-----------------------------------------------------------------*/
8077 genDjnz (iCode * ic, iCode * ifx)
8083 D(emitcode ("; genDjnz",""));
8085 /* if the if condition has a false label
8086 then we cannot save */
8090 /* if the minus is not of the form
8092 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8093 !IS_OP_LITERAL (IC_RIGHT (ic)))
8096 if (operandLitValue (IC_RIGHT (ic)) != 1)
8099 /* dbnz doesn't support extended mode */
8100 if (isOperandInFarSpace (IC_RESULT (ic)))
8103 /* if the size of this greater than one then no
8105 // if (getSize (operandType (IC_RESULT (ic))) > 1)
8107 aopOp (IC_RESULT (ic), ic, FALSE);
8108 if (AOP_SIZE (IC_RESULT (ic))>1)
8110 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8114 /* otherwise we can save BIG */
8115 lbl = newiTempLabel (NULL);
8116 lbl1 = newiTempLabel (NULL);
8119 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
8122 emitBranch ("bra", lbl1);
8124 emitBranch ("jmp", IC_TRUE (ifx));
8127 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8132 /*-----------------------------------------------------------------*/
8133 /* genReceive - generate code for a receive iCode */
8134 /*-----------------------------------------------------------------*/
8136 genReceive (iCode * ic)
8140 D(emitcode ("; genReceive",""));
8142 aopOp (IC_RESULT (ic), ic, FALSE);
8143 size = AOP_SIZE (IC_RESULT (ic));
8148 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
8149 AOP (IC_RESULT (ic)), offset);
8150 if (hc08_aop_pass[offset]->type == AOP_REG)
8151 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
8156 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8159 /*-----------------------------------------------------------------*/
8160 /* genDummyRead - generate code for dummy read of volatiles */
8161 /*-----------------------------------------------------------------*/
8163 genDummyRead (iCode * ic)
8168 D(emitcode("; genDummyRead",""));
8171 if (op && IS_SYMOP (op))
8174 aopOp (op, ic, FALSE);
8176 size = AOP_SIZE (op);
8181 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8182 hc08_freeReg (hc08_reg_a);
8186 freeAsmop (op, NULL, ic, TRUE);
8189 if (op && IS_SYMOP (op))
8192 aopOp (op, ic, FALSE);
8194 size = AOP_SIZE (op);
8199 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8200 hc08_freeReg (hc08_reg_a);
8204 freeAsmop (op, NULL, ic, TRUE);
8208 /*-----------------------------------------------------------------*/
8209 /* genCritical - generate code for start of a critical sequence */
8210 /*-----------------------------------------------------------------*/
8212 genCritical (iCode *ic)
8214 D(emitcode("; genCritical",""));
8217 aopOp (IC_RESULT (ic), ic, TRUE);
8219 emitcode ("tpa", "");
8220 hc08_dirtyReg (hc08_reg_a, FALSE);
8221 emitcode ("sei", "");
8224 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8226 pushReg (hc08_reg_a, FALSE);
8228 hc08_freeReg (hc08_reg_a);
8230 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8233 /*-----------------------------------------------------------------*/
8234 /* genEndCritical - generate code for end of a critical sequence */
8235 /*-----------------------------------------------------------------*/
8237 genEndCritical (iCode *ic)
8239 D(emitcode("; genEndCritical",""));
8243 aopOp (IC_RIGHT (ic), ic, FALSE);
8244 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8245 emitcode ("tap", "");
8246 hc08_freeReg (hc08_reg_a);
8247 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8251 pullReg (hc08_reg_a);
8252 emitcode ("tap", "");
8258 /*-----------------------------------------------------------------*/
8259 /* genhc08Code - generate code for HC08 based controllers */
8260 /*-----------------------------------------------------------------*/
8262 genhc08Code (iCode * lic)
8269 lineHead = lineCurr = NULL;
8271 /* print the allocation information */
8272 if (allocInfo && currFunc)
8273 printAllocInfo (currFunc, codeOutFile);
8274 /* if debug information required */
8275 if (options.debug && currFunc)
8277 debugFile->writeFunction (currFunc, lic);
8280 if (IS_STATIC (currFunc->etype))
8281 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8283 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8287 /* stack pointer name */
8288 if (options.useXstack)
8293 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8295 hc08_aop_pass[0] = newAsmop (AOP_REG);
8296 hc08_aop_pass[0]->size=1;
8297 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8298 hc08_aop_pass[1] = newAsmop (AOP_REG);
8299 hc08_aop_pass[1]->size=1;
8300 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8301 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8302 hc08_aop_pass[2]->size=1;
8303 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8304 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8305 hc08_aop_pass[3]->size=1;
8306 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8308 for (ic = lic; ic; ic = ic->next)
8311 _G.current_iCode = ic;
8313 if (ic->level != clevel || ic->block != cblock)
8317 debugFile->writeScope(ic);
8323 if (ic->lineno && cln != ic->lineno)
8327 debugFile->writeCLine(ic);
8330 emitcode ("", "C$%s$%d$%d$%d ==.",
8331 FileBaseName (ic->filename), ic->lineno,
8332 ic->level, ic->block);
8336 if (!options.noCcodeInAsm) {
8337 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8338 printCLine(ic->filename, ic->lineno));
8342 if (options.iCodeInAsm) {
8346 for (i=0; i<6; i++) {
8347 sprintf (®sInUse[i],
8348 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8351 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8353 /* if the result is marked as
8354 spilt and rematerializable or code for
8355 this has already been generated then
8357 if (resultRemat (ic) || ic->generated)
8365 for (i=A_IDX;i<=XA_IDX;i++)
8367 reg = hc08_regWithIdx(i);
8369 emitcode("","; %s = %s offset %d", reg->name,
8370 aopName(reg->aop), reg->aopofs);
8373 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8375 sym = OP_SYMBOL (IC_LEFT (ic));
8376 if (sym->accuse == ACCUSE_HX)
8378 hc08_reg_h->isFree = FALSE;
8379 hc08_reg_x->isFree = FALSE;
8381 else if (sym->accuse == ACCUSE_XA)
8383 hc08_reg_a->isFree = FALSE;
8385 hc08_reg_x->isFree = FALSE;
8388 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8390 sym = OP_SYMBOL (IC_RIGHT (ic));
8391 if (sym->accuse == ACCUSE_HX)
8393 hc08_reg_h->isFree = FALSE;
8394 hc08_reg_x->isFree = FALSE;
8396 else if (sym->accuse == ACCUSE_XA)
8398 hc08_reg_a->isFree = FALSE;
8400 hc08_reg_x->isFree = FALSE;
8405 /* depending on the operation */
8425 /* IPOP happens only when trying to restore a
8426 spilt live range, if there is an ifx statement
8427 following this pop then the if statement might
8428 be using some of the registers being popped which
8429 would destory the contents of the register so
8430 we need to check for this condition and handle it */
8432 ic->next->op == IFX &&
8433 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8434 genIfx (ic->next, ic);
8452 genEndFunction (ic);
8468 if (!genPointerGetSetOfs (ic))
8473 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8493 genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
8498 genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
8510 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8514 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8518 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8545 case GET_VALUE_AT_ADDRESS:
8547 hasInc (IC_LEFT (ic), ic,
8548 getSize (operandType (IC_RESULT (ic)))),
8549 ifxForOp (IC_RESULT (ic), ic) );
8553 if (POINTER_SET (ic))
8554 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8580 addSet (&_G.sendSet, ic);
8583 case DUMMY_READ_VOLATILE:
8592 genEndCritical (ic);
8603 if (!hc08_reg_a->isFree)
8604 D(emitcode("","; forgot to free a"));
8605 if (!hc08_reg_x->isFree)
8606 D(emitcode("","; forgot to free x"));
8607 if (!hc08_reg_h->isFree)
8608 D(emitcode("","; forgot to free h"));
8609 if (!hc08_reg_hx->isFree)
8610 D(emitcode("","; forgot to free hx"));
8611 if (!hc08_reg_xa->isFree)
8612 D(emitcode("","; forgot to free xa"));
8615 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8618 /* now we are ready to call the
8619 peep hole optimizer */
8620 if (!options.nopeep)
8621 peepHole (&lineHead);
8623 /* now do the actual printing */
8624 printLine (lineHead, codeOutFile);