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;
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;
1380 if (ic->op == ADDRESS_OF)
1383 sprintf (buffer, "(%s %c 0x%04x)",
1384 OP_SYMBOL (IC_LEFT (ic))->rname,
1385 val >= 0 ? '+' : '-',
1386 abs (val) & 0xffff);
1388 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1390 aop = newAsmop (AOP_IMMD);
1391 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1392 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1393 /* set immd2 field if required */
1394 if (aop->aopu.aop_immd.from_cast_remat)
1396 sprintf(buffer,"#0x%02x",ptr_type);
1397 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1398 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1401 else if (ic->op == '=')
1403 val += (int) operandLitValue (IC_RIGHT (ic));
1405 sprintf (buffer, "0x%04x", val);
1406 aop = newAsmop (AOP_LIT);
1407 aop->aopu.aop_lit = constVal (buffer);
1410 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1411 "unexpected rematerialization");
1418 /*-----------------------------------------------------------------*/
1419 /* regsInCommon - two operands have some registers in common */
1420 /*-----------------------------------------------------------------*/
1422 regsInCommon (operand * op1, operand * op2)
1424 symbol *sym1, *sym2;
1427 /* if they have registers in common */
1428 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1431 sym1 = OP_SYMBOL (op1);
1432 sym2 = OP_SYMBOL (op2);
1434 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1437 for (i = 0; i < sym1->nRegs; i++)
1443 for (j = 0; j < sym2->nRegs; j++)
1448 if (sym2->regs[j] == sym1->regs[i])
1456 /*-----------------------------------------------------------------*/
1457 /* operandsEqu - equivalent */
1458 /*-----------------------------------------------------------------*/
1460 operandsEqu (operand * op1, operand * op2)
1462 symbol *sym1, *sym2;
1464 /* if they not symbols */
1465 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1468 sym1 = OP_SYMBOL (op1);
1469 sym2 = OP_SYMBOL (op2);
1471 /* if both are itemps & one is spilt
1472 and the other is not then false */
1473 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1474 sym1->isspilt != sym2->isspilt)
1477 /* if they are the same */
1481 if (strcmp (sym1->rname, sym2->rname) == 0)
1485 /* if left is a tmp & right is not */
1486 if (IS_ITEMP (op1) &&
1489 (sym1->usl.spillLoc == sym2))
1492 if (IS_ITEMP (op2) &&
1496 (sym2->usl.spillLoc == sym1))
1502 /*-----------------------------------------------------------------*/
1503 /* sameRegs - two asmops have the same registers */
1504 /*-----------------------------------------------------------------*/
1506 sameRegs (asmop * aop1, asmop * aop2)
1513 // if (aop1->size != aop2->size)
1516 if (aop1->type == aop2->type)
1521 for (i = 0; i < aop1->size; i++)
1522 if (aop1->aopu.aop_reg[i] !=
1523 aop2->aopu.aop_reg[i])
1527 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1530 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1537 /*-----------------------------------------------------------------*/
1538 /* aopOp - allocates an asmop for an operand : */
1539 /*-----------------------------------------------------------------*/
1541 aopOp (operand * op, iCode * ic, bool result)
1550 // Is this a pointer set result?
1552 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1556 // printf("checking literal\n");
1557 /* if this a literal */
1558 if (IS_OP_LITERAL (op))
1560 op->aop = aop = newAsmop (AOP_LIT);
1561 aop->aopu.aop_lit = op->operand.valOperand;
1562 aop->size = getSize (operandType (op));
1564 aop->isaddr = op->isaddr;
1568 // printf("checking pre-existing\n");
1569 /* if already has a asmop then continue */
1573 op->aop->isaddr = op->isaddr;
1577 // printf("checking underlying sym\n");
1578 /* if the underlying symbol has a aop */
1579 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1581 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1582 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1583 //op->aop = aop = OP_SYMBOL (op)->aop;
1584 aop->size = getSize( operandType (op));
1585 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1586 //printf (" with size = %d\n", aop->size);
1589 aop->isaddr = op->isaddr;
1590 /* if (aop->isaddr & IS_ITEMP (op))
1592 aop->psize=aop->size;
1593 aop->size = getSize( operandType (op)->next);
1598 // printf("checking true sym\n");
1599 /* if this is a true symbol */
1600 if (IS_TRUE_SYMOP (op))
1602 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1604 aop->isaddr = op->isaddr;
1605 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1606 //printf (" with size = %d\n", aop->size);
1610 /* this is a temporary : this has
1616 e) can be a return use only */
1618 sym = OP_SYMBOL (op);
1620 // printf("checking conditional\n");
1621 /* if the type is a conditional */
1622 if (sym->regType == REG_CND)
1624 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1627 aop->isaddr = op->isaddr;
1631 // printf("checking spilt\n");
1632 /* if it is spilt then two situations
1634 b) has a spill location */
1635 if (sym->isspilt || sym->nRegs == 0)
1638 // printf("checking remat\n");
1639 /* rematerialize it NOW */
1642 sym->aop = op->aop = aop =
1644 aop->size = getSize (sym->type);
1646 aop->isaddr = op->isaddr;
1647 /* if (aop->isaddr & IS_ITEMP (op))
1649 aop->psize=aop->size;
1650 aop->size = getSize( operandType (op)->next);
1655 // printf("checking accuse\n");
1658 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1659 aop->size = getSize (sym->type);
1660 switch (sym->accuse)
1663 aop->aopu.aop_reg[0] = hc08_reg_a;
1664 aop->aopu.aop_reg[1] = hc08_reg_x;
1667 aop->aopu.aop_reg[0] = hc08_reg_x;
1668 aop->aopu.aop_reg[1] = hc08_reg_h;
1672 aop->isaddr = op->isaddr;
1676 // printf("checking ruonly\n");
1682 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1683 aop->size = getSize (sym->type);
1684 for (i = 0; i < fReturnSizeHC08; i++)
1685 aop->aopu.aop_str[i] = fReturn2[i];
1687 aop->isaddr = op->isaddr;
1691 /* else spill location */
1692 // printf("checking spill loc\n");
1693 // if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1694 if (sym->usl.spillLoc && sym->usl.spillLoc->aop
1695 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1697 /* force a new aop if sizes differ */
1698 sym->usl.spillLoc->aop = NULL;
1699 //printf ("forcing new aop\n");
1701 sym->aop = op->aop = aop =
1702 aopForSym (ic, sym->usl.spillLoc, result);
1703 aop->size = getSize (sym->type);
1705 aop->isaddr = op->isaddr;
1706 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1707 //printf (" with size = %d\n", aop->size);
1708 /* if (aop->isaddr & IS_ITEMP (op))
1710 aop->psize=aop->size;
1711 aop->size = getSize( operandType (op)->next);
1716 // printf("assuming register\n");
1717 /* must be in a register */
1718 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1719 aop->size = sym->nRegs;
1720 for (i = 0; i < sym->nRegs; i++)
1721 aop->aopu.aop_reg[i] = sym->regs[i];
1723 aop->isaddr = op->isaddr;
1727 /*-----------------------------------------------------------------*/
1728 /* freeAsmop - free up the asmop given to an operand */
1729 /*----------------------------------------------------------------*/
1731 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1753 emitcode ("","; freeAsmop restoring stacked %s", aopName(aop));
1756 for (loffset=0; loffset<aop->size; loffset++)
1757 if (aop->stk_aop[loffset])
1759 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1762 pullNull (stackAdjust);
1766 /* all other cases just dealloc */
1772 OP_SYMBOL (op)->aop = NULL;
1773 /* if the symbol has a spill */
1775 SPIL_LOC (op)->aop = NULL;
1781 /*-----------------------------------------------------------------*/
1782 /* aopDerefAop - treating the aop parameter as a pointer, return */
1783 /* an asmop for the object it references */
1784 /*-----------------------------------------------------------------*/
1786 aopDerefAop (asmop *aop)
1791 asmop *newaop = NULL;
1792 sym_link *type, *etype;
1795 emitcode ("", "; aopDerefAop(%s)", aopName(aop));
1799 type = operandType (aop->op);
1800 etype = getSpec (type);
1801 /* if op is of type of pointer then it is simple */
1802 if (IS_PTR (type) && !IS_FUNC (type->next))
1803 p_type = DCL_TYPE (type);
1806 /* we have to go by the storage class */
1807 p_type = PTR_TYPE (SPEC_OCLS (etype));
1816 if (p_type == POINTER)
1817 newaop = newAsmop (AOP_DIR);
1819 newaop = newAsmop (AOP_EXT);
1820 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1823 adr = (int) floatFromVal (aop->aopu.aop_lit);
1824 if (p_type == POINTER)
1829 newaop = newAsmop (AOP_DIR);
1830 sprintf (s, "0x%02x",adr);
1834 newaop = newAsmop (AOP_EXT);
1835 sprintf (s, "0x%04x",adr);
1837 rs = Safe_calloc (1, strlen (s) + 1);
1839 newaop->aopu.aop_dir = rs;
1842 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1843 "unsupported asmop");
1853 /*-----------------------------------------------------------------*/
1854 /* aopAdrStr - for referencing the address of the aop */
1855 /*-----------------------------------------------------------------*/
1857 aopAdrStr (asmop * aop, int loffset, bool bit16)
1861 int offset = aop->size - 1 - loffset;
1864 /* offset is greater than
1866 if (loffset > (aop->size - 1) &&
1867 aop->type != AOP_LIT)
1870 /* depending on type */
1875 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
1876 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1878 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1882 sprintf (s, "#(%s >> %d)",
1883 aop->aopu.aop_immd.aop_immd1,
1887 aop->aopu.aop_immd.aop_immd1);
1891 aop->aopu.aop_immd.aop_immd1);
1892 rs = Safe_calloc (1, strlen (s) + 1);
1898 sprintf (s, "*(%s + %d)",
1902 sprintf (s, "*%s", aop->aopu.aop_dir);
1903 rs = Safe_calloc (1, strlen (s) + 1);
1909 sprintf (s, "(%s + %d)",
1913 sprintf (s, "%s", aop->aopu.aop_dir);
1914 rs = Safe_calloc (1, strlen (s) + 1);
1919 return aop->aopu.aop_reg[loffset]->name;
1923 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
1925 return aopLiteral (aop->aopu.aop_lit, loffset);
1929 return aop->aopu.aop_str[loffset];
1932 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
1934 rs = Safe_calloc (1, strlen (s) + 1);
1940 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1941 "aopAdrStr got unsupported aop->type");
1950 /*-----------------------------------------------------------------*/
1951 /* opIsGptr: returns non-zero if the passed operand is */
1952 /* a generic pointer type. */
1953 /*-----------------------------------------------------------------*/
1955 opIsGptr (operand * op)
1957 sym_link *type = operandType (op);
1959 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1967 /*-----------------------------------------------------------------*/
1968 /* getDataSize - get the operand data size */
1969 /*-----------------------------------------------------------------*/
1971 getDataSize (operand * op)
1974 size = AOP_SIZE (op);
1978 /*-----------------------------------------------------------------*/
1979 /* outAcc - output Acc */
1980 /*-----------------------------------------------------------------*/
1982 outAcc (operand * result)
1985 size = getDataSize (result);
1988 storeRegToAop (hc08_reg_a, AOP (result), 0);
1991 /* unsigned or positive */
1994 storeConstToAop (zero, AOP (result), offset++);
1999 /*-----------------------------------------------------------------*/
2000 /* outBitC - output a bit C */
2001 /*-----------------------------------------------------------------*/
2003 outBitC (operand * result)
2007 /* if the result is bit */
2008 if (AOP_TYPE (result) == AOP_CRY)
2009 aopPut (AOP (result), "c", 0);
2013 emitcode ("clra", "");
2014 emitcode ("rola", "");
2019 /*-----------------------------------------------------------------*/
2020 /* outBitNV - output a bit N^V */
2021 /*-----------------------------------------------------------------*/
2023 outBitNV (operand * result)
2025 symbol *tlbl, *tlbl1;
2027 tlbl = newiTempLabel (NULL);
2028 tlbl1 = newiTempLabel (NULL);
2030 emitBranch ("blt", tlbl);
2031 loadRegFromConst (hc08_reg_a, zero);
2032 emitBranch ("bra", tlbl1);
2034 loadRegFromConst (hc08_reg_a, one);
2040 /*-----------------------------------------------------------------*/
2041 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2042 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2043 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2044 /*-----------------------------------------------------------------*/
2046 asmopToBool (asmop *aop, bool resultInA)
2048 symbol *tlbl, *tlbl1;
2049 int size = aop->size;
2050 bool needpula = FALSE;
2051 bool flagsonly = TRUE;
2056 hc08_freeReg(hc08_reg_a);
2063 emitcode ("tsta", "");
2066 else if (IS_AOP_X(aop))
2067 emitcode ("tstx", "");
2068 else if (IS_AOP_H(aop))
2070 if (hc08_reg_a->isFree)
2072 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2073 emitcode ("tsta", "");
2075 hc08_freeReg(hc08_reg_a);
2077 else if (hc08_reg_x->isFree)
2079 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2080 emitcode ("tstx", "");
2081 hc08_freeReg(hc08_reg_x);
2085 emitcode ("pshh", "");
2086 emitcode ("tst", "1,s");
2087 emitcode ("ais", "#1");
2090 else if (IS_AOP_HX(aop))
2091 emitcode ("cphx", zero);
2092 else if (IS_AOP_XA(aop))
2094 symbol *tlbl = newiTempLabel (NULL);
2095 emitcode ("tsta", "");
2096 emitcode ("bne", "%05d$", (tlbl->key + 100));
2097 emitcode ("tstx", "");
2098 emitcode ("", "%05d$:", (tlbl->key + 100));
2102 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2103 "Bad rIdx in asmToBool");
2111 needpula = pushRegIfUsed (hc08_reg_a);
2112 loadRegFromAop (hc08_reg_a, aop, 0);
2113 for (offset=1; offset<size; offset++)
2114 accopWithAop ("ora", aop, offset);
2116 pullReg (hc08_reg_a);
2119 hc08_freeReg (hc08_reg_a);
2128 loadRegFromAop (hc08_reg_a, aop, 0);
2129 hc08_freeReg (hc08_reg_a);
2133 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2138 if (hc08_reg_a->isFree)
2140 loadRegFromAop (hc08_reg_a, aop, 0);
2141 accopWithAop ("ora", aop, 1);
2142 hc08_freeReg (hc08_reg_a);
2147 tlbl = newiTempLabel (NULL);
2148 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2149 emitcode ("bne", "%05d$", (tlbl->key + 100));
2150 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2151 emitcode ("", "%05d$:", (tlbl->key + 100));
2157 needpula = pushRegIfUsed (hc08_reg_a);
2158 loadRegFromAop (hc08_reg_a, aop, 0);
2159 for (offset=1; offset<size; offset++)
2160 accopWithAop ("ora", aop, offset);
2162 pullReg (hc08_reg_a);
2165 hc08_freeReg (hc08_reg_a);
2173 tlbl = newiTempLabel (NULL);
2177 tlbl1 = newiTempLabel (NULL);
2178 emitBranch ("bne", tlbl1);
2179 loadRegFromConst (hc08_reg_a, zero);
2180 emitBranch ("bra", tlbl);
2182 loadRegFromConst (hc08_reg_a, one);
2186 emitBranch ("beq", tlbl);
2187 loadRegFromConst (hc08_reg_a, one);
2190 hc08_useReg (hc08_reg_a);
2196 /*-----------------------------------------------------------------*/
2197 /* genNot - generate code for ! operation */
2198 /*-----------------------------------------------------------------*/
2202 D(emitcode ("; genNot",""));
2204 /* assign asmOps to operand & result */
2205 aopOp (IC_LEFT (ic), ic, FALSE);
2206 aopOp (IC_RESULT (ic), ic, TRUE);
2208 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2209 emitcode ("eor", one);
2210 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2212 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2213 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2217 /*-----------------------------------------------------------------*/
2218 /* genCpl - generate code for complement */
2219 /*-----------------------------------------------------------------*/
2225 regs* reg = hc08_reg_a;
2229 D(emitcode ("; genCpl",""));
2231 /* assign asmOps to operand & result */
2232 aopOp (IC_LEFT (ic), ic, FALSE);
2233 aopOp (IC_RESULT (ic), ic, TRUE);
2235 size = AOP_SIZE (IC_RESULT (ic));
2238 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2239 rmwWithReg ("com", reg);
2241 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2245 /* release the aops */
2246 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2247 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2250 /*-----------------------------------------------------------------*/
2251 /* genUminusFloat - unary minus for floating points */
2252 /*-----------------------------------------------------------------*/
2254 genUminusFloat (operand * op, operand * result)
2256 int size, offset = 0;
2259 D(emitcode ("; genUminusFloat",""));
2261 /* for this we just copy and then flip the bit */
2263 size = AOP_SIZE (op) - 1;
2269 needpula = pushRegIfUsed (hc08_reg_a);
2270 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2271 emitcode ("eor", "#0x80");
2272 hc08_useReg (hc08_reg_a);
2273 storeRegToAop (hc08_reg_a, AOP (result), offset);
2274 pullOrFreeReg (hc08_reg_a, needpula);
2277 transferAopAop (AOP (op), offset, AOP (result), offset);
2283 /*-----------------------------------------------------------------*/
2284 /* genUminus - unary minus code generation */
2285 /*-----------------------------------------------------------------*/
2287 genUminus (iCode * ic)
2290 sym_link *optype, *rtype;
2294 D(emitcode ("; genUminus",""));
2297 aopOp (IC_LEFT (ic), ic, FALSE);
2298 aopOp (IC_RESULT (ic), ic, TRUE);
2300 optype = operandType (IC_LEFT (ic));
2301 rtype = operandType (IC_RESULT (ic));
2303 /* if float then do float stuff */
2304 if (IS_FLOAT (optype))
2306 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2310 /* otherwise subtract from zero */
2311 size = AOP_SIZE (IC_LEFT (ic));
2316 needpula = pushRegIfUsed (hc08_reg_a);
2317 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2318 emitcode ("nega", "");
2319 hc08_freeReg (hc08_reg_a);
2320 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2321 SPEC_USIGN (operandType (IC_LEFT (ic))));
2322 pullOrFreeReg (hc08_reg_a, needpula);
2326 needpula = pushRegIfUsed (hc08_reg_a);
2330 loadRegFromConst (hc08_reg_a, zero);
2331 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2332 storeRegToAop (hc08_reg_a, AOP( IC_RESULT (ic)), offset++);
2335 storeRegSignToUpperAop (hc08_reg_a, AOP( IC_RESULT (ic)), offset,
2336 SPEC_USIGN (operandType (IC_LEFT (ic))));
2337 pullOrFreeReg (hc08_reg_a, needpula);
2343 /* release the aops */
2344 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2345 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2348 /*-----------------------------------------------------------------*/
2349 /* saveRegisters - will look for a call and save the registers */
2350 /*-----------------------------------------------------------------*/
2352 saveRegisters (iCode * lic)
2359 for (ic = lic; ic; ic = ic->next)
2360 if (ic->op == CALL || ic->op == PCALL)
2365 fprintf (stderr, "found parameter push with no function call\n");
2369 /* if the registers have been saved already or don't need to be then
2373 if (IS_SYMOP(IC_LEFT(ic)) &&
2374 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2375 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2378 /* safe the registers in use at this time but skip the
2379 ones for the result */
2380 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2381 hc08_rUmaskForOp (IC_RESULT(ic)));
2384 for (i = 0; i < hc08_nRegs; i++)
2386 if (bitVectBitValue (rsave, i))
2387 pushReg ( hc08_regWithIdx (i), FALSE);
2391 /*-----------------------------------------------------------------*/
2392 /* unsaveRegisters - pop the pushed registers */
2393 /*-----------------------------------------------------------------*/
2395 unsaveRegisters (iCode * ic)
2400 /* restore the registers in use at this time but skip the
2401 ones for the result */
2402 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2403 hc08_rUmaskForOp (IC_RESULT(ic)));
2405 for (i = hc08_nRegs; i >= 0; i--)
2407 if (bitVectBitValue (rsave, i))
2408 pullReg ( hc08_regWithIdx (i));
2414 /*-----------------------------------------------------------------*/
2416 /*-----------------------------------------------------------------*/
2418 pushSide (operand * oper, int size)
2423 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2424 pushReg ( hc08_reg_a, TRUE);
2428 /*-----------------------------------------------------------------*/
2429 /* assignResultValue - */
2430 /*-----------------------------------------------------------------*/
2432 assignResultValue (operand * oper)
2434 int size = AOP_SIZE (oper);
2438 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2439 if (hc08_aop_pass[offset]->type == AOP_REG)
2440 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2447 /*-----------------------------------------------------------------*/
2448 /* genIpush - genrate code for pushing this gets a little complex */
2449 /*-----------------------------------------------------------------*/
2451 genIpush (iCode * ic)
2453 int size, offset = 0;
2456 D(emitcode ("; genIpush",""));
2458 /* if this is not a parm push : ie. it is spill push
2459 and spill push is always done on the local stack */
2463 /* and the item is spilt then do nothing */
2464 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2467 aopOp (IC_LEFT (ic), ic, FALSE);
2468 size = AOP_SIZE (IC_LEFT (ic));
2470 /* push it on the stack */
2473 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2474 pushReg ( hc08_reg_a, TRUE);
2480 /* this is a paramter push: in this case we call
2481 the routine to find the call and save those
2482 registers that need to be saved */
2485 /* then do the push */
2486 aopOp (IC_LEFT (ic), ic, FALSE);
2489 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2490 size = AOP_SIZE (IC_LEFT (ic));
2493 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2494 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2496 if ((size==2) && hc08_reg_hx->isFree)
2498 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2499 pushReg (hc08_reg_hx, TRUE);
2506 // printf("loading %d\n", offset);
2507 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2508 // printf("pushing \n");
2509 pushReg (hc08_reg_a, TRUE);
2513 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2516 /*-----------------------------------------------------------------*/
2517 /* genIpop - recover the registers: can happen only for spilling */
2518 /*-----------------------------------------------------------------*/
2520 genIpop (iCode * ic)
2524 D(emitcode ("; genIpop",""));
2526 /* if the temp was not pushed then */
2527 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2530 aopOp (IC_LEFT (ic), ic, FALSE);
2531 size = AOP_SIZE (IC_LEFT (ic));
2535 pullReg (hc08_reg_a);
2536 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2538 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2542 /*-----------------------------------------------------------------*/
2543 /* genSend - gen code for SEND */
2544 /*-----------------------------------------------------------------*/
2545 static void genSend(set *sendSet)
2549 for (sic = setFirstItem (_G.sendSet); sic;
2550 sic = setNextItem (_G.sendSet)) {
2551 int size, offset = 0;
2552 aopOp (IC_LEFT (sic), sic, FALSE);
2553 size = AOP_SIZE (IC_LEFT (sic));
2558 transferAopAop( AOP (IC_LEFT (sic)), offset,
2559 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2563 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2567 /*-----------------------------------------------------------------*/
2568 /* genCall - generates a call statement */
2569 /*-----------------------------------------------------------------*/
2571 genCall (iCode * ic)
2574 // bool restoreBank = FALSE;
2575 // bool swapBanks = FALSE;
2577 D(emitcode("; genCall",""));
2579 dtype = operandType (IC_LEFT (ic));
2580 /* if send set is not empty the assign */
2583 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2584 genSend(reverseSet(_G.sendSet));
2586 genSend(_G.sendSet);
2592 /* if caller saves & we have not saved then */
2598 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2599 OP_SYMBOL (IC_LEFT (ic))->rname :
2600 OP_SYMBOL (IC_LEFT (ic))->name));
2603 /* if we need assign a result value */
2604 if ((IS_ITEMP (IC_RESULT (ic)) &&
2605 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2606 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2607 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2608 IS_TRUE_SYMOP (IC_RESULT (ic)))
2612 aopOp (IC_RESULT (ic), ic, FALSE);
2615 assignResultValue (IC_RESULT (ic));
2617 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2620 /* adjust the stack for parameters if
2624 pullNull (ic->parmBytes);
2627 /* if we had saved some registers then unsave them */
2628 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2629 unsaveRegisters (ic);
2633 /*-----------------------------------------------------------------*/
2634 /* -10l - generates a call by pointer statement */
2635 /*-----------------------------------------------------------------*/
2637 genPcall (iCode * ic)
2640 symbol *rlbl = newiTempLabel (NULL);
2641 symbol *tlbl = newiTempLabel (NULL);
2642 // bool restoreBank=FALSE;
2643 // bool swapBanks = FALSE;
2645 D(emitcode("; genPCall",""));
2647 /* if caller saves & we have not saved then */
2651 /* if we are calling a not _naked function that is not using
2652 the same register bank then we need to save the
2653 destination registers on the stack */
2654 dtype = operandType (IC_LEFT (ic))->next;
2656 /* now push the calling address */
2657 emitBranch ("bsr", tlbl);
2658 emitBranch ("bra", rlbl);
2661 /* Push the function's address */
2662 aopOp (IC_LEFT (ic), ic, FALSE);
2663 pushSide (IC_LEFT (ic), FPTRSIZE);
2664 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2666 /* if send set is not empty the assign */
2669 genSend(reverseSet(_G.sendSet));
2675 emitcode ("rts", "");
2680 /* if we need assign a result value */
2681 if ((IS_ITEMP (IC_RESULT (ic)) &&
2682 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2683 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2684 IS_TRUE_SYMOP (IC_RESULT (ic)))
2688 aopOp (IC_RESULT (ic), ic, FALSE);
2691 assignResultValue (IC_RESULT (ic));
2693 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2696 /* adjust the stack for parameters if
2700 pullNull (ic->parmBytes);
2703 /* if we hade saved some registers then
2705 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2706 unsaveRegisters (ic);
2709 /*-----------------------------------------------------------------*/
2710 /* resultRemat - result is rematerializable */
2711 /*-----------------------------------------------------------------*/
2713 resultRemat (iCode * ic)
2715 if (SKIP_IC (ic) || ic->op == IFX)
2718 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2720 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2721 if (sym->remat && !POINTER_SET (ic))
2728 #if defined(__BORLANDC__) || defined(_MSC_VER)
2729 #define STRCASECMP stricmp
2731 #define STRCASECMP strcasecmp
2734 /*-----------------------------------------------------------------*/
2735 /* inExcludeList - return 1 if the string is in exclude Reg list */
2736 /*-----------------------------------------------------------------*/
2738 regsCmp(void *p1, void *p2)
2740 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2744 inExcludeList (char *s)
2746 const char *p = setFirstItem(options.excludeRegsSet);
2748 if (p == NULL || STRCASECMP(p, "none") == 0)
2752 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2755 /*-----------------------------------------------------------------*/
2756 /* genFunction - generated code for function entry */
2757 /*-----------------------------------------------------------------*/
2759 genFunction (iCode * ic)
2763 int calleesaves_saved_register = -1;
2767 /* create the function header */
2768 emitcode (";", "-----------------------------------------");
2769 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2770 emitcode (";", "-----------------------------------------");
2772 emitcode ("", "%s:", sym->rname);
2773 ftype = operandType (IC_LEFT (ic));
2775 if (IFFUNC_ISNAKED(ftype))
2777 emitcode(";", "naked function: no prologue.");
2783 /* if this is an interrupt service routine then
2785 if (IFFUNC_ISISR (sym->type))
2788 if (!inExcludeList ("h"))
2789 emitcode ("pshh", "");
2793 /* if callee-save to be used for this function
2794 then save the registers being used in this function */
2795 if (IFFUNC_CALLEESAVES(sym->type))
2799 /* if any registers used */
2802 /* save the registers used */
2803 for (i = 0; i < sym->regsUsed->size; i++)
2805 if (bitVectBitValue (sym->regsUsed, i))
2807 /* remember one saved register for later usage */
2808 if (calleesaves_saved_register < 0)
2809 calleesaves_saved_register = i;
2810 pushReg (hc08_regWithIdx (i), FALSE);
2818 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2823 /* adjust the stack for the function */
2829 // werror (W_STACK_OVERFLOW, sym->name);
2833 _G.stackOfs = sym->stack;
2836 /* if critical function then turn interrupts off */
2837 if (IFFUNC_ISCRITICAL (ftype))
2839 if (IFFUNC_ARGS (ftype))
2841 /* Function was passed parameters, so make sure A is preserved */
2842 pushReg (hc08_reg_a, FALSE);
2843 pushReg (hc08_reg_a, FALSE);
2844 emitcode ("tpa", "");
2845 emitcode ("sta", "2,s");
2846 emitcode ("sei", "");
2847 pullReg (hc08_reg_a);
2851 /* No passed parameters, so A can be freely modified */
2852 emitcode ("tpa", "");
2853 pushReg (hc08_reg_a, TRUE);
2854 emitcode ("sei", "");
2860 /*-----------------------------------------------------------------*/
2861 /* genEndFunction - generates epilogue for functions */
2862 /*-----------------------------------------------------------------*/
2864 genEndFunction (iCode * ic)
2866 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2868 if (IFFUNC_ISNAKED(sym->type))
2870 emitcode(";", "naked function: no epilogue.");
2874 if (IFFUNC_ISCRITICAL (sym->type))
2876 if (!IS_VOID(sym->type->next))
2878 /* Function has return value, so make sure A is preserved */
2879 pushReg (hc08_reg_a, FALSE);
2880 emitcode ("lda", "2,s");
2881 emitcode ("tap", "");
2882 pullReg (hc08_reg_a);
2887 /* Function returns void, so A can be freely modified */
2888 pullReg (hc08_reg_a);
2889 emitcode ("tap", "");
2893 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2899 _G.stackPushes += sym->stack;
2900 adjustStack (sym->stack);
2904 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2908 if (IFFUNC_ISISR (sym->type))
2911 if (!inExcludeList ("h"))
2912 emitcode ("pulh", "");
2915 /* if debug then send end of function */
2916 if (options.debug && currFunc)
2919 emitcode ("", "C$%s$%d$%d$%d ==.",
2920 FileBaseName (ic->filename), currFunc->lastLine,
2921 ic->level, ic->block);
2922 if (IS_STATIC (currFunc->etype))
2923 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2925 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2929 emitcode ("rti", "");
2933 if (IFFUNC_CALLEESAVES(sym->type))
2937 /* if any registers used */
2940 /* save the registers used */
2941 for (i = sym->regsUsed->size; i >= 0; i--)
2943 if (bitVectBitValue (sym->regsUsed, i) ||
2944 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
2945 emitcode ("pop", "%s", hc08_regWithIdx (i)->dname);
2951 /* if debug then send end of function */
2952 if (options.debug && currFunc)
2955 emitcode ("", "C$%s$%d$%d$%d ==.",
2956 FileBaseName (ic->filename), currFunc->lastLine,
2957 ic->level, ic->block);
2958 if (IS_STATIC (currFunc->etype))
2959 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2961 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2965 emitcode ("rts", "");
2970 /*-----------------------------------------------------------------*/
2971 /* genRet - generate code for return statement */
2972 /*-----------------------------------------------------------------*/
2976 int size, offset = 0;
2979 D(emitcode ("; genRet",""));
2981 /* if we have no return value then
2982 just generate the "ret" */
2986 /* we have something to return then
2987 move the return value into place */
2988 aopOp (IC_LEFT (ic), ic, FALSE);
2989 size = AOP_SIZE (IC_LEFT (ic));
2995 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3002 /* 4 byte return: store value in the global return variable */
3006 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3007 STA (fReturn2[offset--], FALSE);
3008 hc08_freeReg (hc08_reg_a);
3012 /* 2 byte return: store value in x:a */
3013 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3014 hc08_freeReg (hc08_reg_xa);
3017 /* 1 byte return: store value in a */
3018 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3019 hc08_freeReg (hc08_reg_a);
3024 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3027 /* generate a jump to the return label
3028 if the next is not the return statement */
3029 if (!(ic->next && ic->next->op == LABEL &&
3030 IC_LABEL (ic->next) == returnLabel))
3032 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3036 /*-----------------------------------------------------------------*/
3037 /* genLabel - generates a label */
3038 /*-----------------------------------------------------------------*/
3040 genLabel (iCode * ic)
3045 /* For the high level labels we cannot depend on any */
3046 /* register's contents. Amnesia time. */
3047 for (i=A_IDX;i<=XA_IDX;i++)
3049 reg = hc08_regWithIdx(i);
3054 /* special case never generate */
3055 if (IC_LABEL (ic) == entryLabel)
3058 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3062 /*-----------------------------------------------------------------*/
3063 /* genGoto - generates a jmp */
3064 /*-----------------------------------------------------------------*/
3066 genGoto (iCode * ic)
3068 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3072 /*-----------------------------------------------------------------*/
3073 /* findLabelBackwards: walks back through the iCode chain looking */
3074 /* for the given label. Returns number of iCode instructions */
3075 /* between that label and given ic. */
3076 /* Returns zero if label not found. */
3077 /*-----------------------------------------------------------------*/
3079 findLabelBackwards (iCode * ic, int key)
3088 /* If we have any pushes or pops, we cannot predict the distance.
3089 I don't like this at all, this should be dealt with in the
3091 if (ic->op == IPUSH || ic->op == IPOP) {
3095 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3105 /*-----------------------------------------------------------------*/
3106 /* genPlusIncr :- does addition with increment if possible */
3107 /*-----------------------------------------------------------------*/
3109 genPlusIncr (iCode * ic)
3117 unsigned int size = getDataSize (IC_RESULT (ic));
3119 symbol *tlbl = NULL;
3121 left = IC_LEFT (ic);
3122 result = IC_RESULT (ic);
3124 /* will try to generate an increment */
3125 /* if the right side is not a literal
3127 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3130 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3132 emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left)));
3134 if ((IS_AOP_HX (AOP (left)) ||
3135 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3137 && (icount>=-128) && (icount<=127) && (size==2))
3139 needpulx = pushRegIfUsed (hc08_reg_x);
3140 needpulh = pushRegIfUsed (hc08_reg_h);
3141 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3142 emitcode ("aix","#%d", icount);
3143 hc08_dirtyReg (hc08_reg_hx, FALSE);
3144 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3145 pullOrFreeReg (hc08_reg_h, needpulh);
3146 pullOrFreeReg (hc08_reg_x, needpulx);
3150 emitcode ("", "; icount = %d, sameRegs=%d", icount,
3151 sameRegs (AOP (left), AOP (result)));
3153 if ((icount > 255) || (icount<0))
3156 if (!sameRegs (AOP (left), AOP (result)))
3159 D(emitcode ("; genPlusIncr",""));
3162 tlbl = newiTempLabel (NULL);
3167 rmwWithAop ("inc", AOP (result), 0);
3169 emitBranch ("bne", tlbl);
3173 needpula = pushRegIfUsed (hc08_reg_a);
3174 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3175 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3176 hc08_useReg (hc08_reg_a);
3177 storeRegToAop (hc08_reg_a, AOP (result), 0);
3178 hc08_freeReg (hc08_reg_a);
3180 emitBranch ("bcc", tlbl);
3182 for (offset=1; offset<size; offset++)
3184 rmwWithAop ("inc", AOP (result), offset);
3185 if ((offset+1)<size)
3186 emitBranch ("bne", tlbl);
3192 pullOrFreeReg (hc08_reg_a, needpula);
3199 /*-----------------------------------------------------------------*/
3200 /* genPlus - generates code for addition */
3201 /*-----------------------------------------------------------------*/
3203 genPlus (iCode * ic)
3205 int size, offset = 0;
3207 asmop *leftOp, *rightOp;
3209 /* special cases :- */
3211 D(emitcode ("; genPlus",""));
3213 aopOp (IC_LEFT (ic), ic, FALSE);
3214 aopOp (IC_RIGHT (ic), ic, FALSE);
3215 aopOp (IC_RESULT (ic), ic, TRUE);
3217 /* we want registers on the left and literals on the right */
3218 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3219 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3221 operand *t = IC_RIGHT (ic);
3222 IC_RIGHT (ic) = IC_LEFT (ic);
3227 /* if I can do an increment instead
3228 of add then GOOD for ME */
3229 if (genPlusIncr (ic) == TRUE)
3232 emitcode("","; left size = %d", getDataSize (IC_LEFT(ic)));
3233 emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic)));
3234 emitcode("","; result size = %d", getDataSize (IC_RESULT(ic)));
3236 size = getDataSize (IC_RESULT (ic));
3238 leftOp = AOP(IC_LEFT(ic));
3239 rightOp = AOP(IC_RIGHT(ic));
3245 loadRegFromAop (hc08_reg_a, leftOp, offset);
3246 accopWithAop(add, rightOp, offset);
3247 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3248 hc08_freeReg (hc08_reg_a);
3249 add = "adc"; /* further adds must propagate carry */
3253 // adjustArithmeticResult (ic);
3256 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3257 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3258 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3261 /*-----------------------------------------------------------------*/
3262 /* genMinusDec :- does subtraction with deccrement if possible */
3263 /*-----------------------------------------------------------------*/
3265 genMinusDec (iCode * ic)
3267 unsigned int icount;
3272 unsigned int size = getDataSize (IC_RESULT (ic));
3276 left = IC_LEFT (ic);
3277 result = IC_RESULT (ic);
3279 /* will try to generate an increment */
3280 /* if the right side is not a literal
3282 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3285 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3287 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3288 && (icount>=-127) && (icount<=128) && (size==2))
3290 needpulx = pushRegIfUsed (hc08_reg_x);
3291 needpulh = pushRegIfUsed (hc08_reg_h);
3292 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3293 emitcode ("aix","#%d", -icount);
3294 hc08_dirtyReg (hc08_reg_hx, FALSE);
3295 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3296 pullOrFreeReg (hc08_reg_h, needpulh);
3297 pullOrFreeReg (hc08_reg_x, needpulx);
3301 if ((icount > 1) || (icount<0))
3304 if (!sameRegs (AOP (left), AOP (result)))
3310 D(emitcode ("; genMinusDec",""));
3312 rmwWithAop ("dec", AOP (result), 0);
3317 /*-----------------------------------------------------------------*/
3318 /* addSign - complete with sign */
3319 /*-----------------------------------------------------------------*/
3321 addSign (operand * result, int offset, int sign)
3323 int size = (getDataSize (result) - offset);
3328 emitcode ("rola", "");
3329 emitcode ("clra", "");
3330 emitcode ("sbc", zero);
3332 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3336 storeConstToAop (zero, AOP (result), offset++);
3341 /*-----------------------------------------------------------------*/
3342 /* genMinus - generates code for subtraction */
3343 /*-----------------------------------------------------------------*/
3345 genMinus (iCode * ic)
3348 int size, offset = 0;
3350 asmop *leftOp, *rightOp;
3352 D(emitcode ("; genMinus",""));
3354 aopOp (IC_LEFT (ic), ic, FALSE);
3355 aopOp (IC_RIGHT (ic), ic, FALSE);
3356 aopOp (IC_RESULT (ic), ic, TRUE);
3358 /* special cases :- */
3359 /* if I can do an decrement instead
3360 of subtract then GOOD for ME */
3361 if (genMinusDec (ic) == TRUE)
3364 size = getDataSize (IC_RESULT (ic));
3367 leftOp = AOP(IC_LEFT(ic));
3368 rightOp = AOP(IC_RIGHT(ic));
3374 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3375 accopWithAop(sub, rightOp, offset);
3376 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3381 // adjustArithmeticResult (ic);
3384 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3385 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3386 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3391 /*-----------------------------------------------------------------*/
3392 /* genMultOneByte : 8*8=8/16 bit multiplication */
3393 /*-----------------------------------------------------------------*/
3395 genMultOneByte (operand * left,
3399 sym_link *opetype = operandType (result);
3400 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3401 int size=AOP_SIZE(result);
3402 bool negLiteral = FALSE;
3404 D(emitcode ("; genMultOneByte",""));
3406 if (size<1 || size>2) {
3407 // this should never happen
3408 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3409 AOP_SIZE(result), __FILE__, lineno);
3413 /* (if two literals: the value is computed before) */
3414 /* if one literal, literal on the right */
3415 if (AOP_TYPE (left) == AOP_LIT)
3420 //emitcode (";", "swapped left and right");
3423 if (SPEC_USIGN(opetype))
3425 // just an unsigned 8*8=8/16 multiply
3426 //emitcode (";","unsigned");
3428 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3429 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3430 emitcode ("mul", "");
3431 hc08_dirtyReg (hc08_reg_xa, FALSE);
3432 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3433 hc08_freeReg (hc08_reg_xa);
3438 // we have to do a signed multiply
3441 //emitcode (";", "signed");
3443 emitcode ("clr", "1,s");
3445 tlbl1 = newiTempLabel (NULL);
3446 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3447 emitcode ("tsta","");
3448 emitBranch ("bpl", tlbl1);
3449 emitcode ("inc", "1,s");
3450 rmwWithReg ("neg", hc08_reg_a);
3453 if (AOP_TYPE(right)==AOP_LIT)
3455 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3456 /* AND literal negative */
3458 emitcode ("ldx", "#0x%02x", -val);
3461 emitcode ("ldx", "#0x%02x", val);
3463 hc08_useReg (hc08_reg_x);
3467 tlbl2 = newiTempLabel (NULL);
3468 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3469 emitcode ("tstx", "");
3470 emitBranch ("bpl", tlbl2);
3471 emitcode ("inc", "1,s");
3472 rmwWithReg ("neg", hc08_reg_x);
3476 emitcode ("mul", "");
3477 hc08_dirtyReg (hc08_reg_xa, FALSE);
3479 tlbl3 = newiTempLabel (NULL);
3480 emitcode ("dec", "1,s");
3482 emitBranch ("bne", tlbl3);
3484 emitBranch ("beq", tlbl3);
3486 rmwWithReg ("neg", hc08_reg_a);
3489 tlbl4 = newiTempLabel (NULL);
3490 emitBranch ("bcc", tlbl4);
3491 rmwWithReg ("inc", hc08_reg_x);
3493 rmwWithReg ("neg", hc08_reg_x);
3498 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3499 hc08_freeReg (hc08_reg_xa);
3503 /*-----------------------------------------------------------------*/
3504 /* genMult - generates code for multiplication */
3505 /*-----------------------------------------------------------------*/
3507 genMult (iCode * ic)
3509 operand *left = IC_LEFT (ic);
3510 operand *right = IC_RIGHT (ic);
3511 operand *result = IC_RESULT (ic);
3513 D(emitcode ("; genMult",""));
3515 /* assign the amsops */
3516 aopOp (left, ic, FALSE);
3517 aopOp (right, ic, FALSE);
3518 aopOp (result, ic, TRUE);
3520 /* special cases first */
3521 /* if both are of size == 1 */
3522 // if (getSize(operandType(left)) == 1 &&
3523 // getSize(operandType(right)) == 1)
3524 if (AOP_SIZE (left) == 1 &&
3525 AOP_SIZE (right) == 1)
3527 genMultOneByte (left, right, result);
3531 /* should have been converted to function call */
3532 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3533 getSize(OP_SYMBOL(right)->type));
3534 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3539 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3540 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3541 freeAsmop (result, NULL, ic, TRUE);
3544 /*-----------------------------------------------------------------*/
3545 /* genDivOneByte : 8 bit division */
3546 /*-----------------------------------------------------------------*/
3548 genDivOneByte (operand * left,
3552 sym_link *opetype = operandType (result);
3554 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3556 bool negLiteral = FALSE;
3558 D(emitcode ("; genDivOneByte",""));
3560 size = AOP_SIZE (result);
3561 /* signed or unsigned */
3562 if (SPEC_USIGN (opetype))
3564 /* unsigned is easy */
3565 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3566 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3567 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3568 emitcode ("div", "");
3569 hc08_dirtyReg (hc08_reg_a, FALSE);
3570 hc08_dirtyReg (hc08_reg_h, FALSE);
3571 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3572 hc08_freeReg (hc08_reg_a);
3573 hc08_freeReg (hc08_reg_x);
3574 hc08_freeReg (hc08_reg_h);
3578 /* signed is a little bit more difficult */
3581 emitcode ("clr", "1,s");
3583 tlbl1 = newiTempLabel (NULL);
3584 tlbl2 = newiTempLabel (NULL);
3585 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3586 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3587 emitBranch ("bpl", tlbl1);
3588 emitcode ("inc", "1,s");
3589 rmwWithReg ("neg", hc08_reg_a);
3590 emitBranch ("bcc", tlbl2);
3591 rmwWithReg ("inc", hc08_reg_x);
3593 rmwWithReg ("neg", hc08_reg_x);
3594 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3597 if (AOP_TYPE(right)==AOP_LIT)
3599 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3600 /* AND literal negative */
3602 emitcode ("ldx", "#0x%02x", -val);
3605 emitcode ("ldx", "#0x%02x", val);
3607 hc08_useReg (hc08_reg_x);
3611 tlbl3 = newiTempLabel (NULL);
3612 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3613 emitBranch ("bpl", tlbl3);
3614 emitcode ("inc", "1,s");
3615 rmwWithReg ("neg", hc08_reg_x);
3619 emitcode ("div", "");
3620 hc08_dirtyReg (hc08_reg_x, FALSE);
3621 hc08_dirtyReg (hc08_reg_a, FALSE);
3622 hc08_dirtyReg (hc08_reg_h, FALSE);
3624 tlbl4 = newiTempLabel (NULL);
3625 emitcode ("dec", "1,s");
3627 emitBranch ("bne", tlbl4);
3629 emitBranch ("beq", tlbl4);
3630 rmwWithReg ("neg", hc08_reg_a);
3634 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3635 hc08_freeReg (hc08_reg_a);
3636 hc08_freeReg (hc08_reg_x);
3637 hc08_freeReg (hc08_reg_h);
3642 /*-----------------------------------------------------------------*/
3643 /* genDiv - generates code for division */
3644 /*-----------------------------------------------------------------*/
3648 operand *left = IC_LEFT (ic);
3649 operand *right = IC_RIGHT (ic);
3650 operand *result = IC_RESULT (ic);
3652 D(emitcode ("; genDiv",""));
3654 /* assign the amsops */
3655 aopOp (left, ic, FALSE);
3656 aopOp (right, ic, FALSE);
3657 aopOp (result, ic, TRUE);
3659 /* special cases first */
3660 /* if both are of size == 1 */
3661 if (AOP_SIZE (left) <= 2 &&
3662 AOP_SIZE (right) == 1)
3664 genDivOneByte (left, right, result);
3668 /* should have been converted to function call */
3671 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3672 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3673 freeAsmop (result, NULL, ic, TRUE);
3676 /*-----------------------------------------------------------------*/
3677 /* genModOneByte : 8 bit modulus */
3678 /*-----------------------------------------------------------------*/
3680 genModOneByte (operand * left,
3684 sym_link *opetype = operandType (result);
3686 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3688 bool negLiteral = FALSE;
3690 D(emitcode ("; genModOneByte",""));
3692 size = AOP_SIZE (result);
3693 /* signed or unsigned */
3694 if (SPEC_USIGN (opetype))
3696 /* unsigned is easy */
3697 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3698 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3699 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3700 emitcode ("div", "");
3701 hc08_dirtyReg (hc08_reg_a, FALSE);
3702 hc08_dirtyReg (hc08_reg_h, FALSE);
3703 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3704 hc08_freeReg (hc08_reg_a);
3705 hc08_freeReg (hc08_reg_x);
3706 hc08_freeReg (hc08_reg_h);
3710 /* signed is a little bit more difficult */
3713 emitcode ("clr", "1,s");
3715 tlbl1 = newiTempLabel (NULL);
3716 tlbl2 = newiTempLabel (NULL);
3717 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3718 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3719 emitBranch ("bpl", tlbl1);
3720 emitcode ("inc", "1,s");
3721 rmwWithReg ("neg", hc08_reg_a);
3722 emitBranch ("bcc", tlbl2);
3723 rmwWithReg ("inc", hc08_reg_x);
3725 rmwWithReg ("neg", hc08_reg_x);
3726 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3729 if (AOP_TYPE(right)==AOP_LIT)
3731 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3732 /* AND literal negative */
3734 emitcode ("ldx", "#0x%02x", -val);
3737 emitcode ("ldx", "#0x%02x", val);
3739 hc08_useReg (hc08_reg_x);
3743 tlbl3 = newiTempLabel (NULL);
3744 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3745 emitBranch ("bpl", tlbl3);
3746 emitcode ("inc", "1,s");
3747 rmwWithReg ("neg", hc08_reg_x);
3751 emitcode ("div", "");
3752 hc08_dirtyReg (hc08_reg_x, FALSE);
3753 hc08_dirtyReg (hc08_reg_a, FALSE);
3754 hc08_dirtyReg (hc08_reg_h, FALSE);
3756 tlbl4 = newiTempLabel (NULL);
3757 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
3758 emitcode ("dec", "1,s");
3760 emitBranch ("bne", tlbl4);
3762 emitBranch ("beq", tlbl4);
3763 rmwWithReg ("neg", hc08_reg_a);
3767 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3768 hc08_freeReg (hc08_reg_a);
3769 hc08_freeReg (hc08_reg_x);
3770 hc08_freeReg (hc08_reg_h);
3774 /*-----------------------------------------------------------------*/
3775 /* genMod - generates code for division */
3776 /*-----------------------------------------------------------------*/
3780 operand *left = IC_LEFT (ic);
3781 operand *right = IC_RIGHT (ic);
3782 operand *result = IC_RESULT (ic);
3784 D(emitcode ("; genMod",""));
3786 /* assign the amsops */
3787 aopOp (left, ic, FALSE);
3788 aopOp (right, ic, FALSE);
3789 aopOp (result, ic, TRUE);
3791 /* special cases first */
3792 /* if both are of size == 1 */
3793 if (AOP_SIZE (left) <= 2 &&
3794 AOP_SIZE (right) == 1)
3796 genModOneByte (left, right, result);
3800 /* should have been converted to function call */
3804 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3805 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3806 freeAsmop (result, NULL, ic, TRUE);
3809 /*-----------------------------------------------------------------*/
3810 /* genIfxJump :- will create a jump depending on the ifx */
3811 /*-----------------------------------------------------------------*/
3813 genIfxJump (iCode * ic, char *jval)
3816 symbol *tlbl = newiTempLabel (NULL);
3819 D(emitcode ("; genIfxJump",""));
3821 /* if true label then we jump if condition
3825 jlbl = IC_TRUE (ic);
3826 if (!strcmp (jval, "a"))
3828 else if (!strcmp (jval, "c"))
3835 /* false label is present */
3836 jlbl = IC_FALSE (ic);
3837 if (!strcmp (jval, "a"))
3839 else if (!strcmp (jval, "c"))
3844 emitBranch (inst, tlbl);
3845 emitBranch ("jmp", jlbl);
3848 /* mark the icode as generated */
3852 /*-----------------------------------------------------------------*/
3853 /* genCmp :- greater or less than comparison */
3854 /*-----------------------------------------------------------------*/
3856 genCmp (operand * left, operand * right,
3857 operand * result, iCode * ifx, int sign, iCode *ic)
3859 int size, offset = 0;
3860 unsigned long lit = 0L;
3862 bool needpula = FALSE;
3864 D(emitcode ("; genCmp",""));
3866 /* subtract right from left if at the
3867 end the carry flag is set then we know that
3868 left is greater than right */
3869 size = max (AOP_SIZE (left), AOP_SIZE (right));
3871 if (AOP_TYPE (right) == AOP_LIT)
3873 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3874 /* optimize if(x < 0) or if(x >= 0) */
3883 needpula = pushRegIfUsed (hc08_reg_a);
3884 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
3885 emitcode ("rola", "");
3886 hc08_useReg (hc08_reg_a);
3894 && ((AOP_TYPE (right) == AOP_LIT) ||
3895 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
3896 && hc08_reg_hx->isFree)
3898 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
3899 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
3900 hc08_freeReg (hc08_reg_hx);
3911 loadRegFromAop (hc08_reg_a, AOP (left), offset);
3912 accopWithAop (sub, AOP (right), offset);
3913 hc08_freeReg (hc08_reg_a);
3919 freeAsmop (right, NULL, ic, TRUE);
3920 freeAsmop (left, NULL, ic, TRUE);
3921 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3927 /* if the result is used in the next
3928 ifx conditional branch then generate
3929 code a little differently */
3932 pullOrFreeReg(hc08_reg_a,needpula);
3933 genIfxJump (ifx, sign ? "s" : "c");
3940 pullOrFreeReg(hc08_reg_a,needpula);
3944 /*-----------------------------------------------------------------*/
3945 /* genCmpGt :- greater than comparison */
3946 /*-----------------------------------------------------------------*/
3948 genCmpGt (iCode * ic, iCode * ifx)
3950 operand *left, *right, *result;
3951 sym_link *letype, *retype;
3954 D(emitcode ("; genCmpGt",""));
3956 result = IC_RESULT (ic);
3957 left = IC_LEFT (ic);
3958 right = IC_RIGHT (ic);
3960 letype = getSpec (operandType (left));
3961 retype = getSpec (operandType (right));
3962 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3963 /* assign the amsops */
3964 aopOp (left, ic, FALSE);
3965 aopOp (right, ic, FALSE);
3966 aopOp (result, ic, TRUE);
3968 genCmp (right, left, result, ifx, sign,ic);
3970 freeAsmop (result, NULL, ic, TRUE);
3973 /*-----------------------------------------------------------------*/
3974 /* genCmpLt - less than comparisons */
3975 /*-----------------------------------------------------------------*/
3977 genCmpLt (iCode * ic, iCode * ifx)
3979 operand *left, *right, *result;
3980 sym_link *letype, *retype;
3983 D(emitcode ("; genCmpLt",""));
3985 result = IC_RESULT (ic);
3986 left = IC_LEFT (ic);
3987 right = IC_RIGHT (ic);
3989 letype = getSpec (operandType (left));
3990 retype = getSpec (operandType (right));
3991 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3993 /* assign the amsops */
3994 aopOp (left, ic, FALSE);
3995 aopOp (right, ic, FALSE);
3996 aopOp (result, ic, TRUE);
3998 genCmp (left, right, result, ifx, sign,ic);
4000 freeAsmop (result, NULL, ic, TRUE);
4003 /*-----------------------------------------------------------------*/
4004 /* - compare and branch if not equal */
4005 /*-----------------------------------------------------------------*/
4007 gencbneshort (operand * left, operand * right, symbol * lbl)
4009 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4011 unsigned long lit = 0L;
4013 /* if the left side is a literal or
4014 if the right is in a pointer register and left
4016 if (AOP_TYPE (left) == AOP_LIT)
4022 if (AOP_TYPE (right) == AOP_LIT)
4023 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4027 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4028 accopWithAop ("cmp", AOP (right), offset);
4029 hc08_useReg (hc08_reg_a);
4030 hc08_freeReg (hc08_reg_a);
4031 emitBranch ("bne", lbl);
4037 /*-----------------------------------------------------------------*/
4038 /* gencjne - compare and jump if not equal */
4039 /*-----------------------------------------------------------------*/
4041 gencjne (operand * left, operand * right, symbol * lbl)
4043 symbol *tlbl = newiTempLabel (NULL);
4045 gencbneshort (left, right, lbl);
4047 loadRegFromConst (hc08_reg_a, one);
4048 emitBranch ("bra", tlbl);
4050 loadRegFromConst (hc08_reg_a, zero);
4053 hc08_useReg(hc08_reg_a);
4054 hc08_freeReg(hc08_reg_a);
4057 /*-----------------------------------------------------------------*/
4058 /* genCmpEq - generates code for equal to */
4059 /*-----------------------------------------------------------------*/
4061 genCmpEq (iCode * ic, iCode * ifx)
4063 operand *left, *right, *result;
4065 D(emitcode ("; genCmpEq",""));
4067 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4068 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4069 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4071 /* if literal, literal on the right or
4072 if the right is in a pointer register and left
4074 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4076 operand *t = IC_RIGHT (ic);
4077 IC_RIGHT (ic) = IC_LEFT (ic);
4081 if (ifx && !AOP_SIZE (result))
4084 tlbl = newiTempLabel (NULL);
4085 gencbneshort (left, right, tlbl);
4088 emitBranch ("jmp", IC_TRUE (ifx));
4093 symbol *lbl = newiTempLabel (NULL);
4094 emitBranch ("bra", lbl);
4096 emitBranch ("jmp", IC_FALSE (ifx));
4100 /* mark the icode as generated */
4105 gencjne (left, right, newiTempLabel (NULL));
4106 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4108 storeRegToAop (hc08_reg_a, AOP (result), 0);
4113 genIfxJump (ifx, "a");
4116 /* if the result is used in an arithmetic operation
4117 then put the result in place */
4118 if (AOP_TYPE (result) != AOP_CRY)
4122 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4123 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4124 freeAsmop (result, NULL, ic, TRUE);
4127 /*-----------------------------------------------------------------*/
4128 /* ifxForOp - returns the icode containing the ifx for operand */
4129 /*-----------------------------------------------------------------*/
4131 ifxForOp (operand * op, iCode * ic)
4133 /* if true symbol then needs to be assigned */
4134 if (IS_TRUE_SYMOP (op))
4137 /* if this has register type condition and
4138 the next instruction is ifx with the same operand
4139 and live to of the operand is upto the ifx only then */
4141 ic->next->op == IFX &&
4142 IC_COND (ic->next)->key == op->key &&
4143 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4150 genPointerGetSetOfs (iCode *ic)
4152 iCode *lic = ic->next;
4158 /* Make sure we have a next iCode */
4159 emitcode("","; checking lic");
4163 /* Make sure the result of the addition is an iCode */
4164 emitcode("","; checking IS_ITEMP");
4165 if (!IS_ITEMP (IC_RESULT (ic)))
4168 /* Make sure the next iCode is a pointer set or get */
4169 pset = POINTER_SET(lic);
4170 pget = POINTER_GET(lic);
4171 emitcode("","; pset=%d, pget=%d",pset,pget);
4175 emitcode("", "; checking pset operandsEqu");
4176 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4179 emitcode("", "; checking pget operandsEqu");
4180 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4183 emitcode("", "; checking IS_SYMOP");
4184 if (!IS_SYMOP (IC_LEFT (ic)))
4187 emitcode("", "; checking !IS_TRUE_SYMOP");
4188 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4191 sym = OP_SYMBOL (IC_LEFT (ic));
4193 emitcode("", "; checking remat");
4199 D(emitcode ("; genPointerGetOfs",""));
4200 aopOp (IC_LEFT(ic), ic, FALSE);
4201 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4202 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4204 aopOp (IC_RIGHT(ic), ic, FALSE);
4205 aopOp (IC_RESULT(lic), lic, FALSE);
4208 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4209 size = AOP_SIZE (IC_RESULT(lic));
4210 derefaop->size = size;
4215 emitcode ("lda", "%s,x",
4216 aopAdrStr (derefaop, offset, TRUE));
4217 hc08_useReg (hc08_reg_a);
4218 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
4219 hc08_freeReg (hc08_reg_a);
4223 hc08_freeReg (hc08_reg_hx);
4225 freeAsmop (NULL, derefaop, ic, TRUE);
4226 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4227 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4234 D(emitcode ("; genPointerSetOfs",""));
4235 aopOp (IC_LEFT(ic), ic, FALSE);
4236 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4237 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4239 aopOp (IC_RIGHT(ic), ic, FALSE);
4240 aopOp (IC_RIGHT(lic), lic, FALSE);
4243 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4244 size = AOP_SIZE (IC_RIGHT(lic));
4245 derefaop->size = size;
4250 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
4251 emitcode ("sta", "%s,x",
4252 aopAdrStr (derefaop, offset, TRUE));
4253 hc08_freeReg (hc08_reg_a);
4258 hc08_freeReg (hc08_reg_hx);
4260 freeAsmop (NULL, derefaop, ic, TRUE);
4261 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4262 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4271 /*-----------------------------------------------------------------*/
4272 /* hasInc - operand is incremented before any other use */
4273 /*-----------------------------------------------------------------*/
4275 hasInc (operand *op, iCode *ic,int osize)
4277 sym_link *type = operandType(op);
4278 sym_link *retype = getSpec (type);
4279 iCode *lic = ic->next;
4282 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4283 if (!IS_SYMOP(op)) return NULL;
4285 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4286 if (IS_AGGREGATE(type->next)) return NULL;
4287 if (osize != (isize = getSize(type->next))) return NULL;
4290 /* if operand of the form op = op + <sizeof *op> */
4291 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4292 isOperandEqual(IC_RESULT(lic),op) &&
4293 isOperandLiteral(IC_RIGHT(lic)) &&
4294 operandLitValue(IC_RIGHT(lic)) == isize) {
4297 /* if the operand used or deffed */
4298 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4301 /* if GOTO or IFX */
4302 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4308 /*-----------------------------------------------------------------*/
4309 /* genAndOp - for && operation */
4310 /*-----------------------------------------------------------------*/
4312 genAndOp (iCode * ic)
4314 operand *left, *right, *result;
4315 symbol *tlbl, *tlbl0;
4317 D(emitcode ("; genAndOp",""));
4319 /* note here that && operations that are in an
4320 if statement are taken away by backPatchLabels
4321 only those used in arthmetic operations remain */
4322 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4323 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4324 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4326 tlbl = newiTempLabel (NULL);
4327 tlbl0 = newiTempLabel (NULL);
4329 asmopToBool (AOP (left), FALSE);
4330 emitBranch ("beq", tlbl0);
4331 asmopToBool (AOP (right), FALSE);
4332 emitBranch ("beq", tlbl0);
4333 loadRegFromConst (hc08_reg_a,one);
4334 emitBranch ("bra", tlbl);
4336 loadRegFromConst (hc08_reg_a,zero);
4339 hc08_useReg (hc08_reg_a);
4340 hc08_freeReg (hc08_reg_a);
4342 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4344 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4345 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4346 freeAsmop (result, NULL, ic, TRUE);
4350 /*-----------------------------------------------------------------*/
4351 /* genOrOp - for || operation */
4352 /*-----------------------------------------------------------------*/
4354 genOrOp (iCode * ic)
4356 operand *left, *right, *result;
4357 symbol *tlbl, *tlbl0;
4359 D(emitcode ("; genOrOp",""));
4361 /* note here that || operations that are in an
4362 if statement are taken away by backPatchLabels
4363 only those used in arthmetic operations remain */
4364 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4365 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4366 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4368 tlbl = newiTempLabel (NULL);
4369 tlbl0 = newiTempLabel (NULL);
4371 asmopToBool (AOP (left), FALSE);
4372 emitBranch ("bne", tlbl0);
4373 asmopToBool (AOP (right), FALSE);
4374 emitBranch ("bne", tlbl0);
4375 loadRegFromConst (hc08_reg_a,zero);
4376 emitBranch ("bra", tlbl);
4378 loadRegFromConst (hc08_reg_a,one);
4381 hc08_useReg (hc08_reg_a);
4382 hc08_freeReg (hc08_reg_a);
4384 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4387 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4388 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4389 freeAsmop (result, NULL, ic, TRUE);
4392 /*-----------------------------------------------------------------*/
4393 /* isLiteralBit - test if lit == 2^n */
4394 /*-----------------------------------------------------------------*/
4396 isLiteralBit (unsigned long lit)
4398 unsigned long pw[32] =
4399 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4400 0x100L, 0x200L, 0x400L, 0x800L,
4401 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4402 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4403 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4404 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4405 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4408 for (idx = 0; idx < 32; idx++)
4415 /*-----------------------------------------------------------------*/
4416 /* continueIfTrue - */
4417 /*-----------------------------------------------------------------*/
4419 continueIfTrue (iCode * ic)
4422 emitBranch ("jmp", IC_TRUE (ic));
4426 /*-----------------------------------------------------------------*/
4428 /*-----------------------------------------------------------------*/
4430 jumpIfTrue (iCode * ic)
4433 emitBranch ("jmp", IC_FALSE (ic));
4437 /*-----------------------------------------------------------------*/
4438 /* jmpTrueOrFalse - */
4439 /*-----------------------------------------------------------------*/
4441 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4443 // ugly but optimized by peephole
4446 symbol *nlbl = newiTempLabel (NULL);
4447 emitBranch ("bra", nlbl);
4449 emitBranch ("jmp", IC_TRUE (ic));
4454 emitBranch ("jmp", IC_FALSE (ic));
4461 /*-----------------------------------------------------------------*/
4462 /* genAnd - code for and */
4463 /*-----------------------------------------------------------------*/
4465 genAnd (iCode * ic, iCode * ifx)
4467 operand *left, *right, *result;
4468 int size, offset = 0;
4469 unsigned long lit = 0L;
4470 unsigned long litinv;
4476 D(emitcode ("; genAnd",""));
4478 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4479 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4480 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4483 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4485 AOP_TYPE (left), AOP_TYPE (right));
4486 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4488 AOP_SIZE (left), AOP_SIZE (right));
4491 /* if left is a literal & right is not then exchange them */
4492 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4494 operand *tmp = right;
4499 /* if left is accumulator & right is not then exchange them */
4500 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4502 operand *tmp = right;
4507 size = AOP_SIZE (result);
4509 if (AOP_TYPE (right) == AOP_LIT)
4511 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4512 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4514 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4515 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4517 int bitpos = isLiteralBit(litinv)-1;
4518 emitcode ("bclr","#%d,%s",bitpos & 7,
4519 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4527 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4528 if ((AOP_TYPE (right) != AOP_LIT)
4529 || (((lit >> (offset*8)) & 0xff) != 0xff))
4530 accopWithAop ("and", AOP (right), offset);
4531 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4532 hc08_freeReg( hc08_reg_a);
4536 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4537 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4538 freeAsmop (result, NULL, ic, TRUE);
4541 /*-----------------------------------------------------------------*/
4542 /* genOr - code for or */
4543 /*-----------------------------------------------------------------*/
4545 genOr (iCode * ic, iCode * ifx)
4547 operand *left, *right, *result;
4548 int size, offset = 0;
4549 unsigned long lit = 0L;
4551 D(emitcode ("; genOr",""));
4553 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4554 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4555 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4558 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4560 AOP_TYPE (left), AOP_TYPE (right));
4561 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4563 AOP_SIZE (left), AOP_SIZE (right));
4566 /* if left is a literal & right is not then exchange them */
4567 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4569 operand *tmp = right;
4574 /* if left is accumulator & right is not then exchange them */
4575 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4577 operand *tmp = right;
4582 /* if right is bit then exchange them */
4583 if (AOP_TYPE (right) == AOP_CRY &&
4584 AOP_TYPE (left) != AOP_CRY)
4586 operand *tmp = right;
4590 if (AOP_TYPE (right) == AOP_LIT)
4591 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4593 size = AOP_SIZE (result);
4595 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4596 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
4597 (AOP_TYPE (left) == AOP_DIR))
4599 int bitpos = isLiteralBit(lit)-1;
4600 emitcode ("bset","#%d,%s",bitpos & 7,
4601 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4610 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4611 accopWithAop ("ora", AOP (right), offset);
4612 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4613 hc08_freeReg( hc08_reg_a);
4618 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4619 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4620 freeAsmop (result, NULL, ic, TRUE);
4623 /*-----------------------------------------------------------------*/
4624 /* genXor - code for xclusive or */
4625 /*-----------------------------------------------------------------*/
4627 genXor (iCode * ic, iCode * ifx)
4629 operand *left, *right, *result;
4630 int size, offset = 0;
4631 unsigned long lit = 0L;
4633 D(emitcode ("; genXor",""));
4635 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4636 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4637 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4640 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4642 AOP_TYPE (left), AOP_TYPE (right));
4643 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4645 AOP_SIZE (left), AOP_SIZE (right));
4648 /* if left is a literal & right is not ||
4649 if left needs acc & right does not */
4650 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4652 operand *tmp = right;
4657 /* if left is accumulator & right is not then exchange them */
4658 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4660 operand *tmp = right;
4665 /* if right is bit then exchange them */
4666 if (AOP_TYPE (right) == AOP_CRY &&
4667 AOP_TYPE (left) != AOP_CRY)
4669 operand *tmp = right;
4673 if (AOP_TYPE (right) == AOP_LIT)
4674 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4676 size = AOP_SIZE (result);
4680 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4681 accopWithAop ("eor", AOP (right), offset);
4682 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4683 hc08_freeReg( hc08_reg_a);
4688 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4689 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4690 freeAsmop (result, NULL, ic, TRUE);
4694 emitinline (iCode * ic, char *inlin)
4700 symbol *sym, *tempsym;
4709 while (isalnum(*inlin) || (*inlin == '_'))
4713 //printf("Found possible symbol '%s'\n",symname);
4714 tempsym = newSymbol (symname, ic->level);
4715 tempsym->block = ic->block;
4716 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
4725 aop = aopForSym (ic, sym, FALSE);
4726 l = aopAdrStr (aop, aop->size - 1, TRUE);
4730 if (!sym->allocreq && !sym->ismyparm)
4732 werror (E_ID_UNDEF, sym->name);
4734 " Add 'volatile' to the variable declaration so that it\n"
4735 " can be referenced within inline assembly");
4737 //printf("Replacing with '%s'\n",l);
4741 if ((2+bp-buffer)>sizeof(buffer))
4750 if ((2+bp-buffer)>sizeof(buffer))
4757 if ((2+bp-buffer)>sizeof(buffer))
4758 fprintf(stderr, "Inline assembly buffer overflow\n");
4760 //printf("%s\n",buffer);
4761 emitcode (buffer,"");
4765 /*-----------------------------------------------------------------*/
4766 /* genInline - write the inline code out */
4767 /*-----------------------------------------------------------------*/
4769 genInline (iCode * ic)
4771 char *buffer, *bp, *bp1;
4773 D(emitcode ("; genInline",""));
4775 _G.inLine += (!options.asmpeep);
4777 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4778 strcpy (buffer, IC_INLINE (ic));
4780 /* emit each line as a code */
4786 /* emitcode (bp1, ""); */
4787 emitinline (ic, bp1);
4806 /* emitcode (bp1, ""); */
4807 emitinline (ic, bp1);
4809 /* emitcode("",buffer); */
4810 _G.inLine -= (!options.asmpeep);
4813 /*-----------------------------------------------------------------*/
4814 /* genRRC - rotate right with carry */
4815 /*-----------------------------------------------------------------*/
4819 operand *left, *result;
4820 int size, offset = 0;
4821 bool needpula = FALSE;
4822 bool resultInA = FALSE;
4825 D(emitcode ("; genRRC",""));
4827 /* rotate right with carry */
4828 left = IC_LEFT (ic);
4829 result = IC_RESULT (ic);
4830 aopOp (left, ic, FALSE);
4831 aopOp (result, ic, FALSE);
4833 if ((AOP_TYPE (result) == AOP_REG)
4834 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4837 size = AOP_SIZE (result);
4841 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4845 rmwWithAop (shift, AOP (result), offset--);
4853 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4854 rmwWithReg (shift, hc08_reg_a);
4855 storeRegToAop (hc08_reg_a, AOP (result), offset--);
4856 hc08_freeReg (hc08_reg_a);
4861 if ((!hc08_reg_a->isFree) || resultInA)
4863 pushReg (hc08_reg_a, TRUE);
4867 /* now we need to put the carry into the
4868 highest order byte of the result */
4869 offset = AOP_SIZE (result) - 1;
4870 emitcode ("clra","");
4871 emitcode ("rora","");
4872 hc08_dirtyReg (hc08_reg_a, FALSE);
4875 emitcode ("ora", "1,s");
4876 emitcode ("ais", "#1");
4877 hc08_dirtyReg (hc08_reg_a, FALSE);
4881 accopWithAop ("ora", AOP (result), offset);
4882 storeRegToAop (hc08_reg_a, AOP (result), offset);
4884 pullOrFreeReg (hc08_reg_a, needpula);
4886 freeAsmop (left, NULL, ic, TRUE);
4887 freeAsmop (result, NULL, ic, TRUE);
4890 /*-----------------------------------------------------------------*/
4891 /* genRLC - generate code for rotate left with carry */
4892 /*-----------------------------------------------------------------*/
4896 operand *left, *result;
4897 int size, offset = 0;
4899 bool resultInA = FALSE;
4900 bool needpula = FALSE;
4902 D(emitcode ("; genRLC",""));
4904 /* rotate right with carry */
4905 left = IC_LEFT (ic);
4906 result = IC_RESULT (ic);
4907 aopOp (left, ic, FALSE);
4908 aopOp (result, ic, FALSE);
4910 if ((AOP_TYPE (result) == AOP_REG)
4911 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4914 size = AOP_SIZE (result);
4918 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4922 rmwWithAop (shift, AOP (result), offset--);
4930 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4931 rmwWithReg (shift, hc08_reg_a);
4932 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4933 hc08_freeReg (hc08_reg_a);
4938 if ((!hc08_reg_a->isFree) || resultInA)
4940 pushReg (hc08_reg_a, TRUE);
4944 /* now we need to put the carry into the
4945 lowest order byte of the result */
4947 emitcode ("clra","");
4948 emitcode ("rola","");
4949 hc08_dirtyReg (hc08_reg_a, FALSE);
4952 emitcode ("ora", "1,s");
4953 emitcode ("ais", "#1");
4954 hc08_dirtyReg (hc08_reg_a, FALSE);
4958 accopWithAop ("ora", AOP (result), offset);
4959 storeRegToAop (hc08_reg_a, AOP (result), offset);
4961 pullOrFreeReg (hc08_reg_a, needpula);
4963 freeAsmop (left, NULL, ic, TRUE);
4964 freeAsmop (result, NULL, ic, TRUE);
4967 /*-----------------------------------------------------------------*/
4968 /* genGetHbit - generates code get highest order bit */
4969 /*-----------------------------------------------------------------*/
4971 genGetHbit (iCode * ic)
4973 operand *left, *result;
4975 D(emitcode ("; genGetHbit",""));
4977 left = IC_LEFT (ic);
4978 result = IC_RESULT (ic);
4979 aopOp (left, ic, FALSE);
4980 aopOp (result, ic, FALSE);
4982 /* get the highest order byte into a */
4983 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
4984 emitcode ("rola", "");
4985 emitcode ("clra", "");
4986 emitcode ("rola", "");
4987 hc08_dirtyReg (hc08_reg_a, FALSE);
4988 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4989 hc08_freeReg (hc08_reg_a);
4991 freeAsmop (left, NULL, ic, TRUE);
4992 freeAsmop (result, NULL, ic, TRUE);
4995 /*-----------------------------------------------------------------*/
4996 /* genSwap - generates code to swap nibbles or bytes */
4997 /*-----------------------------------------------------------------*/
4999 genSwap (iCode * ic)
5001 operand *left, *result;
5003 D(emitcode ("; genSwap",""));
5005 left = IC_LEFT (ic);
5006 result = IC_RESULT (ic);
5007 aopOp (left, ic, FALSE);
5008 aopOp (result, ic, FALSE);
5010 switch (AOP_SIZE (left))
5012 case 1: /* swap nibbles in byte */
5013 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5014 emitcode ("nsa", "");
5015 hc08_dirtyReg (hc08_reg_a, FALSE);
5016 storeRegToAop (hc08_reg_a, AOP (result), 0);
5017 hc08_freeReg (hc08_reg_a);
5019 case 2: /* swap bytes in a word */
5020 if (operandsEqu (left, result))
5022 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5023 hc08_useReg (hc08_reg_a);
5024 transferAopAop (AOP (left), 1, AOP (result), 0);
5025 storeRegToAop (hc08_reg_a, AOP (result), 1);
5026 hc08_freeReg (hc08_reg_a);
5030 transferAopAop (AOP (left), 0, AOP (result), 1);
5031 transferAopAop (AOP (left), 1, AOP (result), 0);
5035 wassertl(FALSE, "unsupported SWAP operand size");
5038 freeAsmop (left, NULL, ic, TRUE);
5039 freeAsmop (result, NULL, ic, TRUE);
5043 /*-----------------------------------------------------------------*/
5044 /* AccRol - rotate left accumulator by known count */
5045 /*-----------------------------------------------------------------*/
5047 AccRol (int shCount)
5049 shCount &= 0x0007; // shCount : 0..7
5056 emitcode ("rola", ""); /* 1 cycle */
5059 emitcode ("rola", ""); /* 1 cycle */
5060 emitcode ("rola", ""); /* 1 cycle */
5063 emitcode ("nsa", "");
5064 emitcode ("rora", "");
5067 emitcode ("nsa", ""); /* 3 cycles */
5070 emitcode ("nsa", ""); /* 3 cycles */
5071 emitcode ("rola", ""); /* 1 cycle */
5074 emitcode ("nsa", ""); /* 3 cycles */
5075 emitcode ("rola", ""); /* 1 cycle */
5076 emitcode ("rola", ""); /* 1 cycle */
5079 emitcode ("nsa", ""); /* 3 cycles */
5080 emitcode ("rola", ""); /* 1 cycle */
5081 emitcode ("rola", ""); /* 1 cycle */
5082 emitcode ("rola", ""); /* 1 cycle */
5089 /*-----------------------------------------------------------------*/
5090 /* AccLsh - left shift accumulator by known count */
5091 /*-----------------------------------------------------------------*/
5093 AccLsh (int shCount)
5097 shCount &= 0x0007; // shCount : 0..7
5099 /* Shift counts of 4 and 5 are currently optimized for code size. */
5100 /* Falling through to the unrolled loop would be optimal for code speed. */
5101 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5105 accopWithMisc ("nsa", "");
5106 accopWithMisc ("and", "#0xf0");
5107 /* total: 5 cycles, 3 bytes */
5110 accopWithMisc ("nsa", "");
5111 accopWithMisc ("and", "#0xf0");
5112 accopWithMisc ("lsla", "");
5113 /* total: 6 cycles, 4 bytes */
5116 accopWithMisc ("rora", "");
5117 accopWithMisc ("rora", "");
5118 accopWithMisc ("rora", "");
5119 accopWithMisc ("and", "#0xc0");
5120 /* total: 5 cycles, 5 bytes */
5123 accopWithMisc ("rora", "");
5124 accopWithMisc ("clra", "");
5125 accopWithMisc ("rora", "");
5126 /* total: 3 cycles, 3 bytes */
5130 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5131 /* the fastest (shCount<6) and shortest (shCount<4). */
5132 for (i=0;i<shCount;i++)
5133 accopWithMisc ("lsla", "");
5137 /*-----------------------------------------------------------------*/
5138 /* AccSRsh - signed right shift accumulator by known count */
5139 /*-----------------------------------------------------------------*/
5141 AccSRsh (int shCount)
5145 shCount &= 0x0007; // shCount : 0..7
5149 accopWithMisc ("rola", "");
5150 accopWithMisc ("clra", "");
5151 accopWithMisc ("sbc", zero);
5152 /* total: 4 cycles, 4 bytes */
5156 for (i=0;i<shCount;i++)
5157 accopWithMisc ("asra", "");
5160 /*-----------------------------------------------------------------*/
5161 /* AccRsh - right shift accumulator by known count */
5162 /*-----------------------------------------------------------------*/
5164 AccRsh (int shCount, bool sign)
5174 shCount &= 0x0007; // shCount : 0..7
5176 /* Shift counts of 4 and 5 are currently optimized for code size. */
5177 /* Falling through to the unrolled loop would be optimal for code speed. */
5178 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5182 accopWithMisc ("nsa", "");
5183 accopWithMisc ("and", "#0x0f");
5184 /* total: 5 cycles, 3 bytes */
5187 accopWithMisc ("nsa", "");
5188 accopWithMisc ("and", "#0x0f");
5189 accopWithMisc ("lsra", "");
5190 /* total: 6 cycles, 4 bytes */
5193 accopWithMisc ("rola", "");
5194 accopWithMisc ("rola", "");
5195 accopWithMisc ("rola", "");
5196 accopWithMisc ("and", "#0x03");
5197 /* total: 5 cycles, 5 bytes */
5200 accopWithMisc ("rola", "");
5201 accopWithMisc ("clra", "");
5202 accopWithMisc ("rola", "");
5203 /* total: 3 cycles, 3 bytes */
5207 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5208 /* the fastest (shCount<6) and shortest (shCount<4). */
5209 for (i=0;i<shCount;i++)
5210 accopWithMisc ("lsra", "");
5214 /*-----------------------------------------------------------------*/
5215 /* XAccLsh - left shift register pair XA by known count */
5216 /*-----------------------------------------------------------------*/
5218 XAccLsh (int shCount)
5222 shCount &= 0x000f; // shCount : 0..15
5227 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5228 loadRegFromConst (hc08_reg_a, zero);
5232 /* if we can beat 2n cycles or bytes for some special case, do it here */
5236 /* bytes cycles reg x reg a carry
5237 ** abcd efgh ijkl mnop ?
5238 ** lsrx 1 1 0abc defg ijkl mnop h
5239 ** rora 1 1 0abc defg hijk lmno p
5240 ** tax 1 1 hijk lmno hijk lmno p
5241 ** clra 1 1 hijk lmno 0000 0000 p
5242 ** rora 1 1 hijk lmno p000 0000 0
5243 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5245 rmwWithReg ("lsr", hc08_reg_x);
5246 rmwWithReg ("ror", hc08_reg_a);
5247 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5248 loadRegFromConst (hc08_reg_a, zero);
5249 rmwWithReg ("ror", hc08_reg_a);
5256 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5257 /* the fastest and shortest. */
5258 for (i=0;i<shCount;i++)
5260 rmwWithReg ("lsl", hc08_reg_a);
5261 rmwWithReg ("rol", hc08_reg_x);
5265 /*-----------------------------------------------------------------*/
5266 /* XAccSRsh - signed right shift register pair XA by known count */
5267 /*-----------------------------------------------------------------*/
5269 XAccSRsh (int shCount)
5273 shCount &= 0x000f; // shCount : 0..7
5275 /* if we can beat 2n cycles or bytes for some special case, do it here */
5279 /* bytes cycles reg x reg a carry
5280 ** abcd efgh ijkl mnop ?
5281 ** lslx 1 1 bcde fgh0 ijkl mnop a
5282 ** clra 1 1 bcde fgh0 0000 0000 a
5283 ** rola 1 1 bcde fgh0 0000 000a 0
5284 ** nega 1 1 bcde fgh0 aaaa aaaa a
5285 ** tax 1 1 aaaa aaaa aaaa aaaa a
5286 ** total: 5 cycles, 5 bytes
5288 rmwWithReg ("lsl", hc08_reg_x);
5289 loadRegFromConst (hc08_reg_a, zero);
5290 rmwWithReg ("rol", hc08_reg_a);
5291 rmwWithReg ("neg", hc08_reg_a);
5292 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5302 /* bytes cycles reg x reg a carry
5303 ** abcd efgh ijkl mnop ?
5304 ** txa 1 1 abcd efgh abcd efgh ?
5305 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5306 ** lsla 1 1 abcd efgh ???? ???? a
5307 ** clrx 1 1 0000 0000 ???? ???? a
5308 ** rolx 1 1 0000 000a ???? ???? 0
5309 ** negx 1 1 aaaa aaaa ???? ???? a
5310 ** rora 1 1 aaaa aaaa LSBresult 0
5311 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5313 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5314 AccSRsh (shCount-8);
5315 rmwWithReg ("lsl", hc08_reg_a);
5316 loadRegFromConst (hc08_reg_x, zero);
5317 rmwWithReg ("rol", hc08_reg_x);
5318 rmwWithReg ("neg", hc08_reg_x);
5319 rmwWithReg ("ror", hc08_reg_a);
5326 /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5327 /* the fastest and shortest. */
5328 for (i=0;i<shCount;i++)
5330 rmwWithReg ("asr", hc08_reg_x);
5331 rmwWithReg ("ror", hc08_reg_a);
5335 /*-----------------------------------------------------------------*/
5336 /* XAccRsh - right shift register pair XA by known count */
5337 /*-----------------------------------------------------------------*/
5339 XAccRsh (int shCount, bool sign)
5349 shCount &= 0x000f; // shCount : 0..f
5351 /* if we can beat 2n cycles or bytes for some special case, do it here */
5355 /* bytes cycles reg x reg a carry
5356 ** abcd efgh ijkl mnop ?
5357 ** clra 1 1 abcd efgh 0000 0000 a
5358 ** lslx 1 1 bcde fgh0 0000 0000 a
5359 ** rola 1 1 bcde fgh0 0000 000a 0
5360 ** clrx 1 1 0000 0000 0000 000a 0
5361 ** total: 4 cycles, 4 bytes
5363 loadRegFromConst (hc08_reg_x, zero);
5364 rmwWithReg ("lsl", hc08_reg_x);
5365 rmwWithReg ("rol", hc08_reg_a);
5366 loadRegFromConst (hc08_reg_a, zero);
5370 /* bytes cycles reg x reg a carry
5371 ** abcd efgh ijkl mnop ?
5372 ** clra 1 1 abcd efgh 0000 0000 a
5373 ** lslx 1 1 bcde fgh0 0000 0000 a
5374 ** rola 1 1 bcde fgh0 0000 000a 0
5375 ** lslx 1 1 cdef gh00 0000 000a b
5376 ** rola 1 1 cdef gh00 0000 00ab 0
5377 ** clrx 1 1 0000 0000 0000 00ab 0
5378 ** total: 6 cycles, 6 bytes
5380 loadRegFromConst (hc08_reg_x, zero);
5381 rmwWithReg ("lsl", hc08_reg_x);
5382 rmwWithReg ("rol", hc08_reg_a);
5383 rmwWithReg ("lsl", hc08_reg_x);
5384 rmwWithReg ("rol", hc08_reg_a);
5385 loadRegFromConst (hc08_reg_a, zero);
5394 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5395 AccRsh (shCount-8, FALSE);
5396 loadRegFromConst (hc08_reg_x, zero);
5400 /* bytes cycles reg x reg a carry
5401 ** abcd efgh ijkl mnop ?
5402 ** lsla 1 1 abcd efgh jklm nop0 i
5403 ** txa 1 1 abcd efgh abcd efgh i
5404 ** rola 1 1 abcd efgh bcde fghi a
5405 ** clrx 1 1 0000 0000 bcde fghi a
5406 ** rolx 1 1 0000 000a bcde fghi 0
5407 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5409 rmwWithReg ("lsl", hc08_reg_a);
5410 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5411 rmwWithReg ("rol", hc08_reg_a);
5412 loadRegFromConst (hc08_reg_x, zero);
5413 rmwWithReg ("rol", hc08_reg_x);
5416 /* bytes cycles reg x reg a carry
5417 ** abcd efgh ijkl mnop ?
5418 ** lsla 1 1 abcd efgh jklm nop0 i
5419 ** rolx 1 1 bcde fghi jklm nop0 a
5420 ** rola 1 1 bcde fghi klmn op0a j
5421 ** rolx 1 1 cdef ghij klmn op0a b
5422 ** rola 1 1 cdef ghij lmno p0ab k
5423 ** and #3 2 2 cdef ghij 0000 00ab k
5424 ** psha 1 2 cdef ghij 0000 00ab k
5425 ** txa 1 1 cdef ghij cdef ghij k
5426 ** pula 1 2 0000 00ab cdef ghij k
5427 ** total: 12 cycles, 10 bytes (beats 12 bytes)
5433 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5434 /* the fastest and shortest. */
5435 for (i=0;i<shCount;i++)
5437 rmwWithReg ("lsr", hc08_reg_x);
5438 rmwWithReg ("ror", hc08_reg_a);
5445 /*-----------------------------------------------------------------*/
5446 /* shiftR1Left2Result - shift right one byte from left to result */
5447 /*-----------------------------------------------------------------*/
5449 shiftR1Left2Result (operand * left, int offl,
5450 operand * result, int offr,
5451 int shCount, int sign)
5453 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5454 /* shift right accumulator */
5455 AccRsh (shCount, sign);
5456 storeRegToAop (hc08_reg_a, AOP (result), offr);
5460 /*-----------------------------------------------------------------*/
5461 /* shiftL1Left2Result - shift left one byte from left to result */
5462 /*-----------------------------------------------------------------*/
5464 shiftL1Left2Result (operand * left, int offl,
5465 operand * result, int offr, int shCount)
5467 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5468 /* shift left accumulator */
5470 storeRegToAop (hc08_reg_a, AOP (result), offr);
5473 /*-----------------------------------------------------------------*/
5474 /* movLeft2Result - move byte from left to result */
5475 /*-----------------------------------------------------------------*/
5477 movLeft2Result (operand * left, int offl,
5478 operand * result, int offr, int sign)
5480 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5482 transferAopAop (AOP (left), offl, AOP (result), offr);
5487 /*-----------------------------------------------------------------*/
5488 /* shiftL2Left2Result - shift left two bytes from left to result */
5489 /*-----------------------------------------------------------------*/
5491 shiftL2Left2Result (operand * left, int offl,
5492 operand * result, int offr, int shCount)
5495 bool needpula = FALSE;
5496 bool needpulx = FALSE;
5498 needpula = pushRegIfUsed (hc08_reg_a);
5499 needpulx = pushRegIfUsed (hc08_reg_x);
5501 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5506 rmwWithReg ("lsr", hc08_reg_x);
5507 rmwWithReg ("ror", hc08_reg_a);
5508 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5509 rmwWithReg ("clr", hc08_reg_a);
5510 rmwWithReg ("ror", hc08_reg_a);
5513 for (i=0; i<shCount; i++)
5515 rmwWithReg ("lsl", hc08_reg_a);
5516 rmwWithReg ("rol", hc08_reg_x);
5519 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5521 pullOrFreeReg (hc08_reg_x, needpulx);
5522 pullOrFreeReg (hc08_reg_a, needpula);
5528 /*-----------------------------------------------------------------*/
5529 /* shiftR2Left2Result - shift right two bytes from left to result */
5530 /*-----------------------------------------------------------------*/
5532 shiftR2Left2Result (operand * left, int offl,
5533 operand * result, int offr,
5534 int shCount, int sign)
5537 bool needpula = FALSE;
5538 bool needpulx = FALSE;
5540 needpula = pushRegIfUsed (hc08_reg_a);
5541 needpulx = pushRegIfUsed (hc08_reg_x);
5543 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5544 for (i=0; i<shCount; i++)
5547 rmwWithReg ("asr", hc08_reg_x);
5549 rmwWithReg ("lsr", hc08_reg_x);
5550 rmwWithReg ("ror", hc08_reg_a);
5552 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5554 pullOrFreeReg (hc08_reg_x, needpulx);
5555 pullOrFreeReg (hc08_reg_a, needpula);
5560 /*-----------------------------------------------------------------*/
5561 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5562 /*-----------------------------------------------------------------*/
5564 shiftLLeftOrResult (operand * left, int offl,
5565 operand * result, int offr, int shCount)
5567 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5568 /* shift left accumulator */
5570 /* or with result */
5571 accopWithAop ("ora", AOP (result), offr);
5572 /* back to result */
5573 storeRegToAop (hc08_reg_a, AOP (result), offr);
5574 hc08_freeReg (hc08_reg_a);
5578 /*-----------------------------------------------------------------*/
5579 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5580 /*-----------------------------------------------------------------*/
5582 shiftRLeftOrResult (operand * left, int offl,
5583 operand * result, int offr, int shCount)
5585 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5586 /* shift left accumulator */
5587 AccRsh (shCount, FALSE);
5588 /* or with result */
5589 accopWithAop ("ora", AOP (result), offr);
5590 /* back to result */
5591 storeRegToAop (hc08_reg_a, AOP (result), offr);
5592 hc08_freeReg (hc08_reg_a);
5595 /*-----------------------------------------------------------------*/
5596 /* genlshOne - left shift a one byte quantity by known count */
5597 /*-----------------------------------------------------------------*/
5599 genlshOne (operand * result, operand * left, int shCount)
5601 D(emitcode ("; genlshOne",""));
5603 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5606 /*-----------------------------------------------------------------*/
5607 /* genlshTwo - left shift two bytes by known amount != 0 */
5608 /*-----------------------------------------------------------------*/
5610 genlshTwo (operand * result, operand * left, int shCount)
5614 D(emitcode ("; genlshTwo",""));
5617 size = getDataSize (result);
5619 /* if shCount >= 8 */
5626 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5628 storeRegToAop (hc08_reg_a, AOP (result), 1);
5630 storeConstToAop(zero, AOP (result), LSB);
5633 /* 1 <= shCount <= 7 */
5636 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5638 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
5642 /*-----------------------------------------------------------------*/
5643 /* shiftLLong - shift left one long from left to result */
5644 /* offl = LSB or MSB16 */
5645 /*-----------------------------------------------------------------*/
5647 shiftLLong (operand * left, operand * result, int offr)
5650 // int size = AOP_SIZE (result);
5652 bool needpula = FALSE;
5653 bool needpulx = FALSE;
5655 needpula = pushRegIfUsed (hc08_reg_a);
5656 needpulx = pushRegIfUsed (hc08_reg_x);
5658 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
5659 rmwWithReg ("lsl", hc08_reg_a);
5660 rmwWithReg ("rol", hc08_reg_x);
5661 storeRegToAop (hc08_reg_xa, AOP (result), offr);
5665 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5666 rmwWithReg ("rol", hc08_reg_a);
5667 rmwWithReg ("rol", hc08_reg_x);
5668 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
5670 else if (offr==MSB16)
5672 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
5673 rmwWithReg ("rol", hc08_reg_a);
5674 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
5677 pullOrFreeReg (hc08_reg_x, needpulx);
5678 pullOrFreeReg (hc08_reg_a, needpula);
5681 /*-----------------------------------------------------------------*/
5682 /* genlshFour - shift four byte by a known amount != 0 */
5683 /*-----------------------------------------------------------------*/
5685 genlshFour (operand * result, operand * left, int shCount)
5689 D(emitcode ("; genlshFour",""));
5691 size = AOP_SIZE (result);
5693 /* TODO: deal with the &result == &left case */
5695 /* if shifting more that 3 bytes */
5700 /* lowest order of left goes to the highest
5701 order of the destination */
5702 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5704 movLeft2Result (left, LSB, result, MSB32, 0);
5705 storeConstToAop (zero, AOP (result), LSB);
5706 storeConstToAop (zero, AOP (result), MSB16);
5707 storeConstToAop (zero, AOP (result), MSB24);
5711 /* more than two bytes */
5712 else if (shCount >= 16)
5714 /* lower order two bytes goes to higher order two bytes */
5716 /* if some more remaining */
5718 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5721 movLeft2Result (left, MSB16, result, MSB32, 0);
5722 movLeft2Result (left, LSB, result, MSB24, 0);
5724 storeConstToAop (zero, AOP (result), LSB);
5725 storeConstToAop (zero, AOP (result), MSB16);
5729 /* if more than 1 byte */
5730 else if (shCount >= 8)
5732 /* lower order three bytes goes to higher order three bytes */
5737 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5739 movLeft2Result (left, LSB, result, MSB16, 0);
5745 movLeft2Result (left, MSB24, result, MSB32, 0);
5746 movLeft2Result (left, MSB16, result, MSB24, 0);
5747 movLeft2Result (left, LSB, result, MSB16, 0);
5748 storeConstToAop (zero, AOP (result), LSB);
5750 else if (shCount == 1)
5751 shiftLLong (left, result, MSB16);
5754 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5755 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5756 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5757 storeConstToAop (zero, AOP (result), LSB);
5762 /* 1 <= shCount <= 7 */
5763 else if (shCount <= 2)
5765 shiftLLong (left, result, LSB);
5767 shiftLLong (result, result, LSB);
5769 /* 3 <= shCount <= 7, optimize */
5772 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5773 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5774 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5778 /*-----------------------------------------------------------------*/
5779 /* genLeftShiftLiteral - left shifting by known count */
5780 /*-----------------------------------------------------------------*/
5782 genLeftShiftLiteral (operand * left,
5787 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5790 D(emitcode ("; genLeftShiftLiteral",""));
5792 freeAsmop (right, NULL, ic, TRUE);
5794 aopOp (left, ic, FALSE);
5795 aopOp (result, ic, FALSE);
5797 // size = getSize (operandType (result));
5798 size = AOP_SIZE (result);
5801 emitcode ("; shift left ", "result %d, left %d", size,
5808 transferAopAop( AOP(left), size, AOP(result), size);
5810 else if (shCount >= (size * 8))
5813 storeConstToAop (zero, AOP (result), size);
5820 genlshOne (result, left, shCount);
5824 genlshTwo (result, left, shCount);
5828 genlshFour (result, left, shCount);
5831 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5832 "*** ack! mystery literal shift!\n");
5836 freeAsmop (left, NULL, ic, TRUE);
5837 freeAsmop (result, NULL, ic, TRUE);
5840 /*-----------------------------------------------------------------*/
5841 /* genLeftShift - generates code for left shifting */
5842 /*-----------------------------------------------------------------*/
5844 genLeftShift (iCode * ic)
5846 operand *left, *right, *result;
5848 symbol *tlbl, *tlbl1;
5853 D(emitcode ("; genLeftShift",""));
5855 right = IC_RIGHT (ic);
5856 left = IC_LEFT (ic);
5857 result = IC_RESULT (ic);
5859 aopOp (right, ic, FALSE);
5861 /* if the shift count is known then do it
5862 as efficiently as possible */
5863 if (AOP_TYPE (right) == AOP_LIT)
5865 genLeftShiftLiteral (left, right, result, ic);
5869 /* shift count is unknown then we have to form
5870 a loop get the loop count in A : Note: we take
5871 only the lower order byte since shifting
5872 more that 32 bits make no sense anyway, ( the
5873 largest size of an object can be only 32 bits ) */
5875 aopOp (left, ic, FALSE);
5876 aopOp (result, ic, FALSE);
5878 /* now move the left to the result if they are not the
5880 if (!sameRegs (AOP (left), AOP (result)))
5883 size = AOP_SIZE (result);
5887 transferAopAop (AOP (left), offset, AOP (result), offset);
5891 freeAsmop (left, NULL, ic, TRUE);
5893 tlbl = newiTempLabel (NULL);
5894 size = AOP_SIZE (result);
5896 tlbl1 = newiTempLabel (NULL);
5900 loadRegFromAop (reg, AOP (right), 0);
5901 freeAsmop (right, NULL, ic, TRUE);
5902 emitBranch ("beq", tlbl1);
5906 for (offset=0;offset<size;offset++)
5908 rmwWithAop (shift, AOP (result), offset);
5911 rmwWithReg ("dec", reg);
5912 emitBranch ("bne", tlbl);
5916 freeAsmop (result, NULL, ic, TRUE);
5919 /*-----------------------------------------------------------------*/
5920 /* genrshOne - right shift a one byte quantity by known count */
5921 /*-----------------------------------------------------------------*/
5923 genrshOne (operand * result, operand * left,
5924 int shCount, int sign)
5926 D(emitcode ("; genrshOne",""));
5928 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5929 AccRsh (shCount, sign);
5930 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5933 /*-----------------------------------------------------------------*/
5934 /* genrshTwo - right shift two bytes by known amount != 0 */
5935 /*-----------------------------------------------------------------*/
5937 genrshTwo (operand * result, operand * left,
5938 int shCount, int sign)
5940 D(emitcode ("; genrshTwo",""));
5942 /* if shCount >= 8 */
5945 if (shCount || sign)
5947 loadRegFromAop (hc08_reg_a, AOP (left), 1);
5948 AccRsh (shCount-8, sign);
5949 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5953 transferAopAop (AOP (left), 1, AOP (result), 0);
5954 storeConstToAop (zero, AOP (result), 1);
5958 /* 1 <= shCount <= 7 */
5961 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5962 XAccRsh (shCount, sign);
5963 storeRegToAop (hc08_reg_xa, AOP (result), 0);
5967 /*-----------------------------------------------------------------*/
5968 /* shiftRLong - shift right one long from left to result */
5969 /* offl = LSB or MSB16 */
5970 /*-----------------------------------------------------------------*/
5972 shiftRLong (operand * left, int offl,
5973 operand * result, int sign)
5976 // int size = AOP_SIZE (result);
5978 bool needpula = FALSE;
5979 bool needpulx = FALSE;
5981 needpula = pushRegIfUsed (hc08_reg_a);
5982 needpulx = pushRegIfUsed (hc08_reg_x);
5986 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5988 rmwWithReg ("asr", hc08_reg_x);
5990 rmwWithReg ("lsr", hc08_reg_x);
5991 rmwWithReg ("rol", hc08_reg_a);
5992 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
5994 else if (offl==MSB16)
5996 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
5998 rmwWithReg ("asr", hc08_reg_a);
6000 rmwWithReg ("lsr", hc08_reg_a);
6001 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6004 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6005 rmwWithReg ("ror", hc08_reg_x);
6006 rmwWithReg ("ror", hc08_reg_a);
6007 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6010 pullOrFreeReg (hc08_reg_x, needpulx);
6011 pullOrFreeReg (hc08_reg_a, needpula);
6014 /*-----------------------------------------------------------------*/
6015 /* genrshFour - shift four byte by a known amount != 0 */
6016 /*-----------------------------------------------------------------*/
6018 genrshFour (operand * result, operand * left,
6019 int shCount, int sign)
6021 /* TODO: handle cases where left == result */
6023 D(emitcode ("; genrshFour",""));
6025 /* if shifting more that 3 bytes */
6028 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6029 AccRsh (shCount-24, sign);
6030 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6033 else if (shCount >= 16)
6035 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6036 XAccRsh (shCount-16, sign);
6037 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6040 else if (shCount >= 8)
6043 shiftRLong (left, MSB16, result, sign);
6044 else if (shCount == 8)
6046 transferAopAop (AOP (left), 1, AOP (result), 0);
6047 transferAopAop (AOP (left), 2, AOP (result), 1);
6048 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6049 storeRegToAop (hc08_reg_a, AOP (result), 2);
6050 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6052 else if (shCount == 9)
6054 shiftRLong (left, MSB16, result, sign);
6058 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6059 XAccRsh (shCount-8, FALSE);
6060 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6061 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6062 loadRegFromConst (hc08_reg_a, zero);
6063 XAccRsh (shCount-8, sign);
6064 accopWithAop ("ora", AOP (result), 1);
6065 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6069 { /* 1 <= shCount <= 7 */
6072 shiftRLong (left, LSB, result, sign);
6076 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6077 XAccRsh (shCount, FALSE);
6078 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6079 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6081 accopWithAop ("ora", AOP (result), 1);
6082 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6083 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6084 XAccRsh (shCount, sign);
6085 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6090 /*-----------------------------------------------------------------*/
6091 /* genRightShiftLiteral - right shifting by known count */
6092 /*-----------------------------------------------------------------*/
6094 genRightShiftLiteral (operand * left,
6100 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6103 D(emitcode ("; genRightShiftLiteral",""));
6105 freeAsmop (right, NULL, ic, TRUE);
6107 aopOp (left, ic, FALSE);
6108 aopOp (result, ic, FALSE);
6111 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6115 size = getDataSize (left);
6116 /* test the LEFT size !!! */
6118 /* I suppose that the left size >= result size */
6121 size = getDataSize (result);
6123 transferAopAop (AOP (left), size, AOP(result), size);
6125 else if (shCount >= (size * 8))
6128 /* get sign in acc.7 */
6129 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6131 addSign (result, LSB, sign);
6138 genrshOne (result, left, shCount, sign);
6142 genrshTwo (result, left, shCount, sign);
6146 genrshFour (result, left, shCount, sign);
6152 freeAsmop (left, NULL, ic, TRUE);
6153 freeAsmop (result, NULL, ic, TRUE);
6157 /*-----------------------------------------------------------------*/
6158 /* genRightShift - generate code for right shifting */
6159 /*-----------------------------------------------------------------*/
6161 genRightShift (iCode * ic)
6163 operand *right, *left, *result;
6167 symbol *tlbl, *tlbl1;
6171 D(emitcode ("; genRightShift",""));
6173 /* if signed then we do it the hard way preserve the
6174 sign bit moving it inwards */
6175 retype = getSpec (operandType (IC_RESULT (ic)));
6176 sign = !SPEC_USIGN (retype);
6178 /* signed & unsigned types are treated the same : i.e. the
6179 signed is NOT propagated inwards : quoting from the
6180 ANSI - standard : "for E1 >> E2, is equivalent to division
6181 by 2**E2 if unsigned or if it has a non-negative value,
6182 otherwise the result is implementation defined ", MY definition
6183 is that the sign does not get propagated */
6185 right = IC_RIGHT (ic);
6186 left = IC_LEFT (ic);
6187 result = IC_RESULT (ic);
6189 aopOp (right, ic, FALSE);
6191 /* if the shift count is known then do it
6192 as efficiently as possible */
6193 if (AOP_TYPE (right) == AOP_LIT)
6195 genRightShiftLiteral (left, right, result, ic, sign);
6199 /* shift count is unknown then we have to form
6200 a loop get the loop count in X : Note: we take
6201 only the lower order byte since shifting
6202 more that 32 bits make no sense anyway, ( the
6203 largest size of an object can be only 32 bits ) */
6205 aopOp (left, ic, FALSE);
6206 aopOp (result, ic, FALSE);
6208 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6209 AOP (result) = forceStackedAop (AOP (result));
6211 size = AOP_SIZE (result);
6215 transferAopAop (AOP (left), offset, AOP (result), offset);
6219 tlbl = newiTempLabel (NULL);
6220 size = AOP_SIZE (result);
6222 tlbl1 = newiTempLabel (NULL);
6224 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6225 emitcode ("tstx", "");
6226 emitcode ("beq", "%05d$", tlbl1->key + 100);
6227 emitcode ("", "%05d$:", tlbl->key + 100);
6228 shift= sign ? "asr" : "lsr";
6229 for (offset=size-1;offset>=0;offset--)
6231 rmwWithAop (shift, AOP (result), offset);
6234 rmwWithReg ("dec", hc08_reg_x);
6235 emitcode ("bne","%05d$", tlbl->key + 100);
6236 emitcode ("", "%05d$:", tlbl1->key + 100);
6238 freeAsmop (result, NULL, ic, TRUE);
6239 freeAsmop (left, NULL, ic, TRUE);
6240 freeAsmop (right, NULL, ic, TRUE);
6243 /*-----------------------------------------------------------------*/
6244 /* genUnpackBits - generates code for unpacking bits */
6245 /*-----------------------------------------------------------------*/
6247 genUnpackBits (operand * result)
6249 int offset = 0; /* result byte offset */
6250 int rsize; /* result size */
6251 int rlen = 0; /* remaining bitfield length */
6252 sym_link *etype; /* bitfield type information */
6253 int blen; /* bitfield length */
6254 int bstr; /* bitfield starting bit within byte */
6256 D(emitcode ("; genUnpackBits",""));
6258 etype = getSpec (operandType (result));
6259 rsize = getSize (operandType (result));
6260 blen = SPEC_BLEN (etype);
6261 bstr = SPEC_BSTR (etype);
6263 /* If the bitfield length is less than a byte */
6266 emitcode ("lda", ",x");
6267 hc08_dirtyReg (hc08_reg_a, FALSE);
6268 AccRsh (bstr, FALSE);
6269 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6270 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6274 /* Bit field did not fit in a byte. Copy all
6275 but the partial byte at the end. */
6276 for (rlen=blen;rlen>=8;rlen-=8)
6278 emitcode ("lda", ",x");
6279 hc08_dirtyReg (hc08_reg_a, FALSE);
6280 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6282 emitcode ("aix", "#1");
6285 /* Handle the partial byte at the end */
6288 emitcode ("lda", ",x");
6289 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6290 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6298 storeConstToAop (zero, AOP (result), offset++);
6303 /*-----------------------------------------------------------------*/
6304 /* genDataPointerGet - generates code when ptr offset is known */
6305 /*-----------------------------------------------------------------*/
6307 genDataPointerGet (operand * left,
6311 int size, offset = 0;
6314 D(emitcode ("; genDataPointerGet",""));
6316 aopOp (result, ic, TRUE);
6317 size = AOP_SIZE (result);
6319 derefaop = aopDerefAop (AOP (left));
6320 freeAsmop (left, NULL, ic, TRUE);
6321 derefaop->size = size;
6325 transferAopAop(derefaop, offset, AOP (result), offset);
6329 freeAsmop (NULL, derefaop, ic, TRUE);
6330 freeAsmop (result, NULL, ic, TRUE);
6334 /*-----------------------------------------------------------------*/
6335 /* genNearPointerGet - emitcode for near pointer fetch */
6336 /*-----------------------------------------------------------------*/
6338 genNearPointerGet (operand * left,
6344 sym_link *retype = getSpec (operandType (result));
6346 D(emitcode ("; genNearPointerGet",""));
6348 aopOp (left, ic, FALSE);
6350 /* if left is rematerialisable and
6351 result is not bit variable type and
6352 the left is pointer to data space i.e
6353 lower 128 bytes of space */
6354 if ((AOP_TYPE (left) == AOP_IMMD)
6355 || (AOP_TYPE (left) == AOP_LIT)
6356 /* !IS_BITVAR (retype) */
6357 /* && DCL_TYPE (ltype) == POINTER */ )
6359 genDataPointerGet (left, result, ic);
6363 /* if the operand is already in hx
6364 then we do nothing else we move the value to hx */
6365 if (AOP_TYPE (left) != AOP_STR)
6367 /* if this is remateriazable */
6368 loadRegFromAop (hc08_reg_x, AOP (left), 0);
6369 loadRegFromConst (hc08_reg_h, zero);
6372 /* so hx now contains the address */
6373 aopOp (result, ic, FALSE);
6375 /* if bit then unpack */
6376 if (IS_BITVAR (retype))
6377 genUnpackBits (result);
6380 size = AOP_SIZE (result);
6385 accopWithMisc ("lda", ",x");
6388 rmwWithReg ("inc", hc08_reg_x);
6390 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6391 hc08_freeReg (hc08_reg_a);
6395 freeAsmop (left, NULL, ic, TRUE);
6396 freeAsmop (result, NULL, ic, TRUE);
6398 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6399 aopOp (IC_RESULT (pi), pi, FALSE);
6400 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6401 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6405 hc08_freeReg (hc08_reg_hx);
6409 /*-----------------------------------------------------------------*/
6410 /* genFarPointerGet - get value from far space */
6411 /*-----------------------------------------------------------------*/
6413 genFarPointerGet (operand * left,
6414 operand * result, iCode * ic, iCode * pi)
6417 sym_link *retype = getSpec (operandType (result));
6419 D(emitcode ("; genFarPointerGet",""));
6421 aopOp (left, ic, FALSE);
6423 /* if left is rematerialisable and
6424 result is not bit variable type and
6425 the left is pointer to data space i.e
6426 lower 128 bytes of space */
6427 if (AOP_TYPE (left) == AOP_IMMD &&
6429 /* && DCL_TYPE (ltype) == POINTER */ )
6431 genDataPointerGet (left, result, ic);
6435 /* if the operand is already in hx
6436 then we do nothing else we move the value to hx */
6437 if (AOP_TYPE (left) != AOP_STR)
6439 /* if this is remateriazable */
6440 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
6443 /* so hx now contains the address */
6444 aopOp (result, ic, FALSE);
6446 /* if bit then unpack */
6447 if (IS_BITVAR (retype))
6448 genUnpackBits (result);
6451 size = AOP_SIZE (result);
6456 accopWithMisc ("lda", ",x");
6459 emitcode ("aix", "#1");
6460 hc08_dirtyReg (hc08_reg_hx, FALSE);
6462 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6463 hc08_freeReg (hc08_reg_a);
6467 freeAsmop (left, NULL, ic, TRUE);
6468 freeAsmop (result, NULL, ic, TRUE);
6470 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6471 aopOp (IC_RESULT (pi), pi, FALSE);
6472 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6473 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6477 hc08_freeReg (hc08_reg_hx);
6483 /*-----------------------------------------------------------------*/
6484 /* genPointerGet - generate code for pointer get */
6485 /*-----------------------------------------------------------------*/
6487 genPointerGet (iCode * ic, iCode *pi)
6489 operand *left, *result;
6490 sym_link *type, *etype;
6493 D(emitcode ("; genPointerGet",""));
6495 left = IC_LEFT (ic);
6496 result = IC_RESULT (ic);
6498 /* depending on the type of pointer we need to
6499 move it to the correct pointer register */
6500 type = operandType (left);
6501 etype = getSpec (type);
6502 /* if left is of type of pointer then it is simple */
6503 if (IS_PTR (type) && !IS_FUNC (type->next))
6504 p_type = DCL_TYPE (type);
6507 /* we have to go by the storage class */
6508 p_type = PTR_TYPE (SPEC_OCLS (etype));
6511 /* special case when cast remat */
6512 if (p_type == GPOINTER && IS_SYMOP(left) && OP_SYMBOL(left)->remat &&
6513 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
6514 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
6515 type = operandType (left);
6516 p_type = DCL_TYPE (type);
6518 /* now that we have the pointer type we assign
6519 the pointer values */
6526 genNearPointerGet (left, result, ic, pi);
6532 genFarPointerGet (left, result, ic, pi);
6539 /*-----------------------------------------------------------------*/
6540 /* genPackBits - generates code for packed bit storage */
6541 /*-----------------------------------------------------------------*/
6543 genPackBits (sym_link * etype,
6546 int offset = 0; /* source byte offset */
6547 int rlen = 0; /* remaining bitfield length */
6548 int blen; /* bitfield length */
6549 int bstr; /* bitfield starting bit within byte */
6550 int litval; /* source literal value (if AOP_LIT) */
6551 unsigned char mask; /* bitmask within current byte */
6553 D(emitcode ("; genPackBits",""));
6555 blen = SPEC_BLEN (etype);
6556 bstr = SPEC_BSTR (etype);
6558 /* If the bitfield length is less than a byte */
6561 mask = ((unsigned char) (0xFF << (blen + bstr)) |
6562 (unsigned char) (0xFF >> (8 - bstr)));
6564 if (AOP_TYPE (right) == AOP_LIT)
6566 /* Case with a bitfield length <8 and literal source
6568 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6570 litval &= (~mask) & 0xff;
6572 emitcode ("lda", ",x");
6573 if ((mask|litval)!=0xff)
6574 emitcode ("and","#0x%02x", mask);
6576 emitcode ("ora","#0x%02x", litval);
6577 hc08_dirtyReg (hc08_reg_a, FALSE);
6578 emitcode ("sta", ",x");
6580 hc08_freeReg (hc08_reg_a);
6584 /* Case with a bitfield length < 8 and arbitrary source
6586 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6587 /* shift and mask source value */
6589 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6590 hc08_dirtyReg (hc08_reg_a, FALSE);
6591 pushReg (hc08_reg_a, TRUE);
6593 emitcode ("lda", ",x");
6594 emitcode ("and", "#0x%02x", mask);
6595 emitcode ("ora", "1,s");
6596 emitcode ("sta", ",x");
6597 pullReg (hc08_reg_a);
6599 hc08_freeReg (hc08_reg_a);
6603 /* Bit length is greater than 7 bits. In this case, copy */
6604 /* all except the partial byte at the end */
6605 for (rlen=blen;rlen>=8;rlen-=8)
6607 if (AOP (right)->type == AOP_DIR)
6609 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
6613 loadRegFromAop (hc08_reg_a, AOP (right), offset);
6614 emitcode ("sta", "%d,x", offset);
6619 /* If there was a partial byte at the end */
6622 mask = (((unsigned char) -1 << rlen) & 0xff);
6624 if (AOP_TYPE (right) == AOP_LIT)
6626 /* Case with partial byte and literal source
6628 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6629 litval >>= (blen-rlen);
6630 litval &= (~mask) & 0xff;
6631 emitcode ("lda", "%d,x", offset);
6632 hc08_dirtyReg (hc08_reg_a, FALSE);
6633 if ((mask|litval)!=0xff)
6634 emitcode ("and","#0x%02x", mask);
6636 emitcode ("ora","#0x%02x", litval);
6637 emitcode ("sta", "%d,x", offset);
6638 hc08_dirtyReg (hc08_reg_a, FALSE);
6639 hc08_freeReg (hc08_reg_a);
6643 /* Case with partial byte and arbitrary source
6645 loadRegFromAop (hc08_reg_a, AOP (right), offset++);
6646 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6647 hc08_dirtyReg (hc08_reg_a, FALSE);
6648 pushReg (hc08_reg_a, TRUE);
6650 emitcode ("lda", ",x");
6651 emitcode ("and", "#0x%02x", mask);
6652 emitcode ("ora", "1,s");
6653 emitcode ("sta", ",x");
6654 pullReg (hc08_reg_a);
6657 hc08_freeReg (hc08_reg_a);
6660 /*-----------------------------------------------------------------*/
6661 /* genDataPointerSet - remat pointer to data space */
6662 /*-----------------------------------------------------------------*/
6664 genDataPointerSet (operand * right,
6668 int size, offset = 0;
6671 D(emitcode ("; genDataPointerSet",""));
6673 aopOp (right, ic, FALSE);
6674 size = AOP_SIZE (right);
6676 derefaop = aopDerefAop (AOP (result));
6677 freeAsmop (result, NULL, ic, TRUE);
6678 derefaop->size = size;
6682 transferAopAop (AOP (right), offset, derefaop, offset);
6686 freeAsmop (right, NULL, ic, TRUE);
6687 freeAsmop (NULL, derefaop, ic, TRUE);
6691 /*-----------------------------------------------------------------*/
6692 /* genNearPointerSet - emitcode for near pointer put */
6693 /*-----------------------------------------------------------------*/
6695 genNearPointerSet (operand * right,
6701 sym_link *retype = getSpec (operandType (right));
6702 sym_link *letype = getSpec (operandType (result));
6704 D(emitcode ("; genNearPointerSet",""));
6706 aopOp (result, ic, FALSE);
6708 /* if the result is rematerializable &
6709 in data space & not a bit variable */
6710 if (AOP_TYPE (result) == AOP_IMMD &&
6711 /* DCL_TYPE (ptype) == POINTER && */
6712 !IS_BITVAR (retype) &&
6713 !IS_BITVAR (letype))
6715 genDataPointerSet (right, result, ic);
6719 /* if the operand is already in hx
6720 then we do nothing else we move the value to hx */
6721 if (AOP_TYPE (result) != AOP_STR)
6723 loadRegFromAop (hc08_reg_x, AOP (result), 0);
6724 loadRegFromConst (hc08_reg_h, zero);
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 rmwWithReg ("inc", hc08_reg_x);
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_x, AOP (IC_RESULT (pi)), 0);
6755 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6759 hc08_freeReg (hc08_reg_hx);
6764 /*-----------------------------------------------------------------*/
6765 /* genFarPointerSet - set value from far space */
6766 /*-----------------------------------------------------------------*/
6768 genFarPointerSet (operand * right,
6769 operand * result, iCode * ic, iCode * pi)
6772 sym_link *retype = getSpec (operandType (right));
6773 sym_link *letype = getSpec (operandType (result));
6775 D(emitcode ("; genFarPointerSet",""));
6777 aopOp (result, ic, FALSE);
6779 /* if the result is rematerializable &
6780 in data space & not a bit variable */
6781 if (AOP_TYPE (result) == AOP_IMMD &&
6782 /* DCL_TYPE (ptype) == POINTER && */
6783 !IS_BITVAR (retype) &&
6784 !IS_BITVAR (letype))
6786 genDataPointerSet (right, result, ic);
6790 /* if the operand is already in hx
6791 then we do nothing else we move the value to hx */
6792 if (AOP_TYPE (result) != AOP_STR)
6794 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
6796 /* so hx now contains the address */
6797 aopOp (right, ic, FALSE);
6799 /* if bit then unpack */
6800 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6801 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6804 size = AOP_SIZE (right);
6809 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6810 accopWithMisc ("sta", ",x");
6813 emitcode ("aix", "#1");
6815 hc08_freeReg (hc08_reg_a);
6819 freeAsmop (result, NULL, ic, TRUE);
6820 freeAsmop (right, NULL, ic, TRUE);
6822 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6823 aopOp (IC_RESULT (pi), pi, FALSE);
6824 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6825 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6829 hc08_freeReg (hc08_reg_hx);
6835 /*-----------------------------------------------------------------*/
6836 /* genPointerSet - stores the value into a pointer location */
6837 /*-----------------------------------------------------------------*/
6839 genPointerSet (iCode * ic, iCode *pi)
6841 operand *right, *result;
6842 sym_link *type, *etype;
6845 D(emitcode ("; genPointerSet",""));
6847 right = IC_RIGHT (ic);
6848 result = IC_RESULT (ic);
6850 /* depending on the type of pointer we need to
6851 move it to the correct pointer register */
6852 type = operandType (result);
6853 etype = getSpec (type);
6854 /* if left is of type of pointer then it is simple */
6855 if (IS_PTR (type) && !IS_FUNC (type->next))
6857 p_type = DCL_TYPE (type);
6861 /* we have to go by the storage class */
6862 p_type = PTR_TYPE (SPEC_OCLS (etype));
6865 /* special case when cast remat */
6866 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
6867 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
6868 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
6869 type = operandType (result);
6870 p_type = DCL_TYPE (type);
6872 /* now that we have the pointer type we assign
6873 the pointer values */
6880 genNearPointerSet (right, result, ic, pi);
6886 genFarPointerSet (right, result, ic, pi);
6890 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6891 "genPointerSet: illegal pointer type");
6896 /*-----------------------------------------------------------------*/
6897 /* genIfx - generate code for Ifx statement */
6898 /*-----------------------------------------------------------------*/
6900 genIfx (iCode * ic, iCode * popIc)
6902 operand *cond = IC_COND (ic);
6905 D(emitcode ("; genIfx",""));
6907 aopOp (cond, ic, FALSE);
6909 /* get the value into acc */
6910 if (AOP_TYPE (cond) != AOP_CRY)
6911 asmopToBool (AOP (cond), FALSE);
6914 /* the result is now in the accumulator */
6915 freeAsmop (cond, NULL, ic, TRUE);
6917 /* if there was something to be popped then do it */
6921 /* if the condition is a bit variable */
6922 if (isbit && IS_ITEMP (cond) &&
6924 genIfxJump (ic, SPIL_LOC (cond)->rname);
6925 else if (isbit && !IS_ITEMP (cond))
6926 genIfxJump (ic, OP_SYMBOL (cond)->rname);
6928 genIfxJump (ic, "a");
6933 /*-----------------------------------------------------------------*/
6934 /* genAddrOf - generates code for address of */
6935 /*-----------------------------------------------------------------*/
6937 genAddrOf (iCode * ic)
6939 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
6942 D(emitcode ("; genAddrOf",""));
6944 aopOp (IC_RESULT (ic), ic, FALSE);
6946 /* if the operand is on the stack then we
6947 need to get the stack offset of this
6951 /* if it has an offset then we need to compute
6953 hc08_useReg (hc08_reg_hx);
6954 emitcode ("tsx", "");
6955 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
6956 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
6957 hc08_freeReg (hc08_reg_hx);
6962 /* object not on stack then we need the name */
6963 size = AOP_SIZE (IC_RESULT (ic));
6968 char s[SDCC_NAME_MAX+10];
6971 sprintf (s, "#%s", sym->rname);
6974 sprintf (s, "#>%s", sym->rname);
6977 sprintf (s, "#(%s >> %d)",
6981 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
6985 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
6989 /*-----------------------------------------------------------------*/
6990 /* genAssign - generate code for assignment */
6991 /*-----------------------------------------------------------------*/
6993 genAssign (iCode * ic)
6995 operand *result, *right;
6997 // unsigned long lit = 0L;
6999 D(emitcode("; genAssign",""));
7001 result = IC_RESULT (ic);
7002 right = IC_RIGHT (ic);
7004 /* if they are the same */
7005 if (operandsEqu (result, right)) {
7009 aopOp (right, ic, FALSE);
7010 aopOp (result, ic, TRUE);
7012 /* if they are the same registers */
7013 if (sameRegs (AOP (right), AOP (result)))
7016 if ((AOP_TYPE (right) == AOP_LIT)
7017 && (IS_AOP_HX(AOP(result))))
7019 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7024 size = AOP_SIZE (result);
7029 transferAopAop (AOP (right), offset, AOP (result), offset);
7034 freeAsmop (right, NULL, ic, TRUE);
7035 freeAsmop (result, NULL, ic, TRUE);
7038 /*-----------------------------------------------------------------*/
7039 /* genJumpTab - genrates code for jump table */
7040 /*-----------------------------------------------------------------*/
7042 genJumpTab (iCode * ic)
7047 D(emitcode ("; genJumpTab",""));
7049 aopOp (IC_JTCOND (ic), ic, FALSE);
7050 /* get the condition into accumulator */
7051 loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7052 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7053 /* multiply by three */
7054 pushReg (hc08_reg_a, FALSE);
7055 emitcode ("lsla", "");
7056 emitcode ("add","1,s");
7057 transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7058 loadRegFromConst (hc08_reg_h, zero);
7060 jtab = newiTempLabel (NULL);
7061 emitcode ("jmp", "%05d$,x", jtab->key + 100);
7062 emitcode ("", "%05d$:", jtab->key + 100);
7063 /* now generate the jump labels */
7064 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7065 jtab = setNextItem (IC_JTLABELS (ic)))
7066 emitcode ("jmp", "%05d$", jtab->key + 100);
7068 hc08_dirtyReg (hc08_reg_a, TRUE);
7069 hc08_dirtyReg (hc08_reg_hx, TRUE);
7072 /*-----------------------------------------------------------------*/
7073 /* genCast - gen code for casting */
7074 /*-----------------------------------------------------------------*/
7076 genCast (iCode * ic)
7078 operand *result = IC_RESULT (ic);
7079 sym_link *ctype = operandType (IC_LEFT (ic));
7080 sym_link *rtype = operandType (IC_RIGHT (ic));
7081 operand *right = IC_RIGHT (ic);
7084 D(emitcode("; genCast",""));
7086 /* if they are equivalent then do nothing */
7087 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7090 aopOp (right, ic, FALSE);
7091 aopOp (result, ic, FALSE);
7094 /* if they are the same size : or less */
7095 if (AOP_SIZE (result) <= AOP_SIZE (right))
7098 /* if they are in the same place */
7100 if (sameRegs (AOP (right), AOP (result)))
7104 /* if they in different places then copy */
7105 size = AOP_SIZE (result);
7109 transferAopAop(AOP (right), offset, AOP (result), offset);
7116 /* if the result is of type pointer */
7121 sym_link *type = operandType (right);
7122 sym_link *etype = getSpec (type);
7124 /* pointer to generic pointer */
7125 if (IS_GENPTR (ctype))
7128 p_type = DCL_TYPE (type);
7131 if (SPEC_SCLS(etype)==S_REGISTER) {
7132 // let's assume it is a generic pointer
7135 /* we have to go by the storage class */
7136 p_type = PTR_TYPE (SPEC_OCLS (etype));
7140 /* the first two bytes are known */
7141 size = GPTRSIZE - 1;
7145 transferAopAop(AOP (right), offset, AOP (result), offset);
7148 /* the last byte depending on type */
7151 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7156 // pointerTypeToGPByte will have bitched.
7160 sprintf(gpValStr, "#0x%d", gpVal);
7161 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7167 /* just copy the pointers */
7168 size = AOP_SIZE (result);
7172 transferAopAop(AOP (right), offset, AOP (result), offset);
7178 /* so we now know that the size of destination is greater
7179 than the size of the source */
7180 /* we move to result for the size of source */
7181 size = AOP_SIZE (right);
7185 transferAopAop(AOP (right), offset, AOP (result), offset);
7189 /* now depending on the sign of the source && destination */
7190 size = AOP_SIZE (result) - AOP_SIZE (right);
7191 /* if unsigned or not an integral type */
7192 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7195 storeConstToAop (zero, AOP (result), offset++);
7199 /* we need to extend the sign :{ */
7200 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7201 accopWithMisc ("rola", "");
7202 accopWithMisc ("clra", "");
7203 accopWithMisc ("sbc", zero);
7205 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7208 /* we are done hurray !!!! */
7211 freeAsmop (right, NULL, ic, TRUE);
7212 freeAsmop (result, NULL, ic, TRUE);
7216 /*-----------------------------------------------------------------*/
7217 /* genDjnz - generate decrement & jump if not zero instrucion */
7218 /*-----------------------------------------------------------------*/
7220 genDjnz (iCode * ic, iCode * ifx)
7226 D(emitcode ("; genDjnz",""));
7228 /* if the if condition has a false label
7229 then we cannot save */
7233 /* if the minus is not of the form
7235 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7236 !IS_OP_LITERAL (IC_RIGHT (ic)))
7239 if (operandLitValue (IC_RIGHT (ic)) != 1)
7242 /* dbnz doesn't support extended mode */
7243 if (isOperandInFarSpace (IC_RESULT (ic)))
7246 /* if the size of this greater than one then no
7248 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7250 aopOp (IC_RESULT (ic), ic, FALSE);
7251 if (AOP_SIZE (IC_RESULT (ic))>1)
7253 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7257 /* otherwise we can save BIG */
7258 lbl = newiTempLabel (NULL);
7259 lbl1 = newiTempLabel (NULL);
7262 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7265 emitBranch ("bra", lbl1);
7267 emitBranch ("jmp", IC_TRUE (ifx));
7270 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7275 /*-----------------------------------------------------------------*/
7276 /* genReceive - generate code for a receive iCode */
7277 /*-----------------------------------------------------------------*/
7279 genReceive (iCode * ic)
7283 D(emitcode ("; genReceive",""));
7285 aopOp (IC_RESULT (ic), ic, FALSE);
7286 size = AOP_SIZE (IC_RESULT (ic));
7291 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7292 AOP (IC_RESULT (ic)), offset);
7293 if (hc08_aop_pass[offset]->type == AOP_REG)
7294 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7299 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7302 /*-----------------------------------------------------------------*/
7303 /* genDummyRead - generate code for dummy read of volatiles */
7304 /*-----------------------------------------------------------------*/
7306 genDummyRead (iCode * ic)
7311 D(emitcode("; genDummyRead",""));
7314 if (op && IS_SYMOP (op))
7317 aopOp (op, ic, FALSE);
7319 size = AOP_SIZE (op);
7324 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7325 hc08_freeReg (hc08_reg_a);
7329 freeAsmop (op, NULL, ic, TRUE);
7332 if (op && IS_SYMOP (op))
7335 aopOp (op, ic, FALSE);
7337 size = AOP_SIZE (op);
7342 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7343 hc08_freeReg (hc08_reg_a);
7347 freeAsmop (op, NULL, ic, TRUE);
7351 /*-----------------------------------------------------------------*/
7352 /* genCritical - generate code for start of a critical sequence */
7353 /*-----------------------------------------------------------------*/
7355 genCritical (iCode *ic)
7357 D(emitcode("; genCritical",""));
7360 aopOp (IC_RESULT (ic), ic, TRUE);
7362 emitcode ("tpa", "");
7363 hc08_dirtyReg (hc08_reg_a, FALSE);
7364 emitcode ("sei", "");
7367 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7369 pushReg (hc08_reg_a, FALSE);
7371 hc08_freeReg (hc08_reg_a);
7373 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7376 /*-----------------------------------------------------------------*/
7377 /* genEndCritical - generate code for end of a critical sequence */
7378 /*-----------------------------------------------------------------*/
7380 genEndCritical (iCode *ic)
7382 D(emitcode("; genEndCritical",""));
7386 aopOp (IC_RIGHT (ic), ic, FALSE);
7387 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
7388 emitcode ("tap", "");
7389 hc08_freeReg (hc08_reg_a);
7390 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
7394 pullReg (hc08_reg_a);
7395 emitcode ("tap", "");
7400 /*-----------------------------------------------------------------*/
7401 /* genhc08Code - generate code for HC08 based controllers */
7402 /*-----------------------------------------------------------------*/
7404 genhc08Code (iCode * lic)
7409 lineHead = lineCurr = NULL;
7411 /* print the allocation information */
7412 if (allocInfo && currFunc)
7413 printAllocInfo (currFunc, codeOutFile);
7414 /* if debug information required */
7415 if (options.debug && currFunc)
7417 debugFile->writeFunction(currFunc);
7419 if (IS_STATIC (currFunc->etype))
7420 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7422 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7425 /* stack pointer name */
7426 if (options.useXstack)
7431 hc08_aop_pass[0] = newAsmop (AOP_REG);
7432 hc08_aop_pass[0]->size=1;
7433 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7434 hc08_aop_pass[1] = newAsmop (AOP_REG);
7435 hc08_aop_pass[1]->size=1;
7436 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
7437 hc08_aop_pass[2] = newAsmop (AOP_DIR);
7438 hc08_aop_pass[2]->size=1;
7439 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
7440 hc08_aop_pass[3] = newAsmop (AOP_DIR);
7441 hc08_aop_pass[3]->size=1;
7442 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
7444 for (ic = lic; ic; ic = ic->next)
7447 if (ic->lineno && cln != ic->lineno)
7452 emitcode ("", "C$%s$%d$%d$%d ==.",
7453 FileBaseName (ic->filename), ic->lineno,
7454 ic->level, ic->block);
7457 if (!options.noCcodeInAsm) {
7458 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
7459 printCLine(ic->filename, ic->lineno));
7463 if (options.iCodeInAsm) {
7467 for (i=0; i<6; i++) {
7468 sprintf (®sInUse[i],
7469 "%c", ic->riu & (1<<i) ? i+'0' : '-');
7472 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
7474 /* if the result is marked as
7475 spilt and rematerializable or code for
7476 this has already been generated then
7478 if (resultRemat (ic) || ic->generated)
7486 for (i=A_IDX;i<=XA_IDX;i++)
7488 reg = hc08_regWithIdx(i);
7490 emitcode("","; %s = %s offset %d", reg->name,
7491 aopName(reg->aop), reg->aopofs);
7494 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
7496 sym = OP_SYMBOL (IC_LEFT (ic));
7497 if (sym->accuse == ACCUSE_HX)
7499 hc08_reg_h->isFree = FALSE;
7500 hc08_reg_x->isFree = FALSE;
7502 else if (sym->accuse == ACCUSE_XA)
7504 hc08_reg_a->isFree = FALSE;
7506 hc08_reg_x->isFree = FALSE;
7509 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
7511 sym = OP_SYMBOL (IC_RIGHT (ic));
7512 if (sym->accuse == ACCUSE_HX)
7514 hc08_reg_h->isFree = FALSE;
7515 hc08_reg_x->isFree = FALSE;
7517 else if (sym->accuse == ACCUSE_XA)
7519 hc08_reg_a->isFree = FALSE;
7521 hc08_reg_x->isFree = FALSE;
7526 /* depending on the operation */
7546 /* IPOP happens only when trying to restore a
7547 spilt live range, if there is an ifx statement
7548 following this pop then the if statement might
7549 be using some of the registers being popped which
7550 would destory the contents of the register so
7551 we need to check for this condition and handle it */
7553 ic->next->op == IFX &&
7554 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7555 genIfx (ic->next, ic);
7573 genEndFunction (ic);
7589 if (!genPointerGetSetOfs (ic))
7594 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7611 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7615 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7622 /* note these two are xlated by algebraic equivalence
7623 during parsing SDCC.y */
7624 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7625 "got '>=' or '<=' shouldn't have come here");
7629 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7641 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7645 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7649 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7676 case GET_VALUE_AT_ADDRESS:
7677 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
7681 if (POINTER_SET (ic))
7682 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
7708 addSet (&_G.sendSet, ic);
7711 case DUMMY_READ_VOLATILE:
7720 genEndCritical (ic);
7731 if (!hc08_reg_a->isFree)
7732 emitcode("","; forgot to free a");
7733 if (!hc08_reg_x->isFree)
7734 emitcode("","; forgot to free x");
7735 if (!hc08_reg_h->isFree)
7736 emitcode("","; forgot to free h");
7737 if (!hc08_reg_hx->isFree)
7738 emitcode("","; forgot to free hx");
7739 if (!hc08_reg_xa->isFree)
7740 emitcode("","; forgot to free xa");
7744 /* now we are ready to call the
7745 peep hole optimizer */
7746 if (!options.nopeep)
7747 peepHole (&lineHead);
7749 /* now do the actual printing */
7750 printLine (lineHead, codeOutFile);