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
1151 && dstaop->type == srcaop->type)
1154 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1156 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1160 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1162 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1166 // D(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1167 // aopName (srcaop), srcofs, aopName (dstaop), dstofs));
1168 // D(emitcode ("", "; srcaop->type = %d", srcaop->type));
1169 // D(emitcode ("", "; dstaop->type = %d", dstaop->type));
1171 if (dstofs >= dstaop->size)
1174 if ((dstaop->type == AOP_DIR)
1175 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1177 if (srcaop->type == AOP_LIT)
1180 unsigned long bytemask;
1182 lit = (unsigned long) floatFromVal (srcaop->aopu.aop_lit);
1183 bytemask = (lit >> (srcofs*8)) & 0xff;
1187 emitcode ("clr", "%s", aopAdrStr(dstaop, dstofs, FALSE));
1192 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1193 aopAdrStr(dstaop, dstofs, FALSE));
1197 if (dstaop->type == AOP_REG)
1199 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1200 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1202 reg = dstaop->aopu.aop_reg[dstofs];
1207 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1209 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1210 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1212 reg = srcaop->aopu.aop_reg[srcofs];
1219 if (hc08_reg_a->isFree)
1221 else if (hc08_reg_x->isFree)
1225 pushReg (hc08_reg_a, TRUE);
1231 loadRegFromAop (reg, srcaop, srcofs);
1232 storeRegToAop (reg, dstaop, dstofs);
1235 pullOrFreeReg (hc08_reg_a, needpula);
1239 /*--------------------------------------------------------------------------*/
1240 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1241 /* parameter param. */
1242 /*--------------------------------------------------------------------------*/
1244 accopWithMisc (char *accop, char *param)
1246 emitcode (accop, "%s", param);
1247 hc08_dirtyReg (hc08_reg_a, FALSE);
1250 /*--------------------------------------------------------------------------*/
1251 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1252 /* byte at logical offset loffset of asmop aop. */
1253 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1254 /*--------------------------------------------------------------------------*/
1256 accopWithAop (char *accop, asmop *aop, int loffset)
1258 if (aop->stacked && aop->stk_aop[loffset])
1260 accopWithAop (accop, aop->stk_aop[loffset], 0);
1264 if (aop->type == AOP_DUMMY)
1267 if (aop->type == AOP_REG)
1269 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1270 emitcode (accop, "1,s");
1274 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1276 hc08_dirtyReg (hc08_reg_a, FALSE);
1280 /*--------------------------------------------------------------------------*/
1281 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1282 /* byte at logical offset loffset of asmop aop. Register reg */
1283 /* must be 8-bit. */
1284 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1285 /*--------------------------------------------------------------------------*/
1287 rmwWithReg (char *rmwop, regs *reg)
1290 char *rmwaop = rmwbuf;
1292 if (reg->rIdx == A_IDX)
1294 sprintf(rmwaop,"%sa", rmwop);
1295 emitcode (rmwaop, "");
1296 hc08_dirtyReg (hc08_reg_a, FALSE);
1298 else if (reg->rIdx == X_IDX)
1300 sprintf(rmwaop,"%sx", rmwop);
1301 emitcode (rmwaop, "");
1302 hc08_dirtyReg (hc08_reg_a, FALSE);
1304 else if (hc08_reg_a->isFree)
1306 transferRegReg(reg, hc08_reg_a, FALSE);
1307 sprintf(rmwaop,"%sa", rmwop);
1308 emitcode (rmwaop, "");
1309 hc08_dirtyReg (hc08_reg_a, FALSE);
1310 transferRegReg(hc08_reg_a, reg, TRUE);
1314 pushReg (reg, FALSE);
1315 emitcode (rmwop, "1,s");
1317 hc08_dirtyReg (reg, FALSE);
1321 /*--------------------------------------------------------------------------*/
1322 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1323 /* logical offset loffset of asmop aop. */
1324 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror, tst */
1325 /*--------------------------------------------------------------------------*/
1327 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1329 bool needpula = FALSE;
1331 if (aop->stacked && aop->stk_aop[loffset])
1333 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1340 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1343 needpula = pushRegIfUsed (hc08_reg_a);
1344 loadRegFromAop (hc08_reg_a, aop, loffset);
1345 rmwWithReg (rmwop, hc08_reg_a);
1346 if (strcmp ("tst", rmwop))
1347 storeRegToAop (hc08_reg_a, aop, loffset);
1348 pullOrFreeReg (hc08_reg_a, needpula);
1353 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1359 /*-----------------------------------------------------------------*/
1360 /* newAsmop - creates a new asmOp */
1361 /*-----------------------------------------------------------------*/
1363 newAsmop (short type)
1367 aop = Safe_calloc (1, sizeof (asmop));
1374 /*-----------------------------------------------------------------*/
1375 /* pointerCode - returns the code for a pointer type */
1376 /*-----------------------------------------------------------------*/
1378 pointerCode (sym_link * etype)
1381 return PTR_TYPE (SPEC_OCLS (etype));
1386 /*-----------------------------------------------------------------*/
1387 /* aopForSym - for a true symbol */
1388 /*-----------------------------------------------------------------*/
1390 aopForSym (iCode * ic, symbol * sym, bool result)
1395 wassertl (ic != NULL, "Got a null iCode");
1396 wassertl (sym != NULL, "Got a null symbol");
1398 // printf("in aopForSym for symbol %s\n", sym->name);
1400 space = SPEC_OCLS (sym->etype);
1402 /* if already has one */
1408 /* special case for a function */
1409 if (IS_FUNC (sym->type))
1411 sym->aop = aop = newAsmop (AOP_IMMD);
1412 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1413 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1414 aop->size = FPTRSIZE;
1418 /* if it is in direct space */
1419 if (IN_DIRSPACE (space))
1421 sym->aop = aop = newAsmop (AOP_DIR);
1422 aop->aopu.aop_dir = sym->rname;
1423 aop->size = getSize (sym->type);
1427 /* if it is in far space */
1428 if (IN_FARSPACE (space))
1430 sym->aop = aop = newAsmop (AOP_EXT);
1431 aop->aopu.aop_dir = sym->rname;
1432 aop->size = getSize (sym->type);
1436 if (IN_STACK (sym->etype))
1438 sym->aop = aop = newAsmop (AOP_SOF);
1439 aop->aopu.aop_dir = sym->rname;
1440 aop->size = getSize (sym->type);
1441 aop->aopu.aop_stk = sym->stack;
1447 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1448 "aopForSym should never reach here");
1452 /* if it is in code space */
1453 if (IN_CODESPACE (space))
1459 /*-----------------------------------------------------------------*/
1460 /* aopForRemat - rematerialzes an object */
1461 /*-----------------------------------------------------------------*/
1463 aopForRemat (symbol * sym)
1465 iCode *ic = sym->rematiCode;
1473 val += (int) operandLitValue (IC_RIGHT (ic));
1474 else if (ic->op == '-')
1475 val -= (int) operandLitValue (IC_RIGHT (ic));
1476 else if (IS_CAST_ICODE(ic)) {
1477 sym_link *from_type = operandType(IC_RIGHT(ic));
1478 aop->aopu.aop_immd.from_cast_remat = 1;
1479 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1480 ptr_type = DCL_TYPE(from_type);
1481 if (ptr_type == IPOINTER) {
1488 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1491 if (ic->op == ADDRESS_OF)
1494 sprintf (buffer, "(%s %c 0x%04x)",
1495 OP_SYMBOL (IC_LEFT (ic))->rname,
1496 val >= 0 ? '+' : '-',
1497 abs (val) & 0xffff);
1499 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1501 aop = newAsmop (AOP_IMMD);
1502 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1503 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1504 /* set immd2 field if required */
1505 if (aop->aopu.aop_immd.from_cast_remat)
1507 sprintf(buffer,"#0x%02x",ptr_type);
1508 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1509 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1512 else if (ic->op == '=')
1514 val += (int) operandLitValue (IC_RIGHT (ic));
1516 sprintf (buffer, "0x%04x", val);
1517 aop = newAsmop (AOP_LIT);
1518 aop->aopu.aop_lit = constVal (buffer);
1521 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1522 "unexpected rematerialization");
1529 /*-----------------------------------------------------------------*/
1530 /* regsInCommon - two operands have some registers in common */
1531 /*-----------------------------------------------------------------*/
1533 regsInCommon (operand * op1, operand * op2)
1535 symbol *sym1, *sym2;
1538 /* if they have registers in common */
1539 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1542 sym1 = OP_SYMBOL (op1);
1543 sym2 = OP_SYMBOL (op2);
1545 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1548 for (i = 0; i < sym1->nRegs; i++)
1554 for (j = 0; j < sym2->nRegs; j++)
1559 if (sym2->regs[j] == sym1->regs[i])
1567 /*-----------------------------------------------------------------*/
1568 /* operandsEqu - equivalent */
1569 /*-----------------------------------------------------------------*/
1571 operandsEqu (operand * op1, operand * op2)
1573 symbol *sym1, *sym2;
1575 /* if they not symbols */
1576 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1579 sym1 = OP_SYMBOL (op1);
1580 sym2 = OP_SYMBOL (op2);
1582 /* if both are itemps & one is spilt
1583 and the other is not then false */
1584 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1585 sym1->isspilt != sym2->isspilt)
1588 /* if they are the same */
1592 if (sym1->rname[0] && sym2->rname[0]
1593 && strcmp (sym1->rname, sym2->rname) == 0)
1596 /* if left is a tmp & right is not */
1597 if (IS_ITEMP (op1) &&
1600 (sym1->usl.spillLoc == sym2))
1603 if (IS_ITEMP (op2) &&
1607 (sym2->usl.spillLoc == sym1))
1613 /*-----------------------------------------------------------------*/
1614 /* sameRegs - two asmops have the same registers */
1615 /*-----------------------------------------------------------------*/
1617 sameRegs (asmop * aop1, asmop * aop2)
1624 // if (aop1->size != aop2->size)
1627 if (aop1->type == aop2->type)
1632 for (i = 0; i < aop1->size; i++)
1633 if (aop1->aopu.aop_reg[i] !=
1634 aop2->aopu.aop_reg[i])
1638 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1641 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1648 /*-----------------------------------------------------------------*/
1649 /* aopOp - allocates an asmop for an operand : */
1650 /*-----------------------------------------------------------------*/
1652 aopOp (operand * op, iCode * ic, bool result)
1661 // Is this a pointer set result?
1663 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1667 // printf("checking literal\n");
1668 /* if this a literal */
1669 if (IS_OP_LITERAL (op))
1671 op->aop = aop = newAsmop (AOP_LIT);
1672 aop->aopu.aop_lit = op->operand.valOperand;
1673 aop->size = getSize (operandType (op));
1675 aop->isaddr = op->isaddr;
1679 // printf("checking pre-existing\n");
1680 /* if already has a asmop then continue */
1684 op->aop->isaddr = op->isaddr;
1688 // printf("checking underlying sym\n");
1689 /* if the underlying symbol has a aop */
1690 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1692 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1693 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1694 //op->aop = aop = OP_SYMBOL (op)->aop;
1695 aop->size = getSize( operandType (op));
1696 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1697 //printf (" with size = %d\n", aop->size);
1700 aop->isaddr = op->isaddr;
1701 /* if (aop->isaddr & IS_ITEMP (op))
1703 aop->psize=aop->size;
1704 aop->size = getSize( operandType (op)->next);
1709 // printf("checking true sym\n");
1710 /* if this is a true symbol */
1711 if (IS_TRUE_SYMOP (op))
1713 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1715 aop->isaddr = op->isaddr;
1716 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1717 //printf (" with size = %d\n", aop->size);
1721 /* this is a temporary : this has
1727 e) can be a return use only */
1729 sym = OP_SYMBOL (op);
1731 // printf("checking conditional\n");
1732 /* if the type is a conditional */
1733 if (sym->regType == REG_CND)
1735 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1738 aop->isaddr = op->isaddr;
1742 // printf("checking spilt\n");
1743 /* if it is spilt then two situations
1745 b) has a spill location */
1746 if (sym->isspilt || sym->nRegs == 0)
1749 // printf("checking remat\n");
1750 /* rematerialize it NOW */
1753 sym->aop = op->aop = aop =
1755 aop->size = getSize (sym->type);
1757 aop->isaddr = op->isaddr;
1758 /* if (aop->isaddr & IS_ITEMP (op))
1760 aop->psize=aop->size;
1761 aop->size = getSize( operandType (op)->next);
1766 // printf("checking accuse\n");
1769 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1770 aop->size = getSize (sym->type);
1771 switch (sym->accuse)
1774 aop->aopu.aop_reg[0] = hc08_reg_a;
1775 aop->aopu.aop_reg[1] = hc08_reg_x;
1778 aop->aopu.aop_reg[0] = hc08_reg_x;
1779 aop->aopu.aop_reg[1] = hc08_reg_h;
1783 aop->isaddr = op->isaddr;
1787 // printf("checking ruonly\n");
1793 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1794 aop->size = getSize (sym->type);
1795 for (i = 0; i < fReturnSizeHC08; i++)
1796 aop->aopu.aop_str[i] = fReturn2[i];
1798 aop->isaddr = op->isaddr;
1802 /* else spill location */
1803 if (sym->usl.spillLoc)
1805 asmop *oldAsmOp = NULL;
1807 if (sym->usl.spillLoc->aop
1808 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1810 /* force a new aop if sizes differ */
1811 oldAsmOp = sym->usl.spillLoc->aop;
1812 sym->usl.spillLoc->aop = NULL;
1813 //printf ("forcing new aop\n");
1815 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1816 if (sym->usl.spillLoc->aop->size != getSize (sym->type))
1818 /* Don't reuse the new aop, go with the last one */
1819 sym->usl.spillLoc->aop = oldAsmOp;
1821 aop->size = getSize (sym->type);
1823 aop->isaddr = op->isaddr;
1824 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1825 //printf (" with size = %d\n", aop->size);
1829 /* else must be a dummy iTemp */
1830 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1831 aop->size = getSize (sym->type);
1835 // printf("assuming register\n");
1836 /* must be in a register */
1837 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1838 aop->size = sym->nRegs;
1839 for (i = 0; i < sym->nRegs; i++)
1840 aop->aopu.aop_reg[i] = sym->regs[i];
1842 aop->isaddr = op->isaddr;
1846 /*-----------------------------------------------------------------*/
1847 /* freeAsmop - free up the asmop given to an operand */
1848 /*----------------------------------------------------------------*/
1850 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1872 D(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1875 for (loffset=0; loffset<aop->size; loffset++)
1876 if (aop->stk_aop[loffset])
1878 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1881 pullNull (stackAdjust);
1885 /* all other cases just dealloc */
1891 OP_SYMBOL (op)->aop = NULL;
1892 /* if the symbol has a spill */
1894 SPIL_LOC (op)->aop = NULL;
1900 /*-----------------------------------------------------------------*/
1901 /* aopDerefAop - treating the aop parameter as a pointer, return */
1902 /* an asmop for the object it references */
1903 /*-----------------------------------------------------------------*/
1905 aopDerefAop (asmop *aop)
1910 asmop *newaop = NULL;
1911 sym_link *type, *etype;
1914 D(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1918 type = operandType (aop->op);
1919 etype = getSpec (type);
1920 /* if op is of type of pointer then it is simple */
1921 if (IS_PTR (type) && !IS_FUNC (type->next))
1922 p_type = DCL_TYPE (type);
1925 /* we have to go by the storage class */
1926 p_type = PTR_TYPE (SPEC_OCLS (etype));
1935 if (p_type == POINTER)
1936 newaop = newAsmop (AOP_DIR);
1938 newaop = newAsmop (AOP_EXT);
1939 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1942 adr = (int) floatFromVal (aop->aopu.aop_lit);
1943 if (p_type == POINTER)
1948 newaop = newAsmop (AOP_DIR);
1949 sprintf (s, "0x%02x",adr);
1953 newaop = newAsmop (AOP_EXT);
1954 sprintf (s, "0x%04x",adr);
1956 rs = Safe_calloc (1, strlen (s) + 1);
1958 newaop->aopu.aop_dir = rs;
1961 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1962 "unsupported asmop");
1972 /*-----------------------------------------------------------------*/
1973 /* aopAdrStr - for referencing the address of the aop */
1974 /*-----------------------------------------------------------------*/
1976 aopAdrStr (asmop * aop, int loffset, bool bit16)
1980 int offset = aop->size - 1 - loffset;
1983 /* offset is greater than
1985 if (loffset > (aop->size - 1) &&
1986 aop->type != AOP_LIT)
1989 /* depending on type */
1997 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
1998 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
2000 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
2004 sprintf (s, "#(%s >> %d)",
2005 aop->aopu.aop_immd.aop_immd1,
2009 aop->aopu.aop_immd.aop_immd1);
2013 aop->aopu.aop_immd.aop_immd1);
2014 rs = Safe_calloc (1, strlen (s) + 1);
2020 sprintf (s, "*(%s + %d)",
2024 sprintf (s, "*%s", aop->aopu.aop_dir);
2025 rs = Safe_calloc (1, strlen (s) + 1);
2031 sprintf (s, "(%s + %d)",
2035 sprintf (s, "%s", aop->aopu.aop_dir);
2036 rs = Safe_calloc (1, strlen (s) + 1);
2041 return aop->aopu.aop_reg[loffset]->name;
2045 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
2047 return aopLiteral (aop->aopu.aop_lit, loffset);
2051 return aop->aopu.aop_str[loffset];
2054 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2056 rs = Safe_calloc (1, strlen (s) + 1);
2062 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2063 "aopAdrStr got unsupported aop->type");
2072 /*-----------------------------------------------------------------*/
2073 /* opIsGptr: returns non-zero if the passed operand is */
2074 /* a generic pointer type. */
2075 /*-----------------------------------------------------------------*/
2077 opIsGptr (operand * op)
2079 sym_link *type = operandType (op);
2081 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2089 /*-----------------------------------------------------------------*/
2090 /* getDataSize - get the operand data size */
2091 /*-----------------------------------------------------------------*/
2093 getDataSize (operand * op)
2096 size = AOP_SIZE (op);
2101 /*-----------------------------------------------------------------*/
2102 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2103 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2104 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2105 /*-----------------------------------------------------------------*/
2107 asmopToBool (asmop *aop, bool resultInA)
2109 symbol *tlbl, *tlbl1;
2110 int size = aop->size;
2111 bool needpula = FALSE;
2112 bool flagsonly = TRUE;
2117 hc08_freeReg(hc08_reg_a);
2124 emitcode ("tsta", "");
2127 else if (IS_AOP_X(aop))
2128 emitcode ("tstx", "");
2129 else if (IS_AOP_H(aop))
2131 if (hc08_reg_a->isFree)
2133 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2134 emitcode ("tsta", "");
2136 hc08_freeReg(hc08_reg_a);
2138 else if (hc08_reg_x->isFree)
2140 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2141 emitcode ("tstx", "");
2142 hc08_freeReg(hc08_reg_x);
2146 emitcode ("pshh", "");
2147 emitcode ("tst", "1,s");
2148 emitcode ("ais", "#1");
2151 else if (IS_AOP_HX(aop))
2152 emitcode ("cphx", zero);
2153 else if (IS_AOP_XA(aop))
2155 symbol *tlbl = newiTempLabel (NULL);
2156 emitcode ("tsta", "");
2157 emitcode ("bne", "%05d$", (tlbl->key + 100));
2158 emitcode ("tstx", "");
2159 emitcode ("", "%05d$:", (tlbl->key + 100));
2163 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2164 "Bad rIdx in asmToBool");
2172 needpula = pushRegIfUsed (hc08_reg_a);
2173 loadRegFromAop (hc08_reg_a, aop, 0);
2174 for (offset=1; offset<size; offset++)
2175 accopWithAop ("ora", aop, offset);
2177 pullReg (hc08_reg_a);
2180 hc08_freeReg (hc08_reg_a);
2185 /* Higher levels should optimize this case away but let's be safe */
2186 if ((unsigned long) floatFromVal (aop->aopu.aop_lit))
2187 loadRegFromConst (hc08_reg_a, one);
2189 loadRegFromConst (hc08_reg_a, zero);
2190 hc08_freeReg(hc08_reg_a);
2197 loadRegFromAop (hc08_reg_a, aop, 0);
2198 hc08_freeReg (hc08_reg_a);
2202 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2207 if (hc08_reg_a->isFree)
2209 loadRegFromAop (hc08_reg_a, aop, 0);
2210 accopWithAop ("ora", aop, 1);
2211 hc08_freeReg (hc08_reg_a);
2216 tlbl = newiTempLabel (NULL);
2217 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2218 emitcode ("bne", "%05d$", (tlbl->key + 100));
2219 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2220 emitcode ("", "%05d$:", (tlbl->key + 100));
2226 needpula = pushRegIfUsed (hc08_reg_a);
2227 loadRegFromAop (hc08_reg_a, aop, 0);
2228 for (offset=1; offset<size; offset++)
2229 accopWithAop ("ora", aop, offset);
2231 pullReg (hc08_reg_a);
2234 hc08_freeReg (hc08_reg_a);
2242 tlbl = newiTempLabel (NULL);
2246 tlbl1 = newiTempLabel (NULL);
2247 emitBranch ("bne", tlbl1);
2248 loadRegFromConst (hc08_reg_a, zero);
2249 emitBranch ("bra", tlbl);
2251 loadRegFromConst (hc08_reg_a, one);
2255 emitBranch ("beq", tlbl);
2256 loadRegFromConst (hc08_reg_a, one);
2259 hc08_useReg (hc08_reg_a);
2265 /*-----------------------------------------------------------------*/
2266 /* genNot - generate code for ! operation */
2267 /*-----------------------------------------------------------------*/
2271 D(emitcode ("; genNot",""));
2273 /* assign asmOps to operand & result */
2274 aopOp (IC_LEFT (ic), ic, FALSE);
2275 aopOp (IC_RESULT (ic), ic, TRUE);
2277 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2278 emitcode ("eor", one);
2279 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2281 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2282 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2286 /*-----------------------------------------------------------------*/
2287 /* genCpl - generate code for complement */
2288 /*-----------------------------------------------------------------*/
2294 regs* reg = hc08_reg_a;
2298 D(emitcode ("; genCpl",""));
2300 /* assign asmOps to operand & result */
2301 aopOp (IC_LEFT (ic), ic, FALSE);
2302 aopOp (IC_RESULT (ic), ic, TRUE);
2304 size = AOP_SIZE (IC_RESULT (ic));
2307 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2308 rmwWithReg ("com", reg);
2310 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2315 /* release the aops */
2316 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2317 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2320 /*-----------------------------------------------------------------*/
2321 /* genUminusFloat - unary minus for floating points */
2322 /*-----------------------------------------------------------------*/
2324 genUminusFloat (operand * op, operand * result)
2326 int size, offset = 0;
2329 D(emitcode ("; genUminusFloat",""));
2331 /* for this we just copy and then flip the bit */
2333 size = AOP_SIZE (op) - 1;
2337 transferAopAop (AOP (op), offset, AOP (result), offset);
2341 needpula = pushRegIfUsed (hc08_reg_a);
2342 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2343 emitcode ("eor", "#0x80");
2344 hc08_useReg (hc08_reg_a);
2345 storeRegToAop (hc08_reg_a, AOP (result), offset);
2346 pullOrFreeReg (hc08_reg_a, needpula);
2349 /*-----------------------------------------------------------------*/
2350 /* genUminus - unary minus code generation */
2351 /*-----------------------------------------------------------------*/
2353 genUminus (iCode * ic)
2356 sym_link *optype, *rtype;
2361 D(emitcode ("; genUminus",""));
2364 aopOp (IC_LEFT (ic), ic, FALSE);
2365 aopOp (IC_RESULT (ic), ic, TRUE);
2367 optype = operandType (IC_LEFT (ic));
2368 rtype = operandType (IC_RESULT (ic));
2370 /* if float then do float stuff */
2371 if (IS_FLOAT (optype))
2373 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2377 /* otherwise subtract from zero */
2378 size = AOP_SIZE (IC_LEFT (ic));
2383 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2384 needpula = pushRegIfUsed (hc08_reg_a);
2387 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2388 emitcode ("nega", "");
2389 hc08_freeReg (hc08_reg_a);
2390 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2391 SPEC_USIGN (operandType (IC_LEFT (ic))));
2392 pullOrFreeReg (hc08_reg_a, needpula);
2396 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2397 result = forceStackedAop (AOP (IC_RESULT (ic)));
2399 result = AOP (IC_RESULT (ic));
2401 needpula = pushRegIfUsed (hc08_reg_a);
2405 loadRegFromConst (hc08_reg_a, zero);
2406 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2407 storeRegToAop (hc08_reg_a, result, offset++);
2410 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2411 SPEC_USIGN (operandType (IC_LEFT (ic))));
2412 pullOrFreeReg (hc08_reg_a, needpula);
2414 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2415 freeAsmop (NULL, result, ic, TRUE);
2421 /* release the aops */
2422 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2423 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2426 /*-----------------------------------------------------------------*/
2427 /* saveRegisters - will look for a call and save the registers */
2428 /*-----------------------------------------------------------------*/
2430 saveRegisters (iCode * lic)
2437 for (ic = lic; ic; ic = ic->next)
2438 if (ic->op == CALL || ic->op == PCALL)
2443 fprintf (stderr, "found parameter push with no function call\n");
2447 /* if the registers have been saved already or don't need to be then
2451 if (IS_SYMOP(IC_LEFT(ic)) &&
2452 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2453 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2456 /* safe the registers in use at this time but skip the
2457 ones for the result */
2458 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2459 hc08_rUmaskForOp (IC_RESULT(ic)));
2462 for (i = 0; i < hc08_nRegs; i++)
2464 if (bitVectBitValue (rsave, i))
2465 pushReg ( hc08_regWithIdx (i), FALSE);
2469 /*-----------------------------------------------------------------*/
2470 /* unsaveRegisters - pop the pushed registers */
2471 /*-----------------------------------------------------------------*/
2473 unsaveRegisters (iCode * ic)
2478 /* restore the registers in use at this time but skip the
2479 ones for the result */
2480 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2481 hc08_rUmaskForOp (IC_RESULT(ic)));
2483 for (i = hc08_nRegs; i >= 0; i--)
2485 if (bitVectBitValue (rsave, i))
2486 pullReg ( hc08_regWithIdx (i));
2492 /*-----------------------------------------------------------------*/
2494 /*-----------------------------------------------------------------*/
2496 pushSide (operand * oper, int size)
2501 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2502 pushReg ( hc08_reg_a, TRUE);
2506 /*-----------------------------------------------------------------*/
2507 /* assignResultValue - */
2508 /*-----------------------------------------------------------------*/
2510 assignResultValue (operand * oper)
2512 int size = AOP_SIZE (oper);
2516 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2517 if (hc08_aop_pass[offset]->type == AOP_REG)
2518 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2525 /*-----------------------------------------------------------------*/
2526 /* genIpush - genrate code for pushing this gets a little complex */
2527 /*-----------------------------------------------------------------*/
2529 genIpush (iCode * ic)
2531 int size, offset = 0;
2534 D(emitcode ("; genIpush",""));
2536 /* if this is not a parm push : ie. it is spill push
2537 and spill push is always done on the local stack */
2541 /* and the item is spilt then do nothing */
2542 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2545 aopOp (IC_LEFT (ic), ic, FALSE);
2546 size = AOP_SIZE (IC_LEFT (ic));
2548 /* push it on the stack */
2551 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2552 pushReg ( hc08_reg_a, TRUE);
2558 /* this is a paramter push: in this case we call
2559 the routine to find the call and save those
2560 registers that need to be saved */
2563 /* then do the push */
2564 aopOp (IC_LEFT (ic), ic, FALSE);
2567 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2568 size = AOP_SIZE (IC_LEFT (ic));
2571 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2572 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2574 if ((size==2) && hc08_reg_hx->isFree)
2576 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2577 pushReg (hc08_reg_hx, TRUE);
2584 // printf("loading %d\n", offset);
2585 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2586 // printf("pushing \n");
2587 pushReg (hc08_reg_a, TRUE);
2591 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2594 /*-----------------------------------------------------------------*/
2595 /* genIpop - recover the registers: can happen only for spilling */
2596 /*-----------------------------------------------------------------*/
2598 genIpop (iCode * ic)
2602 D(emitcode ("; genIpop",""));
2604 /* if the temp was not pushed then */
2605 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2608 aopOp (IC_LEFT (ic), ic, FALSE);
2609 size = AOP_SIZE (IC_LEFT (ic));
2613 pullReg (hc08_reg_a);
2614 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2616 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2620 /*-----------------------------------------------------------------*/
2621 /* genSend - gen code for SEND */
2622 /*-----------------------------------------------------------------*/
2623 static void genSend(set *sendSet)
2627 for (sic = setFirstItem (sendSet); sic;
2628 sic = setNextItem (sendSet)) {
2629 int size, offset = 0;
2630 aopOp (IC_LEFT (sic), sic, FALSE);
2631 size = AOP_SIZE (IC_LEFT (sic));
2636 transferAopAop( AOP (IC_LEFT (sic)), offset,
2637 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2641 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2645 /*-----------------------------------------------------------------*/
2646 /* genCall - generates a call statement */
2647 /*-----------------------------------------------------------------*/
2649 genCall (iCode * ic)
2652 // bool restoreBank = FALSE;
2653 // bool swapBanks = FALSE;
2655 D(emitcode("; genCall",""));
2657 dtype = operandType (IC_LEFT (ic));
2658 /* if send set is not empty then assign */
2661 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2662 genSend(reverseSet(_G.sendSet));
2664 genSend(_G.sendSet);
2670 /* if caller saves & we have not saved then */
2676 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2677 OP_SYMBOL (IC_LEFT (ic))->rname :
2678 OP_SYMBOL (IC_LEFT (ic))->name));
2681 /* if we need assign a result value */
2682 if ((IS_ITEMP (IC_RESULT (ic)) &&
2683 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2684 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2685 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2686 IS_TRUE_SYMOP (IC_RESULT (ic)))
2690 aopOp (IC_RESULT (ic), ic, FALSE);
2693 assignResultValue (IC_RESULT (ic));
2695 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2698 /* adjust the stack for parameters if
2702 pullNull (ic->parmBytes);
2705 /* if we had saved some registers then unsave them */
2706 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2707 unsaveRegisters (ic);
2711 /*-----------------------------------------------------------------*/
2712 /* -10l - generates a call by pointer statement */
2713 /*-----------------------------------------------------------------*/
2715 genPcall (iCode * ic)
2718 symbol *rlbl = newiTempLabel (NULL);
2719 symbol *tlbl = newiTempLabel (NULL);
2720 // bool restoreBank=FALSE;
2721 // bool swapBanks = FALSE;
2723 D(emitcode("; genPCall",""));
2725 /* if caller saves & we have not saved then */
2729 /* if we are calling a not _naked function that is not using
2730 the same register bank then we need to save the
2731 destination registers on the stack */
2732 dtype = operandType (IC_LEFT (ic))->next;
2734 /* now push the calling address */
2735 emitBranch ("bsr", tlbl);
2736 emitBranch ("bra", rlbl);
2739 /* Push the function's address */
2740 aopOp (IC_LEFT (ic), ic, FALSE);
2741 pushSide (IC_LEFT (ic), FPTRSIZE);
2742 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2744 /* if send set is not empty the assign */
2747 genSend(reverseSet(_G.sendSet));
2753 emitcode ("rts", "");
2758 /* if we need assign a result value */
2759 if ((IS_ITEMP (IC_RESULT (ic)) &&
2760 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2761 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2762 IS_TRUE_SYMOP (IC_RESULT (ic)))
2766 aopOp (IC_RESULT (ic), ic, FALSE);
2769 assignResultValue (IC_RESULT (ic));
2771 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2774 /* adjust the stack for parameters if
2778 pullNull (ic->parmBytes);
2781 /* if we hade saved some registers then
2783 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2784 unsaveRegisters (ic);
2787 /*-----------------------------------------------------------------*/
2788 /* resultRemat - result is rematerializable */
2789 /*-----------------------------------------------------------------*/
2791 resultRemat (iCode * ic)
2793 if (SKIP_IC (ic) || ic->op == IFX)
2796 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2798 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2799 if (sym->remat && !POINTER_SET (ic))
2806 #if defined(__BORLANDC__) || defined(_MSC_VER)
2807 #define STRCASECMP stricmp
2809 #define STRCASECMP strcasecmp
2812 /*-----------------------------------------------------------------*/
2813 /* inExcludeList - return 1 if the string is in exclude Reg list */
2814 /*-----------------------------------------------------------------*/
2816 regsCmp(void *p1, void *p2)
2818 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2822 inExcludeList (char *s)
2824 const char *p = setFirstItem(options.excludeRegsSet);
2826 if (p == NULL || STRCASECMP(p, "none") == 0)
2830 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2833 /*-----------------------------------------------------------------*/
2834 /* genFunction - generated code for function entry */
2835 /*-----------------------------------------------------------------*/
2837 genFunction (iCode * ic)
2839 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2841 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2842 int stackAdjust = sym->stack;
2843 int accIsFree = sym->recvSize == 0;
2847 /* create the function header */
2848 emitcode (";", "-----------------------------------------");
2849 emitcode (";", " function %s", sym->name);
2850 emitcode (";", "-----------------------------------------");
2852 emitcode ("", "%s:", sym->rname);
2853 ftype = operandType (IC_LEFT (ic));
2857 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2859 if (IFFUNC_ISNAKED(ftype))
2861 emitcode(";", "naked function: no prologue.");
2865 /* if this is an interrupt service routine then
2867 if (IFFUNC_ISISR (sym->type))
2870 if (!inExcludeList ("h"))
2871 pushReg (hc08_reg_h, FALSE);
2874 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2875 /* before setting up the stack frame completely. */
2876 while (ric && ric->next && ric->next->op == RECEIVE)
2878 while (ric && IC_RESULT (ric))
2880 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2881 int rsymSize = rsym ? getSize(rsym->type) : 0;
2885 if (rsym && rsym->regType == REG_CND)
2887 if (rsym && (rsym->accuse || rsym->ruonly))
2889 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2890 rsym = rsym->usl.spillLoc;
2893 /* If the RECEIVE operand immediately spills to the first entry on the */
2894 /* stack, we can push it directly rather than use an sp relative store. */
2895 if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize)
2899 _G.current_iCode = ric;
2900 D(emitcode ("; genReceive",""));
2901 for (ofs=0; ofs < rsymSize; ofs++)
2903 regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
2904 pushReg (reg, TRUE);
2905 if (reg->rIdx == A_IDX)
2909 _G.current_iCode = ic;
2912 ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
2915 /* adjust the stack for the function */
2918 adjustStack (-stackAdjust);
2920 _G.stackOfs = sym->stack;
2923 /* if critical function then turn interrupts off */
2924 if (IFFUNC_ISCRITICAL (ftype))
2928 /* Function was passed parameters, so make sure A is preserved */
2929 pushReg (hc08_reg_a, FALSE);
2930 pushReg (hc08_reg_a, FALSE);
2931 emitcode ("tpa", "");
2932 emitcode ("sta", "2,s");
2933 emitcode ("sei", "");
2934 pullReg (hc08_reg_a);
2938 /* No passed parameters, so A can be freely modified */
2939 emitcode ("tpa", "");
2940 pushReg (hc08_reg_a, TRUE);
2941 emitcode ("sei", "");
2947 /*-----------------------------------------------------------------*/
2948 /* genEndFunction - generates epilogue for functions */
2949 /*-----------------------------------------------------------------*/
2951 genEndFunction (iCode * ic)
2953 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2955 if (IFFUNC_ISNAKED(sym->type))
2957 emitcode(";", "naked function: no epilogue.");
2958 if (options.debug && currFunc)
2959 debugFile->writeEndFunction (currFunc, ic, 0);
2963 if (IFFUNC_ISCRITICAL (sym->type))
2965 if (!IS_VOID(sym->type->next))
2967 /* Function has return value, so make sure A is preserved */
2968 pushReg (hc08_reg_a, FALSE);
2969 emitcode ("lda", "2,s");
2970 emitcode ("tap", "");
2971 pullReg (hc08_reg_a);
2976 /* Function returns void, so A can be freely modified */
2977 pullReg (hc08_reg_a);
2978 emitcode ("tap", "");
2982 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2988 _G.stackPushes += sym->stack;
2989 adjustStack (sym->stack);
2993 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2997 if (IFFUNC_ISISR (sym->type))
3000 if (!inExcludeList ("h"))
3001 pullReg (hc08_reg_h);
3004 /* if debug then send end of function */
3005 if (options.debug && currFunc)
3007 debugFile->writeEndFunction (currFunc, ic, 1);
3010 emitcode ("rti", "");
3014 if (IFFUNC_CALLEESAVES(sym->type))
3018 /* if any registers used */
3021 /* save the registers used */
3022 for (i = sym->regsUsed->size; i >= 0; i--)
3024 if (bitVectBitValue (sym->regsUsed, i) ||
3025 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3026 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3032 /* if debug then send end of function */
3033 if (options.debug && currFunc)
3035 debugFile->writeEndFunction (currFunc, ic, 1);
3038 emitcode ("rts", "");
3043 /*-----------------------------------------------------------------*/
3044 /* genRet - generate code for return statement */
3045 /*-----------------------------------------------------------------*/
3049 int size, offset = 0;
3052 D(emitcode ("; genRet",""));
3054 /* if we have no return value then
3055 just generate the "ret" */
3059 /* we have something to return then
3060 move the return value into place */
3061 aopOp (IC_LEFT (ic), ic, FALSE);
3062 size = AOP_SIZE (IC_LEFT (ic));
3068 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3075 /* 4 byte return: store value in the global return variable */
3079 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3080 STA (fReturn2[offset--], FALSE);
3081 hc08_freeReg (hc08_reg_a);
3085 /* 2 byte return: store value in x:a */
3086 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3087 hc08_freeReg (hc08_reg_xa);
3090 /* 1 byte return: store value in a */
3091 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3092 hc08_freeReg (hc08_reg_a);
3097 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3100 /* generate a jump to the return label
3101 if the next is not the return statement */
3102 if (!(ic->next && ic->next->op == LABEL &&
3103 IC_LABEL (ic->next) == returnLabel))
3105 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3109 /*-----------------------------------------------------------------*/
3110 /* genLabel - generates a label */
3111 /*-----------------------------------------------------------------*/
3113 genLabel (iCode * ic)
3118 /* For the high level labels we cannot depend on any */
3119 /* register's contents. Amnesia time. */
3120 for (i=A_IDX;i<=XA_IDX;i++)
3122 reg = hc08_regWithIdx(i);
3127 /* special case never generate */
3128 if (IC_LABEL (ic) == entryLabel)
3131 debugFile->writeLabel(IC_LABEL (ic), ic);
3133 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3137 /*-----------------------------------------------------------------*/
3138 /* genGoto - generates a jmp */
3139 /*-----------------------------------------------------------------*/
3141 genGoto (iCode * ic)
3143 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3147 /*-----------------------------------------------------------------*/
3148 /* findLabelBackwards: walks back through the iCode chain looking */
3149 /* for the given label. Returns number of iCode instructions */
3150 /* between that label and given ic. */
3151 /* Returns zero if label not found. */
3152 /*-----------------------------------------------------------------*/
3154 findLabelBackwards (iCode * ic, int key)
3163 /* If we have any pushes or pops, we cannot predict the distance.
3164 I don't like this at all, this should be dealt with in the
3166 if (ic->op == IPUSH || ic->op == IPOP) {
3170 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3180 /*-----------------------------------------------------------------*/
3181 /* genPlusIncr :- does addition with increment if possible */
3182 /*-----------------------------------------------------------------*/
3184 genPlusIncr (iCode * ic)
3192 unsigned int size = getDataSize (IC_RESULT (ic));
3193 unsigned int offset;
3194 symbol *tlbl = NULL;
3196 left = IC_LEFT (ic);
3197 result = IC_RESULT (ic);
3199 /* will try to generate an increment */
3200 /* if the right side is not a literal
3202 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3205 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3207 D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3209 if ((IS_AOP_HX (AOP (left)) ||
3210 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3212 && (icount>=-128) && (icount<=127) && (size==2))
3214 if (!IS_AOP_HX (AOP (left)))
3216 needpulx = pushRegIfUsed (hc08_reg_x);
3217 needpulh = pushRegIfUsed (hc08_reg_h);
3224 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3225 emitcode ("aix","#%d", icount);
3226 hc08_dirtyReg (hc08_reg_hx, FALSE);
3227 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3228 pullOrFreeReg (hc08_reg_h, needpulh);
3229 pullOrFreeReg (hc08_reg_x, needpulx);
3233 D(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3234 sameRegs (AOP (left), AOP (result))));
3236 if ((icount > 255) || (icount<0))
3239 if (!sameRegs (AOP (left), AOP (result)))
3242 D(emitcode ("; genPlusIncr",""));
3245 tlbl = newiTempLabel (NULL);
3250 rmwWithAop ("inc", AOP (result), 0);
3252 emitBranch ("bne", tlbl);
3256 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3257 needpula = pushRegIfUsed (hc08_reg_a);
3260 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3261 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3262 hc08_useReg (hc08_reg_a);
3263 storeRegToAop (hc08_reg_a, AOP (result), 0);
3264 hc08_freeReg (hc08_reg_a);
3266 emitBranch ("bcc", tlbl);
3268 for (offset=1; offset<size; offset++)
3270 rmwWithAop ("inc", AOP (result), offset);
3271 if ((offset+1)<size)
3272 emitBranch ("bne", tlbl);
3278 pullOrFreeReg (hc08_reg_a, needpula);
3285 /*-----------------------------------------------------------------*/
3286 /* genPlus - generates code for addition */
3287 /*-----------------------------------------------------------------*/
3289 genPlus (iCode * ic)
3291 int size, offset = 0;
3293 asmop *leftOp, *rightOp;
3295 /* special cases :- */
3297 D(emitcode ("; genPlus",""));
3299 aopOp (IC_LEFT (ic), ic, FALSE);
3300 aopOp (IC_RIGHT (ic), ic, FALSE);
3301 aopOp (IC_RESULT (ic), ic, TRUE);
3303 /* we want registers on the left and literals on the right */
3304 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3305 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3307 operand *t = IC_RIGHT (ic);
3308 IC_RIGHT (ic) = IC_LEFT (ic);
3313 /* if I can do an increment instead
3314 of add then GOOD for ME */
3315 if (genPlusIncr (ic) == TRUE)
3318 D(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3319 D(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3320 D(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3322 size = getDataSize (IC_RESULT (ic));
3324 leftOp = AOP(IC_LEFT(ic));
3325 rightOp = AOP(IC_RIGHT(ic));
3331 loadRegFromAop (hc08_reg_a, leftOp, offset);
3332 accopWithAop(add, rightOp, offset);
3333 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3334 hc08_freeReg (hc08_reg_a);
3335 add = "adc"; /* further adds must propagate carry */
3339 // adjustArithmeticResult (ic);
3342 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3343 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3344 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3347 /*-----------------------------------------------------------------*/
3348 /* genMinusDec :- does subtraction with decrement if possible */
3349 /*-----------------------------------------------------------------*/
3351 genMinusDec (iCode * ic)
3353 unsigned int icount;
3358 unsigned int size = getDataSize (IC_RESULT (ic));
3362 left = IC_LEFT (ic);
3363 result = IC_RESULT (ic);
3365 /* will try to generate an increment */
3366 /* if the right side is not a literal
3368 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3371 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3373 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3374 && (icount>=-127) && (icount<=128) && (size==2))
3376 if (!IS_AOP_HX (AOP (left)))
3378 needpulx = pushRegIfUsed (hc08_reg_x);
3379 needpulh = pushRegIfUsed (hc08_reg_h);
3386 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3387 emitcode ("aix","#%d", -icount);
3388 hc08_dirtyReg (hc08_reg_hx, FALSE);
3389 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3390 pullOrFreeReg (hc08_reg_h, needpulh);
3391 pullOrFreeReg (hc08_reg_x, needpulx);
3395 if ((icount > 1) || (icount<0))
3398 if (!sameRegs (AOP (left), AOP (result)))
3404 D(emitcode ("; genMinusDec",""));
3406 rmwWithAop ("dec", AOP (result), 0);
3411 /*-----------------------------------------------------------------*/
3412 /* addSign - complete with sign */
3413 /*-----------------------------------------------------------------*/
3415 addSign (operand * result, int offset, int sign)
3417 int size = (getDataSize (result) - offset);
3422 emitcode ("rola", "");
3423 emitcode ("clra", "");
3424 emitcode ("sbc", zero);
3426 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3430 storeConstToAop (zero, AOP (result), offset++);
3435 /*-----------------------------------------------------------------*/
3436 /* genMinus - generates code for subtraction */
3437 /*-----------------------------------------------------------------*/
3439 genMinus (iCode * ic)
3442 int size, offset = 0;
3444 asmop *leftOp, *rightOp;
3446 D(emitcode ("; genMinus",""));
3448 aopOp (IC_LEFT (ic), ic, FALSE);
3449 aopOp (IC_RIGHT (ic), ic, FALSE);
3450 aopOp (IC_RESULT (ic), ic, TRUE);
3452 /* special cases :- */
3453 /* if I can do an decrement instead
3454 of subtract then GOOD for ME */
3455 if (genMinusDec (ic) == TRUE)
3458 size = getDataSize (IC_RESULT (ic));
3461 leftOp = AOP(IC_LEFT(ic));
3462 rightOp = AOP(IC_RIGHT(ic));
3466 if (IS_AOP_A (rightOp))
3468 loadRegFromAop ( hc08_reg_a, rightOp, offset);
3469 accopWithAop (sub, leftOp, offset);
3470 accopWithMisc ("nega", "");
3471 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3477 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3478 accopWithAop (sub, rightOp, offset);
3479 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3484 // adjustArithmeticResult (ic);
3487 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3488 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3489 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3494 /*-----------------------------------------------------------------*/
3495 /* genMultOneByte : 8*8=8/16 bit multiplication */
3496 /*-----------------------------------------------------------------*/
3498 genMultOneByte (operand * left,
3502 /* sym_link *opetype = operandType (result); */
3503 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3504 int size=AOP_SIZE(result);
3505 bool negLiteral = FALSE;
3506 bool lUnsigned, rUnsigned;
3508 D(emitcode ("; genMultOneByte",""));
3510 if (size<1 || size>2) {
3511 // this should never happen
3512 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3513 AOP_SIZE(result), __FILE__, lineno);
3517 /* (if two literals: the value is computed before) */
3518 /* if one literal, literal on the right */
3519 if (AOP_TYPE (left) == AOP_LIT)
3525 /* if an operand is in A, make sure it is on the left */
3526 if (IS_AOP_A (AOP (right)))
3533 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3534 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3536 /* lUnsigned rUnsigned negLiteral negate case */
3537 /* false false false odd 3 */
3538 /* false false true even 3 */
3539 /* false true false odd 3 */
3540 /* false true true impossible */
3541 /* true false false odd 3 */
3542 /* true false true always 2 */
3543 /* true true false never 1 */
3544 /* true true true impossible */
3548 || (lUnsigned && rUnsigned))
3550 // just an unsigned 8*8=8/16 multiply
3551 //D(emitcode (";","unsigned"));
3553 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3554 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3555 emitcode ("mul", "");
3556 hc08_dirtyReg (hc08_reg_xa, FALSE);
3557 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3558 hc08_freeReg (hc08_reg_xa);
3563 // we have to do a signed multiply
3566 /* left unsigned, right signed literal -- literal determines sign handling */
3567 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3569 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3571 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3573 emitcode ("ldx", "#0x%02x", -val);
3575 emitcode ("ldx", "#0x%02x", val);
3577 emitcode ("mul", "");
3581 rmwWithReg ("neg", hc08_reg_a);
3582 tlbl4 = newiTempLabel (NULL);
3583 emitBranch ("bcc", tlbl4);
3584 rmwWithReg ("inc", hc08_reg_x);
3586 rmwWithReg ("neg", hc08_reg_x);
3589 hc08_dirtyReg (hc08_reg_xa, FALSE);
3590 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3591 hc08_freeReg (hc08_reg_xa);
3598 emitcode ("clr", "1,s");
3600 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3603 tlbl1 = newiTempLabel (NULL);
3604 emitcode ("tsta","");
3605 emitBranch ("bpl", tlbl1);
3606 emitcode ("inc", "1,s");
3607 rmwWithReg ("neg", hc08_reg_a);
3611 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3613 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3614 /* AND literal negative */
3616 emitcode ("ldx", "#0x%02x", -val);
3619 emitcode ("ldx", "#0x%02x", val);
3621 hc08_useReg (hc08_reg_x);
3625 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3628 tlbl2 = newiTempLabel (NULL);
3629 emitcode ("tstx", "");
3630 emitBranch ("bpl", tlbl2);
3631 emitcode ("inc", "1,s");
3632 rmwWithReg ("neg", hc08_reg_x);
3637 emitcode ("mul", "");
3638 hc08_dirtyReg (hc08_reg_xa, FALSE);
3640 tlbl3 = newiTempLabel (NULL);
3641 emitcode ("dec", "1,s");
3642 if (!lUnsigned && !rUnsigned && negLiteral)
3643 emitBranch ("beq", tlbl3);
3645 emitBranch ("bne", tlbl3);
3647 rmwWithReg ("neg", hc08_reg_a);
3648 tlbl4 = newiTempLabel (NULL);
3649 emitBranch ("bcc", tlbl4);
3650 rmwWithReg ("inc", hc08_reg_x);
3652 rmwWithReg ("neg", hc08_reg_x);
3656 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3657 hc08_freeReg (hc08_reg_xa);
3661 /*-----------------------------------------------------------------*/
3662 /* genMult - generates code for multiplication */
3663 /*-----------------------------------------------------------------*/
3665 genMult (iCode * ic)
3667 operand *left = IC_LEFT (ic);
3668 operand *right = IC_RIGHT (ic);
3669 operand *result = IC_RESULT (ic);
3671 D(emitcode ("; genMult",""));
3673 /* assign the amsops */
3674 aopOp (left, ic, FALSE);
3675 aopOp (right, ic, FALSE);
3676 aopOp (result, ic, TRUE);
3678 /* special cases first */
3679 /* if both are of size == 1 */
3680 // if (getSize(operandType(left)) == 1 &&
3681 // getSize(operandType(right)) == 1)
3682 if (AOP_SIZE (left) == 1 &&
3683 AOP_SIZE (right) == 1)
3685 genMultOneByte (left, right, result);
3689 /* should have been converted to function call */
3690 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3691 getSize(OP_SYMBOL(right)->type));
3692 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3697 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3698 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3699 freeAsmop (result, NULL, ic, TRUE);
3702 /*-----------------------------------------------------------------*/
3703 /* genDivOneByte : 8 bit division */
3704 /*-----------------------------------------------------------------*/
3706 genDivOneByte (operand * left,
3710 symbol *tlbl1, *tlbl2, *tlbl3;
3713 bool lUnsigned, rUnsigned;
3714 bool runtimeSign, compiletimeSign;
3716 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3717 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3719 D(emitcode ("; genDivOneByte",""));
3721 size = AOP_SIZE (result);
3722 /* signed or unsigned */
3723 if (lUnsigned && rUnsigned)
3725 /* unsigned is easy */
3726 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3727 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3728 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3729 emitcode ("div", "");
3730 hc08_dirtyReg (hc08_reg_a, FALSE);
3731 hc08_dirtyReg (hc08_reg_h, FALSE);
3732 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3733 hc08_freeReg (hc08_reg_a);
3734 hc08_freeReg (hc08_reg_x);
3735 hc08_freeReg (hc08_reg_h);
3739 /* signed is a little bit more difficult */
3741 /* now sign adjust for both left & right */
3743 /* let's see what's needed: */
3744 /* apply negative sign during runtime */
3745 runtimeSign = FALSE;
3746 /* negative sign from literals */
3747 compiletimeSign = FALSE;
3751 if (AOP_TYPE(left) == AOP_LIT)
3753 /* signed literal */
3754 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3756 compiletimeSign = TRUE;
3759 /* signed but not literal */
3765 if (AOP_TYPE(right) == AOP_LIT)
3767 /* signed literal */
3768 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3770 compiletimeSign ^= TRUE;
3773 /* signed but not literal */
3777 /* initialize the runtime sign */
3780 if (compiletimeSign)
3781 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3783 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3784 pushReg (hc08_reg_x, TRUE);
3787 /* save the signs of the operands */
3788 if (AOP_TYPE(right) == AOP_LIT)
3790 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3792 if (!rUnsigned && val < 0)
3793 emitcode ("ldx", "#0x%02x", -val);
3795 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3797 else /* ! literal */
3799 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3802 tlbl1 = newiTempLabel (NULL);
3803 emitcode ("tstx", "");
3804 emitBranch ("bpl", tlbl1);
3805 emitcode ("inc", "1,s");
3806 rmwWithReg ("neg", hc08_reg_x);
3811 if (AOP_TYPE(left) == AOP_LIT)
3813 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3815 if (!lUnsigned && val < 0)
3816 emitcode ("lda", "#0x%02x", -val);
3818 emitcode ("lda", "#0x%02x", (unsigned char) val);
3820 else /* ! literal */
3822 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3825 tlbl2 = newiTempLabel (NULL);
3826 emitcode ("tsta", "");
3827 emitBranch ("bpl", tlbl2);
3828 emitcode ("inc", "1,s");
3829 rmwWithReg ("neg", hc08_reg_a);
3834 loadRegFromConst (hc08_reg_h, zero);
3835 emitcode ("div", "");
3836 hc08_dirtyReg (hc08_reg_x, FALSE);
3837 hc08_dirtyReg (hc08_reg_a, FALSE);
3838 hc08_dirtyReg (hc08_reg_h, FALSE);
3840 if (runtimeSign || compiletimeSign)
3842 tlbl3 = newiTempLabel (NULL);
3845 pullReg (hc08_reg_x);
3846 rmwWithReg ("lsr", hc08_reg_x);
3847 rmwWithReg ("ror", hc08_reg_x);
3848 emitBranch ("bpl", tlbl3);
3851 rmwWithReg ("neg", hc08_reg_a);
3855 storeRegToAop (hc08_reg_a, AOP (result), 0);
3859 /* msb is 0x00 or 0xff depending on the sign */
3862 rmwWithReg ("lsl", hc08_reg_x);
3863 emitcode ("clra", "");
3864 emitcode ("sbc", "#0");
3866 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3868 else /* compiletimeSign */
3870 storeConstToAop ("#0xff", AOP (result), ++offset);
3875 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3878 hc08_freeReg (hc08_reg_a);
3879 hc08_freeReg (hc08_reg_x);
3880 hc08_freeReg (hc08_reg_h);
3883 /*-----------------------------------------------------------------*/
3884 /* genDiv - generates code for division */
3885 /*-----------------------------------------------------------------*/
3889 operand *left = IC_LEFT (ic);
3890 operand *right = IC_RIGHT (ic);
3891 operand *result = IC_RESULT (ic);
3893 D(emitcode ("; genDiv",""));
3895 /* assign the amsops */
3896 aopOp (left, ic, FALSE);
3897 aopOp (right, ic, FALSE);
3898 aopOp (result, ic, TRUE);
3900 /* special cases first */
3901 /* if both are of size == 1 */
3902 if (AOP_SIZE (left) <= 2 &&
3903 AOP_SIZE (right) == 1)
3905 genDivOneByte (left, right, result);
3909 /* should have been converted to function call */
3912 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3913 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3914 freeAsmop (result, NULL, ic, TRUE);
3917 /*-----------------------------------------------------------------*/
3918 /* genModOneByte : 8 bit modulus */
3919 /*-----------------------------------------------------------------*/
3921 genModOneByte (operand * left,
3925 symbol *tlbl1, *tlbl2, *tlbl3;
3928 bool lUnsigned, rUnsigned;
3929 bool runtimeSign, compiletimeSign;
3931 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3932 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3934 D(emitcode ("; genModOneByte",""));
3936 size = AOP_SIZE (result);
3938 if (lUnsigned && rUnsigned)
3940 /* unsigned is easy */
3941 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3942 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3943 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3944 emitcode ("div", "");
3945 hc08_freeReg (hc08_reg_a);
3946 hc08_freeReg (hc08_reg_x);
3947 hc08_dirtyReg (hc08_reg_h, FALSE);
3948 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3949 hc08_freeReg (hc08_reg_h);
3953 /* signed is a little bit more difficult */
3955 if (AOP_TYPE(right) == AOP_LIT)
3957 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3959 if (!rUnsigned && val < 0)
3960 emitcode ("ldx", "#0x%02x", -val);
3962 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3964 else /* ! literal */
3966 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3969 tlbl1 = newiTempLabel (NULL);
3970 emitcode ("tstx", "");
3971 emitBranch ("bpl", tlbl1);
3972 rmwWithReg ("neg", hc08_reg_x);
3977 /* let's see what's needed: */
3978 /* apply negative sign during runtime */
3979 runtimeSign = FALSE;
3980 /* negative sign from literals */
3981 compiletimeSign = FALSE;
3983 /* sign adjust left side */
3984 if (AOP_TYPE(left) == AOP_LIT)
3986 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3988 if (!lUnsigned && val < 0)
3990 compiletimeSign = TRUE; /* set sign flag */
3991 emitcode ("lda", "#0x%02x", -val);
3994 emitcode ("lda", "#0x%02x", (unsigned char) val);
3996 else /* ! literal */
3999 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4004 emitcode ("clr", "1,s");
4006 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4007 tlbl2 = newiTempLabel (NULL);
4008 emitcode ("tsta", "");
4009 emitBranch ("bpl", tlbl2);
4010 emitcode ("inc", "1,s");
4011 rmwWithReg ("neg", hc08_reg_a);
4016 loadRegFromConst (hc08_reg_h, zero);
4017 emitcode ("div", "");
4018 hc08_freeReg (hc08_reg_a);
4019 hc08_freeReg (hc08_reg_x);
4020 hc08_dirtyReg (hc08_reg_h, FALSE);
4022 if (runtimeSign || compiletimeSign)
4024 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4025 tlbl3 = newiTempLabel (NULL);
4028 pullReg (hc08_reg_x);
4029 rmwWithReg ("lsr", hc08_reg_x);
4030 rmwWithReg ("ror", hc08_reg_x);
4031 emitBranch ("bpl", tlbl3);
4034 rmwWithReg ("neg", hc08_reg_a);
4038 storeRegToAop (hc08_reg_a, AOP (result), 0);
4042 /* msb is 0x00 or 0xff depending on the sign */
4045 rmwWithReg ("lsl", hc08_reg_x);
4046 emitcode ("clra", "");
4047 emitcode ("sbc", "#0");
4049 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4051 else /* compiletimeSign */
4053 storeConstToAop ("#0xff", AOP (result), ++offset);
4058 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4061 hc08_freeReg (hc08_reg_a);
4062 hc08_freeReg (hc08_reg_x);
4063 hc08_freeReg (hc08_reg_h);
4066 /*-----------------------------------------------------------------*/
4067 /* genMod - generates code for division */
4068 /*-----------------------------------------------------------------*/
4072 operand *left = IC_LEFT (ic);
4073 operand *right = IC_RIGHT (ic);
4074 operand *result = IC_RESULT (ic);
4076 D(emitcode ("; genMod",""));
4078 /* assign the amsops */
4079 aopOp (left, ic, FALSE);
4080 aopOp (right, ic, FALSE);
4081 aopOp (result, ic, TRUE);
4083 /* special cases first */
4084 /* if both are of size == 1 */
4085 if (AOP_SIZE (left) <= 2 &&
4086 AOP_SIZE (right) == 1)
4088 genModOneByte (left, right, result);
4092 /* should have been converted to function call */
4096 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4097 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4098 freeAsmop (result, NULL, ic, TRUE);
4101 /*-----------------------------------------------------------------*/
4102 /* genIfxJump :- will create a jump depending on the ifx */
4103 /*-----------------------------------------------------------------*/
4105 genIfxJump (iCode * ic, char *jval)
4108 symbol *tlbl = newiTempLabel (NULL);
4111 D(emitcode ("; genIfxJump",""));
4113 /* if true label then we jump if condition
4117 jlbl = IC_TRUE (ic);
4118 if (!strcmp (jval, "a"))
4120 else if (!strcmp (jval, "c"))
4127 /* false label is present */
4128 jlbl = IC_FALSE (ic);
4129 if (!strcmp (jval, "a"))
4131 else if (!strcmp (jval, "c"))
4136 emitBranch (inst, tlbl);
4137 emitBranch ("jmp", jlbl);
4140 /* mark the icode as generated */
4145 /*-----------------------------------------------------------------*/
4146 /* exchangedCmp : returns the opcode need if the two operands are */
4147 /* exchanged in a comparison */
4148 /*-----------------------------------------------------------------*/
4150 exchangedCmp (int opcode)
4167 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4168 "opcode not a comparison");
4170 return EQ_OP; /* shouldn't happen, but need to return something */
4173 /*------------------------------------------------------------------*/
4174 /* negatedCmp : returns the equivalent opcode for when a comparison */
4176 /*------------------------------------------------------------------*/
4178 negatedCmp (int opcode)
4195 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4196 "opcode not a comparison");
4198 return EQ_OP; /* shouldn't happen, but need to return something */
4201 /* compile only if the debugging macro D is enabled */
4204 nameCmp (int opcode)
4226 /*------------------------------------------------------------------*/
4227 /* branchInstCmp : returns the conditional branch instruction that */
4228 /* will branch if the comparison is true */
4229 /*------------------------------------------------------------------*/
4231 branchInstCmp (int opcode, int sign)
4239 return "bcs"; /* same as blo */
4254 return "bcc"; /* same as bhs */
4260 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4261 "opcode not a comparison");
4267 /*------------------------------------------------------------------*/
4268 /* genCmp :- greater or less than (and maybe with equal) comparison */
4269 /*------------------------------------------------------------------*/
4271 genCmp (iCode * ic, iCode * ifx)
4273 operand *left, *right, *result;
4274 sym_link *letype, *retype;
4276 int size, offset = 0;
4277 unsigned long lit = 0L;
4279 symbol *jlbl = NULL;
4283 D(emitcode ("; genCmp", "(%s)",nameCmp (opcode)));
4285 result = IC_RESULT (ic);
4286 left = IC_LEFT (ic);
4287 right = IC_RIGHT (ic);
4289 letype = getSpec (operandType (left));
4290 retype = getSpec (operandType (right));
4291 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4292 /* assign the amsops */
4293 aopOp (left, ic, FALSE);
4294 aopOp (right, ic, FALSE);
4295 aopOp (result, ic, TRUE);
4297 /* need register operand on left, prefer literal operand on right */
4298 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4300 operand *temp = left;
4303 opcode = exchangedCmp (opcode);
4310 jlbl = IC_TRUE (ifx);
4311 opcode = negatedCmp (opcode);
4315 /* false label is present */
4316 jlbl = IC_FALSE (ifx);
4320 size = max (AOP_SIZE (left), AOP_SIZE (right));
4323 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4324 && ((AOP_TYPE (right) == AOP_LIT) ||
4325 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4326 && hc08_reg_hx->isFree)
4328 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4329 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4330 hc08_freeReg (hc08_reg_hx);
4341 /* These conditions depend on the Z flag bit, but Z is */
4342 /* only valid for the last byte of the comparison, not */
4343 /* the whole value. So exchange the operands to get a */
4344 /* comparison that doesn't depend on Z. (This is safe */
4345 /* to do here since ralloc won't assign multi-byte */
4346 /* operands to registers for comparisons) */
4347 if ((opcode == '>') || (opcode == LE_OP))
4349 operand *temp = left;
4352 opcode = exchangedCmp (opcode);
4355 if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
4357 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4358 while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
4367 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4368 accopWithAop (sub, AOP (right), offset);
4369 hc08_freeReg (hc08_reg_a);
4374 freeAsmop (right, NULL, ic, FALSE);
4375 freeAsmop (left, NULL, ic, FALSE);
4379 symbol *tlbl = newiTempLabel (NULL);
4382 freeAsmop (result, NULL, ic, TRUE);
4384 inst = branchInstCmp (opcode, sign);
4385 emitBranch (inst, tlbl);
4386 emitBranch ("jmp", jlbl);
4389 /* mark the icode as generated */
4394 symbol *tlbl1 = newiTempLabel (NULL);
4395 symbol *tlbl2 = newiTempLabel (NULL);
4397 emitBranch (branchInstCmp (opcode, sign), tlbl1);
4398 loadRegFromConst (hc08_reg_a, zero);
4399 emitBranch ("bra", tlbl2);
4401 loadRegFromConst (hc08_reg_a, one);
4403 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4404 freeAsmop (result, NULL, ic, TRUE);
4409 /*-----------------------------------------------------------------*/
4410 /* genCmpEQorNE - equal or not equal comparison */
4411 /*-----------------------------------------------------------------*/
4413 genCmpEQorNE (iCode * ic, iCode * ifx)
4415 operand *left, *right, *result;
4416 sym_link *letype, *retype;
4418 int size, offset = 0;
4420 symbol *jlbl = NULL;
4421 symbol *tlbl_NE = NULL;
4422 symbol *tlbl_EQ = NULL;
4426 D(emitcode ("; genCmpEQorNE", "(%s)",nameCmp (opcode)));
4428 result = IC_RESULT (ic);
4429 left = IC_LEFT (ic);
4430 right = IC_RIGHT (ic);
4432 letype = getSpec (operandType (left));
4433 retype = getSpec (operandType (right));
4434 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4435 /* assign the amsops */
4436 aopOp (left, ic, FALSE);
4437 aopOp (right, ic, FALSE);
4438 aopOp (result, ic, TRUE);
4440 /* need register operand on left, prefer literal operand on right */
4441 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4443 operand *temp = left;
4446 opcode = exchangedCmp (opcode);
4453 jlbl = IC_TRUE (ifx);
4454 opcode = negatedCmp (opcode);
4458 /* false label is present */
4459 jlbl = IC_FALSE (ifx);
4463 size = max (AOP_SIZE (left), AOP_SIZE (right));
4466 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4467 && ((AOP_TYPE (right) == AOP_LIT) ||
4468 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4469 && hc08_reg_hx->isFree)
4471 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4472 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4473 hc08_freeReg (hc08_reg_hx);
4481 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4482 accopWithAop (sub, AOP (right), offset);
4486 tlbl_NE = newiTempLabel (NULL);
4487 emitBranch ("bne", tlbl_NE);
4489 hc08_freeReg (hc08_reg_a);
4493 freeAsmop (right, NULL, ic, FALSE);
4494 freeAsmop (left, NULL, ic, FALSE);
4498 freeAsmop (result, NULL, ic, TRUE);
4500 if (opcode == EQ_OP)
4503 tlbl_EQ = newiTempLabel (NULL);
4504 emitBranch ("beq", tlbl_EQ);
4506 emitLabel (tlbl_NE);
4507 emitBranch ("jmp", jlbl);
4508 emitLabel (tlbl_EQ);
4513 tlbl_NE = newiTempLabel (NULL);
4514 emitBranch ("bne", tlbl_NE);
4515 emitBranch ("jmp", jlbl);
4516 emitLabel (tlbl_NE);
4519 /* mark the icode as generated */
4524 symbol *tlbl = newiTempLabel (NULL);
4526 if (opcode == EQ_OP)
4529 tlbl_EQ = newiTempLabel (NULL);
4530 emitBranch ("beq", tlbl_EQ);
4532 emitLabel (tlbl_NE);
4533 loadRegFromConst (hc08_reg_a, zero);
4534 emitBranch ("bra", tlbl);
4535 emitLabel (tlbl_EQ);
4536 loadRegFromConst (hc08_reg_a, one);
4541 tlbl_NE = newiTempLabel (NULL);
4542 emitBranch ("bne", tlbl_NE);
4543 loadRegFromConst (hc08_reg_a, zero);
4544 emitBranch ("bra", tlbl);
4545 emitLabel (tlbl_NE);
4546 loadRegFromConst (hc08_reg_a, one);
4550 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4551 freeAsmop (result, NULL, ic, TRUE);
4557 /*-----------------------------------------------------------------*/
4558 /* ifxForOp - returns the icode containing the ifx for operand */
4559 /*-----------------------------------------------------------------*/
4561 ifxForOp (operand * op, iCode * ic)
4563 /* if true symbol then needs to be assigned */
4564 if (IS_TRUE_SYMOP (op))
4567 /* if this has register type condition and
4568 the next instruction is ifx with the same operand
4569 and live to of the operand is upto the ifx only then */
4571 ic->next->op == IFX &&
4572 IC_COND (ic->next)->key == op->key &&
4573 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4580 genPointerGetSetOfs (iCode *ic)
4582 iCode *lic = ic->next;
4588 /* Make sure we have a next iCode */
4589 D(emitcode("","; checking lic"));
4593 /* Make sure the result of the addition is an iCode */
4594 D(emitcode("","; checking IS_ITEMP"));
4595 if (!IS_ITEMP (IC_RESULT (ic)))
4598 /* Make sure the next iCode is a pointer set or get */
4599 pset = POINTER_SET(lic);
4600 pget = POINTER_GET(lic);
4601 D(emitcode("","; pset=%d, pget=%d",pset,pget));
4605 /* Make sure this is the only use of the pointer */
4606 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4609 D(emitcode("", "; checking pset operandsEqu"));
4610 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4613 D(emitcode("", "; checking pget operandsEqu"));
4614 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4617 D(emitcode("", "; checking IS_SYMOP"));
4618 if (!IS_SYMOP (IC_LEFT (ic)))
4621 D(emitcode("", "; checking !IS_TRUE_SYMOP"));
4622 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4625 sym = OP_SYMBOL (IC_LEFT (ic));
4627 D(emitcode("", "; checking remat"));
4634 D(emitcode ("; genPointerGetOfs",""));
4635 aopOp (IC_LEFT(ic), ic, FALSE);
4636 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4637 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4639 aopOp (IC_RIGHT(ic), ic, FALSE);
4640 aopOp (IC_RESULT(lic), lic, FALSE);
4642 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4644 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4646 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4647 loadRegFromConst (hc08_reg_h, zero);
4651 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4652 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4653 emitcode ("rola","");
4654 emitcode ("clra","");
4655 emitcode ("sbc", "#0");
4656 hc08_useReg (hc08_reg_a);
4657 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4661 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4662 size = AOP_SIZE (IC_RESULT(lic));
4663 derefaop->size = size;
4667 emitcode ("lda", "%s,x",
4668 aopAdrStr (derefaop, size, TRUE));
4669 hc08_useReg (hc08_reg_a);
4670 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
4671 hc08_freeReg (hc08_reg_a);
4675 hc08_freeReg (hc08_reg_hx);
4677 freeAsmop (NULL, derefaop, ic, TRUE);
4678 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4679 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4686 D(emitcode ("; genPointerSetOfs",""));
4687 aopOp (IC_LEFT(ic), ic, FALSE);
4688 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4689 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4691 aopOp (IC_RIGHT(ic), ic, FALSE);
4692 aopOp (IC_RIGHT(lic), lic, FALSE);
4694 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4696 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4698 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4699 loadRegFromConst (hc08_reg_h, zero);
4703 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4704 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4705 emitcode ("rola","");
4706 emitcode ("clra","");
4707 emitcode ("sbc", "#0");
4708 hc08_useReg (hc08_reg_a);
4709 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4713 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4714 size = AOP_SIZE (IC_RIGHT(lic));
4715 derefaop->size = size;
4719 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
4720 emitcode ("sta", "%s,x",
4721 aopAdrStr (derefaop, size, TRUE));
4722 hc08_freeReg (hc08_reg_a);
4726 hc08_freeReg (hc08_reg_hx);
4728 freeAsmop (NULL, derefaop, ic, TRUE);
4729 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4730 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4739 /*-----------------------------------------------------------------*/
4740 /* hasInc - operand is incremented before any other use */
4741 /*-----------------------------------------------------------------*/
4743 hasInc (operand *op, iCode *ic,int osize)
4745 sym_link *type = operandType(op);
4746 sym_link *retype = getSpec (type);
4747 iCode *lic = ic->next;
4750 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4751 if (!IS_SYMOP(op)) return NULL;
4753 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4754 if (IS_AGGREGATE(type->next)) return NULL;
4755 if (osize != (isize = getSize(type->next))) return NULL;
4758 /* if operand of the form op = op + <sizeof *op> */
4759 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4760 isOperandEqual(IC_RESULT(lic),op) &&
4761 isOperandLiteral(IC_RIGHT(lic)) &&
4762 operandLitValue(IC_RIGHT(lic)) == isize) {
4765 /* if the operand used or deffed */
4766 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
4769 /* if GOTO or IFX */
4770 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4776 /*-----------------------------------------------------------------*/
4777 /* genAndOp - for && operation */
4778 /*-----------------------------------------------------------------*/
4780 genAndOp (iCode * ic)
4782 operand *left, *right, *result;
4783 symbol *tlbl, *tlbl0;
4785 D(emitcode ("; genAndOp",""));
4787 /* note here that && operations that are in an
4788 if statement are taken away by backPatchLabels
4789 only those used in arthmetic operations remain */
4790 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4791 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4792 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4794 tlbl = newiTempLabel (NULL);
4795 tlbl0 = newiTempLabel (NULL);
4797 asmopToBool (AOP (left), FALSE);
4798 emitBranch ("beq", tlbl0);
4799 asmopToBool (AOP (right), FALSE);
4800 emitBranch ("beq", tlbl0);
4801 loadRegFromConst (hc08_reg_a,one);
4802 emitBranch ("bra", tlbl);
4804 loadRegFromConst (hc08_reg_a,zero);
4807 hc08_useReg (hc08_reg_a);
4808 hc08_freeReg (hc08_reg_a);
4810 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4812 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4813 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4814 freeAsmop (result, NULL, ic, TRUE);
4818 /*-----------------------------------------------------------------*/
4819 /* genOrOp - for || operation */
4820 /*-----------------------------------------------------------------*/
4822 genOrOp (iCode * ic)
4824 operand *left, *right, *result;
4825 symbol *tlbl, *tlbl0;
4827 D(emitcode ("; genOrOp",""));
4829 /* note here that || operations that are in an
4830 if statement are taken away by backPatchLabels
4831 only those used in arthmetic operations remain */
4832 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4833 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4834 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4836 tlbl = newiTempLabel (NULL);
4837 tlbl0 = newiTempLabel (NULL);
4839 asmopToBool (AOP (left), FALSE);
4840 emitBranch ("bne", tlbl0);
4841 asmopToBool (AOP (right), FALSE);
4842 emitBranch ("bne", tlbl0);
4843 loadRegFromConst (hc08_reg_a,zero);
4844 emitBranch ("bra", tlbl);
4846 loadRegFromConst (hc08_reg_a,one);
4849 hc08_useReg (hc08_reg_a);
4850 hc08_freeReg (hc08_reg_a);
4852 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4855 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4856 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4857 freeAsmop (result, NULL, ic, TRUE);
4860 /*-----------------------------------------------------------------*/
4861 /* isLiteralBit - test if lit == 2^n */
4862 /*-----------------------------------------------------------------*/
4864 isLiteralBit (unsigned long lit)
4866 unsigned long pw[32] =
4867 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4868 0x100L, 0x200L, 0x400L, 0x800L,
4869 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4870 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4871 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4872 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4873 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4876 for (idx = 0; idx < 32; idx++)
4883 /*-----------------------------------------------------------------*/
4884 /* continueIfTrue - */
4885 /*-----------------------------------------------------------------*/
4887 continueIfTrue (iCode * ic)
4890 emitBranch ("jmp", IC_TRUE (ic));
4894 /*-----------------------------------------------------------------*/
4896 /*-----------------------------------------------------------------*/
4898 jumpIfTrue (iCode * ic)
4901 emitBranch ("jmp", IC_FALSE (ic));
4905 /*-----------------------------------------------------------------*/
4906 /* jmpTrueOrFalse - */
4907 /*-----------------------------------------------------------------*/
4909 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4911 // ugly but optimized by peephole
4914 symbol *nlbl = newiTempLabel (NULL);
4915 emitBranch ("bra", nlbl);
4917 emitBranch ("jmp", IC_TRUE (ic));
4922 emitBranch ("jmp", IC_FALSE (ic));
4929 /*-----------------------------------------------------------------*/
4930 /* genAnd - code for and */
4931 /*-----------------------------------------------------------------*/
4933 genAnd (iCode * ic, iCode * ifx)
4935 operand *left, *right, *result;
4936 int size, offset = 0;
4937 unsigned long lit = 0L;
4938 unsigned long litinv;
4939 unsigned char bytemask;
4945 D(emitcode ("; genAnd",""));
4947 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4948 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4949 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4952 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4954 AOP_TYPE (left), AOP_TYPE (right)));
4955 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4957 AOP_SIZE (left), AOP_SIZE (right)));
4960 /* if left is a literal & right is not then exchange them */
4961 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4963 operand *tmp = right;
4968 /* if right is accumulator & left is not then exchange them */
4969 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4971 operand *tmp = right;
4976 if (AOP_TYPE (right) == AOP_LIT)
4977 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4979 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4981 if (AOP_TYPE (result) == AOP_CRY
4983 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
4985 /* this generates ugly code, but meets volatility requirements */
4986 loadRegFromConst (hc08_reg_a, zero);
4987 pushReg (hc08_reg_a, TRUE);
4992 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4993 accopWithAop ("and", AOP (right), offset);
4994 emitcode ("ora", "1,s");
4995 emitcode ("sta", "1,s");
4999 pullReg (hc08_reg_a);
5000 emitcode ("tsta", "");
5001 genIfxJump (ifx, "a");
5005 if (AOP_TYPE (result) == AOP_CRY)
5007 symbol *tlbl = NULL;
5008 wassertl (ifx, "AOP_CRY result without ifx");
5013 bytemask = (lit >> (offset*8)) & 0xff;
5015 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5019 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5021 rmwWithAop ("tst", AOP (left), offset);
5025 tlbl = newiTempLabel (NULL);
5026 emitBranch ("bne", tlbl);
5031 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5032 accopWithAop ("and", AOP (right), offset);
5033 hc08_freeReg( hc08_reg_a);
5037 tlbl = newiTempLabel (NULL);
5038 emitBranch ("bne", tlbl);
5045 genIfxJump (ifx, "a");
5049 size = AOP_SIZE (result);
5051 if (AOP_TYPE (right) == AOP_LIT)
5053 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
5054 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5055 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
5057 int bitpos = isLiteralBit(litinv)-1;
5058 emitcode ("bclr","#%d,%s",bitpos & 7,
5059 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5067 bytemask = (lit >> (offset*8)) & 0xff;
5069 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5071 if (isOperandVolatile (left, FALSE))
5073 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5074 hc08_freeReg( hc08_reg_a);
5076 storeConstToAop (zero, AOP (result), offset);
5078 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5080 transferAopAop (AOP (left), offset, AOP (result), offset);
5084 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5085 accopWithAop ("and", AOP (right), offset);
5086 storeRegToAop (hc08_reg_a, AOP (result), offset);
5087 hc08_freeReg (hc08_reg_a);
5093 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5094 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5095 freeAsmop (result, NULL, ic, TRUE);
5098 /*-----------------------------------------------------------------*/
5099 /* genOr - code for or */
5100 /*-----------------------------------------------------------------*/
5102 genOr (iCode * ic, iCode * ifx)
5104 operand *left, *right, *result;
5105 int size, offset = 0;
5106 unsigned long lit = 0L;
5107 unsigned char bytemask;
5109 D(emitcode ("; genOr",""));
5111 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5112 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5113 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5116 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5118 AOP_TYPE (left), AOP_TYPE (right)));
5119 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5121 AOP_SIZE (left), AOP_SIZE (right)));
5124 /* if left is a literal & right is not then exchange them */
5125 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5127 operand *tmp = right;
5132 /* if left is accumulator & right is not then exchange them */
5133 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5135 operand *tmp = right;
5140 if (AOP_TYPE (right) == AOP_LIT)
5141 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5143 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5145 if (AOP_TYPE (result) == AOP_CRY
5147 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5149 /* this generates ugly code, but meets volatility requirements */
5150 loadRegFromConst (hc08_reg_a, zero);
5151 pushReg (hc08_reg_a, TRUE);
5156 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5157 accopWithAop ("ora", AOP (right), offset);
5158 emitcode ("ora", "1,s");
5159 emitcode ("sta", "1,s");
5163 pullReg (hc08_reg_a);
5164 emitcode ("tsta", "");
5165 genIfxJump (ifx, "a");
5169 if (AOP_TYPE (result) == AOP_CRY)
5171 symbol *tlbl = NULL;
5172 wassertl (ifx, "AOP_CRY result without ifx");
5177 bytemask = (lit >> (offset*8)) & 0xff;
5179 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5181 rmwWithAop ("tst", AOP (left), offset);
5185 tlbl = newiTempLabel (NULL);
5186 emitBranch ("bne", tlbl);
5191 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5192 accopWithAop ("ora", AOP (right), offset);
5193 hc08_freeReg( hc08_reg_a);
5197 tlbl = newiTempLabel (NULL);
5198 emitBranch ("bne", tlbl);
5205 genIfxJump (ifx, "a");
5208 if (AOP_TYPE (right) == AOP_LIT)
5209 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5211 size = AOP_SIZE (result);
5213 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5214 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5215 (AOP_TYPE (left) == AOP_DIR))
5217 int bitpos = isLiteralBit(lit)-1;
5218 emitcode ("bset","#%d,%s",bitpos & 7,
5219 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5226 bytemask = (lit >> (offset*8)) & 0xff;
5228 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5230 if (isOperandVolatile (left, FALSE))
5232 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5233 hc08_freeReg( hc08_reg_a);
5235 transferAopAop (AOP (right), offset, AOP (result), offset);
5237 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5239 transferAopAop (AOP (left), offset, AOP (result), offset);
5243 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5244 accopWithAop ("ora", AOP (right), offset);
5245 storeRegToAop (hc08_reg_a, AOP (result), offset);
5246 hc08_freeReg (hc08_reg_a);
5253 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5254 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5255 freeAsmop (result, NULL, ic, TRUE);
5258 /*-----------------------------------------------------------------*/
5259 /* genXor - code for xclusive or */
5260 /*-----------------------------------------------------------------*/
5262 genXor (iCode * ic, iCode * ifx)
5264 operand *left, *right, *result;
5265 int size, offset = 0;
5266 unsigned long lit = 0L;
5268 D(emitcode ("; genXor",""));
5270 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5271 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5272 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5275 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5277 AOP_TYPE (left), AOP_TYPE (right)));
5278 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5280 AOP_SIZE (left), AOP_SIZE (right)));
5283 /* if left is a literal & right is not ||
5284 if left needs acc & right does not */
5285 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5287 operand *tmp = right;
5292 /* if left is accumulator & right is not then exchange them */
5293 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5295 operand *tmp = right;
5300 if (AOP_TYPE (result) == AOP_CRY)
5303 wassertl (ifx, "AOP_CPY result without ifx");
5305 tlbl = newiTempLabel (NULL);
5306 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5310 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5311 if ((AOP_TYPE (right) == AOP_LIT)
5312 && (((lit >> (offset*8)) & 0xff) == 0))
5313 emitcode ("tsta","");
5315 accopWithAop ("eor", AOP (right), offset);
5316 hc08_freeReg( hc08_reg_a);
5318 emitBranch ("bne", tlbl);
5322 genIfxJump (ifx, "a");
5328 if (AOP_TYPE (right) == AOP_LIT)
5329 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5331 size = AOP_SIZE (result);
5335 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5336 accopWithAop ("eor", AOP (right), offset);
5337 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5338 hc08_freeReg( hc08_reg_a);
5342 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5343 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5344 freeAsmop (result, NULL, ic, TRUE);
5348 emitinline (iCode * ic, char *inlin)
5354 symbol *sym, *tempsym;
5363 while (isalnum((unsigned char)*inlin) || (*inlin == '_'))
5367 //printf("Found possible symbol '%s'\n",symname);
5368 tempsym = newSymbol (symname, ic->level);
5369 tempsym->block = ic->block;
5370 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5379 aop = aopForSym (ic, sym, FALSE);
5380 l = aopAdrStr (aop, aop->size - 1, TRUE);
5384 if (sym->level && !sym->allocreq && !sym->ismyparm)
5386 werror (E_ID_UNDEF, sym->name);
5388 " Add 'volatile' to the variable declaration so that it\n"
5389 " can be referenced within inline assembly");
5391 //printf("Replacing with '%s'\n",l);
5395 if ((2+bp-buffer)>sizeof(buffer))
5404 if ((2+bp-buffer)>sizeof(buffer))
5411 if ((2+bp-buffer)>sizeof(buffer))
5412 fprintf(stderr, "Inline assembly buffer overflow\n");
5414 //printf("%s\n",buffer);
5415 emitcode (buffer,"");
5419 /*-----------------------------------------------------------------*/
5420 /* genInline - write the inline code out */
5421 /*-----------------------------------------------------------------*/
5423 genInline (iCode * ic)
5425 char *buffer, *bp, *bp1;
5427 D(emitcode ("; genInline",""));
5429 _G.inLine += (!options.asmpeep);
5431 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5432 strcpy (buffer, IC_INLINE (ic));
5434 /* emit each line as a code */
5440 /* emitcode (bp1, ""); */
5441 emitinline (ic, bp1);
5460 /* emitcode (bp1, ""); */
5461 emitinline (ic, bp1);
5463 /* emitcode("",buffer); */
5464 _G.inLine -= (!options.asmpeep);
5467 /*-----------------------------------------------------------------*/
5468 /* genRRC - rotate right with carry */
5469 /*-----------------------------------------------------------------*/
5473 operand *left, *result;
5474 int size, offset = 0;
5475 bool needpula = FALSE;
5476 bool resultInA = FALSE;
5479 D(emitcode ("; genRRC",""));
5481 /* rotate right with carry */
5482 left = IC_LEFT (ic);
5483 result = IC_RESULT (ic);
5484 aopOp (left, ic, FALSE);
5485 aopOp (result, ic, FALSE);
5487 if ((AOP_TYPE (result) == AOP_REG)
5488 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5491 size = AOP_SIZE (result);
5495 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5499 rmwWithAop (shift, AOP (result), offset--);
5507 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5508 rmwWithReg (shift, hc08_reg_a);
5509 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5510 hc08_freeReg (hc08_reg_a);
5515 if ((!hc08_reg_a->isFree) || resultInA)
5517 pushReg (hc08_reg_a, TRUE);
5521 /* now we need to put the carry into the
5522 highest order byte of the result */
5523 offset = AOP_SIZE (result) - 1;
5524 emitcode ("clra","");
5525 emitcode ("rora","");
5526 hc08_dirtyReg (hc08_reg_a, FALSE);
5529 emitcode ("ora", "1,s");
5530 emitcode ("ais", "#1");
5531 hc08_dirtyReg (hc08_reg_a, FALSE);
5535 accopWithAop ("ora", AOP (result), offset);
5536 storeRegToAop (hc08_reg_a, AOP (result), offset);
5538 pullOrFreeReg (hc08_reg_a, needpula);
5540 freeAsmop (left, NULL, ic, TRUE);
5541 freeAsmop (result, NULL, ic, TRUE);
5544 /*-----------------------------------------------------------------*/
5545 /* genRLC - generate code for rotate left with carry */
5546 /*-----------------------------------------------------------------*/
5550 operand *left, *result;
5551 int size, offset = 0;
5553 bool resultInA = FALSE;
5554 bool needpula = FALSE;
5556 D(emitcode ("; genRLC",""));
5558 /* rotate right with carry */
5559 left = IC_LEFT (ic);
5560 result = IC_RESULT (ic);
5561 aopOp (left, ic, FALSE);
5562 aopOp (result, ic, FALSE);
5564 if ((AOP_TYPE (result) == AOP_REG)
5565 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5568 size = AOP_SIZE (result);
5572 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5576 rmwWithAop (shift, AOP (result), offset--);
5584 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5585 rmwWithReg (shift, hc08_reg_a);
5586 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5587 hc08_freeReg (hc08_reg_a);
5592 if ((!hc08_reg_a->isFree) || resultInA)
5594 pushReg (hc08_reg_a, TRUE);
5598 /* now we need to put the carry into the
5599 lowest order byte of the result */
5601 emitcode ("clra","");
5602 emitcode ("rola","");
5603 hc08_dirtyReg (hc08_reg_a, FALSE);
5606 emitcode ("ora", "1,s");
5607 emitcode ("ais", "#1");
5608 hc08_dirtyReg (hc08_reg_a, FALSE);
5612 accopWithAop ("ora", AOP (result), offset);
5613 storeRegToAop (hc08_reg_a, AOP (result), offset);
5615 pullOrFreeReg (hc08_reg_a, needpula);
5617 freeAsmop (left, NULL, ic, TRUE);
5618 freeAsmop (result, NULL, ic, TRUE);
5621 /*-----------------------------------------------------------------*/
5622 /* genGetHbit - generates code get highest order bit */
5623 /*-----------------------------------------------------------------*/
5625 genGetHbit (iCode * ic)
5627 operand *left, *result;
5629 D(emitcode ("; genGetHbit",""));
5631 left = IC_LEFT (ic);
5632 result = IC_RESULT (ic);
5633 aopOp (left, ic, FALSE);
5634 aopOp (result, ic, FALSE);
5636 /* get the highest order byte into a */
5637 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5638 emitcode ("rola", "");
5639 emitcode ("clra", "");
5640 emitcode ("rola", "");
5641 hc08_dirtyReg (hc08_reg_a, FALSE);
5642 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5643 hc08_freeReg (hc08_reg_a);
5645 freeAsmop (left, NULL, ic, TRUE);
5646 freeAsmop (result, NULL, ic, TRUE);
5649 /*-----------------------------------------------------------------*/
5650 /* genSwap - generates code to swap nibbles or bytes */
5651 /*-----------------------------------------------------------------*/
5653 genSwap (iCode * ic)
5655 operand *left, *result;
5657 D(emitcode ("; genSwap",""));
5659 left = IC_LEFT (ic);
5660 result = IC_RESULT (ic);
5661 aopOp (left, ic, FALSE);
5662 aopOp (result, ic, FALSE);
5664 switch (AOP_SIZE (left))
5666 case 1: /* swap nibbles in byte */
5667 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5668 emitcode ("nsa", "");
5669 hc08_dirtyReg (hc08_reg_a, FALSE);
5670 storeRegToAop (hc08_reg_a, AOP (result), 0);
5671 hc08_freeReg (hc08_reg_a);
5673 case 2: /* swap bytes in a word */
5674 if (operandsEqu (left, result))
5676 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5677 hc08_useReg (hc08_reg_a);
5678 transferAopAop (AOP (left), 1, AOP (result), 0);
5679 storeRegToAop (hc08_reg_a, AOP (result), 1);
5680 hc08_freeReg (hc08_reg_a);
5684 transferAopAop (AOP (left), 0, AOP (result), 1);
5685 transferAopAop (AOP (left), 1, AOP (result), 0);
5689 wassertl(FALSE, "unsupported SWAP operand size");
5692 freeAsmop (left, NULL, ic, TRUE);
5693 freeAsmop (result, NULL, ic, TRUE);
5697 /*-----------------------------------------------------------------*/
5698 /* AccRol - rotate left accumulator by known count */
5699 /*-----------------------------------------------------------------*/
5701 AccRol (int shCount)
5703 shCount &= 0x0007; // shCount : 0..7
5710 emitcode ("rola", ""); /* 1 cycle */
5713 emitcode ("rola", ""); /* 1 cycle */
5714 emitcode ("rola", ""); /* 1 cycle */
5717 emitcode ("nsa", "");
5718 emitcode ("rora", "");
5721 emitcode ("nsa", ""); /* 3 cycles */
5724 emitcode ("nsa", ""); /* 3 cycles */
5725 emitcode ("rola", ""); /* 1 cycle */
5728 emitcode ("nsa", ""); /* 3 cycles */
5729 emitcode ("rola", ""); /* 1 cycle */
5730 emitcode ("rola", ""); /* 1 cycle */
5733 emitcode ("nsa", ""); /* 3 cycles */
5734 emitcode ("rola", ""); /* 1 cycle */
5735 emitcode ("rola", ""); /* 1 cycle */
5736 emitcode ("rola", ""); /* 1 cycle */
5743 /*-----------------------------------------------------------------*/
5744 /* AccLsh - left shift accumulator by known count */
5745 /*-----------------------------------------------------------------*/
5747 AccLsh (int shCount)
5751 shCount &= 0x0007; // shCount : 0..7
5753 /* Shift counts of 4 and 5 are currently optimized for code size. */
5754 /* Falling through to the unrolled loop would be optimal for code speed. */
5755 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5759 if (optimize.codeSpeed)
5761 accopWithMisc ("nsa", "");
5762 accopWithMisc ("and", "#0xf0");
5763 /* total: 5 cycles, 3 bytes */
5766 if (optimize.codeSpeed)
5768 accopWithMisc ("nsa", "");
5769 accopWithMisc ("and", "#0xf0");
5770 accopWithMisc ("lsla", "");
5771 /* total: 6 cycles, 4 bytes */
5774 accopWithMisc ("rora", "");
5775 accopWithMisc ("rora", "");
5776 accopWithMisc ("rora", "");
5777 accopWithMisc ("and", "#0xc0");
5778 /* total: 5 cycles, 5 bytes */
5781 accopWithMisc ("rora", "");
5782 accopWithMisc ("clra", "");
5783 accopWithMisc ("rora", "");
5784 /* total: 3 cycles, 3 bytes */
5788 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5789 /* the fastest (shCount<6) and shortest (shCount<4). */
5790 for (i=0;i<shCount;i++)
5791 accopWithMisc ("lsla", "");
5795 /*-----------------------------------------------------------------*/
5796 /* AccSRsh - signed right shift accumulator by known count */
5797 /*-----------------------------------------------------------------*/
5799 AccSRsh (int shCount)
5803 shCount &= 0x0007; // shCount : 0..7
5807 accopWithMisc ("rola", "");
5808 accopWithMisc ("clra", "");
5809 accopWithMisc ("sbc", zero);
5810 /* total: 4 cycles, 4 bytes */
5814 for (i=0;i<shCount;i++)
5815 accopWithMisc ("asra", "");
5818 /*-----------------------------------------------------------------*/
5819 /* AccRsh - right shift accumulator by known count */
5820 /*-----------------------------------------------------------------*/
5822 AccRsh (int shCount, bool sign)
5832 shCount &= 0x0007; // shCount : 0..7
5834 /* Shift counts of 4 and 5 are currently optimized for code size. */
5835 /* Falling through to the unrolled loop would be optimal for code speed. */
5836 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5840 if (optimize.codeSpeed)
5842 accopWithMisc ("nsa", "");
5843 accopWithMisc ("and", "#0x0f");
5844 /* total: 5 cycles, 3 bytes */
5847 if (optimize.codeSpeed)
5849 accopWithMisc ("nsa", "");
5850 accopWithMisc ("and", "#0x0f");
5851 accopWithMisc ("lsra", "");
5852 /* total: 6 cycles, 4 bytes */
5855 accopWithMisc ("rola", "");
5856 accopWithMisc ("rola", "");
5857 accopWithMisc ("rola", "");
5858 accopWithMisc ("and", "#0x03");
5859 /* total: 5 cycles, 5 bytes */
5862 accopWithMisc ("rola", "");
5863 accopWithMisc ("clra", "");
5864 accopWithMisc ("rola", "");
5865 /* total: 3 cycles, 3 bytes */
5869 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5870 /* the fastest (shCount<6) and shortest (shCount<4). */
5871 for (i=0;i<shCount;i++)
5872 accopWithMisc ("lsra", "");
5876 /*-----------------------------------------------------------------*/
5877 /* XAccLsh - left shift register pair XA by known count */
5878 /*-----------------------------------------------------------------*/
5880 XAccLsh (int shCount)
5884 shCount &= 0x000f; // shCount : 0..15
5889 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5890 loadRegFromConst (hc08_reg_a, zero);
5894 /* if we can beat 2n cycles or bytes for some special case, do it here */
5898 /* bytes cycles reg x reg a carry
5899 ** abcd efgh ijkl mnop ?
5900 ** lsrx 1 1 0abc defg ijkl mnop h
5901 ** rora 1 1 0abc defg hijk lmno p
5902 ** tax 1 1 hijk lmno hijk lmno p
5903 ** clra 1 1 hijk lmno 0000 0000 p
5904 ** rora 1 1 hijk lmno p000 0000 0
5905 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5907 rmwWithReg ("lsr", hc08_reg_x);
5908 rmwWithReg ("ror", hc08_reg_a);
5909 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5910 loadRegFromConst (hc08_reg_a, zero);
5911 rmwWithReg ("ror", hc08_reg_a);
5918 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5919 /* the fastest and shortest. */
5920 for (i=0;i<shCount;i++)
5922 rmwWithReg ("lsl", hc08_reg_a);
5923 rmwWithReg ("rol", hc08_reg_x);
5927 /*-----------------------------------------------------------------*/
5928 /* XAccSRsh - signed right shift register pair XA by known count */
5929 /*-----------------------------------------------------------------*/
5931 XAccSRsh (int shCount)
5935 shCount &= 0x000f; // shCount : 0..7
5937 /* if we can beat 2n cycles or bytes for some special case, do it here */
5941 /* bytes cycles reg x reg a carry
5942 ** abcd efgh ijkl mnop ?
5943 ** lslx 1 1 bcde fgh0 ijkl mnop a
5944 ** clra 1 1 bcde fgh0 0000 0000 a
5945 ** rola 1 1 bcde fgh0 0000 000a 0
5946 ** nega 1 1 bcde fgh0 aaaa aaaa a
5947 ** tax 1 1 aaaa aaaa aaaa aaaa a
5948 ** total: 5 cycles, 5 bytes
5950 rmwWithReg ("lsl", hc08_reg_x);
5951 loadRegFromConst (hc08_reg_a, zero);
5952 rmwWithReg ("rol", hc08_reg_a);
5953 rmwWithReg ("neg", hc08_reg_a);
5954 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5964 /* bytes cycles reg x reg a carry
5965 ** abcd efgh ijkl mnop ?
5966 ** txa 1 1 abcd efgh abcd efgh ?
5967 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5968 ** lsla 1 1 abcd efgh ???? ???? a
5969 ** clrx 1 1 0000 0000 ???? ???? a
5970 ** rolx 1 1 0000 000a ???? ???? 0
5971 ** negx 1 1 aaaa aaaa ???? ???? a
5972 ** rora 1 1 aaaa aaaa LSBresult 0
5973 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5975 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5976 AccSRsh (shCount-8);
5977 rmwWithReg ("lsl", hc08_reg_a);
5978 loadRegFromConst (hc08_reg_x, zero);
5979 rmwWithReg ("rol", hc08_reg_x);
5980 rmwWithReg ("neg", hc08_reg_x);
5981 rmwWithReg ("ror", hc08_reg_a);
5988 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5989 /* the fastest and shortest. */
5990 for (i=0;i<shCount;i++)
5992 rmwWithReg ("asr", hc08_reg_x);
5993 rmwWithReg ("ror", hc08_reg_a);
5997 /*-----------------------------------------------------------------*/
5998 /* XAccRsh - right shift register pair XA by known count */
5999 /*-----------------------------------------------------------------*/
6001 XAccRsh (int shCount, bool sign)
6011 shCount &= 0x000f; // shCount : 0..f
6013 /* if we can beat 2n cycles or bytes for some special case, do it here */
6017 /* bytes cycles reg x reg a carry
6018 ** abcd efgh ijkl mnop ?
6019 ** clra 1 1 abcd efgh 0000 0000 a
6020 ** lslx 1 1 bcde fgh0 0000 0000 a
6021 ** rola 1 1 bcde fgh0 0000 000a 0
6022 ** clrx 1 1 0000 0000 0000 000a 0
6023 ** total: 4 cycles, 4 bytes
6025 loadRegFromConst (hc08_reg_x, zero);
6026 rmwWithReg ("lsl", hc08_reg_x);
6027 rmwWithReg ("rol", hc08_reg_a);
6028 loadRegFromConst (hc08_reg_a, zero);
6032 /* bytes cycles reg x reg a carry
6033 ** abcd efgh ijkl mnop ?
6034 ** clra 1 1 abcd efgh 0000 0000 a
6035 ** lslx 1 1 bcde fgh0 0000 0000 a
6036 ** rola 1 1 bcde fgh0 0000 000a 0
6037 ** lslx 1 1 cdef gh00 0000 000a b
6038 ** rola 1 1 cdef gh00 0000 00ab 0
6039 ** clrx 1 1 0000 0000 0000 00ab 0
6040 ** total: 6 cycles, 6 bytes
6042 loadRegFromConst (hc08_reg_x, zero);
6043 rmwWithReg ("lsl", hc08_reg_x);
6044 rmwWithReg ("rol", hc08_reg_a);
6045 rmwWithReg ("lsl", hc08_reg_x);
6046 rmwWithReg ("rol", hc08_reg_a);
6047 loadRegFromConst (hc08_reg_a, zero);
6056 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6057 AccRsh (shCount-8, FALSE);
6058 loadRegFromConst (hc08_reg_x, zero);
6062 /* bytes cycles reg x reg a carry
6063 ** abcd efgh ijkl mnop ?
6064 ** lsla 1 1 abcd efgh jklm nop0 i
6065 ** txa 1 1 abcd efgh abcd efgh i
6066 ** rola 1 1 abcd efgh bcde fghi a
6067 ** clrx 1 1 0000 0000 bcde fghi a
6068 ** rolx 1 1 0000 000a bcde fghi 0
6069 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
6071 rmwWithReg ("lsl", hc08_reg_a);
6072 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6073 rmwWithReg ("rol", hc08_reg_a);
6074 loadRegFromConst (hc08_reg_x, zero);
6075 rmwWithReg ("rol", hc08_reg_x);
6078 /* bytes cycles reg x reg a carry
6079 ** abcd efgh ijkl mnop ?
6080 ** lsla 1 1 abcd efgh jklm nop0 i
6081 ** rolx 1 1 bcde fghi jklm nop0 a
6082 ** rola 1 1 bcde fghi klmn op0a j
6083 ** rolx 1 1 cdef ghij klmn op0a b
6084 ** rola 1 1 cdef ghij lmno p0ab k
6085 ** and #3 2 2 cdef ghij 0000 00ab k
6086 ** psha 1 2 cdef ghij 0000 00ab k
6087 ** txa 1 1 cdef ghij cdef ghij k
6088 ** pula 1 2 0000 00ab cdef ghij k
6089 ** total: 12 cycles, 10 bytes (beats 12 bytes)
6095 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6096 /* the fastest and shortest. */
6097 for (i=0;i<shCount;i++)
6099 rmwWithReg ("lsr", hc08_reg_x);
6100 rmwWithReg ("ror", hc08_reg_a);
6107 /*-----------------------------------------------------------------*/
6108 /* shiftR1Left2Result - shift right one byte from left to result */
6109 /*-----------------------------------------------------------------*/
6111 shiftR1Left2Result (operand * left, int offl,
6112 operand * result, int offr,
6113 int shCount, int sign)
6115 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6116 /* shift right accumulator */
6117 AccRsh (shCount, sign);
6118 storeRegToAop (hc08_reg_a, AOP (result), offr);
6122 /*-----------------------------------------------------------------*/
6123 /* shiftL1Left2Result - shift left one byte from left to result */
6124 /*-----------------------------------------------------------------*/
6126 shiftL1Left2Result (operand * left, int offl,
6127 operand * result, int offr, int shCount)
6129 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6130 /* shift left accumulator */
6132 storeRegToAop (hc08_reg_a, AOP (result), offr);
6135 /*-----------------------------------------------------------------*/
6136 /* movLeft2Result - move byte from left to result */
6137 /*-----------------------------------------------------------------*/
6139 movLeft2Result (operand * left, int offl,
6140 operand * result, int offr, int sign)
6142 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6144 transferAopAop (AOP (left), offl, AOP (result), offr);
6149 /*-----------------------------------------------------------------*/
6150 /* shiftL2Left2Result - shift left two bytes from left to result */
6151 /*-----------------------------------------------------------------*/
6153 shiftL2Left2Result (operand * left, int offl,
6154 operand * result, int offr, int shCount)
6157 bool needpula = FALSE;
6158 bool needpulx = FALSE;
6160 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6161 needpula = pushRegIfUsed (hc08_reg_a);
6164 if (!IS_AOP_XA (AOP (left)))
6165 needpulx = pushRegIfUsed (hc08_reg_x);
6169 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6174 rmwWithReg ("lsr", hc08_reg_x);
6175 rmwWithReg ("ror", hc08_reg_a);
6176 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6177 rmwWithReg ("clr", hc08_reg_a);
6178 rmwWithReg ("ror", hc08_reg_a);
6181 for (i=0; i<shCount; i++)
6183 rmwWithReg ("lsl", hc08_reg_a);
6184 rmwWithReg ("rol", hc08_reg_x);
6187 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6189 pullOrFreeReg (hc08_reg_x, needpulx);
6190 pullOrFreeReg (hc08_reg_a, needpula);
6196 /*-----------------------------------------------------------------*/
6197 /* shiftR2Left2Result - shift right two bytes from left to result */
6198 /*-----------------------------------------------------------------*/
6200 shiftR2Left2Result (operand * left, int offl,
6201 operand * result, int offr,
6202 int shCount, int sign)
6205 bool needpula = FALSE;
6206 bool needpulx = FALSE;
6208 needpula = pushRegIfUsed (hc08_reg_a);
6209 needpulx = pushRegIfUsed (hc08_reg_x);
6211 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6212 for (i=0; i<shCount; i++)
6215 rmwWithReg ("asr", hc08_reg_x);
6217 rmwWithReg ("lsr", hc08_reg_x);
6218 rmwWithReg ("ror", hc08_reg_a);
6220 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6222 pullOrFreeReg (hc08_reg_x, needpulx);
6223 pullOrFreeReg (hc08_reg_a, needpula);
6228 /*-----------------------------------------------------------------*/
6229 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6230 /*-----------------------------------------------------------------*/
6232 shiftLLeftOrResult (operand * left, int offl,
6233 operand * result, int offr, int shCount)
6235 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6236 /* shift left accumulator */
6238 /* or with result */
6239 accopWithAop ("ora", AOP (result), offr);
6240 /* back to result */
6241 storeRegToAop (hc08_reg_a, AOP (result), offr);
6242 hc08_freeReg (hc08_reg_a);
6246 /*-----------------------------------------------------------------*/
6247 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6248 /*-----------------------------------------------------------------*/
6250 shiftRLeftOrResult (operand * left, int offl,
6251 operand * result, int offr, int shCount)
6253 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6254 /* shift left accumulator */
6255 AccRsh (shCount, FALSE);
6256 /* or with result */
6257 accopWithAop ("ora", AOP (result), offr);
6258 /* back to result */
6259 storeRegToAop (hc08_reg_a, AOP (result), offr);
6260 hc08_freeReg (hc08_reg_a);
6263 /*-----------------------------------------------------------------*/
6264 /* genlshOne - left shift a one byte quantity by known count */
6265 /*-----------------------------------------------------------------*/
6267 genlshOne (operand * result, operand * left, int shCount)
6269 D(emitcode ("; genlshOne",""));
6271 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6274 /*-----------------------------------------------------------------*/
6275 /* genlshTwo - left shift two bytes by known amount != 0 */
6276 /*-----------------------------------------------------------------*/
6278 genlshTwo (operand * result, operand * left, int shCount)
6282 D(emitcode ("; genlshTwo",""));
6285 size = getDataSize (result);
6287 /* if shCount >= 8 */
6294 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6296 storeRegToAop (hc08_reg_a, AOP (result), 1);
6298 storeConstToAop(zero, AOP (result), LSB);
6301 /* 1 <= shCount <= 7 */
6304 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6306 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6310 /*-----------------------------------------------------------------*/
6311 /* shiftLLong - shift left one long from left to result */
6312 /* offr = LSB or MSB16 */
6313 /*-----------------------------------------------------------------*/
6315 shiftLLong (operand * left, operand * result, int offr)
6318 // int size = AOP_SIZE (result);
6320 bool needpula = FALSE;
6321 bool needpulx = FALSE;
6323 needpula = pushRegIfUsed (hc08_reg_a);
6324 needpulx = pushRegIfUsed (hc08_reg_x);
6326 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6327 rmwWithReg ("lsl", hc08_reg_a);
6328 rmwWithReg ("rol", hc08_reg_x);
6332 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6333 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6334 rmwWithReg ("rol", hc08_reg_a);
6335 rmwWithReg ("rol", hc08_reg_x);
6336 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6338 else if (offr==MSB16)
6340 storeRegToAop (hc08_reg_a, AOP (result), offr);
6341 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6342 storeRegToAop (hc08_reg_x, AOP (result), offr+1);
6343 rmwWithReg ("rol", hc08_reg_a);
6344 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6345 storeConstToAop (zero, AOP (result), 0);
6348 pullOrFreeReg (hc08_reg_x, needpulx);
6349 pullOrFreeReg (hc08_reg_a, needpula);
6352 /*-----------------------------------------------------------------*/
6353 /* genlshFour - shift four byte by a known amount != 0 */
6354 /*-----------------------------------------------------------------*/
6356 genlshFour (operand * result, operand * left, int shCount)
6360 D(emitcode ("; genlshFour",""));
6362 size = AOP_SIZE (result);
6364 /* TODO: deal with the &result == &left case */
6366 /* if shifting more that 3 bytes */
6371 /* lowest order of left goes to the highest
6372 order of the destination */
6373 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6375 movLeft2Result (left, LSB, result, MSB32, 0);
6376 storeConstToAop (zero, AOP (result), LSB);
6377 storeConstToAop (zero, AOP (result), MSB16);
6378 storeConstToAop (zero, AOP (result), MSB24);
6382 /* more than two bytes */
6383 else if (shCount >= 16)
6385 /* lower order two bytes goes to higher order two bytes */
6387 /* if some more remaining */
6389 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6392 movLeft2Result (left, MSB16, result, MSB32, 0);
6393 movLeft2Result (left, LSB, result, MSB24, 0);
6395 storeConstToAop (zero, AOP (result), LSB);
6396 storeConstToAop (zero, AOP (result), MSB16);
6400 /* if more than 1 byte */
6401 else if (shCount >= 8)
6403 /* lower order three bytes goes to higher order three bytes */
6408 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6410 movLeft2Result (left, LSB, result, MSB16, 0);
6416 movLeft2Result (left, MSB24, result, MSB32, 0);
6417 movLeft2Result (left, MSB16, result, MSB24, 0);
6418 movLeft2Result (left, LSB, result, MSB16, 0);
6419 storeConstToAop (zero, AOP (result), LSB);
6421 else if (shCount == 1)
6422 shiftLLong (left, result, MSB16);
6425 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6426 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6427 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6428 storeConstToAop (zero, AOP (result), LSB);
6433 /* 1 <= shCount <= 7 */
6434 else if (shCount <= 2)
6436 shiftLLong (left, result, LSB);
6438 shiftLLong (result, result, LSB);
6440 /* 3 <= shCount <= 7, optimize */
6443 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6444 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6445 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6449 /*-----------------------------------------------------------------*/
6450 /* genLeftShiftLiteral - left shifting by known count */
6451 /*-----------------------------------------------------------------*/
6453 genLeftShiftLiteral (operand * left,
6458 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6461 D(emitcode ("; genLeftShiftLiteral",""));
6463 freeAsmop (right, NULL, ic, TRUE);
6465 aopOp (left, ic, FALSE);
6466 aopOp (result, ic, FALSE);
6468 // size = getSize (operandType (result));
6469 size = AOP_SIZE (result);
6472 D(emitcode ("; shift left ", "result %d, left %d", size,
6479 transferAopAop( AOP(left), size, AOP(result), size);
6481 else if (shCount >= (size * 8))
6484 storeConstToAop (zero, AOP (result), size);
6491 genlshOne (result, left, shCount);
6495 genlshTwo (result, left, shCount);
6499 genlshFour (result, left, shCount);
6502 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6503 "*** ack! mystery literal shift!\n");
6507 freeAsmop (left, NULL, ic, TRUE);
6508 freeAsmop (result, NULL, ic, TRUE);
6511 /*-----------------------------------------------------------------*/
6512 /* genLeftShift - generates code for left shifting */
6513 /*-----------------------------------------------------------------*/
6515 genLeftShift (iCode * ic)
6517 operand *left, *right, *result;
6519 symbol *tlbl, *tlbl1;
6522 D(emitcode ("; genLeftShift",""));
6524 right = IC_RIGHT (ic);
6525 left = IC_LEFT (ic);
6526 result = IC_RESULT (ic);
6528 aopOp (right, ic, FALSE);
6530 /* if the shift count is known then do it
6531 as efficiently as possible */
6532 if (AOP_TYPE (right) == AOP_LIT)
6534 genLeftShiftLiteral (left, right, result, ic);
6538 /* shift count is unknown then we have to form
6539 a loop get the loop count in A : Note: we take
6540 only the lower order byte since shifting
6541 more that 32 bits make no sense anyway, ( the
6542 largest size of an object can be only 32 bits ) */
6544 aopOp (result, ic, FALSE);
6545 aopOp (left, ic, FALSE);
6547 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6548 AOP (result) = forceStackedAop (AOP (result));
6550 /* now move the left to the result if they are not the
6552 if (!sameRegs (AOP (left), AOP (result)))
6554 size = AOP_SIZE (result);
6558 transferAopAop (AOP (left), offset, AOP (result), offset);
6562 freeAsmop (left, NULL, ic, TRUE);
6564 tlbl = newiTempLabel (NULL);
6565 size = AOP_SIZE (result);
6567 tlbl1 = newiTempLabel (NULL);
6569 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6570 emitcode ("tstx", "");
6571 emitBranch ("beq", tlbl1);
6575 for (offset=0;offset<size;offset++)
6577 rmwWithAop (shift, AOP (result), offset);
6580 rmwWithReg ("dec", hc08_reg_x);
6581 emitBranch ("bne", tlbl);
6583 hc08_freeReg (hc08_reg_x);
6585 freeAsmop (result, NULL, ic, TRUE);
6586 freeAsmop (right, NULL, ic, TRUE);
6589 /*-----------------------------------------------------------------*/
6590 /* genrshOne - right shift a one byte quantity by known count */
6591 /*-----------------------------------------------------------------*/
6593 genrshOne (operand * result, operand * left,
6594 int shCount, int sign)
6596 D(emitcode ("; genrshOne",""));
6598 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6599 AccRsh (shCount, sign);
6600 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6603 /*-----------------------------------------------------------------*/
6604 /* genrshTwo - right shift two bytes by known amount != 0 */
6605 /*-----------------------------------------------------------------*/
6607 genrshTwo (operand * result, operand * left,
6608 int shCount, int sign)
6610 D(emitcode ("; genrshTwo",""));
6612 /* if shCount >= 8 */
6615 if (shCount || sign)
6617 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6618 AccRsh (shCount-8, sign);
6619 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6623 transferAopAop (AOP (left), 1, AOP (result), 0);
6624 storeConstToAop (zero, AOP (result), 1);
6628 /* 1 <= shCount <= 7 */
6631 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6632 XAccRsh (shCount, sign);
6633 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6637 /*-----------------------------------------------------------------*/
6638 /* shiftRLong - shift right one long from left to result */
6639 /* offl = LSB or MSB16 */
6640 /*-----------------------------------------------------------------*/
6642 shiftRLong (operand * left, int offl,
6643 operand * result, int sign)
6646 // int size = AOP_SIZE (result);
6648 bool needpula = FALSE;
6649 bool needpulx = FALSE;
6651 needpula = pushRegIfUsed (hc08_reg_a);
6652 needpulx = pushRegIfUsed (hc08_reg_x);
6656 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6658 rmwWithReg ("asr", hc08_reg_x);
6660 rmwWithReg ("lsr", hc08_reg_x);
6661 rmwWithReg ("ror", hc08_reg_a);
6662 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6663 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6665 else if (offl==MSB16)
6667 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6669 rmwWithReg ("asr", hc08_reg_a);
6671 rmwWithReg ("lsr", hc08_reg_a);
6672 loadRegFromAop (hc08_reg_x, AOP (left), MSB24);
6673 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6674 loadRegFromAop (hc08_reg_a, AOP (left), MSB16);
6677 rmwWithReg ("ror", hc08_reg_x);
6678 rmwWithReg ("ror", hc08_reg_a);
6679 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6685 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6686 storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
6690 storeConstToAop (zero, AOP (result), MSB32);
6694 pullOrFreeReg (hc08_reg_x, needpulx);
6695 pullOrFreeReg (hc08_reg_a, needpula);
6698 /*-----------------------------------------------------------------*/
6699 /* genrshFour - shift four byte by a known amount != 0 */
6700 /*-----------------------------------------------------------------*/
6702 genrshFour (operand * result, operand * left,
6703 int shCount, int sign)
6705 /* TODO: handle cases where left == result */
6707 D(emitcode ("; genrshFour",""));
6709 /* if shifting more that 3 bytes */
6712 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6713 AccRsh (shCount-24, sign);
6714 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6717 else if (shCount >= 16)
6719 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6720 XAccRsh (shCount-16, sign);
6721 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6724 else if (shCount >= 8)
6727 shiftRLong (left, MSB16, result, sign);
6728 else if (shCount == 8)
6730 transferAopAop (AOP (left), 1, AOP (result), 0);
6731 transferAopAop (AOP (left), 2, AOP (result), 1);
6732 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6733 storeRegToAop (hc08_reg_a, AOP (result), 2);
6734 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6736 else if (shCount == 9)
6738 shiftRLong (left, MSB16, result, sign);
6742 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6743 XAccRsh (shCount-8, FALSE);
6744 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6745 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6746 loadRegFromConst (hc08_reg_a, zero);
6747 XAccRsh (shCount-8, sign);
6748 accopWithAop ("ora", AOP (result), 1);
6749 storeRegToAop (hc08_reg_xa, AOP (result), 1);
6750 storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
6754 { /* 1 <= shCount <= 7 */
6757 shiftRLong (left, LSB, result, sign);
6761 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6762 XAccRsh (shCount, FALSE);
6763 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6764 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6766 accopWithAop ("ora", AOP (result), 1);
6767 storeRegToAop (hc08_reg_a, AOP (result), 1);
6768 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6769 XAccRsh (shCount, sign);
6770 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6775 /*-----------------------------------------------------------------*/
6776 /* genRightShiftLiteral - right shifting by known count */
6777 /*-----------------------------------------------------------------*/
6779 genRightShiftLiteral (operand * left,
6785 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6788 D(emitcode ("; genRightShiftLiteral",""));
6790 freeAsmop (right, NULL, ic, TRUE);
6792 aopOp (left, ic, FALSE);
6793 aopOp (result, ic, FALSE);
6796 D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6800 size = getDataSize (left);
6801 /* test the LEFT size !!! */
6803 /* I suppose that the left size >= result size */
6806 size = getDataSize (result);
6808 transferAopAop (AOP (left), size, AOP(result), size);
6810 else if (shCount >= (size * 8))
6813 /* get sign in acc.7 */
6814 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6816 addSign (result, LSB, sign);
6823 genrshOne (result, left, shCount, sign);
6827 genrshTwo (result, left, shCount, sign);
6831 genrshFour (result, left, shCount, sign);
6837 freeAsmop (left, NULL, ic, TRUE);
6838 freeAsmop (result, NULL, ic, TRUE);
6842 /*-----------------------------------------------------------------*/
6843 /* genRightShift - generate code for right shifting */
6844 /*-----------------------------------------------------------------*/
6846 genRightShift (iCode * ic)
6848 operand *right, *left, *result;
6851 symbol *tlbl, *tlbl1;
6855 D(emitcode ("; genRightShift",""));
6857 /* if signed then we do it the hard way preserve the
6858 sign bit moving it inwards */
6859 retype = getSpec (operandType (IC_RESULT (ic)));
6860 sign = !SPEC_USIGN (retype);
6862 /* signed & unsigned types are treated the same : i.e. the
6863 signed is NOT propagated inwards : quoting from the
6864 ANSI - standard : "for E1 >> E2, is equivalent to division
6865 by 2**E2 if unsigned or if it has a non-negative value,
6866 otherwise the result is implementation defined ", MY definition
6867 is that the sign does not get propagated */
6869 right = IC_RIGHT (ic);
6870 left = IC_LEFT (ic);
6871 result = IC_RESULT (ic);
6873 aopOp (right, ic, FALSE);
6875 /* if the shift count is known then do it
6876 as efficiently as possible */
6877 if (AOP_TYPE (right) == AOP_LIT)
6879 genRightShiftLiteral (left, right, result, ic, sign);
6883 /* shift count is unknown then we have to form
6884 a loop get the loop count in X : Note: we take
6885 only the lower order byte since shifting
6886 more that 32 bits make no sense anyway, ( the
6887 largest size of an object can be only 32 bits ) */
6889 aopOp (result, ic, FALSE);
6890 aopOp (left, ic, FALSE);
6892 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6893 AOP (result) = forceStackedAop (AOP (result));
6895 /* now move the left to the result if they are not the
6897 if (!sameRegs (AOP (left), AOP (result)))
6899 size = AOP_SIZE (result);
6903 transferAopAop (AOP (left), offset, AOP (result), offset);
6907 freeAsmop (left, NULL, ic, TRUE);
6909 tlbl = newiTempLabel (NULL);
6910 size = AOP_SIZE (result);
6912 tlbl1 = newiTempLabel (NULL);
6914 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6915 emitcode ("tstx", "");
6916 emitBranch ("beq", tlbl1);
6919 shift= sign ? "asr" : "lsr";
6920 for (offset=size-1;offset>=0;offset--)
6922 rmwWithAop (shift, AOP (result), offset);
6925 rmwWithReg ("dec", hc08_reg_x);
6926 emitBranch ("bne", tlbl);
6928 hc08_freeReg (hc08_reg_x);
6930 freeAsmop (result, NULL, ic, TRUE);
6931 freeAsmop (right, NULL, ic, TRUE);
6935 /*-----------------------------------------------------------------*/
6936 /* genUnpackBits - generates code for unpacking bits */
6937 /*-----------------------------------------------------------------*/
6939 genUnpackBits (operand * result, iCode *ifx)
6941 int offset = 0; /* result byte offset */
6942 int rsize; /* result size */
6943 int rlen = 0; /* remaining bitfield length */
6944 sym_link *etype; /* bitfield type information */
6945 int blen; /* bitfield length */
6946 int bstr; /* bitfield starting bit within byte */
6948 D(emitcode ("; genUnpackBits",""));
6950 etype = getSpec (operandType (result));
6951 rsize = getSize (operandType (result));
6952 blen = SPEC_BLEN (etype);
6953 bstr = SPEC_BSTR (etype);
6955 if (ifx && blen <= 8)
6957 emitcode ("lda", ",x");
6958 hc08_dirtyReg (hc08_reg_a, FALSE);
6961 emitcode ("and", "#0x%02x",
6962 (((unsigned char) -1) >> (8 - blen)) << bstr);
6964 genIfxJump (ifx, "a");
6969 /* If the bitfield length is less than a byte */
6972 emitcode ("lda", ",x");
6973 hc08_dirtyReg (hc08_reg_a, FALSE);
6974 AccRsh (bstr, FALSE);
6975 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6976 if (!SPEC_USIGN (etype))
6978 /* signed bitfield */
6979 symbol *tlbl = newiTempLabel (NULL);
6981 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
6982 emitcode ("beq", "%05d$", tlbl->key + 100);
6983 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
6986 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6990 /* Bit field did not fit in a byte. Copy all
6991 but the partial byte at the end. */
6992 for (rlen=blen;rlen>=8;rlen-=8)
6994 emitcode ("lda", ",x");
6995 hc08_dirtyReg (hc08_reg_a, FALSE);
6996 storeRegToAop (hc08_reg_a, AOP (result), offset);
6999 emitcode ("aix", "#1");
7002 /* Handle the partial byte at the end */
7005 emitcode ("lda", ",x");
7006 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7007 if (!SPEC_USIGN (etype))
7009 /* signed bitfield */
7010 symbol *tlbl = newiTempLabel (NULL);
7012 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7013 emitcode ("beq", "%05d$", tlbl->key + 100);
7014 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7017 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7024 if (SPEC_USIGN (etype))
7027 storeConstToAop (zero, AOP (result), offset++);
7031 /* signed bitfield: sign extension with 0x00 or 0xff */
7032 emitcode ("rola", "");
7033 emitcode ("clra", "");
7034 emitcode ("sbc", zero);
7037 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7043 /*-----------------------------------------------------------------*/
7044 /* genUnpackBitsImmed - generates code for unpacking bits */
7045 /*-----------------------------------------------------------------*/
7047 genUnpackBitsImmed (operand * left,
7053 int offset = 0; /* result byte offset */
7054 int rsize; /* result size */
7055 int rlen = 0; /* remaining bitfield length */
7056 sym_link *etype; /* bitfield type information */
7057 int blen; /* bitfield length */
7058 int bstr; /* bitfield starting bit within byte */
7061 D(emitcode ("; genUnpackBitsImmed",""));
7063 aopOp (result, ic, TRUE);
7064 size = AOP_SIZE (result);
7066 derefaop = aopDerefAop (AOP (left));
7067 freeAsmop (left, NULL, ic, TRUE);
7068 derefaop->size = size;
7070 etype = getSpec (operandType (result));
7071 rsize = getSize (operandType (result));
7072 blen = SPEC_BLEN (etype);
7073 bstr = SPEC_BSTR (etype);
7075 /* if the bitfield is a single bit in the direct page */
7076 if (blen == 1 && derefaop->type == AOP_DIR)
7080 symbol *tlbl = newiTempLabel (NULL);
7082 loadRegFromConst (hc08_reg_a, zero);
7083 emitcode ("brclr", "#%d,%s,%05d$",
7084 bstr, aopAdrStr (derefaop, 0, FALSE),
7086 if (SPEC_USIGN (etype))
7087 rmwWithReg ("inc", hc08_reg_a);
7089 rmwWithReg ("dec", hc08_reg_a);
7091 storeRegToAop (hc08_reg_a, AOP (result), offset);
7092 hc08_freeReg (hc08_reg_a);
7098 symbol *tlbl = newiTempLabel (NULL);
7104 jlbl = IC_TRUE (ifx);
7109 jlbl = IC_FALSE (ifx);
7112 emitcode (inst, "#%d,%s,%05d$",
7113 bstr, aopAdrStr (derefaop, 0, FALSE),
7115 emitBranch ("jmp", jlbl);
7123 /* If the bitfield length is less than a byte */
7126 loadRegFromAop (hc08_reg_a, derefaop, 0);
7129 AccRsh (bstr, FALSE);
7130 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7131 hc08_dirtyReg (hc08_reg_a, FALSE);
7132 if (!SPEC_USIGN (etype))
7134 /* signed bitfield */
7135 symbol *tlbl = newiTempLabel (NULL);
7137 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7138 emitcode ("beq", "%05d$", tlbl->key + 100);
7139 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7142 storeRegToAop (hc08_reg_a, AOP (result), offset);
7146 emitcode ("and", "#0x%02x",
7147 (((unsigned char) -1) >> (8 - blen)) << bstr);
7148 hc08_dirtyReg (hc08_reg_a, FALSE);
7154 /* Bit field did not fit in a byte. Copy all
7155 but the partial byte at the end. */
7156 for (rlen=blen;rlen>=8;rlen-=8)
7158 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7160 storeRegToAop (hc08_reg_a, AOP (result), offset);
7162 emitcode ("tsta", "");
7166 /* Handle the partial byte at the end */
7169 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7170 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7171 if (!SPEC_USIGN (etype))
7173 /* signed bitfield */
7174 symbol *tlbl = newiTempLabel (NULL);
7176 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7177 emitcode ("beq", "%05d$", tlbl->key + 100);
7178 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7181 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7188 if (SPEC_USIGN (etype))
7191 storeConstToAop (zero, AOP (result), offset++);
7195 /* signed bitfield: sign extension with 0x00 or 0xff */
7196 emitcode ("rola", "");
7197 emitcode ("clra", "");
7198 emitcode ("sbc", zero);
7201 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7205 freeAsmop (NULL, derefaop, ic, TRUE);
7206 freeAsmop (result, NULL, ic, TRUE);
7208 if (ifx && !ifx->generated)
7210 genIfxJump (ifx, "a");
7215 /*-----------------------------------------------------------------*/
7216 /* genDataPointerGet - generates code when ptr offset is known */
7217 /*-----------------------------------------------------------------*/
7219 genDataPointerGet (operand * left,
7227 D(emitcode ("; genDataPointerGet",""));
7229 aopOp (result, ic, TRUE);
7230 size = AOP_SIZE (result);
7232 derefaop = aopDerefAop (AOP (left));
7233 freeAsmop (left, NULL, ic, TRUE);
7234 derefaop->size = size;
7239 transferAopAop (derefaop, size, AOP (result), size);
7241 loadRegFromAop (hc08_reg_a, derefaop, size);
7244 freeAsmop (NULL, derefaop, ic, TRUE);
7245 freeAsmop (result, NULL, ic, TRUE);
7247 if (ifx && !ifx->generated)
7249 genIfxJump (ifx, "a");
7254 /*-----------------------------------------------------------------*/
7255 /* genPointerGet - generate code for pointer get */
7256 /*-----------------------------------------------------------------*/
7258 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7260 operand *left = IC_LEFT (ic);
7261 operand *result = IC_RESULT (ic);
7263 sym_link *retype = getSpec (operandType (result));
7265 D(emitcode ("; genPointerGet",""));
7267 if (getSize (operandType (result))>1)
7270 aopOp (left, ic, FALSE);
7272 /* if left is rematerialisable and
7273 result is not bit variable type */
7274 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7276 if (!IS_BITVAR (retype))
7278 genDataPointerGet (left, result, ic, ifx);
7283 genUnpackBitsImmed (left, result, ic, ifx);
7288 /* if the operand is already in hx
7289 then we do nothing else we move the value to hx */
7290 if (AOP_TYPE (left) != AOP_STR)
7292 /* if this is remateriazable */
7293 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7296 /* so hx now contains the address */
7297 aopOp (result, ic, FALSE);
7299 /* if bit then unpack */
7300 if (IS_BITVAR (retype))
7301 genUnpackBits (result, ifx);
7304 size = AOP_SIZE (result);
7309 accopWithMisc ("lda", ",x");
7312 emitcode ("aix", "#1");
7313 hc08_dirtyReg (hc08_reg_hx, FALSE);
7316 storeRegToAop (hc08_reg_a, AOP (result), offset);
7318 hc08_freeReg (hc08_reg_a);
7322 freeAsmop (left, NULL, ic, TRUE);
7323 freeAsmop (result, NULL, ic, TRUE);
7326 aopOp (IC_RESULT (pi), pi, FALSE);
7327 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7328 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7332 if (ifx && !ifx->generated)
7334 genIfxJump (ifx, "a");
7337 hc08_freeReg (hc08_reg_hx);
7341 /*-----------------------------------------------------------------*/
7342 /* genPackBits - generates code for packed bit storage */
7343 /*-----------------------------------------------------------------*/
7345 genPackBits (sym_link * etype,
7348 int offset = 0; /* source byte offset */
7349 int rlen = 0; /* remaining bitfield length */
7350 int blen; /* bitfield length */
7351 int bstr; /* bitfield starting bit within byte */
7352 int litval; /* source literal value (if AOP_LIT) */
7353 unsigned char mask; /* bitmask within current byte */
7356 D(emitcode ("; genPackBits",""));
7358 blen = SPEC_BLEN (etype);
7359 bstr = SPEC_BSTR (etype);
7361 /* If the bitfield length is less than a byte */
7364 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7365 (unsigned char) (0xFF >> (8 - bstr)));
7367 if (AOP_TYPE (right) == AOP_LIT)
7369 /* Case with a bitfield length <8 and literal source
7371 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7373 litval &= (~mask) & 0xff;
7375 emitcode ("lda", ",x");
7376 if ((mask|litval)!=0xff)
7377 emitcode ("and","#0x%02x", mask);
7379 emitcode ("ora","#0x%02x", litval);
7380 hc08_dirtyReg (hc08_reg_a, FALSE);
7381 emitcode ("sta", ",x");
7383 hc08_freeReg (hc08_reg_a);
7387 /* Case with a bitfield length < 8 and arbitrary source
7389 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7390 /* shift and mask source value */
7392 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7393 hc08_dirtyReg (hc08_reg_a, FALSE);
7394 pushReg (hc08_reg_a, TRUE);
7396 emitcode ("lda", ",x");
7397 emitcode ("and", "#0x%02x", mask);
7398 emitcode ("ora", "1,s");
7399 emitcode ("sta", ",x");
7400 pullReg (hc08_reg_a);
7402 hc08_freeReg (hc08_reg_a);
7406 /* Bit length is greater than 7 bits. In this case, copy */
7407 /* all except the partial byte at the end */
7408 for (rlen=blen;rlen>=8;rlen-=8)
7410 if (AOP (right)->type == AOP_DIR)
7412 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7417 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7418 emitcode ("sta", "%d,x", offset);
7423 /* If there was a partial byte at the end */
7426 mask = (((unsigned char) -1 << rlen) & 0xff);
7428 if (AOP_TYPE (right) == AOP_LIT)
7430 /* Case with partial byte and literal source
7432 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7433 litval >>= (blen-rlen);
7434 litval &= (~mask) & 0xff;
7435 emitcode ("lda", "%d,x", offset - xoffset);
7436 hc08_dirtyReg (hc08_reg_a, FALSE);
7437 if ((mask|litval)!=0xff)
7438 emitcode ("and","#0x%02x", mask);
7440 emitcode ("ora","#0x%02x", litval);
7441 emitcode ("sta", "%d,x", offset - xoffset);
7442 hc08_dirtyReg (hc08_reg_a, FALSE);
7443 hc08_freeReg (hc08_reg_a);
7447 /* Case with partial byte and arbitrary source
7449 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7450 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7451 hc08_dirtyReg (hc08_reg_a, FALSE);
7452 pushReg (hc08_reg_a, TRUE);
7454 emitcode ("lda", "%d,x", offset - xoffset);
7455 emitcode ("and", "#0x%02x", mask);
7456 emitcode ("ora", "1,s");
7457 emitcode ("sta", "%d,x", offset - xoffset);
7458 pullReg (hc08_reg_a);
7461 hc08_freeReg (hc08_reg_a);
7464 /*-----------------------------------------------------------------*/
7465 /* genPackBitsImmed - generates code for packed bit storage */
7466 /*-----------------------------------------------------------------*/
7468 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7472 int offset = 0; /* source byte offset */
7473 int rlen = 0; /* remaining bitfield length */
7474 int blen; /* bitfield length */
7475 int bstr; /* bitfield starting bit within byte */
7476 int litval; /* source literal value (if AOP_LIT) */
7477 unsigned char mask; /* bitmask within current byte */
7479 D(emitcode ("; genPackBitsImmed",""));
7481 blen = SPEC_BLEN (etype);
7482 bstr = SPEC_BSTR (etype);
7484 aopOp (right, ic, FALSE);
7485 size = AOP_SIZE (right);
7487 derefaop = aopDerefAop (AOP (result));
7488 freeAsmop (result, NULL, ic, TRUE);
7489 derefaop->size = size;
7491 /* if the bitfield is a single bit in the direct page */
7492 if (blen == 1 && derefaop->type == AOP_DIR)
7494 if (AOP_TYPE (right) == AOP_LIT)
7496 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7498 emitcode ((litval & 1) ? "bset" : "bclr",
7499 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7503 symbol *tlbl1 = newiTempLabel (NULL);
7504 symbol *tlbl2 = newiTempLabel (NULL);
7506 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7507 emitcode ("bit", "#1");
7508 emitBranch ("bne", tlbl1);
7509 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7510 emitBranch ("bra", tlbl2);
7512 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7514 hc08_freeReg (hc08_reg_a);
7519 /* If the bitfield length is less than a byte */
7522 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7523 (unsigned char) (0xFF >> (8 - bstr)));
7525 if (AOP_TYPE (right) == AOP_LIT)
7527 /* Case with a bitfield length <8 and literal source
7529 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7531 litval &= (~mask) & 0xff;
7533 loadRegFromAop (hc08_reg_a, derefaop, 0);
7534 if ((mask|litval)!=0xff)
7535 emitcode ("and","#0x%02x", mask);
7537 emitcode ("ora","#0x%02x", litval);
7538 hc08_dirtyReg (hc08_reg_a, FALSE);
7539 storeRegToAop (hc08_reg_a, derefaop, 0);
7541 hc08_freeReg (hc08_reg_a);
7545 /* Case with a bitfield length < 8 and arbitrary source
7547 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7548 /* shift and mask source value */
7550 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7551 hc08_dirtyReg (hc08_reg_a, FALSE);
7552 pushReg (hc08_reg_a, TRUE);
7554 loadRegFromAop (hc08_reg_a, derefaop, 0);
7555 emitcode ("and", "#0x%02x", mask);
7556 emitcode ("ora", "1,s");
7557 storeRegToAop (hc08_reg_a, derefaop, 0);
7558 pullReg (hc08_reg_a);
7560 hc08_freeReg (hc08_reg_a);
7564 /* Bit length is greater than 7 bits. In this case, copy */
7565 /* all except the partial byte at the end */
7566 for (rlen=blen;rlen>=8;rlen-=8)
7568 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7572 /* If there was a partial byte at the end */
7575 mask = (((unsigned char) -1 << rlen) & 0xff);
7577 if (AOP_TYPE (right) == AOP_LIT)
7579 /* Case with partial byte and literal source
7581 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7582 litval >>= (blen-rlen);
7583 litval &= (~mask) & 0xff;
7584 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7585 if ((mask|litval)!=0xff)
7586 emitcode ("and","#0x%02x", mask);
7588 emitcode ("ora","#0x%02x", litval);
7589 hc08_dirtyReg (hc08_reg_a, FALSE);
7590 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7591 hc08_dirtyReg (hc08_reg_a, FALSE);
7592 hc08_freeReg (hc08_reg_a);
7596 /* Case with partial byte and arbitrary source
7598 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7599 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7600 hc08_dirtyReg (hc08_reg_a, FALSE);
7601 pushReg (hc08_reg_a, TRUE);
7603 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7604 emitcode ("and", "#0x%02x", mask);
7605 emitcode ("ora", "1,s");
7606 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7607 pullReg (hc08_reg_a);
7610 hc08_freeReg (hc08_reg_a);
7613 freeAsmop (right, NULL, ic, TRUE);
7614 freeAsmop (NULL, derefaop, ic, TRUE);
7617 /*-----------------------------------------------------------------*/
7618 /* genDataPointerSet - remat pointer to data space */
7619 /*-----------------------------------------------------------------*/
7621 genDataPointerSet (operand * right,
7628 D(emitcode ("; genDataPointerSet",""));
7630 aopOp (right, ic, FALSE);
7631 size = AOP_SIZE (right);
7633 derefaop = aopDerefAop (AOP (result));
7634 freeAsmop (result, NULL, ic, TRUE);
7635 derefaop->size = size;
7639 transferAopAop (AOP (right), size, derefaop, size);
7642 freeAsmop (right, NULL, ic, TRUE);
7643 freeAsmop (NULL, derefaop, ic, TRUE);
7647 /*-----------------------------------------------------------------*/
7648 /* genPointerSet - stores the value into a pointer location */
7649 /*-----------------------------------------------------------------*/
7651 genPointerSet (iCode * ic, iCode *pi)
7653 operand *right = IC_RIGHT (ic);
7654 operand *result = IC_RESULT (ic);
7655 sym_link *type, *etype;
7657 sym_link *retype = getSpec (operandType (right));
7658 sym_link *letype = getSpec (operandType (result));
7660 D(emitcode ("; genPointerSet",""));
7662 type = operandType (result);
7663 etype = getSpec (type);
7665 aopOp (result, ic, FALSE);
7667 /* if the result is rematerializable */
7668 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7670 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7672 genDataPointerSet (right, result, ic);
7677 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7682 /* if the operand is already in hx
7683 then we do nothing else we move the value to hx */
7684 if (AOP_TYPE (result) != AOP_STR)
7686 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7688 /* so hx now contains the address */
7689 aopOp (right, ic, FALSE);
7691 /* if bit then unpack */
7692 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7693 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7696 size = AOP_SIZE (right);
7701 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7702 accopWithMisc ("sta", ",x");
7705 emitcode ("aix", "#1");
7707 hc08_freeReg (hc08_reg_a);
7711 freeAsmop (result, NULL, ic, TRUE);
7712 freeAsmop (right, NULL, ic, TRUE);
7715 aopOp (IC_RESULT (pi), pi, FALSE);
7716 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7717 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7721 hc08_freeReg (hc08_reg_hx);
7725 /*-----------------------------------------------------------------*/
7726 /* genIfx - generate code for Ifx statement */
7727 /*-----------------------------------------------------------------*/
7729 genIfx (iCode * ic, iCode * popIc)
7731 operand *cond = IC_COND (ic);
7734 D(emitcode ("; genIfx",""));
7736 aopOp (cond, ic, FALSE);
7738 /* If the condition is a literal, we can just do an unconditional */
7739 /* branch or no branch */
7740 if (AOP_TYPE (cond) == AOP_LIT)
7742 unsigned long lit = (unsigned long) floatFromVal (AOP (cond)->aopu.aop_lit);
7743 freeAsmop (cond, NULL, ic, TRUE);
7745 /* if there was something to be popped then do it */
7751 emitBranch ("jmp", IC_TRUE (ic));
7756 emitBranch ("jmp", IC_FALSE (ic));
7762 /* get the value into acc */
7763 if (AOP_TYPE (cond) != AOP_CRY)
7764 asmopToBool (AOP (cond), FALSE);
7767 /* the result is now in the accumulator */
7768 freeAsmop (cond, NULL, ic, TRUE);
7770 /* if there was something to be popped then do it */
7774 /* if the condition is a bit variable */
7775 if (isbit && IS_ITEMP (cond) &&
7777 genIfxJump (ic, SPIL_LOC (cond)->rname);
7778 else if (isbit && !IS_ITEMP (cond))
7779 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7781 genIfxJump (ic, "a");
7786 /*-----------------------------------------------------------------*/
7787 /* genAddrOf - generates code for address of */
7788 /*-----------------------------------------------------------------*/
7790 genAddrOf (iCode * ic)
7792 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7795 D(emitcode ("; genAddrOf",""));
7797 aopOp (IC_RESULT (ic), ic, FALSE);
7799 /* if the operand is on the stack then we
7800 need to get the stack offset of this
7804 /* if it has an offset then we need to compute it */
7805 offset = _G.stackOfs + _G.stackPushes + sym->stack;
7806 hc08_useReg (hc08_reg_hx);
7807 emitcode ("tsx", "");
7808 while (offset > 127)
7810 emitcode ("aix", "#127");
7813 while (offset < -128)
7815 emitcode ("aix", "#-128");
7818 emitcode ("aix", "#%d", offset);
7819 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7820 hc08_freeReg (hc08_reg_hx);
7825 /* object not on stack then we need the name */
7826 size = AOP_SIZE (IC_RESULT (ic));
7831 char s[SDCC_NAME_MAX+10];
7834 sprintf (s, "#%s", sym->rname);
7837 sprintf (s, "#>%s", sym->rname);
7840 sprintf (s, "#(%s >> %d)",
7844 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7848 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7852 /*-----------------------------------------------------------------*/
7853 /* genAssign - generate code for assignment */
7854 /*-----------------------------------------------------------------*/
7856 genAssign (iCode * ic)
7858 operand *result, *right;
7860 // unsigned long lit = 0L;
7862 D(emitcode("; genAssign",""));
7864 result = IC_RESULT (ic);
7865 right = IC_RIGHT (ic);
7867 /* if they are the same */
7868 if (operandsEqu (result, right)) {
7872 aopOp (right, ic, FALSE);
7873 aopOp (result, ic, TRUE);
7875 /* if they are the same registers */
7876 if (sameRegs (AOP (right), AOP (result)))
7879 if ((AOP_TYPE (right) == AOP_LIT)
7880 && (IS_AOP_HX(AOP(result))))
7882 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7887 size = AOP_SIZE (result);
7890 transferAopAop (AOP (right), size, AOP (result), size);
7894 freeAsmop (right, NULL, ic, TRUE);
7895 freeAsmop (result, NULL, ic, TRUE);
7898 /*-----------------------------------------------------------------*/
7899 /* genJumpTab - generates code for jump table */
7900 /*-----------------------------------------------------------------*/
7902 genJumpTab (iCode * ic)
7905 symbol *jtablo = newiTempLabel (NULL);
7906 symbol *jtabhi = newiTempLabel (NULL);
7908 D(emitcode ("; genJumpTab",""));
7910 aopOp (IC_JTCOND (ic), ic, FALSE);
7912 if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7914 /* get the condition into x */
7915 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7916 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7917 loadRegFromConst (hc08_reg_h, zero);
7919 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7920 emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7921 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7922 emitcode ("jmp", ",x");
7924 hc08_dirtyReg (hc08_reg_a, TRUE);
7925 hc08_dirtyReg (hc08_reg_hx, TRUE);
7930 pushReg(hc08_reg_hx, TRUE);
7932 /* get the condition into x */
7933 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7934 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7935 loadRegFromConst (hc08_reg_h, zero);
7937 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7938 emitcode ("sta", "3,s");
7939 emitcode ("lda", "%05d$,x", jtablo->key + 100);
7940 emitcode ("sta", "4,s");
7942 pullReg(hc08_reg_hx);
7943 emitcode ("rts", "");
7944 _G.stackPushes += 2;
7948 /* now generate the jump labels */
7950 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7951 jtab = setNextItem (IC_JTLABELS (ic)))
7952 emitcode (".db", "%05d$", jtab->key + 100);
7954 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7955 jtab = setNextItem (IC_JTLABELS (ic)))
7956 emitcode (".db", ">%05d$", jtab->key + 100);
7960 /*-----------------------------------------------------------------*/
7961 /* genCast - gen code for casting */
7962 /*-----------------------------------------------------------------*/
7964 genCast (iCode * ic)
7966 operand *result = IC_RESULT (ic);
7967 sym_link *ctype = operandType (IC_LEFT (ic));
7968 sym_link *rtype = operandType (IC_RIGHT (ic));
7969 operand *right = IC_RIGHT (ic);
7972 D(emitcode("; genCast",""));
7974 /* if they are equivalent then do nothing */
7975 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7978 aopOp (right, ic, FALSE);
7979 aopOp (result, ic, FALSE);
7982 /* if they are the same size : or less */
7983 if (AOP_SIZE (result) <= AOP_SIZE (right))
7986 /* if they are in the same place */
7988 if (sameRegs (AOP (right), AOP (result)))
7992 /* if they in different places then copy */
7993 size = AOP_SIZE (result);
7997 transferAopAop(AOP (right), offset, AOP (result), offset);
8004 /* if the result is of type pointer */
8009 sym_link *type = operandType (right);
8010 sym_link *etype = getSpec (type);
8012 /* pointer to generic pointer */
8013 if (IS_GENPTR (ctype))
8016 p_type = DCL_TYPE (type);
8019 if (SPEC_SCLS(etype)==S_REGISTER) {
8020 // let's assume it is a generic pointer
8023 /* we have to go by the storage class */
8024 p_type = PTR_TYPE (SPEC_OCLS (etype));
8028 /* the first two bytes are known */
8029 size = GPTRSIZE - 1;
8033 transferAopAop(AOP (right), offset, AOP (result), offset);
8036 /* the last byte depending on type */
8039 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8044 // pointerTypeToGPByte will have bitched.
8048 sprintf(gpValStr, "#0x%x", gpVal);
8049 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8055 /* just copy the pointers */
8056 size = AOP_SIZE (result);
8060 transferAopAop(AOP (right), offset, AOP (result), offset);
8066 /* so we now know that the size of destination is greater
8067 than the size of the source */
8068 /* we move to result for the size of source */
8069 size = AOP_SIZE (right);
8073 transferAopAop(AOP (right), offset, AOP (result), offset);
8077 /* now depending on the sign of the source && destination */
8078 size = AOP_SIZE (result) - AOP_SIZE (right);
8079 /* if unsigned or not an integral type */
8080 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8083 storeConstToAop (zero, AOP (result), offset++);
8087 /* we need to extend the sign :{ */
8088 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
8089 accopWithMisc ("rola", "");
8090 accopWithMisc ("clra", "");
8091 accopWithMisc ("sbc", zero);
8093 storeRegToAop (hc08_reg_a, AOP (result), offset++);
8096 /* we are done hurray !!!! */
8099 freeAsmop (right, NULL, ic, TRUE);
8100 freeAsmop (result, NULL, ic, TRUE);
8104 /*-----------------------------------------------------------------*/
8105 /* genDjnz - generate decrement & jump if not zero instrucion */
8106 /*-----------------------------------------------------------------*/
8108 genDjnz (iCode * ic, iCode * ifx)
8114 D(emitcode ("; genDjnz",""));
8116 /* if the if condition has a false label
8117 then we cannot save */
8121 /* if the minus is not of the form
8123 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8124 !IS_OP_LITERAL (IC_RIGHT (ic)))
8127 if (operandLitValue (IC_RIGHT (ic)) != 1)
8130 /* dbnz doesn't support extended mode */
8131 if (isOperandInFarSpace (IC_RESULT (ic)))
8134 /* if the size of this greater than one then no
8136 // if (getSize (operandType (IC_RESULT (ic))) > 1)
8138 aopOp (IC_RESULT (ic), ic, FALSE);
8139 if (AOP_SIZE (IC_RESULT (ic))>1)
8141 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8145 /* otherwise we can save BIG */
8146 lbl = newiTempLabel (NULL);
8147 lbl1 = newiTempLabel (NULL);
8150 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
8153 emitBranch ("bra", lbl1);
8155 emitBranch ("jmp", IC_TRUE (ifx));
8158 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8163 /*-----------------------------------------------------------------*/
8164 /* genReceive - generate code for a receive iCode */
8165 /*-----------------------------------------------------------------*/
8167 genReceive (iCode * ic)
8171 D(emitcode ("; genReceive",""));
8173 aopOp (IC_RESULT (ic), ic, FALSE);
8174 size = AOP_SIZE (IC_RESULT (ic));
8179 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
8180 AOP (IC_RESULT (ic)), offset);
8181 if (hc08_aop_pass[offset]->type == AOP_REG)
8182 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
8187 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8190 /*-----------------------------------------------------------------*/
8191 /* genDummyRead - generate code for dummy read of volatiles */
8192 /*-----------------------------------------------------------------*/
8194 genDummyRead (iCode * ic)
8199 D(emitcode("; genDummyRead",""));
8202 if (op && IS_SYMOP (op))
8205 aopOp (op, ic, FALSE);
8207 size = AOP_SIZE (op);
8212 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8213 hc08_freeReg (hc08_reg_a);
8217 freeAsmop (op, NULL, ic, TRUE);
8220 if (op && IS_SYMOP (op))
8223 aopOp (op, ic, FALSE);
8225 size = AOP_SIZE (op);
8230 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8231 hc08_freeReg (hc08_reg_a);
8235 freeAsmop (op, NULL, ic, TRUE);
8239 /*-----------------------------------------------------------------*/
8240 /* genCritical - generate code for start of a critical sequence */
8241 /*-----------------------------------------------------------------*/
8243 genCritical (iCode *ic)
8245 D(emitcode("; genCritical",""));
8248 aopOp (IC_RESULT (ic), ic, TRUE);
8250 emitcode ("tpa", "");
8251 hc08_dirtyReg (hc08_reg_a, FALSE);
8252 emitcode ("sei", "");
8255 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8257 pushReg (hc08_reg_a, FALSE);
8259 hc08_freeReg (hc08_reg_a);
8261 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8264 /*-----------------------------------------------------------------*/
8265 /* genEndCritical - generate code for end of a critical sequence */
8266 /*-----------------------------------------------------------------*/
8268 genEndCritical (iCode *ic)
8270 D(emitcode("; genEndCritical",""));
8274 aopOp (IC_RIGHT (ic), ic, FALSE);
8275 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8276 emitcode ("tap", "");
8277 hc08_freeReg (hc08_reg_a);
8278 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8282 pullReg (hc08_reg_a);
8283 emitcode ("tap", "");
8289 /*-----------------------------------------------------------------*/
8290 /* genhc08Code - generate code for HC08 based controllers */
8291 /*-----------------------------------------------------------------*/
8293 genhc08Code (iCode * lic)
8300 lineHead = lineCurr = NULL;
8302 /* print the allocation information */
8303 if (allocInfo && currFunc)
8304 printAllocInfo (currFunc, codeOutFile);
8305 /* if debug information required */
8306 if (options.debug && currFunc)
8308 debugFile->writeFunction (currFunc, lic);
8311 if (IS_STATIC (currFunc->etype))
8312 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8314 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8318 /* stack pointer name */
8319 if (options.useXstack)
8324 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8326 hc08_aop_pass[0] = newAsmop (AOP_REG);
8327 hc08_aop_pass[0]->size=1;
8328 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8329 hc08_aop_pass[1] = newAsmop (AOP_REG);
8330 hc08_aop_pass[1]->size=1;
8331 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8332 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8333 hc08_aop_pass[2]->size=1;
8334 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8335 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8336 hc08_aop_pass[3]->size=1;
8337 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8339 for (ic = lic; ic; ic = ic->next)
8342 _G.current_iCode = ic;
8344 if (ic->level != clevel || ic->block != cblock)
8348 debugFile->writeScope(ic);
8354 if (ic->lineno && cln != ic->lineno)
8358 debugFile->writeCLine(ic);
8361 emitcode ("", "C$%s$%d$%d$%d ==.",
8362 FileBaseName (ic->filename), ic->lineno,
8363 ic->level, ic->block);
8367 if (!options.noCcodeInAsm) {
8368 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8369 printCLine(ic->filename, ic->lineno));
8373 if (options.iCodeInAsm) {
8377 for (i=0; i<6; i++) {
8378 sprintf (®sInUse[i],
8379 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8382 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8384 /* if the result is marked as
8385 spilt and rematerializable or code for
8386 this has already been generated then
8388 if (resultRemat (ic) || ic->generated)
8396 for (i=A_IDX;i<=XA_IDX;i++)
8398 reg = hc08_regWithIdx(i);
8400 emitcode("","; %s = %s offset %d", reg->name,
8401 aopName(reg->aop), reg->aopofs);
8404 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8406 sym = OP_SYMBOL (IC_LEFT (ic));
8407 if (sym->accuse == ACCUSE_HX)
8409 hc08_reg_h->isFree = FALSE;
8410 hc08_reg_x->isFree = FALSE;
8412 else if (sym->accuse == ACCUSE_XA)
8414 hc08_reg_a->isFree = FALSE;
8416 hc08_reg_x->isFree = FALSE;
8419 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8421 sym = OP_SYMBOL (IC_RIGHT (ic));
8422 if (sym->accuse == ACCUSE_HX)
8424 hc08_reg_h->isFree = FALSE;
8425 hc08_reg_x->isFree = FALSE;
8427 else if (sym->accuse == ACCUSE_XA)
8429 hc08_reg_a->isFree = FALSE;
8431 hc08_reg_x->isFree = FALSE;
8436 /* depending on the operation */
8456 /* IPOP happens only when trying to restore a
8457 spilt live range, if there is an ifx statement
8458 following this pop then the if statement might
8459 be using some of the registers being popped which
8460 would destory the contents of the register so
8461 we need to check for this condition and handle it */
8463 ic->next->op == IFX &&
8464 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8465 genIfx (ic->next, ic);
8483 genEndFunction (ic);
8499 if (!genPointerGetSetOfs (ic))
8504 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8524 genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
8529 genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
8541 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8545 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8549 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8576 case GET_VALUE_AT_ADDRESS:
8578 hasInc (IC_LEFT (ic), ic,
8579 getSize (operandType (IC_RESULT (ic)))),
8580 ifxForOp (IC_RESULT (ic), ic) );
8584 if (POINTER_SET (ic))
8585 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8611 addSet (&_G.sendSet, ic);
8614 case DUMMY_READ_VOLATILE:
8623 genEndCritical (ic);
8634 if (!hc08_reg_a->isFree)
8635 D(emitcode("","; forgot to free a"));
8636 if (!hc08_reg_x->isFree)
8637 D(emitcode("","; forgot to free x"));
8638 if (!hc08_reg_h->isFree)
8639 D(emitcode("","; forgot to free h"));
8640 if (!hc08_reg_hx->isFree)
8641 D(emitcode("","; forgot to free hx"));
8642 if (!hc08_reg_xa->isFree)
8643 D(emitcode("","; forgot to free xa"));
8646 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8649 /* now we are ready to call the
8650 peep hole optimizer */
8651 if (!options.nopeep)
8652 peepHole (&lineHead);
8654 /* now do the actual printing */
8655 printLine (lineHead, codeOutFile);