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);
49 static char *zero = "#0x00";
50 static char *one = "#0x01";
54 {"a", "x", "_ret2", "_ret3"};
55 unsigned fReturnSizeHC08 = 4; /* shared with ralloc.c */
56 char **fReturn2 = fReturnhc08;
74 static asmop *hc08_aop_pass[4];
76 extern int hc08_ptrRegReq;
77 extern int hc08_nRegs;
78 extern FILE *codeOutFile;
79 //static void saveRBank (int, iCode *, bool);
80 static bool operandsEqu (operand * op1, operand * op2);
81 static void loadRegFromConst (regs *reg, char *c);
82 static char *aopName (asmop *aop);
83 static asmop * newAsmop (short type);
84 static char * aopAdrStr (asmop * aop, int loffset, bool bit16);
85 #define RESULTONSTACK(x) \
86 (IC_RESULT(x) && IC_RESULT(x)->aop && \
87 IC_RESULT(x)->aop->type == AOP_STK )
89 #define IS_AOP_HX(x) \
90 (((x)->type == AOP_REG) \
91 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
92 && ((x)->aopu.aop_reg[1] == hc08_reg_h) )
94 #define IS_AOP_XA(x) \
95 (((x)->type == AOP_REG) \
96 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
97 && ((x)->aopu.aop_reg[1] == hc08_reg_x) )
100 (((x)->type == AOP_REG) \
101 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
102 && ((x)->size == 1) )
104 #define IS_AOP_X(x) \
105 (((x)->type == AOP_REG) \
106 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
107 && ((x)->size == 1) )
109 #define IS_AOP_H(x) \
110 (((x)->type == AOP_REG) \
111 && ((x)->aopu.aop_reg[0] == hc08_reg_h) \
112 && ((x)->size == 1) )
114 #define CLRC emitcode("clc","")
116 static lineNode *lineHead = NULL;
117 static lineNode *lineCurr = NULL;
120 static unsigned char SLMask[] =
121 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
122 0xE0, 0xC0, 0x80, 0x00};
123 static unsigned char SRMask[] =
124 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
125 0x07, 0x03, 0x01, 0x00};
133 #define AOP(op) op->aop
134 #define AOP_TYPE(op) AOP(op)->type
135 #define AOP_SIZE(op) AOP(op)->size
136 #define AOP_OP(aop) aop->op
139 /*-----------------------------------------------------------------*/
140 /* emitcode - writes the code into a file : for now it is simple */
141 /*-----------------------------------------------------------------*/
143 emitcode (char *inst, char *fmt,...)
146 char lb[INITIAL_INLINEASM];
154 sprintf (lb, "%s\t", inst);
156 sprintf (lb, "%s", inst);
157 vsprintf (lb + (strlen (lb)), fmt, ap);
160 vsprintf (lb, fmt, ap);
162 while (isspace (*lbp))
166 lineCurr = (lineCurr ?
167 connectLine (lineCurr, newLineNode (lb)) :
168 (lineHead = newLineNode (lb)));
169 lineCurr->isInline = _G.inLine;
170 lineCurr->isDebug = _G.debugLine;
172 //printf("%s\n", lb);
177 emitBranch (char *branchop, symbol *tlbl)
179 emitcode (branchop, "%05d$", (tlbl->key + 100));
183 emitLabel (symbol *tlbl)
185 emitcode ("", "%05d$:", (tlbl->key +100));
190 /*--------------------------------------------------------------------------*/
191 /* transferRegReg - Transfer from register(s) sreg to register(s) dreg. If */
192 /* freesrc is true, sreg is marked free and available for */
193 /* reuse. sreg and dreg must be of equal size */
194 /*--------------------------------------------------------------------------*/
196 transferRegReg (regs *sreg, regs *dreg, bool freesrc)
202 /* Nothing to do if no destination. */
206 /* But it's definately an error if there's no source. */
209 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
210 "NULL sreg in transferRegReg");
214 emitcode ("", "; transferRegReg(%s,%s)",
215 sreg->name, dreg->name);
228 case H_IDX: /* H to A */
229 emitcode ("pshh", "");
230 emitcode ("pula", "");
232 case X_IDX: /* X to A */
233 emitcode ("txa", "");
242 case A_IDX: /* A to H */
243 emitcode ("psha", "");
244 emitcode ("pulh", "");
246 case X_IDX: /* X to H */
247 emitcode ("pshx", "");
248 emitcode ("pulh", "");
257 case A_IDX: /* A to X */
258 emitcode ("tax", "");
260 case H_IDX: /* H to X */
261 emitcode ("pshh", "");
262 emitcode ("pulx", "");
271 case XA_IDX: /* XA to HX */
272 emitcode ("pshx", "");
273 emitcode ("pulh", "");
274 emitcode ("tax", "");
283 case HX_IDX: /* HX to XA */
284 emitcode ("txa", "");
285 emitcode ("pshh", "");
286 emitcode ("pulx", "");
296 wassertl (!error, "bad combo in transferRegReg");
301 dreg->aop = sreg->aop;
302 dreg->aopofs = sreg->aopofs;
303 dreg->isFree = FALSE;
307 /*--------------------------------------------------------------------------*/
308 /* pushReg - Push register reg onto the stack. If freereg is true, reg is */
309 /* marked free and available for reuse. */
310 /*--------------------------------------------------------------------------*/
312 pushReg (regs *reg, bool freereg)
314 int regidx = reg->rIdx;
319 emitcode ("psha", "");
323 emitcode ("pshx", "");
327 emitcode ("pshh", "");
331 emitcode ("pshx", "");
332 emitcode ("pshh", "");
336 emitcode ("psha", "");
337 emitcode ("pshx", "");
345 return -_G.stackOfs-_G.stackPushes;
348 /*--------------------------------------------------------------------------*/
349 /* pullReg - Pull register reg off the stack. */
350 /*--------------------------------------------------------------------------*/
354 int regidx = reg->rIdx;
359 emitcode ("pula", "");
363 emitcode ("pulx", "");
367 emitcode ("pulh", "");
371 emitcode ("pulx", "");
372 emitcode ("pulh", "");
376 emitcode ("pula", "");
377 emitcode ("pulx", "");
384 hc08_dirtyReg(reg, FALSE);
387 /*--------------------------------------------------------------------------*/
388 /* pullNull - Discard n bytes off the top of the stack */
389 /*--------------------------------------------------------------------------*/
395 emitcode("ais","#%d",n);
400 /*--------------------------------------------------------------------------*/
401 /* pushRegIfUsed - Push register reg if marked in use. Returns true if the */
402 /* push was performed, false otherwise. */
403 /*--------------------------------------------------------------------------*/
405 pushRegIfUsed (regs *reg)
416 /*--------------------------------------------------------------------------*/
417 /* pullOrFreeReg - If needpull is true, register reg is pulled from the */
418 /* stack. Otherwise register reg is marked as free. */
419 /*--------------------------------------------------------------------------*/
421 pullOrFreeReg (regs *reg, bool needpull)
429 /*--------------------------------------------------------------------------*/
430 /* adjustStack - Adjust the stack pointer by n bytes. */
431 /*--------------------------------------------------------------------------*/
440 emitcode ("ais","#127");
445 emitcode ("ais","#-128");
450 emitcode ("ais", "#%d", n);
457 /*--------------------------------------------------------------------------*/
458 /* aopName - Return a string with debugging information about an asmop. */
459 /*--------------------------------------------------------------------------*/
463 static char buffer[256];
467 return "(asmop*)NULL";
472 sprintf (buf,"IMMD(%s)", aop->aopu.aop_immd.aop_immd1);
475 sprintf (buf,"LIT(%s)", aopLiteral (aop->aopu.aop_lit, 0));
478 sprintf (buf,"DIR(%s)", aop->aopu.aop_dir);
481 sprintf (buf,"EXT(%s)", aop->aopu.aop_dir);
484 sprintf (buf,"SOF(%s)", OP_SYMBOL (aop->op)->name);
487 sprintf (buf, "REG(%s,%s,%s,%s)",
488 aop->aopu.aop_reg[3] ? aop->aopu.aop_reg[3]->name : "-",
489 aop->aopu.aop_reg[2] ? aop->aopu.aop_reg[2]->name : "-",
490 aop->aopu.aop_reg[1] ? aop->aopu.aop_reg[1]->name : "-",
491 aop->aopu.aop_reg[0] ? aop->aopu.aop_reg[0]->name : "-");
498 sprintf (buf,"?%d", aop->type);
506 /*--------------------------------------------------------------------------*/
507 /* loadRegFromAop - Load register reg from logical offset loffset of aop. */
508 /*--------------------------------------------------------------------------*/
510 loadRegFromAop (regs *reg, asmop *aop, int loffset)
512 int regidx = reg->rIdx;
514 if (aop->stacked && aop->stk_aop[loffset])
516 loadRegFromAop (reg, aop->stk_aop[loffset], 0);
521 printf("loadRegFromAop called\n");
524 printf(" reg = NULL\n");
527 printf(" reg = %s\n", reg->name);
530 printf(" aop = NULL\n");
533 printf(" aop->type = %d\n", aop->type);
534 printf(" loffset = %d\n", loffset);
537 printf(" aop has operand link\n");
539 printf(" aop missing operand link\n");
541 printf(" reg has operand link\n");
543 printf(" reg missing operand link\n");
546 emitcode ("", "; loadRegFromAop (%s, %s, %d)",
547 reg->name, aopName (aop), loffset);
549 /* If operand is volatile, we cannot optimize. */
550 if (!aop->op || isOperandVolatile (aop->op, FALSE))
554 /* If this register already has this offset of the operand
555 then we need only mark it as in use. */
556 if (reg->aop && reg->aop->op && aop->op
557 && operandsEqu(reg->aop->op,aop->op)
558 && (reg->aopofs == loffset))
561 emitcode ("","; already had correct value for %s", reg->name);
565 /* TODO: check to see if we can transfer from another register */
567 if (hc08_reg_h->aop && hc08_reg_h->aop->op && aop->op
568 && operandsEqu(hc08_reg_h->aop->op,aop->op)
569 && (hc08_reg_h->aopofs == loffset))
571 emitcode ("","; found correct value for %s in h", reg->name);
572 transferRegReg (hc08_reg_h, reg, FALSE);
578 if (hc08_reg_x->aop && hc08_reg_x->aop->op && aop->op
579 && operandsEqu(hc08_reg_x->aop->op,aop->op)
580 && (hc08_reg_x->aopofs == loffset))
582 emitcode ("","; found correct value for %s in x", reg->name);
583 transferRegReg (hc08_reg_x, reg, FALSE);
588 if (hc08_reg_a->aop && hc08_reg_a->aop->op && aop->op
589 && operandsEqu(hc08_reg_a->aop->op,aop->op)
590 && (hc08_reg_a->aopofs == loffset))
592 emitcode ("","; found correct value for %s in a", reg->name);
593 transferRegReg (hc08_reg_a, reg, FALSE);
603 if (aop->type == AOP_REG)
605 if (loffset < aop->size)
606 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
608 emitcode ("clra", ""); /* TODO: handle sign extension */
611 emitcode ("lda","%s", aopAdrStr (aop, loffset, FALSE));
614 if (aop->type == AOP_REG)
616 if (loffset < aop->size)
617 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
619 emitcode ("clrx", ""); /* TODO: handle sign extension */
622 emitcode ("ldx","%s", aopAdrStr (aop, loffset, FALSE));
625 if (hc08_reg_a->isFree)
627 loadRegFromAop (hc08_reg_a, aop, loffset);
628 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
630 else if (hc08_reg_x->isFree)
632 loadRegFromAop (hc08_reg_x, aop, loffset);
633 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
637 pushReg (hc08_reg_a, TRUE);
638 loadRegFromAop (hc08_reg_a, aop, loffset);
639 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
640 pullReg (hc08_reg_a);
646 else if (IS_AOP_XA(aop))
647 transferRegReg (hc08_reg_xa, hc08_reg_hx, FALSE);
648 else if ((aop->type == AOP_DIR))
650 if (aop->size>(loffset+1))
651 emitcode ("ldhx","%s", aopAdrStr (aop, loffset+1, TRUE));
654 loadRegFromAop (hc08_reg_x, aop, loffset);
655 loadRegFromConst (hc08_reg_h, zero);
658 else if ((aop->type == AOP_LIT) || (aop->type == AOP_IMMD))
660 emitcode ("ldhx","%s", aopAdrStr (aop, loffset, TRUE));
665 needpula = pushRegIfUsed (hc08_reg_a);
666 loadRegFromAop (hc08_reg_a, aop, loffset+1);
667 loadRegFromAop (hc08_reg_x, aop, loffset);
668 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
669 pullOrFreeReg (hc08_reg_a, needpula);
675 else if (IS_AOP_HX(aop))
676 transferRegReg (hc08_reg_hx, hc08_reg_xa, FALSE);
679 loadRegFromAop (hc08_reg_a, aop, loffset);
680 loadRegFromAop (hc08_reg_x, aop, loffset+1);
685 // ignore caching for now
688 reg->aopofs = loffset;
693 /*--------------------------------------------------------------------------*/
694 /* forceStackedAop - Reserve space on the stack for asmop aop; when */
695 /* freeAsmop is called with aop, the stacked data will */
696 /* be copied to the original aop location and */
697 /*--------------------------------------------------------------------------*/
699 forceStackedAop (asmop *aop)
702 asmop *newaop = newAsmop (aop->type);
703 memcpy (newaop, aop, sizeof(*newaop));
705 emitcode("", "; forcedStackAop %s", aopName(aop));
706 for (loffset=0; loffset < newaop->size; loffset++)
708 asmop *aopsof = newAsmop (AOP_SOF);
710 aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE);
711 aopsof->op = aop->op;
712 newaop->stk_aop[loffset] = aopsof;
719 /*--------------------------------------------------------------------------*/
720 /* storeRegToAop - Store register reg to logical offset loffset of aop. */
721 /*--------------------------------------------------------------------------*/
723 storeRegToAop (regs *reg, asmop *aop, int loffset)
725 int regidx = reg->rIdx;
731 emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
732 reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr);
734 if ((reg->rIdx == HX_IDX) && aop->stacked
735 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
737 storeRegToAop (hc08_reg_h, aop, loffset+1);
738 storeRegToAop (hc08_reg_x, aop, loffset);
742 if ((reg->rIdx == XA_IDX) && aop->stacked
743 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
745 storeRegToAop (hc08_reg_x, aop, loffset+1);
746 storeRegToAop (hc08_reg_a, aop, loffset);
750 if (aop->stacked && aop->stk_aop[loffset])
752 storeRegToAop (reg, aop->stk_aop[loffset], 0);
756 if (aop->type == AOP_STR)
759 transferRegReg (reg, hc08_reg_x, FALSE);
761 transferRegReg (reg, hc08_reg_h, FALSE);
768 if ((aop->type == AOP_REG) && (loffset < aop->size))
769 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
771 emitcode ("sta","%s", aopAdrStr (aop, loffset, FALSE));
774 if ((aop->type == AOP_REG) && (loffset < aop->size))
775 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
777 emitcode ("stx","%s", aopAdrStr (aop, loffset, FALSE));
780 if (hc08_reg_a->isFree)
782 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
783 storeRegToAop (hc08_reg_a, aop, loffset);
784 hc08_freeReg (hc08_reg_a);
786 else if (hc08_reg_x->isFree)
788 transferRegReg (hc08_reg_h, hc08_reg_x, FALSE);
789 storeRegToAop (hc08_reg_x, aop, loffset);
790 hc08_freeReg (hc08_reg_x);
794 pushReg (hc08_reg_a, TRUE);
795 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
796 storeRegToAop (hc08_reg_a, aop, loffset);
797 pullReg (hc08_reg_a);
801 if ((aop->type == AOP_DIR) )
803 emitcode("sthx","%s", aopAdrStr (aop, loffset+1, TRUE));
805 else if (IS_AOP_XA(aop))
806 transferRegReg(reg, hc08_reg_xa, FALSE);
807 else if (IS_AOP_HX(aop))
812 needpula = pushRegIfUsed (hc08_reg_a);
813 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
814 storeRegToAop (hc08_reg_a, aop, loffset+1);
815 storeRegToAop (hc08_reg_x, aop, loffset);
816 pullOrFreeReg (hc08_reg_a, needpula);
821 transferRegReg(reg, hc08_reg_hx, FALSE);
822 else if (IS_AOP_XA(aop))
826 storeRegToAop (hc08_reg_a, aop, loffset);
827 storeRegToAop (hc08_reg_x, aop, loffset+1);
832 /* Disable the register tracking for now */
834 //if (!reg->aop || (reg->aop && (reg->aop != aop)))
837 for (otheridx=0;otheridx<hc08_nRegs;otheridx++)
839 otherreg=hc08_regWithIdx(otheridx);
840 if (otherreg && otherreg->aop
841 && otherreg->aop->op && aop->op
842 && operandsEqu(otherreg->aop->op,aop->op)
843 && (otherreg->aopofs == loffset))
845 emitcode("","; marking %s stale", otherreg->name);
849 if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
851 hc08_reg_hx->aop = NULL;
852 emitcode("","; marking hx stale");
854 if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
856 hc08_reg_xa->aop = NULL;
857 emitcode("","; marking xa stale");
861 reg->aopofs = loffset;
866 /*--------------------------------------------------------------------------*/
867 /* loadRegFromConst - Load register reg from constant c. */
868 /*--------------------------------------------------------------------------*/
870 loadRegFromConst (regs *reg, char *c)
876 emitcode ("clra", "");
878 emitcode ("lda", "%s", c);
882 emitcode ("clrx", "");
884 emitcode ("ldx", "%s", c);
888 emitcode ("clrh", "");
889 else if (hc08_reg_a->isFree)
891 loadRegFromConst (hc08_reg_a, c);
892 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
894 else if (hc08_reg_x->isFree)
896 loadRegFromConst (hc08_reg_x, c);
897 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
901 pushReg (hc08_reg_a, TRUE);
902 loadRegFromConst (hc08_reg_a, c);
903 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
904 pullReg (hc08_reg_a);
908 emitcode ("ldhx", "%s", c);
911 emitcode ("lda", "%s", c);
912 emitcode ("ldx", "%s >> 8", c);
915 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
916 "Bad rIdx in loadRegFromConst");
923 /*--------------------------------------------------------------------------*/
924 /* storeConstToAop- Store constant c to logical offset loffset of asmop aop.*/
925 /*--------------------------------------------------------------------------*/
927 storeConstToAop (char *c, asmop *aop, int loffset)
929 if (aop->stacked && aop->stk_aop[loffset])
931 storeConstToAop (c, aop->stk_aop[loffset], 0);
939 emitcode ("clr", "%s", aopAdrStr (aop, loffset, FALSE));
941 emitcode ("mov", "%s,%s", c, aopAdrStr (aop, loffset, FALSE));
944 if (loffset>(aop->size-1))
946 loadRegFromConst (aop->aopu.aop_reg[loffset], c);
949 if (hc08_reg_a->isFree)
951 loadRegFromConst (hc08_reg_a, c);
952 storeRegToAop( hc08_reg_a, aop, loffset);
953 hc08_freeReg (hc08_reg_a);
955 else if (hc08_reg_x->isFree)
957 loadRegFromConst (hc08_reg_x, c);
958 storeRegToAop( hc08_reg_x, aop, loffset);
959 hc08_freeReg (hc08_reg_x);
963 pushReg (hc08_reg_a, TRUE);
964 loadRegFromConst (hc08_reg_a, c);
965 storeRegToAop( hc08_reg_a, aop, loffset);
966 pullReg (hc08_reg_a);
972 /*--------------------------------------------------------------------------*/
973 /* storeRegSignToUpperAop - If isSigned is true, the sign bit of register */
974 /* reg is extended to fill logical offsets loffset */
975 /* and above of asmop aop. Otherwise, logical */
976 /* offsets loffset and above of asmop aop are */
977 /* zeroed. reg must be an 8-bit register. */
978 /*--------------------------------------------------------------------------*/
980 storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned)
982 // int regidx = reg->rIdx;
983 int size = aop->size;
992 storeConstToAop(zero, aop, loffset++);
997 transferRegReg (reg, hc08_reg_a, FALSE);
998 emitcode ("rola","");
999 emitcode ("clra","");
1000 emitcode ("sbc", "#0");
1001 hc08_useReg (hc08_reg_a);
1002 while (loffset<size)
1003 storeRegToAop (hc08_reg_a, aop, loffset++);
1004 hc08_freeReg (hc08_reg_a);
1008 /*--------------------------------------------------------------------------*/
1009 /* storeRegToFullAop - Store register reg to asmop aop with appropriate */
1010 /* padding and/or truncation as needed. If isSigned is */
1011 /* true, sign extension will take place in the padding. */
1012 /*--------------------------------------------------------------------------*/
1014 storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
1016 int regidx = reg->rIdx;
1017 int size = aop->size;
1024 storeRegToAop (reg, aop, 0);
1025 storeRegSignToUpperAop (reg, aop, 1, isSigned);
1030 storeRegToAop (hc08_reg_x, aop, 0);
1034 storeRegToAop (reg, aop, 0);
1035 storeRegSignToUpperAop (hc08_reg_h, aop, 2, isSigned);
1041 storeRegToAop (hc08_reg_a, aop, 0);
1045 storeRegToAop (reg, aop, 0);
1046 storeRegSignToUpperAop (hc08_reg_x, aop, 2, isSigned);
1052 /*--------------------------------------------------------------------------*/
1053 /* transferAopAop - Transfer the value at logical offset srcofs of asmop */
1054 /* srcaop to logical offset dstofs of asmop dstofs. */
1055 /*--------------------------------------------------------------------------*/
1057 transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
1059 bool needpula = FALSE;
1062 bool keepreg = FALSE;
1064 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1066 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1070 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1072 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1076 // emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1077 // aopName (srcaop), srcofs, aopName (dstaop), dstofs);
1078 // emitcode ("", "; srcaop->type = %d", srcaop->type);
1079 // emitcode ("", "; dstaop->type = %d", dstaop->type);
1081 if (dstofs >= dstaop->size)
1084 if ((dstaop->type == AOP_DIR)
1085 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1087 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1088 aopAdrStr(dstaop, dstofs, FALSE));
1092 if (dstaop->type == AOP_REG)
1094 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1095 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1097 reg = dstaop->aopu.aop_reg[dstofs];
1102 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1104 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1105 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1107 reg = srcaop->aopu.aop_reg[srcofs];
1114 if (hc08_reg_a->isFree)
1116 else if (hc08_reg_x->isFree)
1120 pushReg (hc08_reg_a, TRUE);
1126 loadRegFromAop (reg, srcaop, srcofs);
1127 storeRegToAop (reg, dstaop, dstofs);
1130 pullOrFreeReg (hc08_reg_a, needpula);
1134 /*--------------------------------------------------------------------------*/
1135 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1136 /* parameter param. */
1137 /*--------------------------------------------------------------------------*/
1139 accopWithMisc (char *accop, char *param)
1141 emitcode (accop, "%s", param);
1142 hc08_dirtyReg (hc08_reg_a, FALSE);
1145 /*--------------------------------------------------------------------------*/
1146 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1147 /* byte at logical offset loffset of asmop aop. */
1148 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1149 /*--------------------------------------------------------------------------*/
1151 accopWithAop (char *accop, asmop *aop, int loffset)
1153 if (aop->stacked && aop->stk_aop[loffset])
1155 accopWithAop (accop, aop->stk_aop[loffset], 0);
1159 if (aop->type == AOP_REG)
1161 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1162 emitcode (accop, "1,s");
1166 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1168 hc08_dirtyReg (hc08_reg_a, FALSE);
1172 /*--------------------------------------------------------------------------*/
1173 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1174 /* byte at logical offset loffset of asmop aop. Register reg */
1175 /* must be 8-bit. */
1176 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1177 /*--------------------------------------------------------------------------*/
1179 rmwWithReg (char *rmwop, regs *reg)
1182 char *rmwaop = rmwbuf;
1184 if (reg->rIdx == A_IDX)
1186 sprintf(rmwaop,"%sa", rmwop);
1187 emitcode (rmwaop, "");
1188 hc08_dirtyReg (hc08_reg_a, FALSE);
1190 else if (reg->rIdx == X_IDX)
1192 sprintf(rmwaop,"%sx", rmwop);
1193 emitcode (rmwaop, "");
1194 hc08_dirtyReg (hc08_reg_a, FALSE);
1196 else if (hc08_reg_a->isFree)
1198 transferRegReg(reg, hc08_reg_a, FALSE);
1199 sprintf(rmwaop,"%sa", rmwop);
1200 emitcode (rmwaop, "");
1201 hc08_dirtyReg (hc08_reg_a, FALSE);
1202 transferRegReg(hc08_reg_a, reg, TRUE);
1206 pushReg (reg, FALSE);
1207 emitcode (rmwop, "1,s");
1209 hc08_dirtyReg (reg, FALSE);
1213 /*--------------------------------------------------------------------------*/
1214 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1215 /* logical offset loffset of asmop aop. */
1216 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1217 /*--------------------------------------------------------------------------*/
1219 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1221 bool needpula = FALSE;
1223 if (aop->stacked && aop->stk_aop[loffset])
1225 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1232 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1235 needpula = pushRegIfUsed (hc08_reg_a);
1236 loadRegFromAop (hc08_reg_a, aop, loffset);
1237 rmwWithReg (rmwop, hc08_reg_a);
1238 storeRegToAop (hc08_reg_a, aop, loffset);
1239 pullOrFreeReg (hc08_reg_a, needpula);
1242 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1248 /*-----------------------------------------------------------------*/
1249 /* newAsmop - creates a new asmOp */
1250 /*-----------------------------------------------------------------*/
1252 newAsmop (short type)
1256 aop = Safe_calloc (1, sizeof (asmop));
1263 /*-----------------------------------------------------------------*/
1264 /* pointerCode - returns the code for a pointer type */
1265 /*-----------------------------------------------------------------*/
1267 pointerCode (sym_link * etype)
1270 return PTR_TYPE (SPEC_OCLS (etype));
1275 /*-----------------------------------------------------------------*/
1276 /* aopForSym - for a true symbol */
1277 /*-----------------------------------------------------------------*/
1279 aopForSym (iCode * ic, symbol * sym, bool result)
1284 wassertl (ic != NULL, "Got a null iCode");
1285 wassertl (sym != NULL, "Got a null symbol");
1287 // printf("in aopForSym for symbol %s\n", sym->name);
1289 space = SPEC_OCLS (sym->etype);
1291 /* if already has one */
1297 /* special case for a function */
1298 if (IS_FUNC (sym->type))
1300 sym->aop = aop = newAsmop (AOP_IMMD);
1301 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1302 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1303 aop->size = FPTRSIZE;
1307 /* if it is in direct space */
1308 if (IN_DIRSPACE (space))
1310 sym->aop = aop = newAsmop (AOP_DIR);
1311 aop->aopu.aop_dir = sym->rname;
1312 aop->size = getSize (sym->type);
1316 /* if it is in far space */
1317 if (IN_FARSPACE (space))
1319 sym->aop = aop = newAsmop (AOP_EXT);
1320 aop->aopu.aop_dir = sym->rname;
1321 aop->size = getSize (sym->type);
1325 if (IN_STACK (sym->etype))
1327 sym->aop = aop = newAsmop (AOP_SOF);
1328 aop->aopu.aop_dir = sym->rname;
1329 aop->size = getSize (sym->type);
1330 aop->aopu.aop_stk = sym->stack;
1336 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1337 "aopForSym should never reach here");
1341 /* if it is in code space */
1342 if (IN_CODESPACE (space))
1348 /*-----------------------------------------------------------------*/
1349 /* aopForRemat - rematerialzes an object */
1350 /*-----------------------------------------------------------------*/
1352 aopForRemat (symbol * sym)
1354 iCode *ic = sym->rematiCode;
1355 asmop *aop = newAsmop (AOP_IMMD);
1362 val += (int) operandLitValue (IC_RIGHT (ic));
1363 else if (ic->op == '-')
1364 val -= (int) operandLitValue (IC_RIGHT (ic));
1365 else if (IS_CAST_ICODE(ic)) {
1366 sym_link *from_type = operandType(IC_RIGHT(ic));
1367 aop->aopu.aop_immd.from_cast_remat = 1;
1368 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1369 ptr_type = DCL_TYPE(from_type);
1370 if (ptr_type == IPOINTER) {
1377 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1381 sprintf (buffer, "(%s %c 0x%04x)",
1382 OP_SYMBOL (IC_LEFT (ic))->rname,
1383 val >= 0 ? '+' : '-',
1384 abs (val) & 0xffff);
1386 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1388 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1389 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1390 /* set immd2 field if required */
1391 if (aop->aopu.aop_immd.from_cast_remat) {
1392 sprintf(buffer,"#0x%02x",ptr_type);
1393 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1394 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1400 /*-----------------------------------------------------------------*/
1401 /* regsInCommon - two operands have some registers in common */
1402 /*-----------------------------------------------------------------*/
1404 regsInCommon (operand * op1, operand * op2)
1406 symbol *sym1, *sym2;
1409 /* if they have registers in common */
1410 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1413 sym1 = OP_SYMBOL (op1);
1414 sym2 = OP_SYMBOL (op2);
1416 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1419 for (i = 0; i < sym1->nRegs; i++)
1425 for (j = 0; j < sym2->nRegs; j++)
1430 if (sym2->regs[j] == sym1->regs[i])
1438 /*-----------------------------------------------------------------*/
1439 /* operandsEqu - equivalent */
1440 /*-----------------------------------------------------------------*/
1442 operandsEqu (operand * op1, operand * op2)
1444 symbol *sym1, *sym2;
1446 /* if they not symbols */
1447 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1450 sym1 = OP_SYMBOL (op1);
1451 sym2 = OP_SYMBOL (op2);
1453 /* if both are itemps & one is spilt
1454 and the other is not then false */
1455 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1456 sym1->isspilt != sym2->isspilt)
1459 /* if they are the same */
1463 if (strcmp (sym1->rname, sym2->rname) == 0)
1467 /* if left is a tmp & right is not */
1468 if (IS_ITEMP (op1) &&
1471 (sym1->usl.spillLoc == sym2))
1474 if (IS_ITEMP (op2) &&
1478 (sym2->usl.spillLoc == sym1))
1484 /*-----------------------------------------------------------------*/
1485 /* sameRegs - two asmops have the same registers */
1486 /*-----------------------------------------------------------------*/
1488 sameRegs (asmop * aop1, asmop * aop2)
1495 // if (aop1->size != aop2->size)
1498 if (aop1->type == aop2->type)
1503 for (i = 0; i < aop1->size; i++)
1504 if (aop1->aopu.aop_reg[i] !=
1505 aop2->aopu.aop_reg[i])
1509 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1512 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1519 /*-----------------------------------------------------------------*/
1520 /* aopOp - allocates an asmop for an operand : */
1521 /*-----------------------------------------------------------------*/
1523 aopOp (operand * op, iCode * ic, bool result)
1532 // Is this a pointer set result?
1534 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1538 // printf("checking literal\n");
1539 /* if this a literal */
1540 if (IS_OP_LITERAL (op))
1542 op->aop = aop = newAsmop (AOP_LIT);
1543 aop->aopu.aop_lit = op->operand.valOperand;
1544 aop->size = getSize (operandType (op));
1546 aop->isaddr = op->isaddr;
1550 // printf("checking pre-existing\n");
1551 /* if already has a asmop then continue */
1555 op->aop->isaddr = op->isaddr;
1559 // printf("checking underlying sym\n");
1560 /* if the underlying symbol has a aop */
1561 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1563 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1564 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1565 //op->aop = aop = OP_SYMBOL (op)->aop;
1566 aop->size = getSize( operandType (op));
1567 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1568 //printf (" with size = %d\n", aop->size);
1571 aop->isaddr = op->isaddr;
1572 /* if (aop->isaddr & IS_ITEMP (op))
1574 aop->psize=aop->size;
1575 aop->size = getSize( operandType (op)->next);
1580 // printf("checking true sym\n");
1581 /* if this is a true symbol */
1582 if (IS_TRUE_SYMOP (op))
1584 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1586 aop->isaddr = op->isaddr;
1587 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1588 //printf (" with size = %d\n", aop->size);
1592 /* this is a temporary : this has
1598 e) can be a return use only */
1600 sym = OP_SYMBOL (op);
1602 // printf("checking conditional\n");
1603 /* if the type is a conditional */
1604 if (sym->regType == REG_CND)
1606 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1609 aop->isaddr = op->isaddr;
1613 // printf("checking spilt\n");
1614 /* if it is spilt then two situations
1616 b) has a spill location */
1617 if (sym->isspilt || sym->nRegs == 0)
1620 // printf("checking remat\n");
1621 /* rematerialize it NOW */
1624 sym->aop = op->aop = aop =
1626 aop->size = getSize (sym->type);
1628 aop->isaddr = op->isaddr;
1629 /* if (aop->isaddr & IS_ITEMP (op))
1631 aop->psize=aop->size;
1632 aop->size = getSize( operandType (op)->next);
1637 // printf("checking accuse\n");
1640 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1641 aop->size = getSize (sym->type);
1642 switch (sym->accuse)
1645 aop->aopu.aop_reg[0] = hc08_reg_a;
1646 aop->aopu.aop_reg[1] = hc08_reg_x;
1649 aop->aopu.aop_reg[0] = hc08_reg_x;
1650 aop->aopu.aop_reg[1] = hc08_reg_h;
1654 aop->isaddr = op->isaddr;
1658 // printf("checking ruonly\n");
1664 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1665 aop->size = getSize (sym->type);
1666 for (i = 0; i < fReturnSizeHC08; i++)
1667 aop->aopu.aop_str[i] = fReturn2[i];
1669 aop->isaddr = op->isaddr;
1673 /* else spill location */
1674 // printf("checking spill loc\n");
1675 // if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1676 if (sym->usl.spillLoc && sym->usl.spillLoc->aop
1677 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1679 /* force a new aop if sizes differ */
1680 sym->usl.spillLoc->aop = NULL;
1681 //printf ("forcing new aop\n");
1683 sym->aop = op->aop = aop =
1684 aopForSym (ic, sym->usl.spillLoc, result);
1685 aop->size = getSize (sym->type);
1687 aop->isaddr = op->isaddr;
1688 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1689 //printf (" with size = %d\n", aop->size);
1690 /* if (aop->isaddr & IS_ITEMP (op))
1692 aop->psize=aop->size;
1693 aop->size = getSize( operandType (op)->next);
1698 // printf("assuming register\n");
1699 /* must be in a register */
1700 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1701 aop->size = sym->nRegs;
1702 for (i = 0; i < sym->nRegs; i++)
1703 aop->aopu.aop_reg[i] = sym->regs[i];
1705 aop->isaddr = op->isaddr;
1709 /*-----------------------------------------------------------------*/
1710 /* freeAsmop - free up the asmop given to an operand */
1711 /*----------------------------------------------------------------*/
1713 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1735 emitcode ("","; freeAsmop restoring stacked %s", aopName(aop));
1738 for (loffset=0; loffset<aop->size; loffset++)
1739 if (aop->stk_aop[loffset])
1741 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1744 pullNull (stackAdjust);
1748 /* all other cases just dealloc */
1754 OP_SYMBOL (op)->aop = NULL;
1755 /* if the symbol has a spill */
1757 SPIL_LOC (op)->aop = NULL;
1763 /*-----------------------------------------------------------------*/
1764 /* aopDerefAop - treating the aop parameter as a pointer, return */
1765 /* an asmop for the object it references */
1766 /*-----------------------------------------------------------------*/
1768 aopDerefAop (asmop *aop)
1773 asmop *newaop = NULL;
1774 sym_link *type, *etype;
1777 emitcode ("", "; aopDerefAop(%s)", aopName(aop));
1781 type = operandType (aop->op);
1782 etype = getSpec (type);
1783 /* if op is of type of pointer then it is simple */
1784 if (IS_PTR (type) && !IS_FUNC (type->next))
1785 p_type = DCL_TYPE (type);
1788 /* we have to go by the storage class */
1789 p_type = PTR_TYPE (SPEC_OCLS (etype));
1798 if (p_type == POINTER)
1799 newaop = newAsmop (AOP_DIR);
1801 newaop = newAsmop (AOP_EXT);
1802 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1805 adr = (int) floatFromVal (aop->aopu.aop_lit);
1806 if (p_type == POINTER)
1811 newaop = newAsmop (AOP_DIR);
1812 sprintf (s, "0x%02x",adr);
1816 newaop = newAsmop (AOP_EXT);
1817 sprintf (s, "0x%04x",adr);
1819 rs = Safe_calloc (1, strlen (s) + 1);
1821 newaop->aopu.aop_dir = rs;
1824 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1825 "unsupported asmop");
1835 /*-----------------------------------------------------------------*/
1836 /* aopAdrStr - for referencing the address of the aop */
1837 /*-----------------------------------------------------------------*/
1839 aopAdrStr (asmop * aop, int loffset, bool bit16)
1843 int offset = aop->size - 1 - loffset;
1846 /* offset is greater than
1848 if (loffset > (aop->size - 1) &&
1849 aop->type != AOP_LIT)
1852 /* depending on type */
1857 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
1858 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1860 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1864 sprintf (s, "#(%s >> %d)",
1865 aop->aopu.aop_immd.aop_immd1,
1869 aop->aopu.aop_immd.aop_immd1);
1873 aop->aopu.aop_immd.aop_immd1);
1874 rs = Safe_calloc (1, strlen (s) + 1);
1880 sprintf (s, "*(%s + %d)",
1884 sprintf (s, "*%s", aop->aopu.aop_dir);
1885 rs = Safe_calloc (1, strlen (s) + 1);
1891 sprintf (s, "(%s + %d)",
1895 sprintf (s, "%s", aop->aopu.aop_dir);
1896 rs = Safe_calloc (1, strlen (s) + 1);
1901 return aop->aopu.aop_reg[loffset]->name;
1905 return aopLiteralLong (aop->aopu.aop_lit, loffset, 2);
1907 return aopLiteral (aop->aopu.aop_lit, loffset);
1911 return aop->aopu.aop_str[loffset];
1914 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
1916 rs = Safe_calloc (1, strlen (s) + 1);
1922 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1923 "aopAdrStr got unsupported aop->type");
1932 /*-----------------------------------------------------------------*/
1933 /* opIsGptr: returns non-zero if the passed operand is */
1934 /* a generic pointer type. */
1935 /*-----------------------------------------------------------------*/
1937 opIsGptr (operand * op)
1939 sym_link *type = operandType (op);
1941 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1949 /*-----------------------------------------------------------------*/
1950 /* getDataSize - get the operand data size */
1951 /*-----------------------------------------------------------------*/
1953 getDataSize (operand * op)
1956 size = AOP_SIZE (op);
1960 /*-----------------------------------------------------------------*/
1961 /* outAcc - output Acc */
1962 /*-----------------------------------------------------------------*/
1964 outAcc (operand * result)
1967 size = getDataSize (result);
1970 storeRegToAop (hc08_reg_a, AOP (result), 0);
1973 /* unsigned or positive */
1976 storeConstToAop (zero, AOP (result), offset++);
1981 /*-----------------------------------------------------------------*/
1982 /* outBitC - output a bit C */
1983 /*-----------------------------------------------------------------*/
1985 outBitC (operand * result)
1989 /* if the result is bit */
1990 if (AOP_TYPE (result) == AOP_CRY)
1991 aopPut (AOP (result), "c", 0);
1995 emitcode ("clra", "");
1996 emitcode ("rola", "");
2001 /*-----------------------------------------------------------------*/
2002 /* outBitNV - output a bit N^V */
2003 /*-----------------------------------------------------------------*/
2005 outBitNV (operand * result)
2007 symbol *tlbl, *tlbl1;
2009 tlbl = newiTempLabel (NULL);
2010 tlbl1 = newiTempLabel (NULL);
2012 emitBranch ("blt", tlbl);
2013 loadRegFromConst (hc08_reg_a, zero);
2014 emitBranch ("bra", tlbl1);
2016 loadRegFromConst (hc08_reg_a, one);
2022 /*-----------------------------------------------------------------*/
2023 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2024 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2025 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2026 /*-----------------------------------------------------------------*/
2028 asmopToBool (asmop *aop, bool resultInA)
2030 symbol *tlbl, *tlbl1;
2031 int size = aop->size;
2032 bool needpula = FALSE;
2033 bool flagsonly = TRUE;
2038 hc08_freeReg(hc08_reg_a);
2045 emitcode ("tsta", "");
2048 else if (IS_AOP_X(aop))
2049 emitcode ("tstx", "");
2050 else if (IS_AOP_H(aop))
2052 if (hc08_reg_a->isFree)
2054 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2055 emitcode ("tsta", "");
2057 hc08_freeReg(hc08_reg_a);
2059 else if (hc08_reg_x->isFree)
2061 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2062 emitcode ("tstx", "");
2063 hc08_freeReg(hc08_reg_x);
2067 emitcode ("pshh", "");
2068 emitcode ("tst", "1,s");
2069 emitcode ("ais", "#1");
2072 else if (IS_AOP_HX(aop))
2073 emitcode ("cphx", zero);
2074 else if (IS_AOP_XA(aop))
2076 symbol *tlbl = newiTempLabel (NULL);
2077 emitcode ("tsta", "");
2078 emitcode ("bne", "%05d$", (tlbl->key + 100));
2079 emitcode ("tstx", "");
2080 emitcode ("", "%05d$:", (tlbl->key + 100));
2083 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2084 "Bad rIdx in asmToBool");
2090 needpula = pushRegIfUsed (hc08_reg_a);
2091 loadRegFromAop (hc08_reg_a, aop, 0);
2092 for (offset=1; offset<size; offset++)
2093 accopWithAop ("ora", aop, offset);
2095 pullReg (hc08_reg_a);
2098 hc08_freeReg (hc08_reg_a);
2107 loadRegFromAop (hc08_reg_a, aop, 0);
2108 hc08_freeReg (hc08_reg_a);
2112 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2117 if (hc08_reg_a->isFree)
2119 loadRegFromAop (hc08_reg_a, aop, 0);
2120 accopWithAop ("ora", aop, 1);
2121 hc08_freeReg (hc08_reg_a);
2126 tlbl = newiTempLabel (NULL);
2127 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2128 emitcode ("bne", "%05d$", (tlbl->key + 100));
2129 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2130 emitcode ("", "%05d$:", (tlbl->key + 100));
2136 needpula = pushRegIfUsed (hc08_reg_a);
2137 loadRegFromAop (hc08_reg_a, aop, 0);
2138 for (offset=1; offset<size; offset++)
2139 accopWithAop ("ora", aop, offset);
2141 pullReg (hc08_reg_a);
2144 hc08_freeReg (hc08_reg_a);
2152 tlbl = newiTempLabel (NULL);
2156 tlbl1 = newiTempLabel (NULL);
2157 emitBranch ("bne", tlbl1);
2158 loadRegFromConst (hc08_reg_a, zero);
2159 emitBranch ("bra", tlbl);
2161 loadRegFromConst (hc08_reg_a, one);
2165 emitBranch ("beq", tlbl);
2166 loadRegFromConst (hc08_reg_a, one);
2169 hc08_useReg (hc08_reg_a);
2175 /*-----------------------------------------------------------------*/
2176 /* genNot - generate code for ! operation */
2177 /*-----------------------------------------------------------------*/
2181 D(emitcode ("; genNot",""));
2183 /* assign asmOps to operand & result */
2184 aopOp (IC_LEFT (ic), ic, FALSE);
2185 aopOp (IC_RESULT (ic), ic, TRUE);
2187 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2188 emitcode ("eor", one);
2189 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2191 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2192 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2196 /*-----------------------------------------------------------------*/
2197 /* genCpl - generate code for complement */
2198 /*-----------------------------------------------------------------*/
2204 regs* reg = hc08_reg_a;
2208 D(emitcode ("; genCpl",""));
2210 /* assign asmOps to operand & result */
2211 aopOp (IC_LEFT (ic), ic, FALSE);
2212 aopOp (IC_RESULT (ic), ic, TRUE);
2214 size = AOP_SIZE (IC_RESULT (ic));
2217 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2218 rmwWithReg ("com", reg);
2220 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2224 /* release the aops */
2225 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2226 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2229 /*-----------------------------------------------------------------*/
2230 /* genUminusFloat - unary minus for floating points */
2231 /*-----------------------------------------------------------------*/
2233 genUminusFloat (operand * op, operand * result)
2235 int size, offset = 0;
2238 D(emitcode ("; genUminusFloat",""));
2240 /* for this we just copy and then flip the bit */
2242 size = AOP_SIZE (op) - 1;
2248 needpula = pushRegIfUsed (hc08_reg_a);
2249 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2250 emitcode ("eor", "#0x80");
2251 hc08_useReg (hc08_reg_a);
2252 storeRegToAop (hc08_reg_a, AOP (result), offset);
2253 pullOrFreeReg (hc08_reg_a, needpula);
2256 transferAopAop (AOP (op), offset, AOP (result), offset);
2262 /*-----------------------------------------------------------------*/
2263 /* genUminus - unary minus code generation */
2264 /*-----------------------------------------------------------------*/
2266 genUminus (iCode * ic)
2269 sym_link *optype, *rtype;
2273 D(emitcode ("; genUminus",""));
2276 aopOp (IC_LEFT (ic), ic, FALSE);
2277 aopOp (IC_RESULT (ic), ic, TRUE);
2279 optype = operandType (IC_LEFT (ic));
2280 rtype = operandType (IC_RESULT (ic));
2282 /* if float then do float stuff */
2283 if (IS_FLOAT (optype))
2285 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2289 /* otherwise subtract from zero */
2290 size = AOP_SIZE (IC_LEFT (ic));
2295 needpula = pushRegIfUsed (hc08_reg_a);
2296 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2297 emitcode ("nega", "");
2298 hc08_freeReg (hc08_reg_a);
2299 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2300 SPEC_USIGN (operandType (IC_LEFT (ic))));
2301 pullOrFreeReg (hc08_reg_a, needpula);
2305 needpula = pushRegIfUsed (hc08_reg_a);
2309 loadRegFromConst (hc08_reg_a, zero);
2310 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2311 storeRegToAop (hc08_reg_a, AOP( IC_RESULT (ic)), offset++);
2314 storeRegSignToUpperAop (hc08_reg_a, AOP( IC_RESULT (ic)), offset,
2315 SPEC_USIGN (operandType (IC_LEFT (ic))));
2316 pullOrFreeReg (hc08_reg_a, needpula);
2322 /* release the aops */
2323 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2324 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2327 /*-----------------------------------------------------------------*/
2328 /* saveRegisters - will look for a call and save the registers */
2329 /*-----------------------------------------------------------------*/
2331 saveRegisters (iCode * lic)
2338 for (ic = lic; ic; ic = ic->next)
2339 if (ic->op == CALL || ic->op == PCALL)
2344 fprintf (stderr, "found parameter push with no function call\n");
2348 /* if the registers have been saved already or don't need to be then
2352 if (IS_SYMOP(IC_LEFT(ic)) &&
2353 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2354 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2357 /* safe the registers in use at this time but skip the
2358 ones for the result */
2359 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2360 hc08_rUmaskForOp (IC_RESULT(ic)));
2363 for (i = 0; i < hc08_nRegs; i++)
2365 if (bitVectBitValue (rsave, i))
2366 pushReg ( hc08_regWithIdx (i), FALSE);
2370 /*-----------------------------------------------------------------*/
2371 /* unsaveRegisters - pop the pushed registers */
2372 /*-----------------------------------------------------------------*/
2374 unsaveRegisters (iCode * ic)
2379 /* restore the registers in use at this time but skip the
2380 ones for the result */
2381 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2382 hc08_rUmaskForOp (IC_RESULT(ic)));
2384 for (i = hc08_nRegs; i >= 0; i--)
2386 if (bitVectBitValue (rsave, i))
2387 pullReg ( hc08_regWithIdx (i));
2393 /*-----------------------------------------------------------------*/
2395 /*-----------------------------------------------------------------*/
2397 pushSide (operand * oper, int size)
2402 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2403 pushReg ( hc08_reg_a, TRUE);
2407 /*-----------------------------------------------------------------*/
2408 /* assignResultValue - */
2409 /*-----------------------------------------------------------------*/
2411 assignResultValue (operand * oper)
2413 int size = AOP_SIZE (oper);
2417 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2418 if (hc08_aop_pass[offset]->type == AOP_REG)
2419 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2426 /*-----------------------------------------------------------------*/
2427 /* genIpush - genrate code for pushing this gets a little complex */
2428 /*-----------------------------------------------------------------*/
2430 genIpush (iCode * ic)
2432 int size, offset = 0;
2435 D(emitcode ("; genIpush",""));
2437 /* if this is not a parm push : ie. it is spill push
2438 and spill push is always done on the local stack */
2442 /* and the item is spilt then do nothing */
2443 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2446 aopOp (IC_LEFT (ic), ic, FALSE);
2447 size = AOP_SIZE (IC_LEFT (ic));
2449 /* push it on the stack */
2452 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2453 pushReg ( hc08_reg_a, TRUE);
2459 /* this is a paramter push: in this case we call
2460 the routine to find the call and save those
2461 registers that need to be saved */
2464 /* then do the push */
2465 aopOp (IC_LEFT (ic), ic, FALSE);
2468 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2469 size = AOP_SIZE (IC_LEFT (ic));
2472 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2473 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2475 if ((size==2) && hc08_reg_hx->isFree)
2477 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2478 pushReg (hc08_reg_hx, TRUE);
2485 // printf("loading %d\n", offset);
2486 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2487 // printf("pushing \n");
2488 pushReg (hc08_reg_a, TRUE);
2492 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2495 /*-----------------------------------------------------------------*/
2496 /* genIpop - recover the registers: can happen only for spilling */
2497 /*-----------------------------------------------------------------*/
2499 genIpop (iCode * ic)
2503 D(emitcode ("; genIpop",""));
2505 /* if the temp was not pushed then */
2506 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2509 aopOp (IC_LEFT (ic), ic, FALSE);
2510 size = AOP_SIZE (IC_LEFT (ic));
2514 pullReg (hc08_reg_a);
2515 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2517 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2521 /*-----------------------------------------------------------------*/
2522 /* genSend - gen code for SEND */
2523 /*-----------------------------------------------------------------*/
2524 static void genSend(set *sendSet)
2528 for (sic = setFirstItem (_G.sendSet); sic;
2529 sic = setNextItem (_G.sendSet)) {
2530 int size, offset = 0;
2531 aopOp (IC_LEFT (sic), sic, FALSE);
2532 size = AOP_SIZE (IC_LEFT (sic));
2537 transferAopAop( AOP (IC_LEFT (sic)), offset,
2538 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2542 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2546 /*-----------------------------------------------------------------*/
2547 /* genCall - generates a call statement */
2548 /*-----------------------------------------------------------------*/
2550 genCall (iCode * ic)
2553 // bool restoreBank = FALSE;
2554 // bool swapBanks = FALSE;
2556 D(emitcode("; genCall",""));
2558 dtype = operandType (IC_LEFT (ic));
2559 /* if send set is not empty the assign */
2562 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2563 genSend(reverseSet(_G.sendSet));
2565 genSend(_G.sendSet);
2571 /* if caller saves & we have not saved then */
2577 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2578 OP_SYMBOL (IC_LEFT (ic))->rname :
2579 OP_SYMBOL (IC_LEFT (ic))->name));
2582 /* if we need assign a result value */
2583 if ((IS_ITEMP (IC_RESULT (ic)) &&
2584 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2585 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2586 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2587 IS_TRUE_SYMOP (IC_RESULT (ic)))
2591 aopOp (IC_RESULT (ic), ic, FALSE);
2594 assignResultValue (IC_RESULT (ic));
2596 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2599 /* adjust the stack for parameters if
2603 pullNull (ic->parmBytes);
2606 /* if we had saved some registers then unsave them */
2607 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2608 unsaveRegisters (ic);
2612 /*-----------------------------------------------------------------*/
2613 /* -10l - generates a call by pointer statement */
2614 /*-----------------------------------------------------------------*/
2616 genPcall (iCode * ic)
2619 symbol *rlbl = newiTempLabel (NULL);
2620 symbol *tlbl = newiTempLabel (NULL);
2621 // bool restoreBank=FALSE;
2622 // bool swapBanks = FALSE;
2624 D(emitcode("; genPCall",""));
2626 /* if caller saves & we have not saved then */
2630 /* if we are calling a not _naked function that is not using
2631 the same register bank then we need to save the
2632 destination registers on the stack */
2633 dtype = operandType (IC_LEFT (ic))->next;
2635 /* now push the calling address */
2636 emitBranch ("bsr", tlbl);
2637 emitBranch ("bra", rlbl);
2640 /* Push the function's address */
2641 aopOp (IC_LEFT (ic), ic, FALSE);
2642 pushSide (IC_LEFT (ic), FPTRSIZE);
2643 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2645 /* if send set is not empty the assign */
2648 genSend(reverseSet(_G.sendSet));
2654 emitcode ("rts", "");
2659 /* if we need assign a result value */
2660 if ((IS_ITEMP (IC_RESULT (ic)) &&
2661 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2662 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2663 IS_TRUE_SYMOP (IC_RESULT (ic)))
2667 aopOp (IC_RESULT (ic), ic, FALSE);
2670 assignResultValue (IC_RESULT (ic));
2672 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2675 /* adjust the stack for parameters if
2679 pullNull (ic->parmBytes);
2682 /* if we hade saved some registers then
2684 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2685 unsaveRegisters (ic);
2688 /*-----------------------------------------------------------------*/
2689 /* resultRemat - result is rematerializable */
2690 /*-----------------------------------------------------------------*/
2692 resultRemat (iCode * ic)
2694 if (SKIP_IC (ic) || ic->op == IFX)
2697 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2699 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2700 if (sym->remat && !POINTER_SET (ic))
2707 #if defined(__BORLANDC__) || defined(_MSC_VER)
2708 #define STRCASECMP stricmp
2710 #define STRCASECMP strcasecmp
2713 /*-----------------------------------------------------------------*/
2714 /* inExcludeList - return 1 if the string is in exclude Reg list */
2715 /*-----------------------------------------------------------------*/
2717 regsCmp(void *p1, void *p2)
2719 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2723 inExcludeList (char *s)
2725 const char *p = setFirstItem(options.excludeRegsSet);
2727 if (p == NULL || STRCASECMP(p, "none") == 0)
2731 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2734 /*-----------------------------------------------------------------*/
2735 /* genFunction - generated code for function entry */
2736 /*-----------------------------------------------------------------*/
2738 genFunction (iCode * ic)
2742 int calleesaves_saved_register = -1;
2746 /* create the function header */
2747 emitcode (";", "-----------------------------------------");
2748 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2749 emitcode (";", "-----------------------------------------");
2751 emitcode ("", "%s:", sym->rname);
2752 ftype = operandType (IC_LEFT (ic));
2754 if (IFFUNC_ISNAKED(ftype))
2756 emitcode(";", "naked function: no prologue.");
2762 /* if this is an interrupt service routine then
2764 if (IFFUNC_ISISR (sym->type))
2767 if (!inExcludeList ("h"))
2768 emitcode ("pshh", "");
2772 /* if callee-save to be used for this function
2773 then save the registers being used in this function */
2774 if (IFFUNC_CALLEESAVES(sym->type))
2778 /* if any registers used */
2781 /* save the registers used */
2782 for (i = 0; i < sym->regsUsed->size; i++)
2784 if (bitVectBitValue (sym->regsUsed, i))
2786 /* remember one saved register for later usage */
2787 if (calleesaves_saved_register < 0)
2788 calleesaves_saved_register = i;
2789 pushReg (hc08_regWithIdx (i), FALSE);
2797 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2802 /* adjust the stack for the function */
2808 // werror (W_STACK_OVERFLOW, sym->name);
2812 _G.stackOfs = sym->stack;
2815 /* if critical function then turn interrupts off */
2816 if (IFFUNC_ISCRITICAL (ftype))
2818 if (IFFUNC_ARGS (ftype))
2820 /* Function was passed parameters, so make sure A is preserved */
2821 pushReg (hc08_reg_a, FALSE);
2822 pushReg (hc08_reg_a, FALSE);
2823 emitcode ("tpa", "");
2824 emitcode ("sta", "2,s");
2825 emitcode ("sei", "");
2826 pullReg (hc08_reg_a);
2830 /* No passed parameters, so A can be freely modified */
2831 emitcode ("tpa", "");
2832 pushReg (hc08_reg_a, TRUE);
2833 emitcode ("sei", "");
2839 /*-----------------------------------------------------------------*/
2840 /* genEndFunction - generates epilogue for functions */
2841 /*-----------------------------------------------------------------*/
2843 genEndFunction (iCode * ic)
2845 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2847 if (IFFUNC_ISNAKED(sym->type))
2849 emitcode(";", "naked function: no epilogue.");
2853 if (IFFUNC_ISCRITICAL (sym->type))
2855 if (!IS_VOID(sym->type->next))
2857 /* Function has return value, so make sure A is preserved */
2858 pushReg (hc08_reg_a, FALSE);
2859 emitcode ("lda", "2,s");
2860 emitcode ("tap", "");
2861 pullReg (hc08_reg_a);
2866 /* Function returns void, so A can be freely modified */
2867 pullReg (hc08_reg_a);
2868 emitcode ("tap", "");
2872 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2878 _G.stackPushes += sym->stack;
2879 adjustStack (sym->stack);
2883 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2887 if (IFFUNC_ISISR (sym->type))
2890 if (!inExcludeList ("h"))
2891 emitcode ("pulh", "");
2894 /* if debug then send end of function */
2895 if (options.debug && currFunc)
2898 emitcode ("", "C$%s$%d$%d$%d ==.",
2899 FileBaseName (ic->filename), currFunc->lastLine,
2900 ic->level, ic->block);
2901 if (IS_STATIC (currFunc->etype))
2902 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2904 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2908 emitcode ("rti", "");
2912 if (IFFUNC_CALLEESAVES(sym->type))
2916 /* if any registers used */
2919 /* save the registers used */
2920 for (i = sym->regsUsed->size; i >= 0; i--)
2922 if (bitVectBitValue (sym->regsUsed, i) ||
2923 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
2924 emitcode ("pop", "%s", hc08_regWithIdx (i)->dname);
2930 /* if debug then send end of function */
2931 if (options.debug && currFunc)
2934 emitcode ("", "C$%s$%d$%d$%d ==.",
2935 FileBaseName (ic->filename), currFunc->lastLine,
2936 ic->level, ic->block);
2937 if (IS_STATIC (currFunc->etype))
2938 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2940 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2944 emitcode ("rts", "");
2949 /*-----------------------------------------------------------------*/
2950 /* genRet - generate code for return statement */
2951 /*-----------------------------------------------------------------*/
2955 int size, offset = 0;
2958 D(emitcode ("; genRet",""));
2960 /* if we have no return value then
2961 just generate the "ret" */
2965 /* we have something to return then
2966 move the return value into place */
2967 aopOp (IC_LEFT (ic), ic, FALSE);
2968 size = AOP_SIZE (IC_LEFT (ic));
2974 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
2981 /* 4 byte return: store value in the global return variable */
2985 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
2986 STA (fReturn2[offset--], FALSE);
2987 hc08_freeReg (hc08_reg_a);
2991 /* 2 byte return: store value in x:a */
2992 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
2993 hc08_freeReg (hc08_reg_xa);
2996 /* 1 byte return: store value in a */
2997 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
2998 hc08_freeReg (hc08_reg_a);
3003 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3006 /* generate a jump to the return label
3007 if the next is not the return statement */
3008 if (!(ic->next && ic->next->op == LABEL &&
3009 IC_LABEL (ic->next) == returnLabel))
3011 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3015 /*-----------------------------------------------------------------*/
3016 /* genLabel - generates a label */
3017 /*-----------------------------------------------------------------*/
3019 genLabel (iCode * ic)
3024 /* For the high level labels we cannot depend on any */
3025 /* register's contents. Amnesia time. */
3026 for (i=A_IDX;i<=XA_IDX;i++)
3028 reg = hc08_regWithIdx(i);
3033 /* special case never generate */
3034 if (IC_LABEL (ic) == entryLabel)
3037 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3041 /*-----------------------------------------------------------------*/
3042 /* genGoto - generates a jmp */
3043 /*-----------------------------------------------------------------*/
3045 genGoto (iCode * ic)
3047 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3051 /*-----------------------------------------------------------------*/
3052 /* findLabelBackwards: walks back through the iCode chain looking */
3053 /* for the given label. Returns number of iCode instructions */
3054 /* between that label and given ic. */
3055 /* Returns zero if label not found. */
3056 /*-----------------------------------------------------------------*/
3058 findLabelBackwards (iCode * ic, int key)
3067 /* If we have any pushes or pops, we cannot predict the distance.
3068 I don't like this at all, this should be dealt with in the
3070 if (ic->op == IPUSH || ic->op == IPOP) {
3074 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3084 /*-----------------------------------------------------------------*/
3085 /* genPlusIncr :- does addition with increment if possible */
3086 /*-----------------------------------------------------------------*/
3088 genPlusIncr (iCode * ic)
3096 unsigned int size = getDataSize (IC_RESULT (ic));
3098 symbol *tlbl = NULL;
3100 left = IC_LEFT (ic);
3101 result = IC_RESULT (ic);
3103 /* will try to generate an increment */
3104 /* if the right side is not a literal
3106 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3109 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3111 emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left)));
3113 if ((IS_AOP_HX (AOP (left)) ||
3114 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3116 && (icount>=-128) && (icount<=127) && (size==2))
3118 needpulx = pushRegIfUsed (hc08_reg_x);
3119 needpulh = pushRegIfUsed (hc08_reg_h);
3120 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3121 emitcode ("aix","#%d", icount);
3122 hc08_dirtyReg (hc08_reg_hx, FALSE);
3123 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3124 pullOrFreeReg (hc08_reg_h, needpulh);
3125 pullOrFreeReg (hc08_reg_x, needpulx);
3129 emitcode ("", "; icount = %d, sameRegs=%d", icount,
3130 sameRegs (AOP (left), AOP (result)));
3132 if ((icount > 255) || (icount<0))
3135 if (!sameRegs (AOP (left), AOP (result)))
3138 D(emitcode ("; genPlusIncr",""));
3141 tlbl = newiTempLabel (NULL);
3146 rmwWithAop ("inc", AOP (result), 0);
3148 emitBranch ("bne", tlbl);
3152 needpula = pushRegIfUsed (hc08_reg_a);
3153 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3154 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3155 hc08_useReg (hc08_reg_a);
3156 storeRegToAop (hc08_reg_a, AOP (result), 0);
3157 hc08_freeReg (hc08_reg_a);
3159 emitBranch ("bcc", tlbl);
3161 for (offset=1; offset<size; offset++)
3163 rmwWithAop ("inc", AOP (result), offset);
3164 if ((offset+1)<size)
3165 emitBranch ("bne", tlbl);
3171 pullOrFreeReg (hc08_reg_a, needpula);
3178 /*-----------------------------------------------------------------*/
3179 /* genPlus - generates code for addition */
3180 /*-----------------------------------------------------------------*/
3182 genPlus (iCode * ic)
3184 int size, offset = 0;
3186 asmop *leftOp, *rightOp;
3188 /* special cases :- */
3190 D(emitcode ("; genPlus",""));
3192 aopOp (IC_LEFT (ic), ic, FALSE);
3193 aopOp (IC_RIGHT (ic), ic, FALSE);
3194 aopOp (IC_RESULT (ic), ic, TRUE);
3196 /* we want registers on the left and literals on the right */
3197 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3198 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3200 operand *t = IC_RIGHT (ic);
3201 IC_RIGHT (ic) = IC_LEFT (ic);
3206 /* if I can do an increment instead
3207 of add then GOOD for ME */
3208 if (genPlusIncr (ic) == TRUE)
3211 emitcode("","; left size = %d", getDataSize (IC_LEFT(ic)));
3212 emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic)));
3213 emitcode("","; result size = %d", getDataSize (IC_RESULT(ic)));
3215 size = getDataSize (IC_RESULT (ic));
3217 leftOp = AOP(IC_LEFT(ic));
3218 rightOp = AOP(IC_RIGHT(ic));
3224 loadRegFromAop (hc08_reg_a, leftOp, offset);
3225 accopWithAop(add, rightOp, offset);
3226 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3227 hc08_freeReg (hc08_reg_a);
3228 add = "adc"; /* further adds must propagate carry */
3232 // adjustArithmeticResult (ic);
3235 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3236 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3237 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3240 /*-----------------------------------------------------------------*/
3241 /* genMinusDec :- does subtraction with deccrement if possible */
3242 /*-----------------------------------------------------------------*/
3244 genMinusDec (iCode * ic)
3246 unsigned int icount;
3251 unsigned int size = getDataSize (IC_RESULT (ic));
3255 left = IC_LEFT (ic);
3256 result = IC_RESULT (ic);
3258 /* will try to generate an increment */
3259 /* if the right side is not a literal
3261 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3264 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3266 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3267 && (icount>=-127) && (icount<=128) && (size==2))
3269 needpulx = pushRegIfUsed (hc08_reg_x);
3270 needpulh = pushRegIfUsed (hc08_reg_h);
3271 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3272 emitcode ("aix","#%d", -icount);
3273 hc08_dirtyReg (hc08_reg_hx, FALSE);
3274 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3275 pullOrFreeReg (hc08_reg_h, needpulh);
3276 pullOrFreeReg (hc08_reg_x, needpulx);
3280 if ((icount > 1) || (icount<0))
3283 if (!sameRegs (AOP (left), AOP (result)))
3289 D(emitcode ("; genMinusDec",""));
3291 rmwWithAop ("dec", AOP (result), 0);
3296 /*-----------------------------------------------------------------*/
3297 /* addSign - complete with sign */
3298 /*-----------------------------------------------------------------*/
3300 addSign (operand * result, int offset, int sign)
3302 int size = (getDataSize (result) - offset);
3307 emitcode ("rola", "");
3308 emitcode ("clra", "");
3309 emitcode ("sbc", zero);
3311 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3315 storeConstToAop (zero, AOP (result), offset++);
3320 /*-----------------------------------------------------------------*/
3321 /* genMinus - generates code for subtraction */
3322 /*-----------------------------------------------------------------*/
3324 genMinus (iCode * ic)
3327 int size, offset = 0;
3329 D(emitcode ("; genMinus",""));
3331 aopOp (IC_LEFT (ic), ic, FALSE);
3332 aopOp (IC_RIGHT (ic), ic, FALSE);
3333 aopOp (IC_RESULT (ic), ic, TRUE);
3335 /* special cases :- */
3336 /* if I can do an decrement instead
3337 of subtract then GOOD for ME */
3338 if (genMinusDec (ic) == TRUE)
3341 size = getDataSize (IC_RESULT (ic));
3343 asmop *leftOp, *rightOp;
3345 leftOp = AOP(IC_LEFT(ic));
3346 rightOp = AOP(IC_RIGHT(ic));
3352 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3353 accopWithAop(sub, rightOp, offset);
3354 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3359 // adjustArithmeticResult (ic);
3362 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3363 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3364 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3369 /*-----------------------------------------------------------------*/
3370 /* genMultOneByte : 8*8=8/16 bit multiplication */
3371 /*-----------------------------------------------------------------*/
3373 genMultOneByte (operand * left,
3377 sym_link *opetype = operandType (result);
3378 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3379 int size=AOP_SIZE(result);
3380 bool negLiteral = FALSE;
3382 D(emitcode ("; genMultOneByte",""));
3384 if (size<1 || size>2) {
3385 // this should never happen
3386 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3387 AOP_SIZE(result), __FILE__, lineno);
3391 /* (if two literals: the value is computed before) */
3392 /* if one literal, literal on the right */
3393 if (AOP_TYPE (left) == AOP_LIT)
3398 //emitcode (";", "swapped left and right");
3401 if (SPEC_USIGN(opetype))
3403 // just an unsigned 8*8=8/16 multiply
3404 //emitcode (";","unsigned");
3406 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3407 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3408 emitcode ("mul", "");
3409 hc08_dirtyReg (hc08_reg_xa, FALSE);
3410 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3411 hc08_freeReg (hc08_reg_xa);
3416 // we have to do a signed multiply
3419 //emitcode (";", "signed");
3421 emitcode ("clr", "1,s");
3423 tlbl1 = newiTempLabel (NULL);
3424 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3425 emitcode ("tsta","");
3426 emitBranch ("bpl", tlbl1);
3427 emitcode ("inc", "1,s");
3428 rmwWithReg ("neg", hc08_reg_a);
3431 if (AOP_TYPE(right)==AOP_LIT)
3433 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3434 /* AND literal negative */
3436 emitcode ("ldx", "#0x%02x", -val);
3439 emitcode ("ldx", "#0x%02x", val);
3441 hc08_useReg (hc08_reg_x);
3445 tlbl2 = newiTempLabel (NULL);
3446 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3447 emitcode ("tstx", "");
3448 emitBranch ("bpl", tlbl2);
3449 emitcode ("inc", "1,s");
3450 rmwWithReg ("neg", hc08_reg_x);
3454 emitcode ("mul", "");
3455 hc08_dirtyReg (hc08_reg_xa, FALSE);
3457 tlbl3 = newiTempLabel (NULL);
3458 emitcode ("dec", "1,s");
3460 emitBranch ("bne", tlbl3);
3462 emitBranch ("beq", tlbl3);
3464 rmwWithReg ("neg", hc08_reg_a);
3467 tlbl4 = newiTempLabel (NULL);
3468 emitBranch ("bcc", tlbl4);
3469 rmwWithReg ("inc", hc08_reg_x);
3471 rmwWithReg ("neg", hc08_reg_x);
3476 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3477 hc08_freeReg (hc08_reg_xa);
3481 /*-----------------------------------------------------------------*/
3482 /* genMult - generates code for multiplication */
3483 /*-----------------------------------------------------------------*/
3485 genMult (iCode * ic)
3487 operand *left = IC_LEFT (ic);
3488 operand *right = IC_RIGHT (ic);
3489 operand *result = IC_RESULT (ic);
3491 D(emitcode ("; genMult",""));
3493 /* assign the amsops */
3494 aopOp (left, ic, FALSE);
3495 aopOp (right, ic, FALSE);
3496 aopOp (result, ic, TRUE);
3498 /* special cases first */
3499 /* if both are of size == 1 */
3500 // if (getSize(operandType(left)) == 1 &&
3501 // getSize(operandType(right)) == 1)
3502 if (AOP_SIZE (left) == 1 &&
3503 AOP_SIZE (right) == 1)
3505 genMultOneByte (left, right, result);
3509 /* should have been converted to function call */
3510 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3511 getSize(OP_SYMBOL(right)->type));
3512 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3517 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3518 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3519 freeAsmop (result, NULL, ic, TRUE);
3522 /*-----------------------------------------------------------------*/
3523 /* genDivOneByte : 8 bit division */
3524 /*-----------------------------------------------------------------*/
3526 genDivOneByte (operand * left,
3530 sym_link *opetype = operandType (result);
3532 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3534 bool negLiteral = FALSE;
3536 D(emitcode ("; genDivOneByte",""));
3538 size = AOP_SIZE (result);
3539 /* signed or unsigned */
3540 if (SPEC_USIGN (opetype))
3542 /* unsigned is easy */
3543 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3544 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3545 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3546 emitcode ("div", "");
3547 hc08_dirtyReg (hc08_reg_a, FALSE);
3548 hc08_dirtyReg (hc08_reg_h, FALSE);
3549 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3550 hc08_freeReg (hc08_reg_a);
3551 hc08_freeReg (hc08_reg_x);
3552 hc08_freeReg (hc08_reg_h);
3556 /* signed is a little bit more difficult */
3559 emitcode ("clr", "1,s");
3561 tlbl1 = newiTempLabel (NULL);
3562 tlbl2 = newiTempLabel (NULL);
3563 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3564 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3565 emitBranch ("bpl", tlbl1);
3566 emitcode ("inc", "1,s");
3567 rmwWithReg ("neg", hc08_reg_a);
3568 emitBranch ("bcc", tlbl2);
3569 rmwWithReg ("inc", hc08_reg_x);
3571 rmwWithReg ("neg", hc08_reg_x);
3572 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3575 if (AOP_TYPE(right)==AOP_LIT)
3577 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3578 /* AND literal negative */
3580 emitcode ("ldx", "#0x%02x", -val);
3583 emitcode ("ldx", "#0x%02x", val);
3585 hc08_useReg (hc08_reg_x);
3589 tlbl3 = newiTempLabel (NULL);
3590 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3591 emitBranch ("bpl", tlbl3);
3592 emitcode ("inc", "1,s");
3593 rmwWithReg ("neg", hc08_reg_x);
3597 emitcode ("div", "");
3598 hc08_dirtyReg (hc08_reg_x, FALSE);
3599 hc08_dirtyReg (hc08_reg_a, FALSE);
3600 hc08_dirtyReg (hc08_reg_h, FALSE);
3602 tlbl4 = newiTempLabel (NULL);
3603 emitcode ("dec", "1,s");
3605 emitBranch ("bne", tlbl4);
3607 emitBranch ("beq", tlbl4);
3608 rmwWithReg ("neg", hc08_reg_a);
3612 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3613 hc08_freeReg (hc08_reg_a);
3614 hc08_freeReg (hc08_reg_x);
3615 hc08_freeReg (hc08_reg_h);
3620 /*-----------------------------------------------------------------*/
3621 /* genDiv - generates code for division */
3622 /*-----------------------------------------------------------------*/
3626 operand *left = IC_LEFT (ic);
3627 operand *right = IC_RIGHT (ic);
3628 operand *result = IC_RESULT (ic);
3630 D(emitcode ("; genDiv",""));
3632 /* assign the amsops */
3633 aopOp (left, ic, FALSE);
3634 aopOp (right, ic, FALSE);
3635 aopOp (result, ic, TRUE);
3637 /* special cases first */
3638 /* if both are of size == 1 */
3639 if (AOP_SIZE (left) <= 2 &&
3640 AOP_SIZE (right) == 1)
3642 genDivOneByte (left, right, result);
3646 /* should have been converted to function call */
3649 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3650 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3651 freeAsmop (result, NULL, ic, TRUE);
3654 /*-----------------------------------------------------------------*/
3655 /* genModOneByte : 8 bit modulus */
3656 /*-----------------------------------------------------------------*/
3658 genModOneByte (operand * left,
3662 sym_link *opetype = operandType (result);
3664 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3666 bool negLiteral = FALSE;
3668 D(emitcode ("; genModOneByte",""));
3670 size = AOP_SIZE (result);
3671 /* signed or unsigned */
3672 if (SPEC_USIGN (opetype))
3674 /* unsigned is easy */
3675 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3676 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3677 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3678 emitcode ("div", "");
3679 hc08_dirtyReg (hc08_reg_a, FALSE);
3680 hc08_dirtyReg (hc08_reg_h, FALSE);
3681 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3682 hc08_freeReg (hc08_reg_a);
3683 hc08_freeReg (hc08_reg_x);
3684 hc08_freeReg (hc08_reg_h);
3688 /* signed is a little bit more difficult */
3691 emitcode ("clr", "1,s");
3693 tlbl1 = newiTempLabel (NULL);
3694 tlbl2 = newiTempLabel (NULL);
3695 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3696 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3697 emitBranch ("bpl", tlbl1);
3698 emitcode ("inc", "1,s");
3699 rmwWithReg ("neg", hc08_reg_a);
3700 emitBranch ("bcc", tlbl2);
3701 rmwWithReg ("inc", hc08_reg_x);
3703 rmwWithReg ("neg", hc08_reg_x);
3704 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3707 if (AOP_TYPE(right)==AOP_LIT)
3709 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3710 /* AND literal negative */
3712 emitcode ("ldx", "#0x%02x", -val);
3715 emitcode ("ldx", "#0x%02x", val);
3717 hc08_useReg (hc08_reg_x);
3721 tlbl3 = newiTempLabel (NULL);
3722 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3723 emitBranch ("bpl", tlbl3);
3724 emitcode ("inc", "1,s");
3725 rmwWithReg ("neg", hc08_reg_x);
3729 emitcode ("div", "");
3730 hc08_dirtyReg (hc08_reg_x, FALSE);
3731 hc08_dirtyReg (hc08_reg_a, FALSE);
3732 hc08_dirtyReg (hc08_reg_h, FALSE);
3734 tlbl4 = newiTempLabel (NULL);
3735 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
3736 emitcode ("dec", "1,s");
3738 emitBranch ("bne", tlbl4);
3740 emitBranch ("beq", tlbl4);
3741 rmwWithReg ("neg", hc08_reg_a);
3745 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3746 hc08_freeReg (hc08_reg_a);
3747 hc08_freeReg (hc08_reg_x);
3748 hc08_freeReg (hc08_reg_h);
3752 /*-----------------------------------------------------------------*/
3753 /* genMod - generates code for division */
3754 /*-----------------------------------------------------------------*/
3758 operand *left = IC_LEFT (ic);
3759 operand *right = IC_RIGHT (ic);
3760 operand *result = IC_RESULT (ic);
3762 D(emitcode ("; genMod",""));
3764 /* assign the amsops */
3765 aopOp (left, ic, FALSE);
3766 aopOp (right, ic, FALSE);
3767 aopOp (result, ic, TRUE);
3769 /* special cases first */
3770 /* if both are of size == 1 */
3771 if (AOP_SIZE (left) <= 2 &&
3772 AOP_SIZE (right) == 1)
3774 genModOneByte (left, right, result);
3778 /* should have been converted to function call */
3782 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3783 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3784 freeAsmop (result, NULL, ic, TRUE);
3787 /*-----------------------------------------------------------------*/
3788 /* genIfxJump :- will create a jump depending on the ifx */
3789 /*-----------------------------------------------------------------*/
3791 genIfxJump (iCode * ic, char *jval)
3794 symbol *tlbl = newiTempLabel (NULL);
3797 D(emitcode ("; genIfxJump",""));
3799 /* if true label then we jump if condition
3803 jlbl = IC_TRUE (ic);
3804 if (!strcmp (jval, "a"))
3806 else if (!strcmp (jval, "c"))
3813 /* false label is present */
3814 jlbl = IC_FALSE (ic);
3815 if (!strcmp (jval, "a"))
3817 else if (!strcmp (jval, "c"))
3822 emitBranch (inst, tlbl);
3823 emitBranch ("jmp", jlbl);
3826 /* mark the icode as generated */
3830 /*-----------------------------------------------------------------*/
3831 /* genCmp :- greater or less than comparison */
3832 /*-----------------------------------------------------------------*/
3834 genCmp (operand * left, operand * right,
3835 operand * result, iCode * ifx, int sign, iCode *ic)
3837 int size, offset = 0;
3838 unsigned long lit = 0L;
3840 bool needpula = FALSE;
3842 D(emitcode ("; genCmp",""));
3844 /* subtract right from left if at the
3845 end the carry flag is set then we know that
3846 left is greater than right */
3847 size = max (AOP_SIZE (left), AOP_SIZE (right));
3849 if (AOP_TYPE (right) == AOP_LIT)
3851 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3852 /* optimize if(x < 0) or if(x >= 0) */
3861 needpula = pushRegIfUsed (hc08_reg_a);
3862 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
3863 emitcode ("rola", "");
3864 hc08_useReg (hc08_reg_a);
3872 && ((AOP_TYPE (right) == AOP_LIT) ||
3873 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
3874 && hc08_reg_hx->isFree)
3876 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
3877 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
3878 hc08_freeReg (hc08_reg_hx);
3889 loadRegFromAop (hc08_reg_a, AOP (left), offset);
3890 accopWithAop (sub, AOP (right), offset);
3891 hc08_freeReg (hc08_reg_a);
3897 freeAsmop (right, NULL, ic, TRUE);
3898 freeAsmop (left, NULL, ic, TRUE);
3899 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3905 /* if the result is used in the next
3906 ifx conditional branch then generate
3907 code a little differently */
3910 pullOrFreeReg(hc08_reg_a,needpula);
3911 genIfxJump (ifx, sign ? "s" : "c");
3918 pullOrFreeReg(hc08_reg_a,needpula);
3922 /*-----------------------------------------------------------------*/
3923 /* genCmpGt :- greater than comparison */
3924 /*-----------------------------------------------------------------*/
3926 genCmpGt (iCode * ic, iCode * ifx)
3928 operand *left, *right, *result;
3929 sym_link *letype, *retype;
3932 D(emitcode ("; genCmpGt",""));
3934 result = IC_RESULT (ic);
3935 left = IC_LEFT (ic);
3936 right = IC_RIGHT (ic);
3938 letype = getSpec (operandType (left));
3939 retype = getSpec (operandType (right));
3940 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3941 /* assign the amsops */
3942 aopOp (left, ic, FALSE);
3943 aopOp (right, ic, FALSE);
3944 aopOp (result, ic, TRUE);
3946 genCmp (right, left, result, ifx, sign,ic);
3948 freeAsmop (result, NULL, ic, TRUE);
3951 /*-----------------------------------------------------------------*/
3952 /* genCmpLt - less than comparisons */
3953 /*-----------------------------------------------------------------*/
3955 genCmpLt (iCode * ic, iCode * ifx)
3957 operand *left, *right, *result;
3958 sym_link *letype, *retype;
3961 D(emitcode ("; genCmpLt",""));
3963 result = IC_RESULT (ic);
3964 left = IC_LEFT (ic);
3965 right = IC_RIGHT (ic);
3967 letype = getSpec (operandType (left));
3968 retype = getSpec (operandType (right));
3969 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3971 /* assign the amsops */
3972 aopOp (left, ic, FALSE);
3973 aopOp (right, ic, FALSE);
3974 aopOp (result, ic, TRUE);
3976 genCmp (left, right, result, ifx, sign,ic);
3978 freeAsmop (result, NULL, ic, TRUE);
3981 /*-----------------------------------------------------------------*/
3982 /* - compare and branch if not equal */
3983 /*-----------------------------------------------------------------*/
3985 gencbneshort (operand * left, operand * right, symbol * lbl)
3987 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3989 unsigned long lit = 0L;
3991 /* if the left side is a literal or
3992 if the right is in a pointer register and left
3994 if (AOP_TYPE (left) == AOP_LIT)
4000 if (AOP_TYPE (right) == AOP_LIT)
4001 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4005 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4006 accopWithAop ("cmp", AOP (right), offset);
4007 hc08_useReg (hc08_reg_a);
4008 hc08_freeReg (hc08_reg_a);
4009 emitBranch ("bne", lbl);
4015 /*-----------------------------------------------------------------*/
4016 /* gencjne - compare and jump if not equal */
4017 /*-----------------------------------------------------------------*/
4019 gencjne (operand * left, operand * right, symbol * lbl)
4021 symbol *tlbl = newiTempLabel (NULL);
4023 gencbneshort (left, right, lbl);
4025 loadRegFromConst (hc08_reg_a, one);
4026 emitBranch ("bra", tlbl);
4028 loadRegFromConst (hc08_reg_a, zero);
4031 hc08_useReg(hc08_reg_a);
4032 hc08_freeReg(hc08_reg_a);
4035 /*-----------------------------------------------------------------*/
4036 /* genCmpEq - generates code for equal to */
4037 /*-----------------------------------------------------------------*/
4039 genCmpEq (iCode * ic, iCode * ifx)
4041 operand *left, *right, *result;
4043 D(emitcode ("; genCmpEq",""));
4045 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4046 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4047 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4049 /* if literal, literal on the right or
4050 if the right is in a pointer register and left
4052 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4054 operand *t = IC_RIGHT (ic);
4055 IC_RIGHT (ic) = IC_LEFT (ic);
4059 if (ifx && !AOP_SIZE (result))
4062 tlbl = newiTempLabel (NULL);
4063 gencbneshort (left, right, tlbl);
4066 emitBranch ("jmp", IC_TRUE (ifx));
4071 symbol *lbl = newiTempLabel (NULL);
4072 emitBranch ("bra", lbl);
4074 emitBranch ("jmp", IC_FALSE (ifx));
4078 /* mark the icode as generated */
4083 gencjne (left, right, newiTempLabel (NULL));
4084 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4086 storeRegToAop (hc08_reg_a, AOP (result), 0);
4091 genIfxJump (ifx, "a");
4094 /* if the result is used in an arithmetic operation
4095 then put the result in place */
4096 if (AOP_TYPE (result) != AOP_CRY)
4100 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4101 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4102 freeAsmop (result, NULL, ic, TRUE);
4105 /*-----------------------------------------------------------------*/
4106 /* ifxForOp - returns the icode containing the ifx for operand */
4107 /*-----------------------------------------------------------------*/
4109 ifxForOp (operand * op, iCode * ic)
4111 /* if true symbol then needs to be assigned */
4112 if (IS_TRUE_SYMOP (op))
4115 /* if this has register type condition and
4116 the next instruction is ifx with the same operand
4117 and live to of the operand is upto the ifx only then */
4119 ic->next->op == IFX &&
4120 IC_COND (ic->next)->key == op->key &&
4121 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4128 genPointerGetSetOfs (iCode *ic)
4130 iCode *lic = ic->next;
4136 /* Make sure we have a next iCode */
4137 emitcode("","; checking lic");
4141 /* Make sure the result of the addition is an iCode */
4142 emitcode("","; checking IS_ITEMP");
4143 if (!IS_ITEMP (IC_RESULT (ic)))
4146 /* Make sure the next iCode is a pointer set or get */
4147 pset = POINTER_SET(lic);
4148 pget = POINTER_GET(lic);
4149 emitcode("","; pset=%d, pget=%d",pset,pget);
4153 emitcode("", "; checking pset operandsEqu");
4154 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4157 emitcode("", "; checking pget operandsEqu");
4158 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4161 emitcode("", "; checking IS_SYMOP");
4162 if (!IS_SYMOP (IC_LEFT (ic)))
4165 emitcode("", "; checking !IS_TRUE_SYMOP");
4166 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4169 sym = OP_SYMBOL (IC_LEFT (ic));
4171 emitcode("", "; checking remat");
4177 D(emitcode ("; genPointerGetOfs",""));
4178 aopOp (IC_LEFT(ic), ic, FALSE);
4179 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4180 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4182 aopOp (IC_RIGHT(ic), ic, FALSE);
4183 aopOp (IC_RESULT(lic), lic, FALSE);
4186 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4187 size = AOP_SIZE (IC_RESULT(lic));
4188 derefaop->size = size;
4193 emitcode ("lda", "%s,x",
4194 aopAdrStr (derefaop, offset, TRUE));
4195 hc08_useReg (hc08_reg_a);
4196 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
4197 hc08_freeReg (hc08_reg_a);
4201 hc08_freeReg (hc08_reg_hx);
4203 freeAsmop (NULL, derefaop, ic, TRUE);
4204 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4205 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4212 D(emitcode ("; genPointerSetOfs",""));
4213 aopOp (IC_LEFT(ic), ic, FALSE);
4214 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4215 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4217 aopOp (IC_RIGHT(ic), ic, FALSE);
4218 aopOp (IC_RIGHT(lic), lic, FALSE);
4221 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4222 size = AOP_SIZE (IC_RIGHT(lic));
4223 derefaop->size = size;
4228 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
4229 emitcode ("sta", "%s,x",
4230 aopAdrStr (derefaop, offset, TRUE));
4231 hc08_freeReg (hc08_reg_a);
4236 hc08_freeReg (hc08_reg_hx);
4238 freeAsmop (NULL, derefaop, ic, TRUE);
4239 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4240 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4249 /*-----------------------------------------------------------------*/
4250 /* hasInc - operand is incremented before any other use */
4251 /*-----------------------------------------------------------------*/
4253 hasInc (operand *op, iCode *ic,int osize)
4255 sym_link *type = operandType(op);
4256 sym_link *retype = getSpec (type);
4257 iCode *lic = ic->next;
4260 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4261 if (!IS_SYMOP(op)) return NULL;
4263 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4264 if (IS_AGGREGATE(type->next)) return NULL;
4265 if (osize != (isize = getSize(type->next))) return NULL;
4268 /* if operand of the form op = op + <sizeof *op> */
4269 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4270 isOperandEqual(IC_RESULT(lic),op) &&
4271 isOperandLiteral(IC_RIGHT(lic)) &&
4272 operandLitValue(IC_RIGHT(lic)) == isize) {
4275 /* if the operand used or deffed */
4276 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4279 /* if GOTO or IFX */
4280 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4286 /*-----------------------------------------------------------------*/
4287 /* genAndOp - for && operation */
4288 /*-----------------------------------------------------------------*/
4290 genAndOp (iCode * ic)
4292 operand *left, *right, *result;
4293 symbol *tlbl, *tlbl0;
4295 D(emitcode ("; genAndOp",""));
4297 /* note here that && operations that are in an
4298 if statement are taken away by backPatchLabels
4299 only those used in arthmetic operations remain */
4300 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4301 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4302 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4304 tlbl = newiTempLabel (NULL);
4305 tlbl0 = newiTempLabel (NULL);
4307 asmopToBool (AOP (left), FALSE);
4308 emitBranch ("beq", tlbl0);
4309 asmopToBool (AOP (right), FALSE);
4310 emitBranch ("beq", tlbl0);
4311 loadRegFromConst (hc08_reg_a,one);
4312 emitBranch ("bra", tlbl);
4314 loadRegFromConst (hc08_reg_a,zero);
4317 hc08_useReg (hc08_reg_a);
4318 hc08_freeReg (hc08_reg_a);
4320 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4322 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4323 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4324 freeAsmop (result, NULL, ic, TRUE);
4328 /*-----------------------------------------------------------------*/
4329 /* genOrOp - for || operation */
4330 /*-----------------------------------------------------------------*/
4332 genOrOp (iCode * ic)
4334 operand *left, *right, *result;
4335 symbol *tlbl, *tlbl0;
4337 D(emitcode ("; genOrOp",""));
4339 /* note here that || operations that are in an
4340 if statement are taken away by backPatchLabels
4341 only those used in arthmetic operations remain */
4342 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4343 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4344 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4346 tlbl = newiTempLabel (NULL);
4347 tlbl0 = newiTempLabel (NULL);
4349 asmopToBool (AOP (left), FALSE);
4350 emitBranch ("bne", tlbl0);
4351 asmopToBool (AOP (right), FALSE);
4352 emitBranch ("bne", tlbl0);
4353 loadRegFromConst (hc08_reg_a,zero);
4354 emitBranch ("bra", tlbl);
4356 loadRegFromConst (hc08_reg_a,one);
4359 hc08_useReg (hc08_reg_a);
4360 hc08_freeReg (hc08_reg_a);
4362 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4365 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4366 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4367 freeAsmop (result, NULL, ic, TRUE);
4370 /*-----------------------------------------------------------------*/
4371 /* isLiteralBit - test if lit == 2^n */
4372 /*-----------------------------------------------------------------*/
4374 isLiteralBit (unsigned long lit)
4376 unsigned long pw[32] =
4377 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4378 0x100L, 0x200L, 0x400L, 0x800L,
4379 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4380 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4381 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4382 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4383 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4386 for (idx = 0; idx < 32; idx++)
4393 /*-----------------------------------------------------------------*/
4394 /* continueIfTrue - */
4395 /*-----------------------------------------------------------------*/
4397 continueIfTrue (iCode * ic)
4400 emitBranch ("jmp", IC_TRUE (ic));
4404 /*-----------------------------------------------------------------*/
4406 /*-----------------------------------------------------------------*/
4408 jumpIfTrue (iCode * ic)
4411 emitBranch ("jmp", IC_FALSE (ic));
4415 /*-----------------------------------------------------------------*/
4416 /* jmpTrueOrFalse - */
4417 /*-----------------------------------------------------------------*/
4419 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4421 // ugly but optimized by peephole
4424 symbol *nlbl = newiTempLabel (NULL);
4425 emitBranch ("bra", nlbl);
4427 emitBranch ("jmp", IC_TRUE (ic));
4432 emitBranch ("jmp", IC_FALSE (ic));
4439 /*-----------------------------------------------------------------*/
4440 /* genAnd - code for and */
4441 /*-----------------------------------------------------------------*/
4443 genAnd (iCode * ic, iCode * ifx)
4445 operand *left, *right, *result;
4446 int size, offset = 0;
4447 unsigned long lit = 0L;
4448 unsigned long litinv;
4454 D(emitcode ("; genAnd",""));
4456 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4457 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4458 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4461 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4463 AOP_TYPE (left), AOP_TYPE (right));
4464 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4466 AOP_SIZE (left), AOP_SIZE (right));
4469 /* if left is a literal & right is not then exchange them */
4470 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4472 operand *tmp = right;
4477 /* if left is accumulator & right is not then exchange them */
4478 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4480 operand *tmp = right;
4485 size = AOP_SIZE (result);
4487 if (AOP_TYPE (right) == AOP_LIT)
4489 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4490 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4492 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4493 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4495 int bitpos = isLiteralBit(litinv)-1;
4496 emitcode ("bclr","#%d,%s",bitpos & 7,
4497 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4505 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4506 if ((AOP_TYPE (right) != AOP_LIT)
4507 || (((lit >> (offset*8)) & 0xff) != 0xff))
4508 accopWithAop ("and", AOP (right), offset);
4509 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4510 hc08_freeReg( hc08_reg_a);
4514 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4515 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4516 freeAsmop (result, NULL, ic, TRUE);
4519 /*-----------------------------------------------------------------*/
4520 /* genOr - code for or */
4521 /*-----------------------------------------------------------------*/
4523 genOr (iCode * ic, iCode * ifx)
4525 operand *left, *right, *result;
4526 int size, offset = 0;
4527 unsigned long lit = 0L;
4529 D(emitcode ("; genOr",""));
4531 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4532 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4533 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4536 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4538 AOP_TYPE (left), AOP_TYPE (right));
4539 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4541 AOP_SIZE (left), AOP_SIZE (right));
4544 /* if left is a literal & right is not then exchange them */
4545 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4547 operand *tmp = right;
4552 /* if left is accumulator & right is not then exchange them */
4553 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4555 operand *tmp = right;
4560 /* if right is bit then exchange them */
4561 if (AOP_TYPE (right) == AOP_CRY &&
4562 AOP_TYPE (left) != AOP_CRY)
4564 operand *tmp = right;
4568 if (AOP_TYPE (right) == AOP_LIT)
4569 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4571 size = AOP_SIZE (result);
4573 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4574 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
4575 (AOP_TYPE (left) == AOP_DIR))
4577 int bitpos = isLiteralBit(lit)-1;
4578 emitcode ("bset","#%d,%s",bitpos & 7,
4579 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4588 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4589 accopWithAop ("ora", AOP (right), offset);
4590 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4591 hc08_freeReg( hc08_reg_a);
4596 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4597 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4598 freeAsmop (result, NULL, ic, TRUE);
4601 /*-----------------------------------------------------------------*/
4602 /* genXor - code for xclusive or */
4603 /*-----------------------------------------------------------------*/
4605 genXor (iCode * ic, iCode * ifx)
4607 operand *left, *right, *result;
4608 int size, offset = 0;
4609 unsigned long lit = 0L;
4611 D(emitcode ("; genXor",""));
4613 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4614 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4615 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4618 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4620 AOP_TYPE (left), AOP_TYPE (right));
4621 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4623 AOP_SIZE (left), AOP_SIZE (right));
4626 /* if left is a literal & right is not ||
4627 if left needs acc & right does not */
4628 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4630 operand *tmp = right;
4635 /* if left is accumulator & right is not then exchange them */
4636 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4638 operand *tmp = right;
4643 /* if right is bit then exchange them */
4644 if (AOP_TYPE (right) == AOP_CRY &&
4645 AOP_TYPE (left) != AOP_CRY)
4647 operand *tmp = right;
4651 if (AOP_TYPE (right) == AOP_LIT)
4652 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4654 size = AOP_SIZE (result);
4658 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4659 accopWithAop ("eor", AOP (right), offset);
4660 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4661 hc08_freeReg( hc08_reg_a);
4666 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4667 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4668 freeAsmop (result, NULL, ic, TRUE);
4672 emitinline (iCode * ic, char *inlin)
4678 symbol *sym, *tempsym;
4687 while (isalnum(*inlin) || (*inlin == '_'))
4691 //printf("Found possible symbol '%s'\n",symname);
4692 tempsym = newSymbol (symname, ic->level);
4693 tempsym->block = ic->block;
4694 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
4703 aop = aopForSym (ic, sym, FALSE);
4704 l = aopAdrStr (aop, aop->size - 1, TRUE);
4708 if (!sym->allocreq && !sym->ismyparm)
4710 werror (E_ID_UNDEF, sym->name);
4712 " Add 'volatile' to the variable declaration so that it\n"
4713 " can be referenced within inline assembly");
4715 //printf("Replacing with '%s'\n",l);
4719 if ((2+bp-buffer)>sizeof(buffer))
4728 if ((2+bp-buffer)>sizeof(buffer))
4735 if ((2+bp-buffer)>sizeof(buffer))
4736 fprintf(stderr, "Inline assembly buffer overflow\n");
4738 //printf("%s\n",buffer);
4739 emitcode (buffer,"");
4743 /*-----------------------------------------------------------------*/
4744 /* genInline - write the inline code out */
4745 /*-----------------------------------------------------------------*/
4747 genInline (iCode * ic)
4749 char *buffer, *bp, *bp1;
4751 D(emitcode ("; genInline",""));
4753 _G.inLine += (!options.asmpeep);
4755 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4756 strcpy (buffer, IC_INLINE (ic));
4758 /* emit each line as a code */
4764 /* emitcode (bp1, ""); */
4765 emitinline (ic, bp1);
4784 /* emitcode (bp1, ""); */
4785 emitinline (ic, bp1);
4787 /* emitcode("",buffer); */
4788 _G.inLine -= (!options.asmpeep);
4791 /*-----------------------------------------------------------------*/
4792 /* genRRC - rotate right with carry */
4793 /*-----------------------------------------------------------------*/
4797 operand *left, *result;
4798 int size, offset = 0;
4799 bool needpula = FALSE;
4800 bool resultInA = FALSE;
4803 D(emitcode ("; genRRC",""));
4805 /* rotate right with carry */
4806 left = IC_LEFT (ic);
4807 result = IC_RESULT (ic);
4808 aopOp (left, ic, FALSE);
4809 aopOp (result, ic, FALSE);
4811 if ((AOP_TYPE (result) == AOP_REG)
4812 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4815 size = AOP_SIZE (result);
4819 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4823 rmwWithAop (shift, AOP (result), offset--);
4831 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4832 rmwWithReg (shift, hc08_reg_a);
4833 storeRegToAop (hc08_reg_a, AOP (result), offset--);
4834 hc08_freeReg (hc08_reg_a);
4839 if ((!hc08_reg_a->isFree) || resultInA)
4841 pushReg (hc08_reg_a, TRUE);
4845 /* now we need to put the carry into the
4846 highest order byte of the result */
4847 offset = AOP_SIZE (result) - 1;
4848 emitcode ("clra","");
4849 emitcode ("rora","");
4850 hc08_dirtyReg (hc08_reg_a, FALSE);
4853 emitcode ("ora", "1,s");
4854 emitcode ("ais", "#1");
4855 hc08_dirtyReg (hc08_reg_a, FALSE);
4859 accopWithAop ("ora", AOP (result), offset);
4860 storeRegToAop (hc08_reg_a, AOP (result), offset);
4862 pullOrFreeReg (hc08_reg_a, needpula);
4864 freeAsmop (left, NULL, ic, TRUE);
4865 freeAsmop (result, NULL, ic, TRUE);
4868 /*-----------------------------------------------------------------*/
4869 /* genRLC - generate code for rotate left with carry */
4870 /*-----------------------------------------------------------------*/
4874 operand *left, *result;
4875 int size, offset = 0;
4877 bool resultInA = FALSE;
4878 bool needpula = FALSE;
4880 D(emitcode ("; genRLC",""));
4882 /* rotate right with carry */
4883 left = IC_LEFT (ic);
4884 result = IC_RESULT (ic);
4885 aopOp (left, ic, FALSE);
4886 aopOp (result, ic, FALSE);
4888 if ((AOP_TYPE (result) == AOP_REG)
4889 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4892 size = AOP_SIZE (result);
4896 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4900 rmwWithAop (shift, AOP (result), offset--);
4908 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4909 rmwWithReg (shift, hc08_reg_a);
4910 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4911 hc08_freeReg (hc08_reg_a);
4916 if ((!hc08_reg_a->isFree) || resultInA)
4918 pushReg (hc08_reg_a, TRUE);
4922 /* now we need to put the carry into the
4923 lowest order byte of the result */
4925 emitcode ("clra","");
4926 emitcode ("rola","");
4927 hc08_dirtyReg (hc08_reg_a, FALSE);
4930 emitcode ("ora", "1,s");
4931 emitcode ("ais", "#1");
4932 hc08_dirtyReg (hc08_reg_a, FALSE);
4936 accopWithAop ("ora", AOP (result), offset);
4937 storeRegToAop (hc08_reg_a, AOP (result), offset);
4939 pullOrFreeReg (hc08_reg_a, needpula);
4941 freeAsmop (left, NULL, ic, TRUE);
4942 freeAsmop (result, NULL, ic, TRUE);
4945 /*-----------------------------------------------------------------*/
4946 /* genGetHbit - generates code get highest order bit */
4947 /*-----------------------------------------------------------------*/
4949 genGetHbit (iCode * ic)
4951 operand *left, *result;
4953 D(emitcode ("; genGetHbit",""));
4955 left = IC_LEFT (ic);
4956 result = IC_RESULT (ic);
4957 aopOp (left, ic, FALSE);
4958 aopOp (result, ic, FALSE);
4960 /* get the highest order byte into a */
4961 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
4962 emitcode ("rola", "");
4963 emitcode ("clra", "");
4964 emitcode ("rola", "");
4965 hc08_dirtyReg (hc08_reg_a, FALSE);
4966 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4968 freeAsmop (left, NULL, ic, TRUE);
4969 freeAsmop (result, NULL, ic, TRUE);
4973 /*-----------------------------------------------------------------*/
4974 /* AccRol - rotate left accumulator by known count */
4975 /*-----------------------------------------------------------------*/
4977 AccRol (int shCount)
4979 shCount &= 0x0007; // shCount : 0..7
4986 emitcode ("rola", ""); /* 1 cycle */
4989 emitcode ("rola", ""); /* 1 cycle */
4990 emitcode ("rola", ""); /* 1 cycle */
4993 emitcode ("nsa", "");
4994 emitcode ("rora", "");
4997 emitcode ("nsa", ""); /* 3 cycles */
5000 emitcode ("nsa", ""); /* 3 cycles */
5001 emitcode ("rola", ""); /* 1 cycle */
5004 emitcode ("nsa", ""); /* 3 cycles */
5005 emitcode ("rola", ""); /* 1 cycle */
5006 emitcode ("rola", ""); /* 1 cycle */
5009 emitcode ("nsa", ""); /* 3 cycles */
5010 emitcode ("rola", ""); /* 1 cycle */
5011 emitcode ("rola", ""); /* 1 cycle */
5012 emitcode ("rola", ""); /* 1 cycle */
5019 /*-----------------------------------------------------------------*/
5020 /* AccLsh - left shift accumulator by known count */
5021 /*-----------------------------------------------------------------*/
5023 AccLsh (int shCount)
5027 shCount &= 0x0007; // shCount : 0..7
5029 /* Shift counts of 4 and 5 are currently optimized for code size. */
5030 /* Falling through to the unrolled loop would be optimal for code speed. */
5031 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5035 accopWithMisc ("nsa", "");
5036 accopWithMisc ("and", "#0xf0");
5037 /* total: 5 cycles, 3 bytes */
5040 accopWithMisc ("nsa", "");
5041 accopWithMisc ("and", "#0xf0");
5042 accopWithMisc ("lsla", "");
5043 /* total: 6 cycles, 4 bytes */
5046 accopWithMisc ("rora", "");
5047 accopWithMisc ("rora", "");
5048 accopWithMisc ("rora", "");
5049 accopWithMisc ("and", "#0xc0");
5050 /* total: 5 cycles, 5 bytes */
5053 accopWithMisc ("rora", "");
5054 accopWithMisc ("clra", "");
5055 accopWithMisc ("rora", "");
5056 /* total: 3 cycles, 3 bytes */
5060 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5061 /* the fastest (shCount<6) and shortest (shCount<4). */
5062 for (i=0;i<shCount;i++)
5063 accopWithMisc ("lsla", "");
5067 /*-----------------------------------------------------------------*/
5068 /* AccSRsh - signed right shift accumulator by known count */
5069 /*-----------------------------------------------------------------*/
5071 AccSRsh (int shCount)
5075 shCount &= 0x0007; // shCount : 0..7
5079 accopWithMisc ("rola", "");
5080 accopWithMisc ("clra", "");
5081 accopWithMisc ("sbc", zero);
5082 /* total: 4 cycles, 4 bytes */
5086 for (i=0;i<shCount;i++)
5087 accopWithMisc ("asra", "");
5090 /*-----------------------------------------------------------------*/
5091 /* AccRsh - right shift accumulator by known count */
5092 /*-----------------------------------------------------------------*/
5094 AccRsh (int shCount, bool sign)
5104 shCount &= 0x0007; // shCount : 0..7
5106 /* Shift counts of 4 and 5 are currently optimized for code size. */
5107 /* Falling through to the unrolled loop would be optimal for code speed. */
5108 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5112 accopWithMisc ("nsa", "");
5113 accopWithMisc ("and", "#0x0f");
5114 /* total: 5 cycles, 3 bytes */
5117 accopWithMisc ("nsa", "");
5118 accopWithMisc ("and", "#0x0f");
5119 accopWithMisc ("lsra", "");
5120 /* total: 6 cycles, 4 bytes */
5123 accopWithMisc ("rola", "");
5124 accopWithMisc ("rola", "");
5125 accopWithMisc ("rola", "");
5126 accopWithMisc ("and", "#0x03");
5127 /* total: 5 cycles, 5 bytes */
5130 accopWithMisc ("rola", "");
5131 accopWithMisc ("clra", "");
5132 accopWithMisc ("rola", "");
5133 /* total: 3 cycles, 3 bytes */
5137 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5138 /* the fastest (shCount<6) and shortest (shCount<4). */
5139 for (i=0;i<shCount;i++)
5140 accopWithMisc ("lsra", "");
5144 /*-----------------------------------------------------------------*/
5145 /* XAccLsh - left shift register pair XA by known count */
5146 /*-----------------------------------------------------------------*/
5148 XAccLsh (int shCount)
5152 shCount &= 0x000f; // shCount : 0..15
5157 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5158 loadRegFromConst (hc08_reg_a, zero);
5162 /* if we can beat 2n cycles or bytes for some special case, do it here */
5166 /* bytes cycles reg x reg a carry
5167 ** abcd efgh ijkl mnop ?
5168 ** lsrx 1 1 0abc defg ijkl mnop h
5169 ** rora 1 1 0abc defg hijk lmno p
5170 ** tax 1 1 hijk lmno hijk lmno p
5171 ** clra 1 1 hijk lmno 0000 0000 p
5172 ** rora 1 1 hijk lmno p000 0000 0
5173 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5175 rmwWithReg ("lsr", hc08_reg_x);
5176 rmwWithReg ("ror", hc08_reg_a);
5177 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5178 loadRegFromConst (hc08_reg_a, zero);
5179 rmwWithReg ("ror", hc08_reg_a);
5186 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5187 /* the fastest and shortest. */
5188 for (i=0;i<shCount;i++)
5190 rmwWithReg ("lsl", hc08_reg_a);
5191 rmwWithReg ("rol", hc08_reg_x);
5195 /*-----------------------------------------------------------------*/
5196 /* XAccSRsh - signed right shift register pair XA by known count */
5197 /*-----------------------------------------------------------------*/
5199 XAccSRsh (int shCount)
5203 shCount &= 0x000f; // shCount : 0..7
5205 /* if we can beat 2n cycles or bytes for some special case, do it here */
5209 /* bytes cycles reg x reg a carry
5210 ** abcd efgh ijkl mnop ?
5211 ** lslx 1 1 bcde fgh0 ijkl mnop a
5212 ** clra 1 1 bcde fgh0 0000 0000 a
5213 ** rola 1 1 bcde fgh0 0000 000a 0
5214 ** nega 1 1 bcde fgh0 aaaa aaaa a
5215 ** tax 1 1 aaaa aaaa aaaa aaaa a
5216 ** total: 5 cycles, 5 bytes
5218 rmwWithReg ("lsl", hc08_reg_x);
5219 loadRegFromConst (hc08_reg_a, zero);
5220 rmwWithReg ("rol", hc08_reg_a);
5221 rmwWithReg ("neg", hc08_reg_a);
5222 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5232 /* bytes cycles reg x reg a carry
5233 ** abcd efgh ijkl mnop ?
5234 ** txa 1 1 abcd efgh abcd efgh ?
5235 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5236 ** lsla 1 1 abcd efgh ???? ???? a
5237 ** clrx 1 1 0000 0000 ???? ???? a
5238 ** rolx 1 1 0000 000a ???? ???? 0
5239 ** negx 1 1 aaaa aaaa ???? ???? a
5240 ** rora 1 1 aaaa aaaa LSBresult 0
5241 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5243 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5244 AccSRsh (shCount-8);
5245 rmwWithReg ("lsl", hc08_reg_a);
5246 loadRegFromConst (hc08_reg_x, zero);
5247 rmwWithReg ("rol", hc08_reg_x);
5248 rmwWithReg ("neg", hc08_reg_x);
5249 rmwWithReg ("ror", hc08_reg_a);
5256 /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5257 /* the fastest and shortest. */
5258 for (i=0;i<shCount;i++)
5260 rmwWithReg ("asr", hc08_reg_x);
5261 rmwWithReg ("ror", hc08_reg_a);
5265 /*-----------------------------------------------------------------*/
5266 /* XAccRsh - right shift register pair XA by known count */
5267 /*-----------------------------------------------------------------*/
5269 XAccRsh (int shCount, bool sign)
5279 shCount &= 0x000f; // shCount : 0..7
5281 /* if we can beat 2n cycles or bytes for some special case, do it here */
5285 /* bytes cycles reg x reg a carry
5286 ** abcd efgh ijkl mnop ?
5287 ** clra 1 1 abcd efgh 0000 0000 a
5288 ** lslx 1 1 bcde fgh0 0000 0000 a
5289 ** rola 1 1 bcde fgh0 0000 000a 0
5290 ** clrx 1 1 0000 0000 0000 000a 0
5291 ** total: 4 cycles, 4 bytes
5293 loadRegFromConst (hc08_reg_x, zero);
5294 rmwWithReg ("lsl", hc08_reg_x);
5295 rmwWithReg ("rol", hc08_reg_a);
5296 loadRegFromConst (hc08_reg_a, zero);
5300 /* bytes cycles reg x reg a carry
5301 ** abcd efgh ijkl mnop ?
5302 ** clra 1 1 abcd efgh 0000 0000 a
5303 ** lslx 1 1 bcde fgh0 0000 0000 a
5304 ** rola 1 1 bcde fgh0 0000 000a 0
5305 ** lslx 1 1 cdef gh00 0000 000a b
5306 ** rola 1 1 cdef gh00 0000 00ab 0
5307 ** clrx 1 1 0000 0000 0000 000a 0
5308 ** total: 6 cycles, 6 bytes
5310 loadRegFromConst (hc08_reg_x, zero);
5311 rmwWithReg ("lsl", hc08_reg_x);
5312 rmwWithReg ("rol", hc08_reg_a);
5313 rmwWithReg ("lsl", hc08_reg_x);
5314 rmwWithReg ("rol", hc08_reg_a);
5315 loadRegFromConst (hc08_reg_a, zero);
5324 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5325 AccRsh (shCount-8, FALSE);
5326 loadRegFromConst (hc08_reg_x, zero);
5330 /* bytes cycles reg x reg a carry
5331 ** abcd efgh ijkl mnop ?
5332 ** lsla 1 1 abcd efgh jklm nop0 i
5333 ** txa 1 1 abcd efgh abcd efgh i
5334 ** rola 1 1 abcd efgh bcde fghi a
5335 ** clrx 1 1 0000 0000 bcde fghi a
5336 ** rolx 1 1 0000 000a bcde fghi 0
5337 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5339 rmwWithReg ("lsl", hc08_reg_a);
5340 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5341 rmwWithReg ("rol", hc08_reg_a);
5342 loadRegFromConst (hc08_reg_x, zero);
5343 rmwWithReg ("rol", hc08_reg_x);
5346 /* bytes cycles reg x reg a carry
5347 ** abcd efgh ijkl mnop ?
5348 ** lsla 1 1 abcd efgh jklm nop0 i
5349 ** rolx 1 1 bcde fghi jklm nop0 a
5350 ** rola 1 1 bcde fghi klmn op0a j
5351 ** rolx 1 1 cdef ghij klmn op0a b
5352 ** rola 1 1 cdef ghij lmno p0ab k
5353 ** and #3 2 2 cdef ghij 0000 00ab k
5354 ** psha 1 2 cdef ghij 0000 00ab k
5355 ** txa 1 1 cdef ghij cdef ghij k
5356 ** pula 1 2 0000 00ab cdef ghij k
5357 ** total: 12 cycles, 10 bytes (beats 12 bytes)
5363 /* lslx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5364 /* the fastest and shortest. */
5365 for (i=0;i<shCount;i++)
5367 rmwWithReg ("lsl", hc08_reg_x);
5368 rmwWithReg ("rol", hc08_reg_a);
5375 /*-----------------------------------------------------------------*/
5376 /* shiftR1Left2Result - shift right one byte from left to result */
5377 /*-----------------------------------------------------------------*/
5379 shiftR1Left2Result (operand * left, int offl,
5380 operand * result, int offr,
5381 int shCount, int sign)
5383 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5384 /* shift right accumulator */
5385 AccRsh (shCount, sign);
5386 storeRegToAop (hc08_reg_a, AOP (result), offr);
5390 /*-----------------------------------------------------------------*/
5391 /* shiftL1Left2Result - shift left one byte from left to result */
5392 /*-----------------------------------------------------------------*/
5394 shiftL1Left2Result (operand * left, int offl,
5395 operand * result, int offr, int shCount)
5397 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5398 /* shift left accumulator */
5400 storeRegToAop (hc08_reg_a, AOP (result), offr);
5403 /*-----------------------------------------------------------------*/
5404 /* movLeft2Result - move byte from left to result */
5405 /*-----------------------------------------------------------------*/
5407 movLeft2Result (operand * left, int offl,
5408 operand * result, int offr, int sign)
5410 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5412 transferAopAop (AOP (left), offl, AOP (result), offr);
5417 /*-----------------------------------------------------------------*/
5418 /* AccAXRsh1 - right shift 0->a:x->c by 1 */
5419 /*-----------------------------------------------------------------*/
5423 emitcode ("lsra", "");
5424 emitcode ("ror", "%s", x);
5428 /*-----------------------------------------------------------------*/
5429 /* AccAXRshS1 - signed right shift s->a:x->c by 1 */
5430 /*-----------------------------------------------------------------*/
5432 AccAXRshS1 (char *x)
5434 emitcode ("asra", "");
5435 emitcode ("ror", "%s", x);
5438 /*-----------------------------------------------------------------*/
5439 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5440 /*-----------------------------------------------------------------*/
5444 emitcode ("rol", "%s", x);
5445 emitcode ("rola", "");
5448 /*-----------------------------------------------------------------*/
5449 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5450 /*-----------------------------------------------------------------*/
5454 emitcode ("lsl", "%s", x);
5455 emitcode ("rola", "");
5458 /*-----------------------------------------------------------------*/
5459 /* AccAXLsh - left shift a:x by known count (0..7) */
5460 /*-----------------------------------------------------------------*/
5462 AccAXLsh (char *x, int shCount)
5466 for (i=0;i<shCount;i++) {
5471 /*-----------------------------------------------------------------*/
5472 /* AccAXRsh - right shift a:x known count (0..7) */
5473 /*-----------------------------------------------------------------*/
5475 AccAXRsh (char *x, int shCount)
5479 for (i=0;i<shCount;i++) {
5485 /*-----------------------------------------------------------------*/
5486 /* AccAXRshS - right shift signed a:x known count (0..7) */
5487 /*-----------------------------------------------------------------*/
5489 AccAXRshS (char *x, int shCount)
5493 for (i=0;i<shCount;i++) {
5498 /*-----------------------------------------------------------------*/
5499 /* shiftL2Left2Result - shift left two bytes from left to result */
5500 /*-----------------------------------------------------------------*/
5502 shiftL2Left2Result (operand * left, int offl,
5503 operand * result, int offr, int shCount)
5506 bool needpula = FALSE;
5507 bool needpulx = FALSE;
5509 needpula = pushRegIfUsed (hc08_reg_a);
5510 needpulx = pushRegIfUsed (hc08_reg_x);
5512 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5517 rmwWithReg ("lsr", hc08_reg_x);
5518 rmwWithReg ("ror", hc08_reg_a);
5519 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5520 rmwWithReg ("clr", hc08_reg_a);
5521 rmwWithReg ("ror", hc08_reg_a);
5524 for (i=0; i<shCount; i++)
5526 rmwWithReg ("lsl", hc08_reg_a);
5527 rmwWithReg ("rol", hc08_reg_x);
5530 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5532 pullOrFreeReg (hc08_reg_x, needpulx);
5533 pullOrFreeReg (hc08_reg_a, needpula);
5539 /*-----------------------------------------------------------------*/
5540 /* shiftR2Left2Result - shift right two bytes from left to result */
5541 /*-----------------------------------------------------------------*/
5543 shiftR2Left2Result (operand * left, int offl,
5544 operand * result, int offr,
5545 int shCount, int sign)
5548 bool needpula = FALSE;
5549 bool needpulx = FALSE;
5551 needpula = pushRegIfUsed (hc08_reg_a);
5552 needpulx = pushRegIfUsed (hc08_reg_x);
5554 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5555 for (i=0; i<shCount; i++)
5558 rmwWithReg ("asr", hc08_reg_x);
5560 rmwWithReg ("lsr", hc08_reg_x);
5561 rmwWithReg ("ror", hc08_reg_a);
5563 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5565 pullOrFreeReg (hc08_reg_x, needpulx);
5566 pullOrFreeReg (hc08_reg_a, needpula);
5571 /*-----------------------------------------------------------------*/
5572 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5573 /*-----------------------------------------------------------------*/
5575 shiftLLeftOrResult (operand * left, int offl,
5576 operand * result, int offr, int shCount)
5578 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5579 /* shift left accumulator */
5581 /* or with result */
5582 accopWithAop ("ora", AOP (result), offr);
5583 /* back to result */
5584 storeRegToAop (hc08_reg_a, AOP (result), offr);
5585 hc08_freeReg (hc08_reg_a);
5589 /*-----------------------------------------------------------------*/
5590 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5591 /*-----------------------------------------------------------------*/
5593 shiftRLeftOrResult (operand * left, int offl,
5594 operand * result, int offr, int shCount)
5596 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5597 /* shift left accumulator */
5598 AccRsh (shCount, FALSE);
5599 /* or with result */
5600 accopWithAop ("ora", AOP (result), offr);
5601 /* back to result */
5602 storeRegToAop (hc08_reg_a, AOP (result), offr);
5603 hc08_freeReg (hc08_reg_a);
5606 /*-----------------------------------------------------------------*/
5607 /* genlshOne - left shift a one byte quantity by known count */
5608 /*-----------------------------------------------------------------*/
5610 genlshOne (operand * result, operand * left, int shCount)
5612 D(emitcode ("; genlshOne",""));
5614 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5617 /*-----------------------------------------------------------------*/
5618 /* genlshTwo - left shift two bytes by known amount != 0 */
5619 /*-----------------------------------------------------------------*/
5621 genlshTwo (operand * result, operand * left, int shCount)
5625 D(emitcode ("; genlshTwo",""));
5627 size = getDataSize (result);
5629 /* if shCount >= 8 */
5637 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5639 movLeft2Result (left, LSB, result, MSB16, 0);
5641 storeConstToAop(zero, AOP (result), LSB);
5644 /* 1 <= shCount <= 7 */
5648 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5650 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5654 /*-----------------------------------------------------------------*/
5655 /* shiftLLong - shift left one long from left to result */
5656 /* offl = LSB or MSB16 */
5657 /*-----------------------------------------------------------------*/
5659 shiftLLong (operand * left, operand * result, int offr)
5662 // int size = AOP_SIZE (result);
5664 bool needpula = FALSE;
5665 bool needpulx = FALSE;
5667 needpula = pushRegIfUsed (hc08_reg_a);
5668 needpulx = pushRegIfUsed (hc08_reg_x);
5670 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
5671 rmwWithReg ("lsl", hc08_reg_a);
5672 rmwWithReg ("rol", hc08_reg_x);
5673 storeRegToAop (hc08_reg_xa, AOP (result), offr);
5677 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5678 rmwWithReg ("rol", hc08_reg_a);
5679 rmwWithReg ("rol", hc08_reg_x);
5680 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
5682 else if (offr==MSB16)
5684 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
5685 rmwWithReg ("rol", hc08_reg_a);
5686 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
5689 pullOrFreeReg (hc08_reg_x, needpulx);
5690 pullOrFreeReg (hc08_reg_a, needpula);
5693 /*-----------------------------------------------------------------*/
5694 /* genlshFour - shift four byte by a known amount != 0 */
5695 /*-----------------------------------------------------------------*/
5697 genlshFour (operand * result, operand * left, int shCount)
5701 D(emitcode ("; genlshFour",""));
5703 size = AOP_SIZE (result);
5705 /* TODO: deal with the &result == &left case */
5707 /* if shifting more that 3 bytes */
5712 /* lowest order of left goes to the highest
5713 order of the destination */
5714 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5716 movLeft2Result (left, LSB, result, MSB32, 0);
5717 storeConstToAop (zero, AOP (result), LSB);
5718 storeConstToAop (zero, AOP (result), MSB16);
5719 storeConstToAop (zero, AOP (result), MSB24);
5723 /* more than two bytes */
5724 else if (shCount >= 16)
5726 /* lower order two bytes goes to higher order two bytes */
5728 /* if some more remaining */
5730 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5733 movLeft2Result (left, MSB16, result, MSB32, 0);
5734 movLeft2Result (left, LSB, result, MSB24, 0);
5736 storeConstToAop (zero, AOP (result), LSB);
5737 storeConstToAop (zero, AOP (result), MSB16);
5741 /* if more than 1 byte */
5742 else if (shCount >= 8)
5744 /* lower order three bytes goes to higher order three bytes */
5749 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5751 movLeft2Result (left, LSB, result, MSB16, 0);
5757 movLeft2Result (left, MSB24, result, MSB32, 0);
5758 movLeft2Result (left, MSB16, result, MSB24, 0);
5759 movLeft2Result (left, LSB, result, MSB16, 0);
5760 storeConstToAop (zero, AOP (result), LSB);
5762 else if (shCount == 1)
5763 shiftLLong (left, result, MSB16);
5766 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5767 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5768 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5769 storeConstToAop (zero, AOP (result), LSB);
5774 /* 1 <= shCount <= 7 */
5775 else if (shCount <= 2)
5777 shiftLLong (left, result, LSB);
5779 shiftLLong (result, result, LSB);
5781 /* 3 <= shCount <= 7, optimize */
5784 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5785 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5786 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5790 /*-----------------------------------------------------------------*/
5791 /* genLeftShiftLiteral - left shifting by known count */
5792 /*-----------------------------------------------------------------*/
5794 genLeftShiftLiteral (operand * left,
5799 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5802 D(emitcode ("; genLeftShiftLiteral",""));
5804 freeAsmop (right, NULL, ic, TRUE);
5806 aopOp (left, ic, FALSE);
5807 aopOp (result, ic, FALSE);
5809 // size = getSize (operandType (result));
5810 size = AOP_SIZE (result);
5813 emitcode ("; shift left ", "result %d, left %d", size,
5820 transferAopAop( AOP(left), size, AOP(result), size);
5822 else if (shCount >= (size * 8))
5825 storeConstToAop (zero, AOP (result), size);
5832 genlshOne (result, left, shCount);
5836 genlshTwo (result, left, shCount);
5840 genlshFour (result, left, shCount);
5843 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5844 "*** ack! mystery literal shift!\n");
5848 freeAsmop (left, NULL, ic, TRUE);
5849 freeAsmop (result, NULL, ic, TRUE);
5852 /*-----------------------------------------------------------------*/
5853 /* genLeftShift - generates code for left shifting */
5854 /*-----------------------------------------------------------------*/
5856 genLeftShift (iCode * ic)
5858 operand *left, *right, *result;
5860 symbol *tlbl, *tlbl1;
5865 D(emitcode ("; genLeftShift",""));
5867 right = IC_RIGHT (ic);
5868 left = IC_LEFT (ic);
5869 result = IC_RESULT (ic);
5871 aopOp (right, ic, FALSE);
5873 /* if the shift count is known then do it
5874 as efficiently as possible */
5875 if (AOP_TYPE (right) == AOP_LIT)
5877 genLeftShiftLiteral (left, right, result, ic);
5881 /* shift count is unknown then we have to form
5882 a loop get the loop count in A : Note: we take
5883 only the lower order byte since shifting
5884 more that 32 bits make no sense anyway, ( the
5885 largest size of an object can be only 32 bits ) */
5887 aopOp (left, ic, FALSE);
5888 aopOp (result, ic, FALSE);
5890 /* now move the left to the result if they are not the
5892 if (!sameRegs (AOP (left), AOP (result)))
5895 size = AOP_SIZE (result);
5899 transferAopAop (AOP (left), offset, AOP (result), offset);
5903 freeAsmop (left, NULL, ic, TRUE);
5905 tlbl = newiTempLabel (NULL);
5906 size = AOP_SIZE (result);
5908 tlbl1 = newiTempLabel (NULL);
5912 loadRegFromAop (reg, AOP (right), 0);
5913 freeAsmop (right, NULL, ic, TRUE);
5914 emitBranch ("beq", tlbl1);
5918 for (offset=0;offset<size;offset++)
5920 rmwWithAop (shift, AOP (result), offset);
5923 rmwWithReg ("dec", reg);
5924 emitBranch ("bne", tlbl);
5928 freeAsmop (result, NULL, ic, TRUE);
5931 /*-----------------------------------------------------------------*/
5932 /* genrshOne - right shift a one byte quantity by known count */
5933 /*-----------------------------------------------------------------*/
5935 genrshOne (operand * result, operand * left,
5936 int shCount, int sign)
5938 D(emitcode ("; genrshOne",""));
5940 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5941 AccRsh (shCount, sign);
5942 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5945 /*-----------------------------------------------------------------*/
5946 /* genrshTwo - right shift two bytes by known amount != 0 */
5947 /*-----------------------------------------------------------------*/
5949 genrshTwo (operand * result, operand * left,
5950 int shCount, int sign)
5952 D(emitcode ("; genrshTwo",""));
5954 /* if shCount >= 8 */
5957 if (shCount || sign)
5959 loadRegFromAop (hc08_reg_a, AOP (left), 1);
5960 AccRsh (shCount-8, sign);
5961 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5965 transferAopAop (AOP (left), 1, AOP (result), 0);
5966 storeConstToAop (zero, AOP (result), 1);
5970 /* 1 <= shCount <= 7 */
5973 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5974 XAccRsh (shCount, sign);
5975 storeRegToAop (hc08_reg_xa, AOP (result), 0);
5979 /*-----------------------------------------------------------------*/
5980 /* shiftRLong - shift right one long from left to result */
5981 /* offl = LSB or MSB16 */
5982 /*-----------------------------------------------------------------*/
5984 shiftRLong (operand * left, int offl,
5985 operand * result, int sign)
5988 // int size = AOP_SIZE (result);
5990 bool needpula = FALSE;
5991 bool needpulx = FALSE;
5993 needpula = pushRegIfUsed (hc08_reg_a);
5994 needpulx = pushRegIfUsed (hc08_reg_x);
5998 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6000 rmwWithReg ("asr", hc08_reg_x);
6002 rmwWithReg ("lsr", hc08_reg_x);
6003 rmwWithReg ("rol", hc08_reg_a);
6004 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6006 else if (offl==MSB16)
6008 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6010 rmwWithReg ("asr", hc08_reg_a);
6012 rmwWithReg ("lsr", hc08_reg_a);
6013 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6016 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6017 rmwWithReg ("ror", hc08_reg_x);
6018 rmwWithReg ("ror", hc08_reg_a);
6019 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6022 pullOrFreeReg (hc08_reg_x, needpulx);
6023 pullOrFreeReg (hc08_reg_a, needpula);
6026 /*-----------------------------------------------------------------*/
6027 /* genrshFour - shift four byte by a known amount != 0 */
6028 /*-----------------------------------------------------------------*/
6030 genrshFour (operand * result, operand * left,
6031 int shCount, int sign)
6033 /* TODO: handle cases where left == result */
6035 D(emitcode ("; genrshFour",""));
6037 /* if shifting more that 3 bytes */
6040 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6041 AccRsh (shCount-24, sign);
6042 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6045 else if (shCount >= 16)
6047 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6048 XAccRsh (shCount-16, sign);
6049 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6052 else if (shCount >= 8)
6055 shiftRLong (left, MSB16, result, sign);
6056 else if (shCount == 8)
6058 transferAopAop (AOP (left), 1, AOP (result), 0);
6059 transferAopAop (AOP (left), 2, AOP (result), 1);
6060 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6061 storeRegToAop (hc08_reg_a, AOP (result), 2);
6062 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6064 else if (shCount == 9)
6066 shiftRLong (left, MSB16, result, sign);
6070 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6071 XAccRsh (shCount-8, FALSE);
6072 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6073 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6074 loadRegFromConst (hc08_reg_a, zero);
6075 XAccRsh (shCount-8, sign);
6076 accopWithAop ("ora", AOP (result), 1);
6077 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6081 { /* 1 <= shCount <= 7 */
6084 shiftRLong (left, LSB, result, sign);
6088 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6089 XAccRsh (shCount, FALSE);
6090 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6091 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6093 accopWithAop ("ora", AOP (result), 1);
6094 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6095 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6096 XAccRsh (shCount, sign);
6097 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6102 /*-----------------------------------------------------------------*/
6103 /* genRightShiftLiteral - right shifting by known count */
6104 /*-----------------------------------------------------------------*/
6106 genRightShiftLiteral (operand * left,
6112 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6115 D(emitcode ("; genRightShiftLiteral",""));
6117 freeAsmop (right, NULL, ic, TRUE);
6119 aopOp (left, ic, FALSE);
6120 aopOp (result, ic, FALSE);
6123 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6127 size = getDataSize (left);
6128 /* test the LEFT size !!! */
6130 /* I suppose that the left size >= result size */
6133 size = getDataSize (result);
6135 transferAopAop (AOP (left), size, AOP(result), size);
6137 else if (shCount >= (size * 8))
6140 /* get sign in acc.7 */
6141 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6143 addSign (result, LSB, sign);
6150 genrshOne (result, left, shCount, sign);
6154 genrshTwo (result, left, shCount, sign);
6158 genrshFour (result, left, shCount, sign);
6164 freeAsmop (left, NULL, ic, TRUE);
6165 freeAsmop (result, NULL, ic, TRUE);
6169 /*-----------------------------------------------------------------*/
6170 /* genRightShift - generate code for right shifting */
6171 /*-----------------------------------------------------------------*/
6173 genRightShift (iCode * ic)
6175 operand *right, *left, *result;
6179 symbol *tlbl, *tlbl1;
6183 D(emitcode ("; genRightShift",""));
6185 /* if signed then we do it the hard way preserve the
6186 sign bit moving it inwards */
6187 retype = getSpec (operandType (IC_RESULT (ic)));
6188 sign = !SPEC_USIGN (retype);
6190 /* signed & unsigned types are treated the same : i.e. the
6191 signed is NOT propagated inwards : quoting from the
6192 ANSI - standard : "for E1 >> E2, is equivalent to division
6193 by 2**E2 if unsigned or if it has a non-negative value,
6194 otherwise the result is implementation defined ", MY definition
6195 is that the sign does not get propagated */
6197 right = IC_RIGHT (ic);
6198 left = IC_LEFT (ic);
6199 result = IC_RESULT (ic);
6201 aopOp (right, ic, FALSE);
6203 /* if the shift count is known then do it
6204 as efficiently as possible */
6205 if (AOP_TYPE (right) == AOP_LIT)
6207 genRightShiftLiteral (left, right, result, ic, sign);
6211 /* shift count is unknown then we have to form
6212 a loop get the loop count in X : Note: we take
6213 only the lower order byte since shifting
6214 more that 32 bits make no sense anyway, ( the
6215 largest size of an object can be only 32 bits ) */
6217 aopOp (left, ic, FALSE);
6218 aopOp (result, ic, FALSE);
6220 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6221 AOP (result) = forceStackedAop (AOP (result));
6223 size = AOP_SIZE (result);
6227 transferAopAop (AOP (left), offset, AOP (result), offset);
6231 tlbl = newiTempLabel (NULL);
6232 size = AOP_SIZE (result);
6234 tlbl1 = newiTempLabel (NULL);
6236 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6237 emitcode ("tstx", "");
6238 emitcode ("beq", "%05d$", tlbl1->key + 100);
6239 emitcode ("", "%05d$:", tlbl->key + 100);
6240 shift= sign ? "asr" : "lsr";
6241 for (offset=size-1;offset>=0;offset--)
6243 rmwWithAop (shift, AOP (result), offset);
6246 rmwWithReg ("dec", hc08_reg_x);
6247 emitcode ("bne","%05d$", tlbl->key + 100);
6248 emitcode ("", "%05d$:", tlbl1->key + 100);
6250 freeAsmop (result, NULL, ic, TRUE);
6251 freeAsmop (left, NULL, ic, TRUE);
6252 freeAsmop (right, NULL, ic, TRUE);
6255 /*-----------------------------------------------------------------*/
6256 /* genUnpackBits - generates code for unpacking bits */
6257 /*-----------------------------------------------------------------*/
6259 genUnpackBits (operand * result)
6261 int offset = 0; /* result byte offset */
6262 int rsize; /* result size */
6263 int rlen = 0; /* remaining bitfield length */
6264 sym_link *etype; /* bitfield type information */
6265 int blen; /* bitfield length */
6266 int bstr; /* bitfield starting bit within byte */
6268 D(emitcode ("; genUnpackBits",""));
6270 etype = getSpec (operandType (result));
6271 rsize = getSize (operandType (result));
6272 blen = SPEC_BLEN (etype);
6273 bstr = SPEC_BSTR (etype);
6275 /* If the bitfield length is less than a byte */
6278 emitcode ("lda", ",x");
6279 hc08_dirtyReg (hc08_reg_a, FALSE);
6280 AccRsh (bstr, FALSE);
6281 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6282 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6286 /* Bit field did not fit in a byte. Copy all
6287 but the partial byte at the end. */
6288 for (rlen=blen;rlen>=8;rlen-=8)
6290 emitcode ("lda", ",x");
6291 hc08_dirtyReg (hc08_reg_a, FALSE);
6292 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6294 emitcode ("aix", "#1");
6297 /* Handle the partial byte at the end */
6300 emitcode ("lda", ",x");
6301 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6302 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6310 storeConstToAop (zero, AOP (result), offset++);
6315 /*-----------------------------------------------------------------*/
6316 /* genDataPointerGet - generates code when ptr offset is known */
6317 /*-----------------------------------------------------------------*/
6319 genDataPointerGet (operand * left,
6323 int size, offset = 0;
6326 D(emitcode ("; genDataPointerGet",""));
6328 aopOp (result, ic, TRUE);
6329 size = AOP_SIZE (result);
6331 derefaop = aopDerefAop (AOP (left));
6332 freeAsmop (left, NULL, ic, TRUE);
6333 derefaop->size = size;
6337 transferAopAop(derefaop, offset, AOP (result), offset);
6341 freeAsmop (NULL, derefaop, ic, TRUE);
6342 freeAsmop (result, NULL, ic, TRUE);
6345 /*-----------------------------------------------------------------*/
6346 /* genNearPointerGet - emitcode for near pointer fetch */
6347 /*-----------------------------------------------------------------*/
6349 genNearPointerGet (operand * left,
6355 sym_link *retype = getSpec (operandType (result));
6357 D(emitcode ("; genNearPointerGet",""));
6359 aopOp (left, ic, FALSE);
6361 /* if left is rematerialisable and
6362 result is not bit variable type and
6363 the left is pointer to data space i.e
6364 lower 128 bytes of space */
6365 if ((AOP_TYPE (left) == AOP_IMMD)
6366 || (AOP_TYPE (left) == AOP_LIT)
6367 /* !IS_BITVAR (retype) */
6368 /* && DCL_TYPE (ltype) == POINTER */ )
6370 genDataPointerGet (left, result, ic);
6374 /* if the operand is already in hx
6375 then we do nothing else we move the value to hx */
6376 if (AOP_TYPE (left) != AOP_STR)
6378 /* if this is remateriazable */
6379 loadRegFromAop (hc08_reg_x, AOP (left), 0);
6380 loadRegFromConst (hc08_reg_h, zero);
6383 /* so hx now contains the address */
6384 aopOp (result, ic, FALSE);
6386 /* if bit then unpack */
6387 if (IS_BITVAR (retype))
6388 genUnpackBits (result);
6391 size = AOP_SIZE (result);
6396 accopWithMisc ("lda", ",x");
6399 rmwWithReg ("inc", hc08_reg_x);
6401 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6402 hc08_freeReg (hc08_reg_a);
6406 freeAsmop (left, NULL, ic, TRUE);
6407 freeAsmop (result, NULL, ic, TRUE);
6409 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6410 aopOp (IC_RESULT (pi), pi, FALSE);
6411 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6412 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6416 hc08_freeReg (hc08_reg_hx);
6421 /*-----------------------------------------------------------------*/
6422 /* genFarPointerGet - get value from far space */
6423 /*-----------------------------------------------------------------*/
6425 genFarPointerGet (operand * left,
6426 operand * result, iCode * ic, iCode * pi)
6429 sym_link *retype = getSpec (operandType (result));
6431 D(emitcode ("; genFarPointerGet",""));
6433 aopOp (left, ic, FALSE);
6435 /* if left is rematerialisable and
6436 result is not bit variable type and
6437 the left is pointer to data space i.e
6438 lower 128 bytes of space */
6439 if (AOP_TYPE (left) == AOP_IMMD &&
6441 /* && DCL_TYPE (ltype) == POINTER */ )
6443 genDataPointerGet (left, result, ic);
6447 /* if the operand is already in hx
6448 then we do nothing else we move the value to hx */
6449 if (AOP_TYPE (left) != AOP_STR)
6451 /* if this is remateriazable */
6452 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
6455 /* so hx now contains the address */
6456 aopOp (result, ic, FALSE);
6458 /* if bit then unpack */
6459 if (IS_BITVAR (retype))
6460 genUnpackBits (result);
6463 size = AOP_SIZE (result);
6468 accopWithMisc ("lda", ",x");
6471 emitcode ("aix", "#1");
6472 hc08_dirtyReg (hc08_reg_hx, FALSE);
6474 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6475 hc08_freeReg (hc08_reg_a);
6479 freeAsmop (left, NULL, ic, TRUE);
6480 freeAsmop (result, NULL, ic, TRUE);
6482 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6483 aopOp (IC_RESULT (pi), pi, FALSE);
6484 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6485 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6489 hc08_freeReg (hc08_reg_hx);
6495 /*-----------------------------------------------------------------*/
6496 /* genPointerGet - generate code for pointer get */
6497 /*-----------------------------------------------------------------*/
6499 genPointerGet (iCode * ic, iCode *pi)
6501 operand *left, *result;
6502 sym_link *type, *etype;
6505 D(emitcode ("; genPointerGet",""));
6507 left = IC_LEFT (ic);
6508 result = IC_RESULT (ic);
6510 /* depending on the type of pointer we need to
6511 move it to the correct pointer register */
6512 type = operandType (left);
6513 etype = getSpec (type);
6514 /* if left is of type of pointer then it is simple */
6515 if (IS_PTR (type) && !IS_FUNC (type->next))
6516 p_type = DCL_TYPE (type);
6519 /* we have to go by the storage class */
6520 p_type = PTR_TYPE (SPEC_OCLS (etype));
6523 /* special case when cast remat */
6524 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
6525 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
6526 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
6527 type = operandType (left);
6528 p_type = DCL_TYPE (type);
6530 /* now that we have the pointer type we assign
6531 the pointer values */
6538 genNearPointerGet (left, result, ic, pi);
6544 genFarPointerGet (left, result, ic, pi);
6551 /*-----------------------------------------------------------------*/
6552 /* genPackBits - generates code for packed bit storage */
6553 /*-----------------------------------------------------------------*/
6555 genPackBits (sym_link * etype,
6558 int offset = 0; /* source byte offset */
6559 int rlen = 0; /* remaining bitfield length */
6560 int blen; /* bitfield length */
6561 int bstr; /* bitfield starting bit within byte */
6562 int litval; /* source literal value (if AOP_LIT) */
6563 unsigned char mask; /* bitmask within current byte */
6565 D(emitcode ("; genPackBits",""));
6567 blen = SPEC_BLEN (etype);
6568 bstr = SPEC_BSTR (etype);
6570 /* If the bitfield length is less than a byte */
6573 mask = ((unsigned char) (0xFF << (blen + bstr)) |
6574 (unsigned char) (0xFF >> (8 - bstr)));
6576 if (AOP_TYPE (right) == AOP_LIT)
6578 /* Case with a bitfield length <8 and literal source
6580 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6582 litval &= (~mask) & 0xff;
6584 emitcode ("lda", ",x");
6585 if ((mask|litval)!=0xff)
6586 emitcode ("and","#0x%02x", mask);
6588 emitcode ("ora","#0x%02x", litval);
6589 hc08_dirtyReg (hc08_reg_a, FALSE);
6590 emitcode ("sta", ",x");
6592 hc08_freeReg (hc08_reg_a);
6596 /* Case with a bitfield length < 8 and arbitrary source
6598 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6599 /* shift and mask source value */
6601 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6602 hc08_dirtyReg (hc08_reg_a, FALSE);
6603 pushReg (hc08_reg_a, TRUE);
6605 emitcode ("lda", ",x");
6606 emitcode ("and", "#0x%02x", mask);
6607 emitcode ("ora", "1,s");
6608 emitcode ("sta", ",x");
6609 pullReg (hc08_reg_a);
6611 hc08_freeReg (hc08_reg_a);
6615 /* Bit length is greater than 7 bits. In this case, copy */
6616 /* all except the partial byte at the end */
6617 for (rlen=blen;rlen>=8;rlen-=8)
6619 if (AOP (right)->type == AOP_DIR)
6621 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
6625 loadRegFromAop (hc08_reg_a, AOP (right), offset);
6626 emitcode ("sta", "%d,x", offset);
6631 /* If there was a partial byte at the end */
6634 mask = (((unsigned char) -1 << rlen) & 0xff);
6636 if (AOP_TYPE (right) == AOP_LIT)
6638 /* Case with partial byte and literal source
6640 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6641 litval >>= (blen-rlen);
6642 litval &= (~mask) & 0xff;
6643 emitcode ("lda", "%d,x", offset);
6644 hc08_dirtyReg (hc08_reg_a, FALSE);
6645 if ((mask|litval)!=0xff)
6646 emitcode ("and","#0x%02x", mask);
6648 emitcode ("ora","#0x%02x", litval);
6649 emitcode ("sta", "%d,x", offset);
6650 hc08_dirtyReg (hc08_reg_a, FALSE);
6651 hc08_freeReg (hc08_reg_a);
6655 /* Case with partial byte and arbitrary source
6657 loadRegFromAop (hc08_reg_a, AOP (right), offset++);
6658 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6659 hc08_dirtyReg (hc08_reg_a, FALSE);
6660 pushReg (hc08_reg_a, TRUE);
6662 emitcode ("lda", ",x");
6663 emitcode ("and", "#0x%02x", mask);
6664 emitcode ("ora", "1,s");
6665 emitcode ("sta", ",x");
6668 hc08_freeReg (hc08_reg_a);
6671 /*-----------------------------------------------------------------*/
6672 /* genDataPointerSet - remat pointer to data space */
6673 /*-----------------------------------------------------------------*/
6675 genDataPointerSet (operand * right,
6679 int size, offset = 0;
6682 D(emitcode ("; genDataPointerSet",""));
6684 aopOp (right, ic, FALSE);
6685 size = AOP_SIZE (right);
6687 derefaop = aopDerefAop (AOP (result));
6688 freeAsmop (result, NULL, ic, TRUE);
6689 derefaop->size = size;
6693 transferAopAop (AOP (right), offset, derefaop, offset);
6697 freeAsmop (right, NULL, ic, TRUE);
6698 freeAsmop (NULL, derefaop, ic, TRUE);
6701 /*-----------------------------------------------------------------*/
6702 /* genNearPointerSet - emitcode for near pointer put */
6703 /*-----------------------------------------------------------------*/
6705 genNearPointerSet (operand * right,
6711 sym_link *retype = getSpec (operandType (right));
6712 sym_link *letype = getSpec (operandType (result));
6714 D(emitcode ("; genNearPointerSet",""));
6716 aopOp (result, ic, FALSE);
6718 /* if the result is rematerializable &
6719 in data space & not a bit variable */
6720 if (AOP_TYPE (result) == AOP_IMMD &&
6721 /* DCL_TYPE (ptype) == POINTER && */
6722 !IS_BITVAR (retype) &&
6723 !IS_BITVAR (letype))
6725 genDataPointerSet (right, result, ic);
6729 /* if the operand is already in hx
6730 then we do nothing else we move the value to hx */
6731 if (AOP_TYPE (result) != AOP_STR)
6733 loadRegFromAop (hc08_reg_x, AOP (result), 0);
6734 loadRegFromConst (hc08_reg_h, zero);
6736 /* so hx now contains the address */
6737 aopOp (right, ic, FALSE);
6739 /* if bit then unpack */
6740 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6741 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6744 size = AOP_SIZE (right);
6749 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6750 accopWithMisc ("sta", ",x");
6753 rmwWithReg ("inc", hc08_reg_x);
6755 hc08_freeReg (hc08_reg_a);
6759 freeAsmop (result, NULL, ic, TRUE);
6760 freeAsmop (right, NULL, ic, TRUE);
6762 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6763 aopOp (IC_RESULT (pi), pi, FALSE);
6764 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6765 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6769 hc08_freeReg (hc08_reg_hx);
6774 /*-----------------------------------------------------------------*/
6775 /* genFarPointerSet - set value from far space */
6776 /*-----------------------------------------------------------------*/
6778 genFarPointerSet (operand * right,
6779 operand * result, iCode * ic, iCode * pi)
6782 sym_link *retype = getSpec (operandType (right));
6783 sym_link *letype = getSpec (operandType (result));
6785 D(emitcode ("; genFarPointerSet",""));
6787 aopOp (result, ic, FALSE);
6789 /* if the result is rematerializable &
6790 in data space & not a bit variable */
6791 if (AOP_TYPE (result) == AOP_IMMD &&
6792 /* DCL_TYPE (ptype) == POINTER && */
6793 !IS_BITVAR (retype) &&
6794 !IS_BITVAR (letype))
6796 genDataPointerSet (right, result, ic);
6800 /* if the operand is already in hx
6801 then we do nothing else we move the value to hx */
6802 if (AOP_TYPE (result) != AOP_STR)
6804 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
6806 /* so hx now contains the address */
6807 aopOp (right, ic, FALSE);
6809 /* if bit then unpack */
6810 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6811 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6814 size = AOP_SIZE (right);
6819 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6820 accopWithMisc ("sta", ",x");
6823 emitcode ("aix", "#1");
6825 hc08_freeReg (hc08_reg_a);
6829 freeAsmop (result, NULL, ic, TRUE);
6830 freeAsmop (right, NULL, ic, TRUE);
6832 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6833 aopOp (IC_RESULT (pi), pi, FALSE);
6834 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6835 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6839 hc08_freeReg (hc08_reg_hx);
6845 /*-----------------------------------------------------------------*/
6846 /* genPointerSet - stores the value into a pointer location */
6847 /*-----------------------------------------------------------------*/
6849 genPointerSet (iCode * ic, iCode *pi)
6851 operand *right, *result;
6852 sym_link *type, *etype;
6855 D(emitcode ("; genPointerSet",""));
6857 right = IC_RIGHT (ic);
6858 result = IC_RESULT (ic);
6860 /* depending on the type of pointer we need to
6861 move it to the correct pointer register */
6862 type = operandType (result);
6863 etype = getSpec (type);
6864 /* if left is of type of pointer then it is simple */
6865 if (IS_PTR (type) && !IS_FUNC (type->next))
6867 p_type = DCL_TYPE (type);
6871 /* we have to go by the storage class */
6872 p_type = PTR_TYPE (SPEC_OCLS (etype));
6875 /* special case when cast remat */
6876 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
6877 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
6878 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
6879 type = operandType (result);
6880 p_type = DCL_TYPE (type);
6882 /* now that we have the pointer type we assign
6883 the pointer values */
6890 genNearPointerSet (right, result, ic, pi);
6896 genFarPointerSet (right, result, ic, pi);
6900 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6901 "genPointerSet: illegal pointer type");
6906 /*-----------------------------------------------------------------*/
6907 /* genIfx - generate code for Ifx statement */
6908 /*-----------------------------------------------------------------*/
6910 genIfx (iCode * ic, iCode * popIc)
6912 operand *cond = IC_COND (ic);
6915 D(emitcode ("; genIfx",""));
6917 aopOp (cond, ic, FALSE);
6919 /* get the value into acc */
6920 if (AOP_TYPE (cond) != AOP_CRY)
6921 asmopToBool (AOP (cond), FALSE);
6924 /* the result is now in the accumulator */
6925 freeAsmop (cond, NULL, ic, TRUE);
6927 /* if there was something to be popped then do it */
6931 /* if the condition is a bit variable */
6932 if (isbit && IS_ITEMP (cond) &&
6934 genIfxJump (ic, SPIL_LOC (cond)->rname);
6935 else if (isbit && !IS_ITEMP (cond))
6936 genIfxJump (ic, OP_SYMBOL (cond)->rname);
6938 genIfxJump (ic, "a");
6943 /*-----------------------------------------------------------------*/
6944 /* genAddrOf - generates code for address of */
6945 /*-----------------------------------------------------------------*/
6947 genAddrOf (iCode * ic)
6949 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
6952 D(emitcode ("; genAddrOf",""));
6954 aopOp (IC_RESULT (ic), ic, FALSE);
6956 /* if the operand is on the stack then we
6957 need to get the stack offset of this
6961 /* if it has an offset then we need to compute
6963 hc08_useReg (hc08_reg_hx);
6964 emitcode ("tsx", "");
6965 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
6966 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
6967 hc08_freeReg (hc08_reg_hx);
6972 /* object not on stack then we need the name */
6973 size = AOP_SIZE (IC_RESULT (ic));
6978 char s[SDCC_NAME_MAX+10];
6981 sprintf (s, "#%s", sym->rname);
6984 sprintf (s, "#>%s", sym->rname);
6987 sprintf (s, "#(%s >> %d)",
6991 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
6995 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
6999 /*-----------------------------------------------------------------*/
7000 /* genAssign - generate code for assignment */
7001 /*-----------------------------------------------------------------*/
7003 genAssign (iCode * ic)
7005 operand *result, *right;
7007 // unsigned long lit = 0L;
7009 D(emitcode("; genAssign",""));
7011 result = IC_RESULT (ic);
7012 right = IC_RIGHT (ic);
7014 /* if they are the same */
7015 if (operandsEqu (result, right)) {
7019 aopOp (right, ic, FALSE);
7020 aopOp (result, ic, TRUE);
7022 /* if they are the same registers */
7023 if (sameRegs (AOP (right), AOP (result)))
7026 if ((AOP_TYPE (right) == AOP_LIT)
7027 && (IS_AOP_HX(AOP(result))))
7029 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7034 size = AOP_SIZE (result);
7039 transferAopAop (AOP (right), offset, AOP (result), offset);
7044 freeAsmop (right, NULL, ic, TRUE);
7045 freeAsmop (result, NULL, ic, TRUE);
7048 /*-----------------------------------------------------------------*/
7049 /* genJumpTab - genrates code for jump table */
7050 /*-----------------------------------------------------------------*/
7052 genJumpTab (iCode * ic)
7057 D(emitcode ("; genJumpTab",""));
7059 aopOp (IC_JTCOND (ic), ic, FALSE);
7060 /* get the condition into accumulator */
7061 loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7062 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7063 /* multiply by three */
7064 pushReg (hc08_reg_a, FALSE);
7065 emitcode ("lsla", "");
7066 emitcode ("add","1,s");
7067 transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7068 loadRegFromConst (hc08_reg_h, zero);
7070 jtab = newiTempLabel (NULL);
7071 emitcode ("jmp", "%05d$,x", jtab->key + 100);
7072 emitcode ("", "%05d$:", jtab->key + 100);
7073 /* now generate the jump labels */
7074 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7075 jtab = setNextItem (IC_JTLABELS (ic)))
7076 emitcode ("jmp", "%05d$", jtab->key + 100);
7078 hc08_dirtyReg (hc08_reg_a, TRUE);
7079 hc08_dirtyReg (hc08_reg_hx, TRUE);
7082 /*-----------------------------------------------------------------*/
7083 /* genCast - gen code for casting */
7084 /*-----------------------------------------------------------------*/
7086 genCast (iCode * ic)
7088 operand *result = IC_RESULT (ic);
7089 sym_link *ctype = operandType (IC_LEFT (ic));
7090 sym_link *rtype = operandType (IC_RIGHT (ic));
7091 operand *right = IC_RIGHT (ic);
7094 D(emitcode("; genCast",""));
7096 /* if they are equivalent then do nothing */
7097 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7100 aopOp (right, ic, FALSE);
7101 aopOp (result, ic, FALSE);
7104 /* if they are the same size : or less */
7105 if (AOP_SIZE (result) <= AOP_SIZE (right))
7108 /* if they are in the same place */
7110 if (sameRegs (AOP (right), AOP (result)))
7114 /* if they in different places then copy */
7115 size = AOP_SIZE (result);
7119 transferAopAop(AOP (right), offset, AOP (result), offset);
7126 /* if the result is of type pointer */
7131 sym_link *type = operandType (right);
7132 sym_link *etype = getSpec (type);
7134 /* pointer to generic pointer */
7135 if (IS_GENPTR (ctype))
7138 p_type = DCL_TYPE (type);
7141 if (SPEC_SCLS(etype)==S_REGISTER) {
7142 // let's assume it is a generic pointer
7145 /* we have to go by the storage class */
7146 p_type = PTR_TYPE (SPEC_OCLS (etype));
7150 /* the first two bytes are known */
7151 size = GPTRSIZE - 1;
7155 transferAopAop(AOP (right), offset, AOP (result), offset);
7158 /* the last byte depending on type */
7161 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7166 // pointerTypeToGPByte will have bitched.
7170 sprintf(gpValStr, "#0x%d", gpVal);
7171 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7177 /* just copy the pointers */
7178 size = AOP_SIZE (result);
7182 transferAopAop(AOP (right), offset, AOP (result), offset);
7188 /* so we now know that the size of destination is greater
7189 than the size of the source */
7190 /* we move to result for the size of source */
7191 size = AOP_SIZE (right);
7195 transferAopAop(AOP (right), offset, AOP (result), offset);
7199 /* now depending on the sign of the source && destination */
7200 size = AOP_SIZE (result) - AOP_SIZE (right);
7201 /* if unsigned or not an integral type */
7202 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7205 storeConstToAop (zero, AOP (result), offset++);
7209 /* we need to extend the sign :{ */
7210 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7211 accopWithMisc ("rola", "");
7212 accopWithMisc ("clra", "");
7213 accopWithMisc ("sbc", zero);
7215 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7218 /* we are done hurray !!!! */
7221 freeAsmop (right, NULL, ic, TRUE);
7222 freeAsmop (result, NULL, ic, TRUE);
7226 /*-----------------------------------------------------------------*/
7227 /* genDjnz - generate decrement & jump if not zero instrucion */
7228 /*-----------------------------------------------------------------*/
7230 genDjnz (iCode * ic, iCode * ifx)
7236 D(emitcode ("; genDjnz",""));
7238 /* if the if condition has a false label
7239 then we cannot save */
7243 /* if the minus is not of the form
7245 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7246 !IS_OP_LITERAL (IC_RIGHT (ic)))
7249 if (operandLitValue (IC_RIGHT (ic)) != 1)
7252 /* if the size of this greater than one then no
7254 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7256 aopOp (IC_RESULT (ic), ic, FALSE);
7257 if (AOP_SIZE (IC_RESULT (ic))>1)
7259 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7263 /* otherwise we can save BIG */
7264 lbl = newiTempLabel (NULL);
7265 lbl1 = newiTempLabel (NULL);
7268 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7271 emitBranch ("bra", lbl1);
7273 emitBranch ("jmp", IC_TRUE (ifx));
7276 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7281 /*-----------------------------------------------------------------*/
7282 /* genReceive - generate code for a receive iCode */
7283 /*-----------------------------------------------------------------*/
7285 genReceive (iCode * ic)
7289 D(emitcode ("; genReceive",""));
7291 aopOp (IC_RESULT (ic), ic, FALSE);
7292 size = AOP_SIZE (IC_RESULT (ic));
7297 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7298 AOP (IC_RESULT (ic)), offset);
7299 if (hc08_aop_pass[offset]->type == AOP_REG)
7300 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7305 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7308 /*-----------------------------------------------------------------*/
7309 /* genhc08Code - generate code for HC08 based controllers */
7310 /*-----------------------------------------------------------------*/
7312 genhc08Code (iCode * lic)
7317 lineHead = lineCurr = NULL;
7319 /* print the allocation information */
7320 if (allocInfo && currFunc)
7321 printAllocInfo (currFunc, codeOutFile);
7322 /* if debug information required */
7323 if (options.debug && currFunc)
7325 debugFile->writeFunction(currFunc);
7327 if (IS_STATIC (currFunc->etype))
7328 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7330 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7333 /* stack pointer name */
7334 if (options.useXstack)
7339 hc08_aop_pass[0] = newAsmop (AOP_REG);
7340 hc08_aop_pass[0]->size=1;
7341 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7342 hc08_aop_pass[1] = newAsmop (AOP_REG);
7343 hc08_aop_pass[1]->size=1;
7344 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
7345 hc08_aop_pass[2] = newAsmop (AOP_DIR);
7346 hc08_aop_pass[2]->size=1;
7347 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
7348 hc08_aop_pass[3] = newAsmop (AOP_DIR);
7349 hc08_aop_pass[3]->size=1;
7350 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
7352 for (ic = lic; ic; ic = ic->next)
7355 if (ic->lineno && cln != ic->lineno)
7360 emitcode ("", "C$%s$%d$%d$%d ==.",
7361 FileBaseName (ic->filename), ic->lineno,
7362 ic->level, ic->block);
7365 if (!options.noCcodeInAsm) {
7366 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
7367 printCLine(ic->filename, ic->lineno));
7371 if (options.iCodeInAsm) {
7375 for (i=0; i<6; i++) {
7376 sprintf (®sInUse[i],
7377 "%c", ic->riu & (1<<i) ? i+'0' : '-');
7380 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
7382 /* if the result is marked as
7383 spilt and rematerializable or code for
7384 this has already been generated then
7386 if (resultRemat (ic) || ic->generated)
7394 for (i=A_IDX;i<=XA_IDX;i++)
7396 reg = hc08_regWithIdx(i);
7398 emitcode("","; %s = %s offset %d", reg->name,
7399 aopName(reg->aop), reg->aopofs);
7402 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
7404 sym = OP_SYMBOL (IC_LEFT (ic));
7405 if (sym->accuse == ACCUSE_HX)
7407 hc08_reg_h->isFree = FALSE;
7408 hc08_reg_x->isFree = FALSE;
7410 else if (sym->accuse == ACCUSE_XA)
7412 hc08_reg_a->isFree = FALSE;
7414 hc08_reg_x->isFree = FALSE;
7417 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
7419 sym = OP_SYMBOL (IC_RIGHT (ic));
7420 if (sym->accuse == ACCUSE_HX)
7422 hc08_reg_h->isFree = FALSE;
7423 hc08_reg_x->isFree = FALSE;
7425 else if (sym->accuse == ACCUSE_XA)
7427 hc08_reg_a->isFree = FALSE;
7429 hc08_reg_x->isFree = FALSE;
7434 /* depending on the operation */
7454 /* IPOP happens only when trying to restore a
7455 spilt live range, if there is an ifx statement
7456 following this pop then the if statement might
7457 be using some of the registers being popped which
7458 would destory the contents of the register so
7459 we need to check for this condition and handle it */
7461 ic->next->op == IFX &&
7462 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7463 genIfx (ic->next, ic);
7481 genEndFunction (ic);
7497 if (!genPointerGetSetOfs (ic))
7502 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7519 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7523 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7530 /* note these two are xlated by algebraic equivalence
7531 during parsing SDCC.y */
7532 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7533 "got '>=' or '<=' shouldn't have come here");
7537 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7549 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7553 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7557 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7584 case GET_VALUE_AT_ADDRESS:
7585 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
7589 if (POINTER_SET (ic))
7590 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
7616 addSet (&_G.sendSet, ic);
7623 if (!hc08_reg_a->isFree)
7624 emitcode("","; forgot to free a");
7625 if (!hc08_reg_x->isFree)
7626 emitcode("","; forgot to free x");
7627 if (!hc08_reg_h->isFree)
7628 emitcode("","; forgot to free h");
7629 if (!hc08_reg_hx->isFree)
7630 emitcode("","; forgot to free hx");
7631 if (!hc08_reg_xa->isFree)
7632 emitcode("","; forgot to free xa");
7636 /* now we are ready to call the
7637 peep hole optimizer */
7638 if (!options.nopeep)
7639 peepHole (&lineHead);
7641 /* now do the actual printing */
7642 printLine (lineHead, codeOutFile);