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 asmop *leftOp, *rightOp;
3331 D(emitcode ("; genMinus",""));
3333 aopOp (IC_LEFT (ic), ic, FALSE);
3334 aopOp (IC_RIGHT (ic), ic, FALSE);
3335 aopOp (IC_RESULT (ic), ic, TRUE);
3337 /* special cases :- */
3338 /* if I can do an decrement instead
3339 of subtract then GOOD for ME */
3340 if (genMinusDec (ic) == TRUE)
3343 size = getDataSize (IC_RESULT (ic));
3346 leftOp = AOP(IC_LEFT(ic));
3347 rightOp = AOP(IC_RIGHT(ic));
3353 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3354 accopWithAop(sub, rightOp, offset);
3355 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3360 // adjustArithmeticResult (ic);
3363 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3364 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3365 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3370 /*-----------------------------------------------------------------*/
3371 /* genMultOneByte : 8*8=8/16 bit multiplication */
3372 /*-----------------------------------------------------------------*/
3374 genMultOneByte (operand * left,
3378 sym_link *opetype = operandType (result);
3379 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3380 int size=AOP_SIZE(result);
3381 bool negLiteral = FALSE;
3383 D(emitcode ("; genMultOneByte",""));
3385 if (size<1 || size>2) {
3386 // this should never happen
3387 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3388 AOP_SIZE(result), __FILE__, lineno);
3392 /* (if two literals: the value is computed before) */
3393 /* if one literal, literal on the right */
3394 if (AOP_TYPE (left) == AOP_LIT)
3399 //emitcode (";", "swapped left and right");
3402 if (SPEC_USIGN(opetype))
3404 // just an unsigned 8*8=8/16 multiply
3405 //emitcode (";","unsigned");
3407 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3408 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3409 emitcode ("mul", "");
3410 hc08_dirtyReg (hc08_reg_xa, FALSE);
3411 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3412 hc08_freeReg (hc08_reg_xa);
3417 // we have to do a signed multiply
3420 //emitcode (";", "signed");
3422 emitcode ("clr", "1,s");
3424 tlbl1 = newiTempLabel (NULL);
3425 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3426 emitcode ("tsta","");
3427 emitBranch ("bpl", tlbl1);
3428 emitcode ("inc", "1,s");
3429 rmwWithReg ("neg", hc08_reg_a);
3432 if (AOP_TYPE(right)==AOP_LIT)
3434 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3435 /* AND literal negative */
3437 emitcode ("ldx", "#0x%02x", -val);
3440 emitcode ("ldx", "#0x%02x", val);
3442 hc08_useReg (hc08_reg_x);
3446 tlbl2 = newiTempLabel (NULL);
3447 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3448 emitcode ("tstx", "");
3449 emitBranch ("bpl", tlbl2);
3450 emitcode ("inc", "1,s");
3451 rmwWithReg ("neg", hc08_reg_x);
3455 emitcode ("mul", "");
3456 hc08_dirtyReg (hc08_reg_xa, FALSE);
3458 tlbl3 = newiTempLabel (NULL);
3459 emitcode ("dec", "1,s");
3461 emitBranch ("bne", tlbl3);
3463 emitBranch ("beq", tlbl3);
3465 rmwWithReg ("neg", hc08_reg_a);
3468 tlbl4 = newiTempLabel (NULL);
3469 emitBranch ("bcc", tlbl4);
3470 rmwWithReg ("inc", hc08_reg_x);
3472 rmwWithReg ("neg", hc08_reg_x);
3477 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3478 hc08_freeReg (hc08_reg_xa);
3482 /*-----------------------------------------------------------------*/
3483 /* genMult - generates code for multiplication */
3484 /*-----------------------------------------------------------------*/
3486 genMult (iCode * ic)
3488 operand *left = IC_LEFT (ic);
3489 operand *right = IC_RIGHT (ic);
3490 operand *result = IC_RESULT (ic);
3492 D(emitcode ("; genMult",""));
3494 /* assign the amsops */
3495 aopOp (left, ic, FALSE);
3496 aopOp (right, ic, FALSE);
3497 aopOp (result, ic, TRUE);
3499 /* special cases first */
3500 /* if both are of size == 1 */
3501 // if (getSize(operandType(left)) == 1 &&
3502 // getSize(operandType(right)) == 1)
3503 if (AOP_SIZE (left) == 1 &&
3504 AOP_SIZE (right) == 1)
3506 genMultOneByte (left, right, result);
3510 /* should have been converted to function call */
3511 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3512 getSize(OP_SYMBOL(right)->type));
3513 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3518 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3519 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3520 freeAsmop (result, NULL, ic, TRUE);
3523 /*-----------------------------------------------------------------*/
3524 /* genDivOneByte : 8 bit division */
3525 /*-----------------------------------------------------------------*/
3527 genDivOneByte (operand * left,
3531 sym_link *opetype = operandType (result);
3533 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3535 bool negLiteral = FALSE;
3537 D(emitcode ("; genDivOneByte",""));
3539 size = AOP_SIZE (result);
3540 /* signed or unsigned */
3541 if (SPEC_USIGN (opetype))
3543 /* unsigned is easy */
3544 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3545 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3546 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3547 emitcode ("div", "");
3548 hc08_dirtyReg (hc08_reg_a, FALSE);
3549 hc08_dirtyReg (hc08_reg_h, FALSE);
3550 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3551 hc08_freeReg (hc08_reg_a);
3552 hc08_freeReg (hc08_reg_x);
3553 hc08_freeReg (hc08_reg_h);
3557 /* signed is a little bit more difficult */
3560 emitcode ("clr", "1,s");
3562 tlbl1 = newiTempLabel (NULL);
3563 tlbl2 = newiTempLabel (NULL);
3564 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3565 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3566 emitBranch ("bpl", tlbl1);
3567 emitcode ("inc", "1,s");
3568 rmwWithReg ("neg", hc08_reg_a);
3569 emitBranch ("bcc", tlbl2);
3570 rmwWithReg ("inc", hc08_reg_x);
3572 rmwWithReg ("neg", hc08_reg_x);
3573 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3576 if (AOP_TYPE(right)==AOP_LIT)
3578 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3579 /* AND literal negative */
3581 emitcode ("ldx", "#0x%02x", -val);
3584 emitcode ("ldx", "#0x%02x", val);
3586 hc08_useReg (hc08_reg_x);
3590 tlbl3 = newiTempLabel (NULL);
3591 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3592 emitBranch ("bpl", tlbl3);
3593 emitcode ("inc", "1,s");
3594 rmwWithReg ("neg", hc08_reg_x);
3598 emitcode ("div", "");
3599 hc08_dirtyReg (hc08_reg_x, FALSE);
3600 hc08_dirtyReg (hc08_reg_a, FALSE);
3601 hc08_dirtyReg (hc08_reg_h, FALSE);
3603 tlbl4 = newiTempLabel (NULL);
3604 emitcode ("dec", "1,s");
3606 emitBranch ("bne", tlbl4);
3608 emitBranch ("beq", tlbl4);
3609 rmwWithReg ("neg", hc08_reg_a);
3613 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3614 hc08_freeReg (hc08_reg_a);
3615 hc08_freeReg (hc08_reg_x);
3616 hc08_freeReg (hc08_reg_h);
3621 /*-----------------------------------------------------------------*/
3622 /* genDiv - generates code for division */
3623 /*-----------------------------------------------------------------*/
3627 operand *left = IC_LEFT (ic);
3628 operand *right = IC_RIGHT (ic);
3629 operand *result = IC_RESULT (ic);
3631 D(emitcode ("; genDiv",""));
3633 /* assign the amsops */
3634 aopOp (left, ic, FALSE);
3635 aopOp (right, ic, FALSE);
3636 aopOp (result, ic, TRUE);
3638 /* special cases first */
3639 /* if both are of size == 1 */
3640 if (AOP_SIZE (left) <= 2 &&
3641 AOP_SIZE (right) == 1)
3643 genDivOneByte (left, right, result);
3647 /* should have been converted to function call */
3650 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3651 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3652 freeAsmop (result, NULL, ic, TRUE);
3655 /*-----------------------------------------------------------------*/
3656 /* genModOneByte : 8 bit modulus */
3657 /*-----------------------------------------------------------------*/
3659 genModOneByte (operand * left,
3663 sym_link *opetype = operandType (result);
3665 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3667 bool negLiteral = FALSE;
3669 D(emitcode ("; genModOneByte",""));
3671 size = AOP_SIZE (result);
3672 /* signed or unsigned */
3673 if (SPEC_USIGN (opetype))
3675 /* unsigned is easy */
3676 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3677 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3678 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3679 emitcode ("div", "");
3680 hc08_dirtyReg (hc08_reg_a, FALSE);
3681 hc08_dirtyReg (hc08_reg_h, FALSE);
3682 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3683 hc08_freeReg (hc08_reg_a);
3684 hc08_freeReg (hc08_reg_x);
3685 hc08_freeReg (hc08_reg_h);
3689 /* signed is a little bit more difficult */
3692 emitcode ("clr", "1,s");
3694 tlbl1 = newiTempLabel (NULL);
3695 tlbl2 = newiTempLabel (NULL);
3696 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3697 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3698 emitBranch ("bpl", tlbl1);
3699 emitcode ("inc", "1,s");
3700 rmwWithReg ("neg", hc08_reg_a);
3701 emitBranch ("bcc", tlbl2);
3702 rmwWithReg ("inc", hc08_reg_x);
3704 rmwWithReg ("neg", hc08_reg_x);
3705 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3708 if (AOP_TYPE(right)==AOP_LIT)
3710 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3711 /* AND literal negative */
3713 emitcode ("ldx", "#0x%02x", -val);
3716 emitcode ("ldx", "#0x%02x", val);
3718 hc08_useReg (hc08_reg_x);
3722 tlbl3 = newiTempLabel (NULL);
3723 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3724 emitBranch ("bpl", tlbl3);
3725 emitcode ("inc", "1,s");
3726 rmwWithReg ("neg", hc08_reg_x);
3730 emitcode ("div", "");
3731 hc08_dirtyReg (hc08_reg_x, FALSE);
3732 hc08_dirtyReg (hc08_reg_a, FALSE);
3733 hc08_dirtyReg (hc08_reg_h, FALSE);
3735 tlbl4 = newiTempLabel (NULL);
3736 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
3737 emitcode ("dec", "1,s");
3739 emitBranch ("bne", tlbl4);
3741 emitBranch ("beq", tlbl4);
3742 rmwWithReg ("neg", hc08_reg_a);
3746 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3747 hc08_freeReg (hc08_reg_a);
3748 hc08_freeReg (hc08_reg_x);
3749 hc08_freeReg (hc08_reg_h);
3753 /*-----------------------------------------------------------------*/
3754 /* genMod - generates code for division */
3755 /*-----------------------------------------------------------------*/
3759 operand *left = IC_LEFT (ic);
3760 operand *right = IC_RIGHT (ic);
3761 operand *result = IC_RESULT (ic);
3763 D(emitcode ("; genMod",""));
3765 /* assign the amsops */
3766 aopOp (left, ic, FALSE);
3767 aopOp (right, ic, FALSE);
3768 aopOp (result, ic, TRUE);
3770 /* special cases first */
3771 /* if both are of size == 1 */
3772 if (AOP_SIZE (left) <= 2 &&
3773 AOP_SIZE (right) == 1)
3775 genModOneByte (left, right, result);
3779 /* should have been converted to function call */
3783 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3784 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3785 freeAsmop (result, NULL, ic, TRUE);
3788 /*-----------------------------------------------------------------*/
3789 /* genIfxJump :- will create a jump depending on the ifx */
3790 /*-----------------------------------------------------------------*/
3792 genIfxJump (iCode * ic, char *jval)
3795 symbol *tlbl = newiTempLabel (NULL);
3798 D(emitcode ("; genIfxJump",""));
3800 /* if true label then we jump if condition
3804 jlbl = IC_TRUE (ic);
3805 if (!strcmp (jval, "a"))
3807 else if (!strcmp (jval, "c"))
3814 /* false label is present */
3815 jlbl = IC_FALSE (ic);
3816 if (!strcmp (jval, "a"))
3818 else if (!strcmp (jval, "c"))
3823 emitBranch (inst, tlbl);
3824 emitBranch ("jmp", jlbl);
3827 /* mark the icode as generated */
3831 /*-----------------------------------------------------------------*/
3832 /* genCmp :- greater or less than comparison */
3833 /*-----------------------------------------------------------------*/
3835 genCmp (operand * left, operand * right,
3836 operand * result, iCode * ifx, int sign, iCode *ic)
3838 int size, offset = 0;
3839 unsigned long lit = 0L;
3841 bool needpula = FALSE;
3843 D(emitcode ("; genCmp",""));
3845 /* subtract right from left if at the
3846 end the carry flag is set then we know that
3847 left is greater than right */
3848 size = max (AOP_SIZE (left), AOP_SIZE (right));
3850 if (AOP_TYPE (right) == AOP_LIT)
3852 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3853 /* optimize if(x < 0) or if(x >= 0) */
3862 needpula = pushRegIfUsed (hc08_reg_a);
3863 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
3864 emitcode ("rola", "");
3865 hc08_useReg (hc08_reg_a);
3873 && ((AOP_TYPE (right) == AOP_LIT) ||
3874 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
3875 && hc08_reg_hx->isFree)
3877 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
3878 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
3879 hc08_freeReg (hc08_reg_hx);
3890 loadRegFromAop (hc08_reg_a, AOP (left), offset);
3891 accopWithAop (sub, AOP (right), offset);
3892 hc08_freeReg (hc08_reg_a);
3898 freeAsmop (right, NULL, ic, TRUE);
3899 freeAsmop (left, NULL, ic, TRUE);
3900 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3906 /* if the result is used in the next
3907 ifx conditional branch then generate
3908 code a little differently */
3911 pullOrFreeReg(hc08_reg_a,needpula);
3912 genIfxJump (ifx, sign ? "s" : "c");
3919 pullOrFreeReg(hc08_reg_a,needpula);
3923 /*-----------------------------------------------------------------*/
3924 /* genCmpGt :- greater than comparison */
3925 /*-----------------------------------------------------------------*/
3927 genCmpGt (iCode * ic, iCode * ifx)
3929 operand *left, *right, *result;
3930 sym_link *letype, *retype;
3933 D(emitcode ("; genCmpGt",""));
3935 result = IC_RESULT (ic);
3936 left = IC_LEFT (ic);
3937 right = IC_RIGHT (ic);
3939 letype = getSpec (operandType (left));
3940 retype = getSpec (operandType (right));
3941 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3942 /* assign the amsops */
3943 aopOp (left, ic, FALSE);
3944 aopOp (right, ic, FALSE);
3945 aopOp (result, ic, TRUE);
3947 genCmp (right, left, result, ifx, sign,ic);
3949 freeAsmop (result, NULL, ic, TRUE);
3952 /*-----------------------------------------------------------------*/
3953 /* genCmpLt - less than comparisons */
3954 /*-----------------------------------------------------------------*/
3956 genCmpLt (iCode * ic, iCode * ifx)
3958 operand *left, *right, *result;
3959 sym_link *letype, *retype;
3962 D(emitcode ("; genCmpLt",""));
3964 result = IC_RESULT (ic);
3965 left = IC_LEFT (ic);
3966 right = IC_RIGHT (ic);
3968 letype = getSpec (operandType (left));
3969 retype = getSpec (operandType (right));
3970 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3972 /* assign the amsops */
3973 aopOp (left, ic, FALSE);
3974 aopOp (right, ic, FALSE);
3975 aopOp (result, ic, TRUE);
3977 genCmp (left, right, result, ifx, sign,ic);
3979 freeAsmop (result, NULL, ic, TRUE);
3982 /*-----------------------------------------------------------------*/
3983 /* - compare and branch if not equal */
3984 /*-----------------------------------------------------------------*/
3986 gencbneshort (operand * left, operand * right, symbol * lbl)
3988 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3990 unsigned long lit = 0L;
3992 /* if the left side is a literal or
3993 if the right is in a pointer register and left
3995 if (AOP_TYPE (left) == AOP_LIT)
4001 if (AOP_TYPE (right) == AOP_LIT)
4002 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4006 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4007 accopWithAop ("cmp", AOP (right), offset);
4008 hc08_useReg (hc08_reg_a);
4009 hc08_freeReg (hc08_reg_a);
4010 emitBranch ("bne", lbl);
4016 /*-----------------------------------------------------------------*/
4017 /* gencjne - compare and jump if not equal */
4018 /*-----------------------------------------------------------------*/
4020 gencjne (operand * left, operand * right, symbol * lbl)
4022 symbol *tlbl = newiTempLabel (NULL);
4024 gencbneshort (left, right, lbl);
4026 loadRegFromConst (hc08_reg_a, one);
4027 emitBranch ("bra", tlbl);
4029 loadRegFromConst (hc08_reg_a, zero);
4032 hc08_useReg(hc08_reg_a);
4033 hc08_freeReg(hc08_reg_a);
4036 /*-----------------------------------------------------------------*/
4037 /* genCmpEq - generates code for equal to */
4038 /*-----------------------------------------------------------------*/
4040 genCmpEq (iCode * ic, iCode * ifx)
4042 operand *left, *right, *result;
4044 D(emitcode ("; genCmpEq",""));
4046 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4047 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4048 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4050 /* if literal, literal on the right or
4051 if the right is in a pointer register and left
4053 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4055 operand *t = IC_RIGHT (ic);
4056 IC_RIGHT (ic) = IC_LEFT (ic);
4060 if (ifx && !AOP_SIZE (result))
4063 tlbl = newiTempLabel (NULL);
4064 gencbneshort (left, right, tlbl);
4067 emitBranch ("jmp", IC_TRUE (ifx));
4072 symbol *lbl = newiTempLabel (NULL);
4073 emitBranch ("bra", lbl);
4075 emitBranch ("jmp", IC_FALSE (ifx));
4079 /* mark the icode as generated */
4084 gencjne (left, right, newiTempLabel (NULL));
4085 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4087 storeRegToAop (hc08_reg_a, AOP (result), 0);
4092 genIfxJump (ifx, "a");
4095 /* if the result is used in an arithmetic operation
4096 then put the result in place */
4097 if (AOP_TYPE (result) != AOP_CRY)
4101 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4102 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4103 freeAsmop (result, NULL, ic, TRUE);
4106 /*-----------------------------------------------------------------*/
4107 /* ifxForOp - returns the icode containing the ifx for operand */
4108 /*-----------------------------------------------------------------*/
4110 ifxForOp (operand * op, iCode * ic)
4112 /* if true symbol then needs to be assigned */
4113 if (IS_TRUE_SYMOP (op))
4116 /* if this has register type condition and
4117 the next instruction is ifx with the same operand
4118 and live to of the operand is upto the ifx only then */
4120 ic->next->op == IFX &&
4121 IC_COND (ic->next)->key == op->key &&
4122 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4129 genPointerGetSetOfs (iCode *ic)
4131 iCode *lic = ic->next;
4137 /* Make sure we have a next iCode */
4138 emitcode("","; checking lic");
4142 /* Make sure the result of the addition is an iCode */
4143 emitcode("","; checking IS_ITEMP");
4144 if (!IS_ITEMP (IC_RESULT (ic)))
4147 /* Make sure the next iCode is a pointer set or get */
4148 pset = POINTER_SET(lic);
4149 pget = POINTER_GET(lic);
4150 emitcode("","; pset=%d, pget=%d",pset,pget);
4154 emitcode("", "; checking pset operandsEqu");
4155 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4158 emitcode("", "; checking pget operandsEqu");
4159 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4162 emitcode("", "; checking IS_SYMOP");
4163 if (!IS_SYMOP (IC_LEFT (ic)))
4166 emitcode("", "; checking !IS_TRUE_SYMOP");
4167 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4170 sym = OP_SYMBOL (IC_LEFT (ic));
4172 emitcode("", "; checking remat");
4178 D(emitcode ("; genPointerGetOfs",""));
4179 aopOp (IC_LEFT(ic), ic, FALSE);
4180 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4181 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4183 aopOp (IC_RIGHT(ic), ic, FALSE);
4184 aopOp (IC_RESULT(lic), lic, FALSE);
4187 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4188 size = AOP_SIZE (IC_RESULT(lic));
4189 derefaop->size = size;
4194 emitcode ("lda", "%s,x",
4195 aopAdrStr (derefaop, offset, TRUE));
4196 hc08_useReg (hc08_reg_a);
4197 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
4198 hc08_freeReg (hc08_reg_a);
4202 hc08_freeReg (hc08_reg_hx);
4204 freeAsmop (NULL, derefaop, ic, TRUE);
4205 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4206 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4213 D(emitcode ("; genPointerSetOfs",""));
4214 aopOp (IC_LEFT(ic), ic, FALSE);
4215 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4216 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4218 aopOp (IC_RIGHT(ic), ic, FALSE);
4219 aopOp (IC_RIGHT(lic), lic, FALSE);
4222 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4223 size = AOP_SIZE (IC_RIGHT(lic));
4224 derefaop->size = size;
4229 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
4230 emitcode ("sta", "%s,x",
4231 aopAdrStr (derefaop, offset, TRUE));
4232 hc08_freeReg (hc08_reg_a);
4237 hc08_freeReg (hc08_reg_hx);
4239 freeAsmop (NULL, derefaop, ic, TRUE);
4240 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4241 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4250 /*-----------------------------------------------------------------*/
4251 /* hasInc - operand is incremented before any other use */
4252 /*-----------------------------------------------------------------*/
4254 hasInc (operand *op, iCode *ic,int osize)
4256 sym_link *type = operandType(op);
4257 sym_link *retype = getSpec (type);
4258 iCode *lic = ic->next;
4261 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4262 if (!IS_SYMOP(op)) return NULL;
4264 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4265 if (IS_AGGREGATE(type->next)) return NULL;
4266 if (osize != (isize = getSize(type->next))) return NULL;
4269 /* if operand of the form op = op + <sizeof *op> */
4270 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4271 isOperandEqual(IC_RESULT(lic),op) &&
4272 isOperandLiteral(IC_RIGHT(lic)) &&
4273 operandLitValue(IC_RIGHT(lic)) == isize) {
4276 /* if the operand used or deffed */
4277 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4280 /* if GOTO or IFX */
4281 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4287 /*-----------------------------------------------------------------*/
4288 /* genAndOp - for && operation */
4289 /*-----------------------------------------------------------------*/
4291 genAndOp (iCode * ic)
4293 operand *left, *right, *result;
4294 symbol *tlbl, *tlbl0;
4296 D(emitcode ("; genAndOp",""));
4298 /* note here that && operations that are in an
4299 if statement are taken away by backPatchLabels
4300 only those used in arthmetic operations remain */
4301 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4302 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4303 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4305 tlbl = newiTempLabel (NULL);
4306 tlbl0 = newiTempLabel (NULL);
4308 asmopToBool (AOP (left), FALSE);
4309 emitBranch ("beq", tlbl0);
4310 asmopToBool (AOP (right), FALSE);
4311 emitBranch ("beq", tlbl0);
4312 loadRegFromConst (hc08_reg_a,one);
4313 emitBranch ("bra", tlbl);
4315 loadRegFromConst (hc08_reg_a,zero);
4318 hc08_useReg (hc08_reg_a);
4319 hc08_freeReg (hc08_reg_a);
4321 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4323 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4324 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4325 freeAsmop (result, NULL, ic, TRUE);
4329 /*-----------------------------------------------------------------*/
4330 /* genOrOp - for || operation */
4331 /*-----------------------------------------------------------------*/
4333 genOrOp (iCode * ic)
4335 operand *left, *right, *result;
4336 symbol *tlbl, *tlbl0;
4338 D(emitcode ("; genOrOp",""));
4340 /* note here that || operations that are in an
4341 if statement are taken away by backPatchLabels
4342 only those used in arthmetic operations remain */
4343 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4344 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4345 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4347 tlbl = newiTempLabel (NULL);
4348 tlbl0 = newiTempLabel (NULL);
4350 asmopToBool (AOP (left), FALSE);
4351 emitBranch ("bne", tlbl0);
4352 asmopToBool (AOP (right), FALSE);
4353 emitBranch ("bne", tlbl0);
4354 loadRegFromConst (hc08_reg_a,zero);
4355 emitBranch ("bra", tlbl);
4357 loadRegFromConst (hc08_reg_a,one);
4360 hc08_useReg (hc08_reg_a);
4361 hc08_freeReg (hc08_reg_a);
4363 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4366 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4367 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4368 freeAsmop (result, NULL, ic, TRUE);
4371 /*-----------------------------------------------------------------*/
4372 /* isLiteralBit - test if lit == 2^n */
4373 /*-----------------------------------------------------------------*/
4375 isLiteralBit (unsigned long lit)
4377 unsigned long pw[32] =
4378 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4379 0x100L, 0x200L, 0x400L, 0x800L,
4380 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4381 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4382 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4383 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4384 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4387 for (idx = 0; idx < 32; idx++)
4394 /*-----------------------------------------------------------------*/
4395 /* continueIfTrue - */
4396 /*-----------------------------------------------------------------*/
4398 continueIfTrue (iCode * ic)
4401 emitBranch ("jmp", IC_TRUE (ic));
4405 /*-----------------------------------------------------------------*/
4407 /*-----------------------------------------------------------------*/
4409 jumpIfTrue (iCode * ic)
4412 emitBranch ("jmp", IC_FALSE (ic));
4416 /*-----------------------------------------------------------------*/
4417 /* jmpTrueOrFalse - */
4418 /*-----------------------------------------------------------------*/
4420 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4422 // ugly but optimized by peephole
4425 symbol *nlbl = newiTempLabel (NULL);
4426 emitBranch ("bra", nlbl);
4428 emitBranch ("jmp", IC_TRUE (ic));
4433 emitBranch ("jmp", IC_FALSE (ic));
4440 /*-----------------------------------------------------------------*/
4441 /* genAnd - code for and */
4442 /*-----------------------------------------------------------------*/
4444 genAnd (iCode * ic, iCode * ifx)
4446 operand *left, *right, *result;
4447 int size, offset = 0;
4448 unsigned long lit = 0L;
4449 unsigned long litinv;
4455 D(emitcode ("; genAnd",""));
4457 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4458 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4459 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4462 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4464 AOP_TYPE (left), AOP_TYPE (right));
4465 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4467 AOP_SIZE (left), AOP_SIZE (right));
4470 /* if left is a literal & right is not then exchange them */
4471 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4473 operand *tmp = right;
4478 /* if left is accumulator & right is not then exchange them */
4479 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4481 operand *tmp = right;
4486 size = AOP_SIZE (result);
4488 if (AOP_TYPE (right) == AOP_LIT)
4490 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4491 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4493 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4494 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4496 int bitpos = isLiteralBit(litinv)-1;
4497 emitcode ("bclr","#%d,%s",bitpos & 7,
4498 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4506 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4507 if ((AOP_TYPE (right) != AOP_LIT)
4508 || (((lit >> (offset*8)) & 0xff) != 0xff))
4509 accopWithAop ("and", AOP (right), offset);
4510 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4511 hc08_freeReg( hc08_reg_a);
4515 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4516 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4517 freeAsmop (result, NULL, ic, TRUE);
4520 /*-----------------------------------------------------------------*/
4521 /* genOr - code for or */
4522 /*-----------------------------------------------------------------*/
4524 genOr (iCode * ic, iCode * ifx)
4526 operand *left, *right, *result;
4527 int size, offset = 0;
4528 unsigned long lit = 0L;
4530 D(emitcode ("; genOr",""));
4532 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4533 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4534 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4537 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4539 AOP_TYPE (left), AOP_TYPE (right));
4540 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4542 AOP_SIZE (left), AOP_SIZE (right));
4545 /* if left is a literal & right is not then exchange them */
4546 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4548 operand *tmp = right;
4553 /* if left is accumulator & right is not then exchange them */
4554 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4556 operand *tmp = right;
4561 /* if right is bit then exchange them */
4562 if (AOP_TYPE (right) == AOP_CRY &&
4563 AOP_TYPE (left) != AOP_CRY)
4565 operand *tmp = right;
4569 if (AOP_TYPE (right) == AOP_LIT)
4570 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4572 size = AOP_SIZE (result);
4574 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4575 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
4576 (AOP_TYPE (left) == AOP_DIR))
4578 int bitpos = isLiteralBit(lit)-1;
4579 emitcode ("bset","#%d,%s",bitpos & 7,
4580 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4589 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4590 accopWithAop ("ora", AOP (right), offset);
4591 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4592 hc08_freeReg( hc08_reg_a);
4597 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4598 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4599 freeAsmop (result, NULL, ic, TRUE);
4602 /*-----------------------------------------------------------------*/
4603 /* genXor - code for xclusive or */
4604 /*-----------------------------------------------------------------*/
4606 genXor (iCode * ic, iCode * ifx)
4608 operand *left, *right, *result;
4609 int size, offset = 0;
4610 unsigned long lit = 0L;
4612 D(emitcode ("; genXor",""));
4614 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4615 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4616 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4619 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4621 AOP_TYPE (left), AOP_TYPE (right));
4622 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4624 AOP_SIZE (left), AOP_SIZE (right));
4627 /* if left is a literal & right is not ||
4628 if left needs acc & right does not */
4629 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4631 operand *tmp = right;
4636 /* if left is accumulator & right is not then exchange them */
4637 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4639 operand *tmp = right;
4644 /* if right is bit then exchange them */
4645 if (AOP_TYPE (right) == AOP_CRY &&
4646 AOP_TYPE (left) != AOP_CRY)
4648 operand *tmp = right;
4652 if (AOP_TYPE (right) == AOP_LIT)
4653 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4655 size = AOP_SIZE (result);
4659 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4660 accopWithAop ("eor", AOP (right), offset);
4661 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4662 hc08_freeReg( hc08_reg_a);
4667 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4668 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4669 freeAsmop (result, NULL, ic, TRUE);
4673 emitinline (iCode * ic, char *inlin)
4679 symbol *sym, *tempsym;
4688 while (isalnum(*inlin) || (*inlin == '_'))
4692 //printf("Found possible symbol '%s'\n",symname);
4693 tempsym = newSymbol (symname, ic->level);
4694 tempsym->block = ic->block;
4695 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
4704 aop = aopForSym (ic, sym, FALSE);
4705 l = aopAdrStr (aop, aop->size - 1, TRUE);
4709 if (!sym->allocreq && !sym->ismyparm)
4711 werror (E_ID_UNDEF, sym->name);
4713 " Add 'volatile' to the variable declaration so that it\n"
4714 " can be referenced within inline assembly");
4716 //printf("Replacing with '%s'\n",l);
4720 if ((2+bp-buffer)>sizeof(buffer))
4729 if ((2+bp-buffer)>sizeof(buffer))
4736 if ((2+bp-buffer)>sizeof(buffer))
4737 fprintf(stderr, "Inline assembly buffer overflow\n");
4739 //printf("%s\n",buffer);
4740 emitcode (buffer,"");
4744 /*-----------------------------------------------------------------*/
4745 /* genInline - write the inline code out */
4746 /*-----------------------------------------------------------------*/
4748 genInline (iCode * ic)
4750 char *buffer, *bp, *bp1;
4752 D(emitcode ("; genInline",""));
4754 _G.inLine += (!options.asmpeep);
4756 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4757 strcpy (buffer, IC_INLINE (ic));
4759 /* emit each line as a code */
4765 /* emitcode (bp1, ""); */
4766 emitinline (ic, bp1);
4785 /* emitcode (bp1, ""); */
4786 emitinline (ic, bp1);
4788 /* emitcode("",buffer); */
4789 _G.inLine -= (!options.asmpeep);
4792 /*-----------------------------------------------------------------*/
4793 /* genRRC - rotate right with carry */
4794 /*-----------------------------------------------------------------*/
4798 operand *left, *result;
4799 int size, offset = 0;
4800 bool needpula = FALSE;
4801 bool resultInA = FALSE;
4804 D(emitcode ("; genRRC",""));
4806 /* rotate right with carry */
4807 left = IC_LEFT (ic);
4808 result = IC_RESULT (ic);
4809 aopOp (left, ic, FALSE);
4810 aopOp (result, ic, FALSE);
4812 if ((AOP_TYPE (result) == AOP_REG)
4813 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4816 size = AOP_SIZE (result);
4820 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4824 rmwWithAop (shift, AOP (result), offset--);
4832 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4833 rmwWithReg (shift, hc08_reg_a);
4834 storeRegToAop (hc08_reg_a, AOP (result), offset--);
4835 hc08_freeReg (hc08_reg_a);
4840 if ((!hc08_reg_a->isFree) || resultInA)
4842 pushReg (hc08_reg_a, TRUE);
4846 /* now we need to put the carry into the
4847 highest order byte of the result */
4848 offset = AOP_SIZE (result) - 1;
4849 emitcode ("clra","");
4850 emitcode ("rora","");
4851 hc08_dirtyReg (hc08_reg_a, FALSE);
4854 emitcode ("ora", "1,s");
4855 emitcode ("ais", "#1");
4856 hc08_dirtyReg (hc08_reg_a, FALSE);
4860 accopWithAop ("ora", AOP (result), offset);
4861 storeRegToAop (hc08_reg_a, AOP (result), offset);
4863 pullOrFreeReg (hc08_reg_a, needpula);
4865 freeAsmop (left, NULL, ic, TRUE);
4866 freeAsmop (result, NULL, ic, TRUE);
4869 /*-----------------------------------------------------------------*/
4870 /* genRLC - generate code for rotate left with carry */
4871 /*-----------------------------------------------------------------*/
4875 operand *left, *result;
4876 int size, offset = 0;
4878 bool resultInA = FALSE;
4879 bool needpula = FALSE;
4881 D(emitcode ("; genRLC",""));
4883 /* rotate right with carry */
4884 left = IC_LEFT (ic);
4885 result = IC_RESULT (ic);
4886 aopOp (left, ic, FALSE);
4887 aopOp (result, ic, FALSE);
4889 if ((AOP_TYPE (result) == AOP_REG)
4890 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4893 size = AOP_SIZE (result);
4897 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4901 rmwWithAop (shift, AOP (result), offset--);
4909 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4910 rmwWithReg (shift, hc08_reg_a);
4911 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4912 hc08_freeReg (hc08_reg_a);
4917 if ((!hc08_reg_a->isFree) || resultInA)
4919 pushReg (hc08_reg_a, TRUE);
4923 /* now we need to put the carry into the
4924 lowest order byte of the result */
4926 emitcode ("clra","");
4927 emitcode ("rola","");
4928 hc08_dirtyReg (hc08_reg_a, FALSE);
4931 emitcode ("ora", "1,s");
4932 emitcode ("ais", "#1");
4933 hc08_dirtyReg (hc08_reg_a, FALSE);
4937 accopWithAop ("ora", AOP (result), offset);
4938 storeRegToAop (hc08_reg_a, AOP (result), offset);
4940 pullOrFreeReg (hc08_reg_a, needpula);
4942 freeAsmop (left, NULL, ic, TRUE);
4943 freeAsmop (result, NULL, ic, TRUE);
4946 /*-----------------------------------------------------------------*/
4947 /* genGetHbit - generates code get highest order bit */
4948 /*-----------------------------------------------------------------*/
4950 genGetHbit (iCode * ic)
4952 operand *left, *result;
4954 D(emitcode ("; genGetHbit",""));
4956 left = IC_LEFT (ic);
4957 result = IC_RESULT (ic);
4958 aopOp (left, ic, FALSE);
4959 aopOp (result, ic, FALSE);
4961 /* get the highest order byte into a */
4962 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
4963 emitcode ("rola", "");
4964 emitcode ("clra", "");
4965 emitcode ("rola", "");
4966 hc08_dirtyReg (hc08_reg_a, FALSE);
4967 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4969 freeAsmop (left, NULL, ic, TRUE);
4970 freeAsmop (result, NULL, ic, TRUE);
4974 /*-----------------------------------------------------------------*/
4975 /* AccRol - rotate left accumulator by known count */
4976 /*-----------------------------------------------------------------*/
4978 AccRol (int shCount)
4980 shCount &= 0x0007; // shCount : 0..7
4987 emitcode ("rola", ""); /* 1 cycle */
4990 emitcode ("rola", ""); /* 1 cycle */
4991 emitcode ("rola", ""); /* 1 cycle */
4994 emitcode ("nsa", "");
4995 emitcode ("rora", "");
4998 emitcode ("nsa", ""); /* 3 cycles */
5001 emitcode ("nsa", ""); /* 3 cycles */
5002 emitcode ("rola", ""); /* 1 cycle */
5005 emitcode ("nsa", ""); /* 3 cycles */
5006 emitcode ("rola", ""); /* 1 cycle */
5007 emitcode ("rola", ""); /* 1 cycle */
5010 emitcode ("nsa", ""); /* 3 cycles */
5011 emitcode ("rola", ""); /* 1 cycle */
5012 emitcode ("rola", ""); /* 1 cycle */
5013 emitcode ("rola", ""); /* 1 cycle */
5020 /*-----------------------------------------------------------------*/
5021 /* AccLsh - left shift accumulator by known count */
5022 /*-----------------------------------------------------------------*/
5024 AccLsh (int shCount)
5028 shCount &= 0x0007; // shCount : 0..7
5030 /* Shift counts of 4 and 5 are currently optimized for code size. */
5031 /* Falling through to the unrolled loop would be optimal for code speed. */
5032 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5036 accopWithMisc ("nsa", "");
5037 accopWithMisc ("and", "#0xf0");
5038 /* total: 5 cycles, 3 bytes */
5041 accopWithMisc ("nsa", "");
5042 accopWithMisc ("and", "#0xf0");
5043 accopWithMisc ("lsla", "");
5044 /* total: 6 cycles, 4 bytes */
5047 accopWithMisc ("rora", "");
5048 accopWithMisc ("rora", "");
5049 accopWithMisc ("rora", "");
5050 accopWithMisc ("and", "#0xc0");
5051 /* total: 5 cycles, 5 bytes */
5054 accopWithMisc ("rora", "");
5055 accopWithMisc ("clra", "");
5056 accopWithMisc ("rora", "");
5057 /* total: 3 cycles, 3 bytes */
5061 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5062 /* the fastest (shCount<6) and shortest (shCount<4). */
5063 for (i=0;i<shCount;i++)
5064 accopWithMisc ("lsla", "");
5068 /*-----------------------------------------------------------------*/
5069 /* AccSRsh - signed right shift accumulator by known count */
5070 /*-----------------------------------------------------------------*/
5072 AccSRsh (int shCount)
5076 shCount &= 0x0007; // shCount : 0..7
5080 accopWithMisc ("rola", "");
5081 accopWithMisc ("clra", "");
5082 accopWithMisc ("sbc", zero);
5083 /* total: 4 cycles, 4 bytes */
5087 for (i=0;i<shCount;i++)
5088 accopWithMisc ("asra", "");
5091 /*-----------------------------------------------------------------*/
5092 /* AccRsh - right shift accumulator by known count */
5093 /*-----------------------------------------------------------------*/
5095 AccRsh (int shCount, bool sign)
5105 shCount &= 0x0007; // shCount : 0..7
5107 /* Shift counts of 4 and 5 are currently optimized for code size. */
5108 /* Falling through to the unrolled loop would be optimal for code speed. */
5109 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5113 accopWithMisc ("nsa", "");
5114 accopWithMisc ("and", "#0x0f");
5115 /* total: 5 cycles, 3 bytes */
5118 accopWithMisc ("nsa", "");
5119 accopWithMisc ("and", "#0x0f");
5120 accopWithMisc ("lsra", "");
5121 /* total: 6 cycles, 4 bytes */
5124 accopWithMisc ("rola", "");
5125 accopWithMisc ("rola", "");
5126 accopWithMisc ("rola", "");
5127 accopWithMisc ("and", "#0x03");
5128 /* total: 5 cycles, 5 bytes */
5131 accopWithMisc ("rola", "");
5132 accopWithMisc ("clra", "");
5133 accopWithMisc ("rola", "");
5134 /* total: 3 cycles, 3 bytes */
5138 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5139 /* the fastest (shCount<6) and shortest (shCount<4). */
5140 for (i=0;i<shCount;i++)
5141 accopWithMisc ("lsra", "");
5145 /*-----------------------------------------------------------------*/
5146 /* XAccLsh - left shift register pair XA by known count */
5147 /*-----------------------------------------------------------------*/
5149 XAccLsh (int shCount)
5153 shCount &= 0x000f; // shCount : 0..15
5158 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5159 loadRegFromConst (hc08_reg_a, zero);
5163 /* if we can beat 2n cycles or bytes for some special case, do it here */
5167 /* bytes cycles reg x reg a carry
5168 ** abcd efgh ijkl mnop ?
5169 ** lsrx 1 1 0abc defg ijkl mnop h
5170 ** rora 1 1 0abc defg hijk lmno p
5171 ** tax 1 1 hijk lmno hijk lmno p
5172 ** clra 1 1 hijk lmno 0000 0000 p
5173 ** rora 1 1 hijk lmno p000 0000 0
5174 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5176 rmwWithReg ("lsr", hc08_reg_x);
5177 rmwWithReg ("ror", hc08_reg_a);
5178 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5179 loadRegFromConst (hc08_reg_a, zero);
5180 rmwWithReg ("ror", hc08_reg_a);
5187 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5188 /* the fastest and shortest. */
5189 for (i=0;i<shCount;i++)
5191 rmwWithReg ("lsl", hc08_reg_a);
5192 rmwWithReg ("rol", hc08_reg_x);
5196 /*-----------------------------------------------------------------*/
5197 /* XAccSRsh - signed right shift register pair XA by known count */
5198 /*-----------------------------------------------------------------*/
5200 XAccSRsh (int shCount)
5204 shCount &= 0x000f; // shCount : 0..7
5206 /* if we can beat 2n cycles or bytes for some special case, do it here */
5210 /* bytes cycles reg x reg a carry
5211 ** abcd efgh ijkl mnop ?
5212 ** lslx 1 1 bcde fgh0 ijkl mnop a
5213 ** clra 1 1 bcde fgh0 0000 0000 a
5214 ** rola 1 1 bcde fgh0 0000 000a 0
5215 ** nega 1 1 bcde fgh0 aaaa aaaa a
5216 ** tax 1 1 aaaa aaaa aaaa aaaa a
5217 ** total: 5 cycles, 5 bytes
5219 rmwWithReg ("lsl", hc08_reg_x);
5220 loadRegFromConst (hc08_reg_a, zero);
5221 rmwWithReg ("rol", hc08_reg_a);
5222 rmwWithReg ("neg", hc08_reg_a);
5223 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5233 /* bytes cycles reg x reg a carry
5234 ** abcd efgh ijkl mnop ?
5235 ** txa 1 1 abcd efgh abcd efgh ?
5236 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5237 ** lsla 1 1 abcd efgh ???? ???? a
5238 ** clrx 1 1 0000 0000 ???? ???? a
5239 ** rolx 1 1 0000 000a ???? ???? 0
5240 ** negx 1 1 aaaa aaaa ???? ???? a
5241 ** rora 1 1 aaaa aaaa LSBresult 0
5242 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5244 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5245 AccSRsh (shCount-8);
5246 rmwWithReg ("lsl", hc08_reg_a);
5247 loadRegFromConst (hc08_reg_x, zero);
5248 rmwWithReg ("rol", hc08_reg_x);
5249 rmwWithReg ("neg", hc08_reg_x);
5250 rmwWithReg ("ror", hc08_reg_a);
5257 /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5258 /* the fastest and shortest. */
5259 for (i=0;i<shCount;i++)
5261 rmwWithReg ("asr", hc08_reg_x);
5262 rmwWithReg ("ror", hc08_reg_a);
5266 /*-----------------------------------------------------------------*/
5267 /* XAccRsh - right shift register pair XA by known count */
5268 /*-----------------------------------------------------------------*/
5270 XAccRsh (int shCount, bool sign)
5280 shCount &= 0x000f; // shCount : 0..f
5282 /* if we can beat 2n cycles or bytes for some special case, do it here */
5286 /* bytes cycles reg x reg a carry
5287 ** abcd efgh ijkl mnop ?
5288 ** clra 1 1 abcd efgh 0000 0000 a
5289 ** lslx 1 1 bcde fgh0 0000 0000 a
5290 ** rola 1 1 bcde fgh0 0000 000a 0
5291 ** clrx 1 1 0000 0000 0000 000a 0
5292 ** total: 4 cycles, 4 bytes
5294 loadRegFromConst (hc08_reg_x, zero);
5295 rmwWithReg ("lsl", hc08_reg_x);
5296 rmwWithReg ("rol", hc08_reg_a);
5297 loadRegFromConst (hc08_reg_a, zero);
5301 /* bytes cycles reg x reg a carry
5302 ** abcd efgh ijkl mnop ?
5303 ** clra 1 1 abcd efgh 0000 0000 a
5304 ** lslx 1 1 bcde fgh0 0000 0000 a
5305 ** rola 1 1 bcde fgh0 0000 000a 0
5306 ** lslx 1 1 cdef gh00 0000 000a b
5307 ** rola 1 1 cdef gh00 0000 00ab 0
5308 ** clrx 1 1 0000 0000 0000 000a 0
5309 ** total: 6 cycles, 6 bytes
5311 loadRegFromConst (hc08_reg_x, zero);
5312 rmwWithReg ("lsl", hc08_reg_x);
5313 rmwWithReg ("rol", hc08_reg_a);
5314 rmwWithReg ("lsl", hc08_reg_x);
5315 rmwWithReg ("rol", hc08_reg_a);
5316 loadRegFromConst (hc08_reg_a, zero);
5325 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5326 AccRsh (shCount-8, FALSE);
5327 loadRegFromConst (hc08_reg_x, zero);
5331 /* bytes cycles reg x reg a carry
5332 ** abcd efgh ijkl mnop ?
5333 ** lsla 1 1 abcd efgh jklm nop0 i
5334 ** txa 1 1 abcd efgh abcd efgh i
5335 ** rola 1 1 abcd efgh bcde fghi a
5336 ** clrx 1 1 0000 0000 bcde fghi a
5337 ** rolx 1 1 0000 000a bcde fghi 0
5338 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5340 rmwWithReg ("lsl", hc08_reg_a);
5341 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5342 rmwWithReg ("rol", hc08_reg_a);
5343 loadRegFromConst (hc08_reg_x, zero);
5344 rmwWithReg ("rol", hc08_reg_x);
5347 /* bytes cycles reg x reg a carry
5348 ** abcd efgh ijkl mnop ?
5349 ** lsla 1 1 abcd efgh jklm nop0 i
5350 ** rolx 1 1 bcde fghi jklm nop0 a
5351 ** rola 1 1 bcde fghi klmn op0a j
5352 ** rolx 1 1 cdef ghij klmn op0a b
5353 ** rola 1 1 cdef ghij lmno p0ab k
5354 ** and #3 2 2 cdef ghij 0000 00ab k
5355 ** psha 1 2 cdef ghij 0000 00ab k
5356 ** txa 1 1 cdef ghij cdef ghij k
5357 ** pula 1 2 0000 00ab cdef ghij k
5358 ** total: 12 cycles, 10 bytes (beats 12 bytes)
5364 /* lslx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5365 /* the fastest and shortest. */
5366 for (i=0;i<shCount;i++)
5368 rmwWithReg ("lsl", hc08_reg_x);
5369 rmwWithReg ("rol", hc08_reg_a);
5376 /*-----------------------------------------------------------------*/
5377 /* shiftR1Left2Result - shift right one byte from left to result */
5378 /*-----------------------------------------------------------------*/
5380 shiftR1Left2Result (operand * left, int offl,
5381 operand * result, int offr,
5382 int shCount, int sign)
5384 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5385 /* shift right accumulator */
5386 AccRsh (shCount, sign);
5387 storeRegToAop (hc08_reg_a, AOP (result), offr);
5391 /*-----------------------------------------------------------------*/
5392 /* shiftL1Left2Result - shift left one byte from left to result */
5393 /*-----------------------------------------------------------------*/
5395 shiftL1Left2Result (operand * left, int offl,
5396 operand * result, int offr, int shCount)
5398 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5399 /* shift left accumulator */
5401 storeRegToAop (hc08_reg_a, AOP (result), offr);
5404 /*-----------------------------------------------------------------*/
5405 /* movLeft2Result - move byte from left to result */
5406 /*-----------------------------------------------------------------*/
5408 movLeft2Result (operand * left, int offl,
5409 operand * result, int offr, int sign)
5411 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5413 transferAopAop (AOP (left), offl, AOP (result), offr);
5418 /*-----------------------------------------------------------------*/
5419 /* shiftL2Left2Result - shift left two bytes from left to result */
5420 /*-----------------------------------------------------------------*/
5422 shiftL2Left2Result (operand * left, int offl,
5423 operand * result, int offr, int shCount)
5426 bool needpula = FALSE;
5427 bool needpulx = FALSE;
5429 needpula = pushRegIfUsed (hc08_reg_a);
5430 needpulx = pushRegIfUsed (hc08_reg_x);
5432 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5437 rmwWithReg ("lsr", hc08_reg_x);
5438 rmwWithReg ("ror", hc08_reg_a);
5439 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5440 rmwWithReg ("clr", hc08_reg_a);
5441 rmwWithReg ("ror", hc08_reg_a);
5444 for (i=0; i<shCount; i++)
5446 rmwWithReg ("lsl", hc08_reg_a);
5447 rmwWithReg ("rol", hc08_reg_x);
5450 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5452 pullOrFreeReg (hc08_reg_x, needpulx);
5453 pullOrFreeReg (hc08_reg_a, needpula);
5459 /*-----------------------------------------------------------------*/
5460 /* shiftR2Left2Result - shift right two bytes from left to result */
5461 /*-----------------------------------------------------------------*/
5463 shiftR2Left2Result (operand * left, int offl,
5464 operand * result, int offr,
5465 int shCount, int sign)
5468 bool needpula = FALSE;
5469 bool needpulx = FALSE;
5471 needpula = pushRegIfUsed (hc08_reg_a);
5472 needpulx = pushRegIfUsed (hc08_reg_x);
5474 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5475 for (i=0; i<shCount; i++)
5478 rmwWithReg ("asr", hc08_reg_x);
5480 rmwWithReg ("lsr", hc08_reg_x);
5481 rmwWithReg ("ror", hc08_reg_a);
5483 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5485 pullOrFreeReg (hc08_reg_x, needpulx);
5486 pullOrFreeReg (hc08_reg_a, needpula);
5491 /*-----------------------------------------------------------------*/
5492 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5493 /*-----------------------------------------------------------------*/
5495 shiftLLeftOrResult (operand * left, int offl,
5496 operand * result, int offr, int shCount)
5498 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5499 /* shift left accumulator */
5501 /* or with result */
5502 accopWithAop ("ora", AOP (result), offr);
5503 /* back to result */
5504 storeRegToAop (hc08_reg_a, AOP (result), offr);
5505 hc08_freeReg (hc08_reg_a);
5509 /*-----------------------------------------------------------------*/
5510 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5511 /*-----------------------------------------------------------------*/
5513 shiftRLeftOrResult (operand * left, int offl,
5514 operand * result, int offr, int shCount)
5516 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5517 /* shift left accumulator */
5518 AccRsh (shCount, FALSE);
5519 /* or with result */
5520 accopWithAop ("ora", AOP (result), offr);
5521 /* back to result */
5522 storeRegToAop (hc08_reg_a, AOP (result), offr);
5523 hc08_freeReg (hc08_reg_a);
5526 /*-----------------------------------------------------------------*/
5527 /* genlshOne - left shift a one byte quantity by known count */
5528 /*-----------------------------------------------------------------*/
5530 genlshOne (operand * result, operand * left, int shCount)
5532 D(emitcode ("; genlshOne",""));
5534 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5537 /*-----------------------------------------------------------------*/
5538 /* genlshTwo - left shift two bytes by known amount != 0 */
5539 /*-----------------------------------------------------------------*/
5541 genlshTwo (operand * result, operand * left, int shCount)
5545 D(emitcode ("; genlshTwo",""));
5548 size = getDataSize (result);
5550 /* if shCount >= 8 */
5557 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5559 storeRegToAop (hc08_reg_a, AOP (result), 1);
5561 storeConstToAop(zero, AOP (result), LSB);
5564 /* 1 <= shCount <= 7 */
5567 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5569 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
5573 /*-----------------------------------------------------------------*/
5574 /* shiftLLong - shift left one long from left to result */
5575 /* offl = LSB or MSB16 */
5576 /*-----------------------------------------------------------------*/
5578 shiftLLong (operand * left, operand * result, int offr)
5581 // int size = AOP_SIZE (result);
5583 bool needpula = FALSE;
5584 bool needpulx = FALSE;
5586 needpula = pushRegIfUsed (hc08_reg_a);
5587 needpulx = pushRegIfUsed (hc08_reg_x);
5589 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
5590 rmwWithReg ("lsl", hc08_reg_a);
5591 rmwWithReg ("rol", hc08_reg_x);
5592 storeRegToAop (hc08_reg_xa, AOP (result), offr);
5596 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5597 rmwWithReg ("rol", hc08_reg_a);
5598 rmwWithReg ("rol", hc08_reg_x);
5599 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
5601 else if (offr==MSB16)
5603 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
5604 rmwWithReg ("rol", hc08_reg_a);
5605 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
5608 pullOrFreeReg (hc08_reg_x, needpulx);
5609 pullOrFreeReg (hc08_reg_a, needpula);
5612 /*-----------------------------------------------------------------*/
5613 /* genlshFour - shift four byte by a known amount != 0 */
5614 /*-----------------------------------------------------------------*/
5616 genlshFour (operand * result, operand * left, int shCount)
5620 D(emitcode ("; genlshFour",""));
5622 size = AOP_SIZE (result);
5624 /* TODO: deal with the &result == &left case */
5626 /* if shifting more that 3 bytes */
5631 /* lowest order of left goes to the highest
5632 order of the destination */
5633 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5635 movLeft2Result (left, LSB, result, MSB32, 0);
5636 storeConstToAop (zero, AOP (result), LSB);
5637 storeConstToAop (zero, AOP (result), MSB16);
5638 storeConstToAop (zero, AOP (result), MSB24);
5642 /* more than two bytes */
5643 else if (shCount >= 16)
5645 /* lower order two bytes goes to higher order two bytes */
5647 /* if some more remaining */
5649 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5652 movLeft2Result (left, MSB16, result, MSB32, 0);
5653 movLeft2Result (left, LSB, result, MSB24, 0);
5655 storeConstToAop (zero, AOP (result), LSB);
5656 storeConstToAop (zero, AOP (result), MSB16);
5660 /* if more than 1 byte */
5661 else if (shCount >= 8)
5663 /* lower order three bytes goes to higher order three bytes */
5668 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5670 movLeft2Result (left, LSB, result, MSB16, 0);
5676 movLeft2Result (left, MSB24, result, MSB32, 0);
5677 movLeft2Result (left, MSB16, result, MSB24, 0);
5678 movLeft2Result (left, LSB, result, MSB16, 0);
5679 storeConstToAop (zero, AOP (result), LSB);
5681 else if (shCount == 1)
5682 shiftLLong (left, result, MSB16);
5685 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5686 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5687 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5688 storeConstToAop (zero, AOP (result), LSB);
5693 /* 1 <= shCount <= 7 */
5694 else if (shCount <= 2)
5696 shiftLLong (left, result, LSB);
5698 shiftLLong (result, result, LSB);
5700 /* 3 <= shCount <= 7, optimize */
5703 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5704 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5705 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5709 /*-----------------------------------------------------------------*/
5710 /* genLeftShiftLiteral - left shifting by known count */
5711 /*-----------------------------------------------------------------*/
5713 genLeftShiftLiteral (operand * left,
5718 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5721 D(emitcode ("; genLeftShiftLiteral",""));
5723 freeAsmop (right, NULL, ic, TRUE);
5725 aopOp (left, ic, FALSE);
5726 aopOp (result, ic, FALSE);
5728 // size = getSize (operandType (result));
5729 size = AOP_SIZE (result);
5732 emitcode ("; shift left ", "result %d, left %d", size,
5739 transferAopAop( AOP(left), size, AOP(result), size);
5741 else if (shCount >= (size * 8))
5744 storeConstToAop (zero, AOP (result), size);
5751 genlshOne (result, left, shCount);
5755 genlshTwo (result, left, shCount);
5759 genlshFour (result, left, shCount);
5762 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5763 "*** ack! mystery literal shift!\n");
5767 freeAsmop (left, NULL, ic, TRUE);
5768 freeAsmop (result, NULL, ic, TRUE);
5771 /*-----------------------------------------------------------------*/
5772 /* genLeftShift - generates code for left shifting */
5773 /*-----------------------------------------------------------------*/
5775 genLeftShift (iCode * ic)
5777 operand *left, *right, *result;
5779 symbol *tlbl, *tlbl1;
5784 D(emitcode ("; genLeftShift",""));
5786 right = IC_RIGHT (ic);
5787 left = IC_LEFT (ic);
5788 result = IC_RESULT (ic);
5790 aopOp (right, ic, FALSE);
5792 /* if the shift count is known then do it
5793 as efficiently as possible */
5794 if (AOP_TYPE (right) == AOP_LIT)
5796 genLeftShiftLiteral (left, right, result, ic);
5800 /* shift count is unknown then we have to form
5801 a loop get the loop count in A : Note: we take
5802 only the lower order byte since shifting
5803 more that 32 bits make no sense anyway, ( the
5804 largest size of an object can be only 32 bits ) */
5806 aopOp (left, ic, FALSE);
5807 aopOp (result, ic, FALSE);
5809 /* now move the left to the result if they are not the
5811 if (!sameRegs (AOP (left), AOP (result)))
5814 size = AOP_SIZE (result);
5818 transferAopAop (AOP (left), offset, AOP (result), offset);
5822 freeAsmop (left, NULL, ic, TRUE);
5824 tlbl = newiTempLabel (NULL);
5825 size = AOP_SIZE (result);
5827 tlbl1 = newiTempLabel (NULL);
5831 loadRegFromAop (reg, AOP (right), 0);
5832 freeAsmop (right, NULL, ic, TRUE);
5833 emitBranch ("beq", tlbl1);
5837 for (offset=0;offset<size;offset++)
5839 rmwWithAop (shift, AOP (result), offset);
5842 rmwWithReg ("dec", reg);
5843 emitBranch ("bne", tlbl);
5847 freeAsmop (result, NULL, ic, TRUE);
5850 /*-----------------------------------------------------------------*/
5851 /* genrshOne - right shift a one byte quantity by known count */
5852 /*-----------------------------------------------------------------*/
5854 genrshOne (operand * result, operand * left,
5855 int shCount, int sign)
5857 D(emitcode ("; genrshOne",""));
5859 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5860 AccRsh (shCount, sign);
5861 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5864 /*-----------------------------------------------------------------*/
5865 /* genrshTwo - right shift two bytes by known amount != 0 */
5866 /*-----------------------------------------------------------------*/
5868 genrshTwo (operand * result, operand * left,
5869 int shCount, int sign)
5871 D(emitcode ("; genrshTwo",""));
5873 /* if shCount >= 8 */
5876 if (shCount || sign)
5878 loadRegFromAop (hc08_reg_a, AOP (left), 1);
5879 AccRsh (shCount-8, sign);
5880 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5884 transferAopAop (AOP (left), 1, AOP (result), 0);
5885 storeConstToAop (zero, AOP (result), 1);
5889 /* 1 <= shCount <= 7 */
5892 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5893 XAccRsh (shCount, sign);
5894 storeRegToAop (hc08_reg_xa, AOP (result), 0);
5898 /*-----------------------------------------------------------------*/
5899 /* shiftRLong - shift right one long from left to result */
5900 /* offl = LSB or MSB16 */
5901 /*-----------------------------------------------------------------*/
5903 shiftRLong (operand * left, int offl,
5904 operand * result, int sign)
5907 // int size = AOP_SIZE (result);
5909 bool needpula = FALSE;
5910 bool needpulx = FALSE;
5912 needpula = pushRegIfUsed (hc08_reg_a);
5913 needpulx = pushRegIfUsed (hc08_reg_x);
5917 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5919 rmwWithReg ("asr", hc08_reg_x);
5921 rmwWithReg ("lsr", hc08_reg_x);
5922 rmwWithReg ("rol", hc08_reg_a);
5923 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
5925 else if (offl==MSB16)
5927 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
5929 rmwWithReg ("asr", hc08_reg_a);
5931 rmwWithReg ("lsr", hc08_reg_a);
5932 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
5935 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5936 rmwWithReg ("ror", hc08_reg_x);
5937 rmwWithReg ("ror", hc08_reg_a);
5938 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
5941 pullOrFreeReg (hc08_reg_x, needpulx);
5942 pullOrFreeReg (hc08_reg_a, needpula);
5945 /*-----------------------------------------------------------------*/
5946 /* genrshFour - shift four byte by a known amount != 0 */
5947 /*-----------------------------------------------------------------*/
5949 genrshFour (operand * result, operand * left,
5950 int shCount, int sign)
5952 /* TODO: handle cases where left == result */
5954 D(emitcode ("; genrshFour",""));
5956 /* if shifting more that 3 bytes */
5959 loadRegFromAop (hc08_reg_a, AOP (left), 3);
5960 AccRsh (shCount-24, sign);
5961 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5964 else if (shCount >= 16)
5966 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
5967 XAccRsh (shCount-16, sign);
5968 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
5971 else if (shCount >= 8)
5974 shiftRLong (left, MSB16, result, sign);
5975 else if (shCount == 8)
5977 transferAopAop (AOP (left), 1, AOP (result), 0);
5978 transferAopAop (AOP (left), 2, AOP (result), 1);
5979 loadRegFromAop (hc08_reg_a, AOP (left), 3);
5980 storeRegToAop (hc08_reg_a, AOP (result), 2);
5981 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
5983 else if (shCount == 9)
5985 shiftRLong (left, MSB16, result, sign);
5989 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
5990 XAccRsh (shCount-8, FALSE);
5991 storeRegToAop (hc08_reg_xa, AOP (result), 0);
5992 loadRegFromAop (hc08_reg_x, AOP (left), 3);
5993 loadRegFromConst (hc08_reg_a, zero);
5994 XAccRsh (shCount-8, sign);
5995 accopWithAop ("ora", AOP (result), 1);
5996 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6000 { /* 1 <= shCount <= 7 */
6003 shiftRLong (left, LSB, result, sign);
6007 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6008 XAccRsh (shCount, FALSE);
6009 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6010 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6012 accopWithAop ("ora", AOP (result), 1);
6013 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6014 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6015 XAccRsh (shCount, sign);
6016 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6021 /*-----------------------------------------------------------------*/
6022 /* genRightShiftLiteral - right shifting by known count */
6023 /*-----------------------------------------------------------------*/
6025 genRightShiftLiteral (operand * left,
6031 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6034 D(emitcode ("; genRightShiftLiteral",""));
6036 freeAsmop (right, NULL, ic, TRUE);
6038 aopOp (left, ic, FALSE);
6039 aopOp (result, ic, FALSE);
6042 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6046 size = getDataSize (left);
6047 /* test the LEFT size !!! */
6049 /* I suppose that the left size >= result size */
6052 size = getDataSize (result);
6054 transferAopAop (AOP (left), size, AOP(result), size);
6056 else if (shCount >= (size * 8))
6059 /* get sign in acc.7 */
6060 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6062 addSign (result, LSB, sign);
6069 genrshOne (result, left, shCount, sign);
6073 genrshTwo (result, left, shCount, sign);
6077 genrshFour (result, left, shCount, sign);
6083 freeAsmop (left, NULL, ic, TRUE);
6084 freeAsmop (result, NULL, ic, TRUE);
6088 /*-----------------------------------------------------------------*/
6089 /* genRightShift - generate code for right shifting */
6090 /*-----------------------------------------------------------------*/
6092 genRightShift (iCode * ic)
6094 operand *right, *left, *result;
6098 symbol *tlbl, *tlbl1;
6102 D(emitcode ("; genRightShift",""));
6104 /* if signed then we do it the hard way preserve the
6105 sign bit moving it inwards */
6106 retype = getSpec (operandType (IC_RESULT (ic)));
6107 sign = !SPEC_USIGN (retype);
6109 /* signed & unsigned types are treated the same : i.e. the
6110 signed is NOT propagated inwards : quoting from the
6111 ANSI - standard : "for E1 >> E2, is equivalent to division
6112 by 2**E2 if unsigned or if it has a non-negative value,
6113 otherwise the result is implementation defined ", MY definition
6114 is that the sign does not get propagated */
6116 right = IC_RIGHT (ic);
6117 left = IC_LEFT (ic);
6118 result = IC_RESULT (ic);
6120 aopOp (right, ic, FALSE);
6122 /* if the shift count is known then do it
6123 as efficiently as possible */
6124 if (AOP_TYPE (right) == AOP_LIT)
6126 genRightShiftLiteral (left, right, result, ic, sign);
6130 /* shift count is unknown then we have to form
6131 a loop get the loop count in X : Note: we take
6132 only the lower order byte since shifting
6133 more that 32 bits make no sense anyway, ( the
6134 largest size of an object can be only 32 bits ) */
6136 aopOp (left, ic, FALSE);
6137 aopOp (result, ic, FALSE);
6139 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6140 AOP (result) = forceStackedAop (AOP (result));
6142 size = AOP_SIZE (result);
6146 transferAopAop (AOP (left), offset, AOP (result), offset);
6150 tlbl = newiTempLabel (NULL);
6151 size = AOP_SIZE (result);
6153 tlbl1 = newiTempLabel (NULL);
6155 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6156 emitcode ("tstx", "");
6157 emitcode ("beq", "%05d$", tlbl1->key + 100);
6158 emitcode ("", "%05d$:", tlbl->key + 100);
6159 shift= sign ? "asr" : "lsr";
6160 for (offset=size-1;offset>=0;offset--)
6162 rmwWithAop (shift, AOP (result), offset);
6165 rmwWithReg ("dec", hc08_reg_x);
6166 emitcode ("bne","%05d$", tlbl->key + 100);
6167 emitcode ("", "%05d$:", tlbl1->key + 100);
6169 freeAsmop (result, NULL, ic, TRUE);
6170 freeAsmop (left, NULL, ic, TRUE);
6171 freeAsmop (right, NULL, ic, TRUE);
6174 /*-----------------------------------------------------------------*/
6175 /* genUnpackBits - generates code for unpacking bits */
6176 /*-----------------------------------------------------------------*/
6178 genUnpackBits (operand * result)
6180 int offset = 0; /* result byte offset */
6181 int rsize; /* result size */
6182 int rlen = 0; /* remaining bitfield length */
6183 sym_link *etype; /* bitfield type information */
6184 int blen; /* bitfield length */
6185 int bstr; /* bitfield starting bit within byte */
6187 D(emitcode ("; genUnpackBits",""));
6189 etype = getSpec (operandType (result));
6190 rsize = getSize (operandType (result));
6191 blen = SPEC_BLEN (etype);
6192 bstr = SPEC_BSTR (etype);
6194 /* If the bitfield length is less than a byte */
6197 emitcode ("lda", ",x");
6198 hc08_dirtyReg (hc08_reg_a, FALSE);
6199 AccRsh (bstr, FALSE);
6200 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6201 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6205 /* Bit field did not fit in a byte. Copy all
6206 but the partial byte at the end. */
6207 for (rlen=blen;rlen>=8;rlen-=8)
6209 emitcode ("lda", ",x");
6210 hc08_dirtyReg (hc08_reg_a, FALSE);
6211 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6213 emitcode ("aix", "#1");
6216 /* Handle the partial byte at the end */
6219 emitcode ("lda", ",x");
6220 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6221 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6229 storeConstToAop (zero, AOP (result), offset++);
6234 /*-----------------------------------------------------------------*/
6235 /* genDataPointerGet - generates code when ptr offset is known */
6236 /*-----------------------------------------------------------------*/
6238 genDataPointerGet (operand * left,
6242 int size, offset = 0;
6245 D(emitcode ("; genDataPointerGet",""));
6247 aopOp (result, ic, TRUE);
6248 size = AOP_SIZE (result);
6250 derefaop = aopDerefAop (AOP (left));
6251 freeAsmop (left, NULL, ic, TRUE);
6252 derefaop->size = size;
6256 transferAopAop(derefaop, offset, AOP (result), offset);
6260 freeAsmop (NULL, derefaop, ic, TRUE);
6261 freeAsmop (result, NULL, ic, TRUE);
6265 /*-----------------------------------------------------------------*/
6266 /* genNearPointerGet - emitcode for near pointer fetch */
6267 /*-----------------------------------------------------------------*/
6269 genNearPointerGet (operand * left,
6275 sym_link *retype = getSpec (operandType (result));
6277 D(emitcode ("; genNearPointerGet",""));
6279 aopOp (left, ic, FALSE);
6281 /* if left is rematerialisable and
6282 result is not bit variable type and
6283 the left is pointer to data space i.e
6284 lower 128 bytes of space */
6285 if ((AOP_TYPE (left) == AOP_IMMD)
6286 || (AOP_TYPE (left) == AOP_LIT)
6287 /* !IS_BITVAR (retype) */
6288 /* && DCL_TYPE (ltype) == POINTER */ )
6290 genDataPointerGet (left, result, ic);
6294 /* if the operand is already in hx
6295 then we do nothing else we move the value to hx */
6296 if (AOP_TYPE (left) != AOP_STR)
6298 /* if this is remateriazable */
6299 loadRegFromAop (hc08_reg_x, AOP (left), 0);
6300 loadRegFromConst (hc08_reg_h, zero);
6303 /* so hx now contains the address */
6304 aopOp (result, ic, FALSE);
6306 /* if bit then unpack */
6307 if (IS_BITVAR (retype))
6308 genUnpackBits (result);
6311 size = AOP_SIZE (result);
6316 accopWithMisc ("lda", ",x");
6319 rmwWithReg ("inc", hc08_reg_x);
6321 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6322 hc08_freeReg (hc08_reg_a);
6326 freeAsmop (left, NULL, ic, TRUE);
6327 freeAsmop (result, NULL, ic, TRUE);
6329 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6330 aopOp (IC_RESULT (pi), pi, FALSE);
6331 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6332 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6336 hc08_freeReg (hc08_reg_hx);
6340 /*-----------------------------------------------------------------*/
6341 /* genFarPointerGet - get value from far space */
6342 /*-----------------------------------------------------------------*/
6344 genFarPointerGet (operand * left,
6345 operand * result, iCode * ic, iCode * pi)
6348 sym_link *retype = getSpec (operandType (result));
6350 D(emitcode ("; genFarPointerGet",""));
6352 aopOp (left, ic, FALSE);
6354 /* if left is rematerialisable and
6355 result is not bit variable type and
6356 the left is pointer to data space i.e
6357 lower 128 bytes of space */
6358 if (AOP_TYPE (left) == AOP_IMMD &&
6360 /* && DCL_TYPE (ltype) == POINTER */ )
6362 genDataPointerGet (left, result, ic);
6366 /* if the operand is already in hx
6367 then we do nothing else we move the value to hx */
6368 if (AOP_TYPE (left) != AOP_STR)
6370 /* if this is remateriazable */
6371 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
6374 /* so hx now contains the address */
6375 aopOp (result, ic, FALSE);
6377 /* if bit then unpack */
6378 if (IS_BITVAR (retype))
6379 genUnpackBits (result);
6382 size = AOP_SIZE (result);
6387 accopWithMisc ("lda", ",x");
6390 emitcode ("aix", "#1");
6391 hc08_dirtyReg (hc08_reg_hx, FALSE);
6393 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6394 hc08_freeReg (hc08_reg_a);
6398 freeAsmop (left, NULL, ic, TRUE);
6399 freeAsmop (result, NULL, ic, TRUE);
6401 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6402 aopOp (IC_RESULT (pi), pi, FALSE);
6403 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6404 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6408 hc08_freeReg (hc08_reg_hx);
6414 /*-----------------------------------------------------------------*/
6415 /* genPointerGet - generate code for pointer get */
6416 /*-----------------------------------------------------------------*/
6418 genPointerGet (iCode * ic, iCode *pi)
6420 operand *left, *result;
6421 sym_link *type, *etype;
6424 D(emitcode ("; genPointerGet",""));
6426 left = IC_LEFT (ic);
6427 result = IC_RESULT (ic);
6429 /* depending on the type of pointer we need to
6430 move it to the correct pointer register */
6431 type = operandType (left);
6432 etype = getSpec (type);
6433 /* if left is of type of pointer then it is simple */
6434 if (IS_PTR (type) && !IS_FUNC (type->next))
6435 p_type = DCL_TYPE (type);
6438 /* we have to go by the storage class */
6439 p_type = PTR_TYPE (SPEC_OCLS (etype));
6442 /* special case when cast remat */
6443 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
6444 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
6445 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
6446 type = operandType (left);
6447 p_type = DCL_TYPE (type);
6449 /* now that we have the pointer type we assign
6450 the pointer values */
6457 genNearPointerGet (left, result, ic, pi);
6463 genFarPointerGet (left, result, ic, pi);
6470 /*-----------------------------------------------------------------*/
6471 /* genPackBits - generates code for packed bit storage */
6472 /*-----------------------------------------------------------------*/
6474 genPackBits (sym_link * etype,
6477 int offset = 0; /* source byte offset */
6478 int rlen = 0; /* remaining bitfield length */
6479 int blen; /* bitfield length */
6480 int bstr; /* bitfield starting bit within byte */
6481 int litval; /* source literal value (if AOP_LIT) */
6482 unsigned char mask; /* bitmask within current byte */
6484 D(emitcode ("; genPackBits",""));
6486 blen = SPEC_BLEN (etype);
6487 bstr = SPEC_BSTR (etype);
6489 /* If the bitfield length is less than a byte */
6492 mask = ((unsigned char) (0xFF << (blen + bstr)) |
6493 (unsigned char) (0xFF >> (8 - bstr)));
6495 if (AOP_TYPE (right) == AOP_LIT)
6497 /* Case with a bitfield length <8 and literal source
6499 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6501 litval &= (~mask) & 0xff;
6503 emitcode ("lda", ",x");
6504 if ((mask|litval)!=0xff)
6505 emitcode ("and","#0x%02x", mask);
6507 emitcode ("ora","#0x%02x", litval);
6508 hc08_dirtyReg (hc08_reg_a, FALSE);
6509 emitcode ("sta", ",x");
6511 hc08_freeReg (hc08_reg_a);
6515 /* Case with a bitfield length < 8 and arbitrary source
6517 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6518 /* shift and mask source value */
6520 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6521 hc08_dirtyReg (hc08_reg_a, FALSE);
6522 pushReg (hc08_reg_a, TRUE);
6524 emitcode ("lda", ",x");
6525 emitcode ("and", "#0x%02x", mask);
6526 emitcode ("ora", "1,s");
6527 emitcode ("sta", ",x");
6528 pullReg (hc08_reg_a);
6530 hc08_freeReg (hc08_reg_a);
6534 /* Bit length is greater than 7 bits. In this case, copy */
6535 /* all except the partial byte at the end */
6536 for (rlen=blen;rlen>=8;rlen-=8)
6538 if (AOP (right)->type == AOP_DIR)
6540 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
6544 loadRegFromAop (hc08_reg_a, AOP (right), offset);
6545 emitcode ("sta", "%d,x", offset);
6550 /* If there was a partial byte at the end */
6553 mask = (((unsigned char) -1 << rlen) & 0xff);
6555 if (AOP_TYPE (right) == AOP_LIT)
6557 /* Case with partial byte and literal source
6559 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6560 litval >>= (blen-rlen);
6561 litval &= (~mask) & 0xff;
6562 emitcode ("lda", "%d,x", offset);
6563 hc08_dirtyReg (hc08_reg_a, FALSE);
6564 if ((mask|litval)!=0xff)
6565 emitcode ("and","#0x%02x", mask);
6567 emitcode ("ora","#0x%02x", litval);
6568 emitcode ("sta", "%d,x", offset);
6569 hc08_dirtyReg (hc08_reg_a, FALSE);
6570 hc08_freeReg (hc08_reg_a);
6574 /* Case with partial byte and arbitrary source
6576 loadRegFromAop (hc08_reg_a, AOP (right), offset++);
6577 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6578 hc08_dirtyReg (hc08_reg_a, FALSE);
6579 pushReg (hc08_reg_a, TRUE);
6581 emitcode ("lda", ",x");
6582 emitcode ("and", "#0x%02x", mask);
6583 emitcode ("ora", "1,s");
6584 emitcode ("sta", ",x");
6587 hc08_freeReg (hc08_reg_a);
6590 /*-----------------------------------------------------------------*/
6591 /* genDataPointerSet - remat pointer to data space */
6592 /*-----------------------------------------------------------------*/
6594 genDataPointerSet (operand * right,
6598 int size, offset = 0;
6601 D(emitcode ("; genDataPointerSet",""));
6603 aopOp (right, ic, FALSE);
6604 size = AOP_SIZE (right);
6606 derefaop = aopDerefAop (AOP (result));
6607 freeAsmop (result, NULL, ic, TRUE);
6608 derefaop->size = size;
6612 transferAopAop (AOP (right), offset, derefaop, offset);
6616 freeAsmop (right, NULL, ic, TRUE);
6617 freeAsmop (NULL, derefaop, ic, TRUE);
6621 /*-----------------------------------------------------------------*/
6622 /* genNearPointerSet - emitcode for near pointer put */
6623 /*-----------------------------------------------------------------*/
6625 genNearPointerSet (operand * right,
6631 sym_link *retype = getSpec (operandType (right));
6632 sym_link *letype = getSpec (operandType (result));
6634 D(emitcode ("; genNearPointerSet",""));
6636 aopOp (result, ic, FALSE);
6638 /* if the result is rematerializable &
6639 in data space & not a bit variable */
6640 if (AOP_TYPE (result) == AOP_IMMD &&
6641 /* DCL_TYPE (ptype) == POINTER && */
6642 !IS_BITVAR (retype) &&
6643 !IS_BITVAR (letype))
6645 genDataPointerSet (right, result, ic);
6649 /* if the operand is already in hx
6650 then we do nothing else we move the value to hx */
6651 if (AOP_TYPE (result) != AOP_STR)
6653 loadRegFromAop (hc08_reg_x, AOP (result), 0);
6654 loadRegFromConst (hc08_reg_h, zero);
6656 /* so hx now contains the address */
6657 aopOp (right, ic, FALSE);
6659 /* if bit then unpack */
6660 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6661 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6664 size = AOP_SIZE (right);
6669 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6670 accopWithMisc ("sta", ",x");
6673 rmwWithReg ("inc", hc08_reg_x);
6675 hc08_freeReg (hc08_reg_a);
6679 freeAsmop (result, NULL, ic, TRUE);
6680 freeAsmop (right, NULL, ic, TRUE);
6682 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6683 aopOp (IC_RESULT (pi), pi, FALSE);
6684 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6685 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6689 hc08_freeReg (hc08_reg_hx);
6694 /*-----------------------------------------------------------------*/
6695 /* genFarPointerSet - set value from far space */
6696 /*-----------------------------------------------------------------*/
6698 genFarPointerSet (operand * right,
6699 operand * result, iCode * ic, iCode * pi)
6702 sym_link *retype = getSpec (operandType (right));
6703 sym_link *letype = getSpec (operandType (result));
6705 D(emitcode ("; genFarPointerSet",""));
6707 aopOp (result, ic, FALSE);
6709 /* if the result is rematerializable &
6710 in data space & not a bit variable */
6711 if (AOP_TYPE (result) == AOP_IMMD &&
6712 /* DCL_TYPE (ptype) == POINTER && */
6713 !IS_BITVAR (retype) &&
6714 !IS_BITVAR (letype))
6716 genDataPointerSet (right, result, ic);
6720 /* if the operand is already in hx
6721 then we do nothing else we move the value to hx */
6722 if (AOP_TYPE (result) != AOP_STR)
6724 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
6726 /* so hx now contains the address */
6727 aopOp (right, ic, FALSE);
6729 /* if bit then unpack */
6730 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6731 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6734 size = AOP_SIZE (right);
6739 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6740 accopWithMisc ("sta", ",x");
6743 emitcode ("aix", "#1");
6745 hc08_freeReg (hc08_reg_a);
6749 freeAsmop (result, NULL, ic, TRUE);
6750 freeAsmop (right, NULL, ic, TRUE);
6752 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6753 aopOp (IC_RESULT (pi), pi, FALSE);
6754 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6755 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6759 hc08_freeReg (hc08_reg_hx);
6765 /*-----------------------------------------------------------------*/
6766 /* genPointerSet - stores the value into a pointer location */
6767 /*-----------------------------------------------------------------*/
6769 genPointerSet (iCode * ic, iCode *pi)
6771 operand *right, *result;
6772 sym_link *type, *etype;
6775 D(emitcode ("; genPointerSet",""));
6777 right = IC_RIGHT (ic);
6778 result = IC_RESULT (ic);
6780 /* depending on the type of pointer we need to
6781 move it to the correct pointer register */
6782 type = operandType (result);
6783 etype = getSpec (type);
6784 /* if left is of type of pointer then it is simple */
6785 if (IS_PTR (type) && !IS_FUNC (type->next))
6787 p_type = DCL_TYPE (type);
6791 /* we have to go by the storage class */
6792 p_type = PTR_TYPE (SPEC_OCLS (etype));
6795 /* special case when cast remat */
6796 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
6797 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
6798 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
6799 type = operandType (result);
6800 p_type = DCL_TYPE (type);
6802 /* now that we have the pointer type we assign
6803 the pointer values */
6810 genNearPointerSet (right, result, ic, pi);
6816 genFarPointerSet (right, result, ic, pi);
6820 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6821 "genPointerSet: illegal pointer type");
6826 /*-----------------------------------------------------------------*/
6827 /* genIfx - generate code for Ifx statement */
6828 /*-----------------------------------------------------------------*/
6830 genIfx (iCode * ic, iCode * popIc)
6832 operand *cond = IC_COND (ic);
6835 D(emitcode ("; genIfx",""));
6837 aopOp (cond, ic, FALSE);
6839 /* get the value into acc */
6840 if (AOP_TYPE (cond) != AOP_CRY)
6841 asmopToBool (AOP (cond), FALSE);
6844 /* the result is now in the accumulator */
6845 freeAsmop (cond, NULL, ic, TRUE);
6847 /* if there was something to be popped then do it */
6851 /* if the condition is a bit variable */
6852 if (isbit && IS_ITEMP (cond) &&
6854 genIfxJump (ic, SPIL_LOC (cond)->rname);
6855 else if (isbit && !IS_ITEMP (cond))
6856 genIfxJump (ic, OP_SYMBOL (cond)->rname);
6858 genIfxJump (ic, "a");
6863 /*-----------------------------------------------------------------*/
6864 /* genAddrOf - generates code for address of */
6865 /*-----------------------------------------------------------------*/
6867 genAddrOf (iCode * ic)
6869 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
6872 D(emitcode ("; genAddrOf",""));
6874 aopOp (IC_RESULT (ic), ic, FALSE);
6876 /* if the operand is on the stack then we
6877 need to get the stack offset of this
6881 /* if it has an offset then we need to compute
6883 hc08_useReg (hc08_reg_hx);
6884 emitcode ("tsx", "");
6885 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
6886 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
6887 hc08_freeReg (hc08_reg_hx);
6892 /* object not on stack then we need the name */
6893 size = AOP_SIZE (IC_RESULT (ic));
6898 char s[SDCC_NAME_MAX+10];
6901 sprintf (s, "#%s", sym->rname);
6904 sprintf (s, "#>%s", sym->rname);
6907 sprintf (s, "#(%s >> %d)",
6911 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
6915 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
6919 /*-----------------------------------------------------------------*/
6920 /* genAssign - generate code for assignment */
6921 /*-----------------------------------------------------------------*/
6923 genAssign (iCode * ic)
6925 operand *result, *right;
6927 // unsigned long lit = 0L;
6929 D(emitcode("; genAssign",""));
6931 result = IC_RESULT (ic);
6932 right = IC_RIGHT (ic);
6934 /* if they are the same */
6935 if (operandsEqu (result, right)) {
6939 aopOp (right, ic, FALSE);
6940 aopOp (result, ic, TRUE);
6942 /* if they are the same registers */
6943 if (sameRegs (AOP (right), AOP (result)))
6946 if ((AOP_TYPE (right) == AOP_LIT)
6947 && (IS_AOP_HX(AOP(result))))
6949 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
6954 size = AOP_SIZE (result);
6959 transferAopAop (AOP (right), offset, AOP (result), offset);
6964 freeAsmop (right, NULL, ic, TRUE);
6965 freeAsmop (result, NULL, ic, TRUE);
6968 /*-----------------------------------------------------------------*/
6969 /* genJumpTab - genrates code for jump table */
6970 /*-----------------------------------------------------------------*/
6972 genJumpTab (iCode * ic)
6977 D(emitcode ("; genJumpTab",""));
6979 aopOp (IC_JTCOND (ic), ic, FALSE);
6980 /* get the condition into accumulator */
6981 loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
6982 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
6983 /* multiply by three */
6984 pushReg (hc08_reg_a, FALSE);
6985 emitcode ("lsla", "");
6986 emitcode ("add","1,s");
6987 transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
6988 loadRegFromConst (hc08_reg_h, zero);
6990 jtab = newiTempLabel (NULL);
6991 emitcode ("jmp", "%05d$,x", jtab->key + 100);
6992 emitcode ("", "%05d$:", jtab->key + 100);
6993 /* now generate the jump labels */
6994 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
6995 jtab = setNextItem (IC_JTLABELS (ic)))
6996 emitcode ("jmp", "%05d$", jtab->key + 100);
6998 hc08_dirtyReg (hc08_reg_a, TRUE);
6999 hc08_dirtyReg (hc08_reg_hx, TRUE);
7002 /*-----------------------------------------------------------------*/
7003 /* genCast - gen code for casting */
7004 /*-----------------------------------------------------------------*/
7006 genCast (iCode * ic)
7008 operand *result = IC_RESULT (ic);
7009 sym_link *ctype = operandType (IC_LEFT (ic));
7010 sym_link *rtype = operandType (IC_RIGHT (ic));
7011 operand *right = IC_RIGHT (ic);
7014 D(emitcode("; genCast",""));
7016 /* if they are equivalent then do nothing */
7017 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7020 aopOp (right, ic, FALSE);
7021 aopOp (result, ic, FALSE);
7024 /* if they are the same size : or less */
7025 if (AOP_SIZE (result) <= AOP_SIZE (right))
7028 /* if they are in the same place */
7030 if (sameRegs (AOP (right), AOP (result)))
7034 /* if they in different places then copy */
7035 size = AOP_SIZE (result);
7039 transferAopAop(AOP (right), offset, AOP (result), offset);
7046 /* if the result is of type pointer */
7051 sym_link *type = operandType (right);
7052 sym_link *etype = getSpec (type);
7054 /* pointer to generic pointer */
7055 if (IS_GENPTR (ctype))
7058 p_type = DCL_TYPE (type);
7061 if (SPEC_SCLS(etype)==S_REGISTER) {
7062 // let's assume it is a generic pointer
7065 /* we have to go by the storage class */
7066 p_type = PTR_TYPE (SPEC_OCLS (etype));
7070 /* the first two bytes are known */
7071 size = GPTRSIZE - 1;
7075 transferAopAop(AOP (right), offset, AOP (result), offset);
7078 /* the last byte depending on type */
7081 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7086 // pointerTypeToGPByte will have bitched.
7090 sprintf(gpValStr, "#0x%d", gpVal);
7091 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7097 /* just copy the pointers */
7098 size = AOP_SIZE (result);
7102 transferAopAop(AOP (right), offset, AOP (result), offset);
7108 /* so we now know that the size of destination is greater
7109 than the size of the source */
7110 /* we move to result for the size of source */
7111 size = AOP_SIZE (right);
7115 transferAopAop(AOP (right), offset, AOP (result), offset);
7119 /* now depending on the sign of the source && destination */
7120 size = AOP_SIZE (result) - AOP_SIZE (right);
7121 /* if unsigned or not an integral type */
7122 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7125 storeConstToAop (zero, AOP (result), offset++);
7129 /* we need to extend the sign :{ */
7130 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7131 accopWithMisc ("rola", "");
7132 accopWithMisc ("clra", "");
7133 accopWithMisc ("sbc", zero);
7135 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7138 /* we are done hurray !!!! */
7141 freeAsmop (right, NULL, ic, TRUE);
7142 freeAsmop (result, NULL, ic, TRUE);
7146 /*-----------------------------------------------------------------*/
7147 /* genDjnz - generate decrement & jump if not zero instrucion */
7148 /*-----------------------------------------------------------------*/
7150 genDjnz (iCode * ic, iCode * ifx)
7156 D(emitcode ("; genDjnz",""));
7158 /* if the if condition has a false label
7159 then we cannot save */
7163 /* if the minus is not of the form
7165 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7166 !IS_OP_LITERAL (IC_RIGHT (ic)))
7169 if (operandLitValue (IC_RIGHT (ic)) != 1)
7172 /* if the size of this greater than one then no
7174 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7176 aopOp (IC_RESULT (ic), ic, FALSE);
7177 if (AOP_SIZE (IC_RESULT (ic))>1)
7179 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7183 /* otherwise we can save BIG */
7184 lbl = newiTempLabel (NULL);
7185 lbl1 = newiTempLabel (NULL);
7188 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7191 emitBranch ("bra", lbl1);
7193 emitBranch ("jmp", IC_TRUE (ifx));
7196 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7201 /*-----------------------------------------------------------------*/
7202 /* genReceive - generate code for a receive iCode */
7203 /*-----------------------------------------------------------------*/
7205 genReceive (iCode * ic)
7209 D(emitcode ("; genReceive",""));
7211 aopOp (IC_RESULT (ic), ic, FALSE);
7212 size = AOP_SIZE (IC_RESULT (ic));
7217 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7218 AOP (IC_RESULT (ic)), offset);
7219 if (hc08_aop_pass[offset]->type == AOP_REG)
7220 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7225 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7228 /*-----------------------------------------------------------------*/
7229 /* genDummyRead - generate code for dummy read of volatiles */
7230 /*-----------------------------------------------------------------*/
7232 genDummyRead (iCode * ic)
7237 D(emitcode("; genDummyRead",""));
7239 right = IC_RIGHT (ic);
7241 aopOp (right, ic, FALSE);
7243 /* bit variables done */
7245 size = AOP_SIZE (right);
7250 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7251 hc08_freeReg (hc08_reg_a);
7255 freeAsmop (right, NULL, ic, TRUE);
7258 /*-----------------------------------------------------------------*/
7259 /* genCritical - generate code for start of a critical sequence */
7260 /*-----------------------------------------------------------------*/
7262 genCritical (iCode *ic)
7264 D(emitcode("; genCritical",""));
7267 aopOp (IC_RESULT (ic), ic, TRUE);
7269 emitcode ("tpa", "");
7270 hc08_dirtyReg (hc08_reg_a, FALSE);
7271 emitcode ("sei", "");
7274 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7276 pushReg (hc08_reg_a, FALSE);
7278 hc08_freeReg (hc08_reg_a);
7280 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7283 /*-----------------------------------------------------------------*/
7284 /* genEndCritical - generate code for end of a critical sequence */
7285 /*-----------------------------------------------------------------*/
7287 genEndCritical (iCode *ic)
7289 D(emitcode("; genEndCritical",""));
7293 aopOp (IC_RIGHT (ic), ic, FALSE);
7294 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
7295 emitcode ("tap", "");
7296 hc08_freeReg (hc08_reg_a);
7297 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
7301 pullReg (hc08_reg_a);
7302 emitcode ("tap", "");
7307 /*-----------------------------------------------------------------*/
7308 /* genhc08Code - generate code for HC08 based controllers */
7309 /*-----------------------------------------------------------------*/
7311 genhc08Code (iCode * lic)
7316 lineHead = lineCurr = NULL;
7318 /* print the allocation information */
7319 if (allocInfo && currFunc)
7320 printAllocInfo (currFunc, codeOutFile);
7321 /* if debug information required */
7322 if (options.debug && currFunc)
7324 debugFile->writeFunction(currFunc);
7326 if (IS_STATIC (currFunc->etype))
7327 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7329 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7332 /* stack pointer name */
7333 if (options.useXstack)
7338 hc08_aop_pass[0] = newAsmop (AOP_REG);
7339 hc08_aop_pass[0]->size=1;
7340 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7341 hc08_aop_pass[1] = newAsmop (AOP_REG);
7342 hc08_aop_pass[1]->size=1;
7343 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
7344 hc08_aop_pass[2] = newAsmop (AOP_DIR);
7345 hc08_aop_pass[2]->size=1;
7346 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
7347 hc08_aop_pass[3] = newAsmop (AOP_DIR);
7348 hc08_aop_pass[3]->size=1;
7349 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
7351 for (ic = lic; ic; ic = ic->next)
7354 if (ic->lineno && cln != ic->lineno)
7359 emitcode ("", "C$%s$%d$%d$%d ==.",
7360 FileBaseName (ic->filename), ic->lineno,
7361 ic->level, ic->block);
7364 if (!options.noCcodeInAsm) {
7365 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
7366 printCLine(ic->filename, ic->lineno));
7370 if (options.iCodeInAsm) {
7374 for (i=0; i<6; i++) {
7375 sprintf (®sInUse[i],
7376 "%c", ic->riu & (1<<i) ? i+'0' : '-');
7379 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
7381 /* if the result is marked as
7382 spilt and rematerializable or code for
7383 this has already been generated then
7385 if (resultRemat (ic) || ic->generated)
7393 for (i=A_IDX;i<=XA_IDX;i++)
7395 reg = hc08_regWithIdx(i);
7397 emitcode("","; %s = %s offset %d", reg->name,
7398 aopName(reg->aop), reg->aopofs);
7401 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
7403 sym = OP_SYMBOL (IC_LEFT (ic));
7404 if (sym->accuse == ACCUSE_HX)
7406 hc08_reg_h->isFree = FALSE;
7407 hc08_reg_x->isFree = FALSE;
7409 else if (sym->accuse == ACCUSE_XA)
7411 hc08_reg_a->isFree = FALSE;
7413 hc08_reg_x->isFree = FALSE;
7416 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
7418 sym = OP_SYMBOL (IC_RIGHT (ic));
7419 if (sym->accuse == ACCUSE_HX)
7421 hc08_reg_h->isFree = FALSE;
7422 hc08_reg_x->isFree = FALSE;
7424 else if (sym->accuse == ACCUSE_XA)
7426 hc08_reg_a->isFree = FALSE;
7428 hc08_reg_x->isFree = FALSE;
7433 /* depending on the operation */
7453 /* IPOP happens only when trying to restore a
7454 spilt live range, if there is an ifx statement
7455 following this pop then the if statement might
7456 be using some of the registers being popped which
7457 would destory the contents of the register so
7458 we need to check for this condition and handle it */
7460 ic->next->op == IFX &&
7461 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7462 genIfx (ic->next, ic);
7480 genEndFunction (ic);
7496 if (!genPointerGetSetOfs (ic))
7501 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7518 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7522 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7529 /* note these two are xlated by algebraic equivalence
7530 during parsing SDCC.y */
7531 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7532 "got '>=' or '<=' shouldn't have come here");
7536 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7548 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7552 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7556 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7583 case GET_VALUE_AT_ADDRESS:
7584 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
7588 if (POINTER_SET (ic))
7589 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
7615 addSet (&_G.sendSet, ic);
7618 case DUMMY_READ_VOLATILE:
7627 genEndCritical (ic);
7634 if (!hc08_reg_a->isFree)
7635 emitcode("","; forgot to free a");
7636 if (!hc08_reg_x->isFree)
7637 emitcode("","; forgot to free x");
7638 if (!hc08_reg_h->isFree)
7639 emitcode("","; forgot to free h");
7640 if (!hc08_reg_hx->isFree)
7641 emitcode("","; forgot to free hx");
7642 if (!hc08_reg_xa->isFree)
7643 emitcode("","; forgot to free xa");
7647 /* now we are ready to call the
7648 peep hole optimizer */
7649 if (!options.nopeep)
7650 peepHole (&lineHead);
7652 /* now do the actual printing */
7653 printLine (lineHead, codeOutFile);