1 /* The only ops for now are:
9 /*-------------------------------------------------------------------------
10 SDCCgen51.c - source file for code generation for 8051
12 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
13 and - Jean-Louis VERN.jlvern@writeme.com (1999)
14 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
16 This program is free software; you can redistribute it and/or modify it
17 under the terms of the GNU General Public License as published by the
18 Free Software Foundation; either version 2, or (at your option) any
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 In other words, you are welcome to use, share and improve this program.
31 You are forbidden to forbid anyone else to use, share and improve
32 what you give them. Help stamp out software-hoarding!
35 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
36 Made everything static
37 -------------------------------------------------------------------------*/
46 #include "SDCCglobl.h"
49 #ifdef HAVE_SYS_ISA_DEFS_H
50 #include <sys/isa_defs.h>
52 #ifdef HAVE_MACHINE_ENDIAN_H
53 #include <machine/endian.h>
58 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
59 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
60 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
67 #include "SDCCpeeph.h"
71 #if defined(__BORLANDC__) || defined(_MSC_VER)
72 #define STRCASECMP stricmp
74 #define STRCASECMP strcasecmp
79 /* this is the down and dirty file with all kinds of
80 kludgy & hacky stuff. This is what it is all about
81 CODE GENERATION for a specific MCU . some of the
82 routines may be reusable, will have to see */
93 extern int xa51_ptrRegReq;
94 extern int xa51_nRegs;
95 extern FILE *codeOutFile;
97 static lineNode *lineHead = NULL;
98 static lineNode *lineCurr = NULL;
105 static char *MOVB="mov.b";
106 static char *MOVW="mov.w";
107 static char *MOVCB="movc.b";
108 static char *MOVCW="movc.w";
110 void bailOut (char *mesg) {
111 fprintf (stderr, "%s: bailing out\n", mesg);
115 /*-----------------------------------------------------------------*/
116 /* emitcode - writes the code into a file : for now it is simple */
117 /*-----------------------------------------------------------------*/
118 static void emitcode (char *inst, char *fmt,...) {
120 char lb[INITIAL_INLINEASM];
128 sprintf (lb, "%s\t", inst);
130 sprintf (lb, "%s", inst);
131 vsprintf (lb + (strlen (lb)), fmt, ap);
134 vsprintf (lb, fmt, ap);
136 while (isspace ((int)*lbp))
140 lineCurr = (lineCurr ?
141 connectLine (lineCurr, newLineNode (lb)) :
142 (lineHead = newLineNode (lb)));
143 lineCurr->isInline = _G.inLine;
144 lineCurr->isDebug = _G.debugLine;
148 char *getStackOffset(int stack) {
149 static char gsoBuf[1024];
150 // dit slaat natuurlijk nergens op
151 sprintf (gsoBuf, "r7+(%+d+0%+d%+d)", stack,
152 FUNC_ISISR(currFunc->type) ?
153 port->stack.isr_overhead : port->stack.call_overhead,
158 /*-----------------------------------------------------------------*/
159 /* newAsmop - creates a new asmOp */
160 /*-----------------------------------------------------------------*/
162 newAsmop (short type)
166 aop = Safe_calloc (1, sizeof (asmop));
171 char *aopTypeName(asmop *aop) {
174 case AOP_LIT: return "lit";
175 case AOP_REG: return "reg";
176 case AOP_DIR: return "dir";
177 case AOP_FAR: return "far";
178 case AOP_CODE: return "code";
179 case AOP_STK: return "stack";
180 case AOP_IMMD: return "imm";
181 case AOP_CRY: return "bit";
186 /*-----------------------------------------------------------------*/
187 /* aopForSym - for a true symbol */
188 /*-----------------------------------------------------------------*/
189 static asmop *aopForSym(symbol *sym, bool result) {
193 sym->aop = aop = newAsmop(0);
194 size=aop->size=getSize(sym->type);
196 // if the sym has registers
197 if (sym->nRegs && sym->regs[0]) {
199 sprintf (aop->name[0], sym->regs[0]->name);
201 sprintf (aop->name[1], sym->regs[1]->name);
209 sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
211 sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
216 // if it has a spillLoc
217 if (sym->usl.spillLoc) {
218 return aopForSym (sym->usl.spillLoc, result);
222 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
224 sprintf (aop->name[0], sym->rname);
228 // if in direct space
229 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
231 sprintf (aop->name[0], sym->rname);
233 sprintf (aop->name[0], "%s+2", sym->rname);
239 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
241 bailOut("aopForSym: result can not be in code space");
244 emitcode ("mov", "r0,#%s", sym->rname);
245 sprintf (aop->name[0], "[r0]");
247 sprintf (aop->name[1], "[r0+1]");
253 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
255 emitcode ("mov", "r0,#%s", sym->rname);
256 sprintf (aop->name[0], "[r0]");
258 sprintf (aop->name[1], "[r0+1]");
263 bailOut("aopForSym");
267 /*-----------------------------------------------------------------*/
268 /* aopForVal - for a value */
269 /*-----------------------------------------------------------------*/
270 static asmop *aopForVal(operand *op) {
272 long v=(long long)floatFromVal(OP_VALUE(op));
274 if (IS_OP_LITERAL(op)) {
275 op->aop = aop = newAsmop (AOP_LIT);
276 switch ((aop->size=getSize(operandType(op))))
279 sprintf (aop->name[0], "#0x%02lx", v);
282 sprintf (aop->name[0], "#0x%04lx", v);
285 sprintf (aop->name[0], "#(0x%08lx >> 16)", v);
286 sprintf (aop->name[1], "#(0x%08lx & 0xffff)", v);
289 bailOut("aopForVal");
296 op->aop = aop = newAsmop (AOP_IMMD);
297 switch ((aop->size=getSize(OP_SYMBOL(op)->type)))
301 sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
303 case 3: // generic pointer
304 sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
305 sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
309 bailOut ("aopForVal: unknown type");
313 static void aopOp(operand *op, bool result) {
316 op->aop=aopForSym (OP_SYMBOL(op), result);
321 bailOut("aopOp: result can not be a value");
327 bailOut("aopOp: unexpected operand");
330 char *opRegName(operand *op, int offset, char *opName) {
333 if (OP_SYMBOL(op)->onStack) {
334 sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
337 if (IS_TRUE_SYMOP(op))
338 return OP_SYMBOL(op)->rname;
339 else if (OP_SYMBOL(op)->regs[offset])
340 return OP_SYMBOL(op)->regs[offset]->name;
342 bailOut("opRegName: unknown regs");
346 switch (SPEC_NOUN(OP_VALUE(op)->type)) {
349 if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
350 SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
351 bailOut("opRegName: invalid bit value");
355 sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
358 if (SPEC_LONG(OP_VALUE(op)->type)) {
359 sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
361 sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
365 sprintf (opName, "#%f", SPEC_CVAL(OP_VALUE(op)->type).v_float);
368 bailOut("opRegName: unexpected noun");
372 bailOut("opRegName: unexpected operand type");
376 char * printOp (operand *op) {
377 static char line[132];
378 sym_link *optype=operandType(op);
379 bool isPtr = IS_PTR(optype);
382 symbol *sym=OP_SYMBOL(op);
383 if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
384 sym=SYM_SPIL_LOC(sym);
388 if (DCL_TYPE(optype)==FPOINTER)
389 strcat (line, "far * ");
390 else if (DCL_TYPE(optype)==CPOINTER)
391 strcat (line, "code * ");
392 else if (DCL_TYPE(optype)==GPOINTER)
393 strcat (line, "gen * ");
394 else if (DCL_TYPE(optype)==POINTER)
395 strcat (line, "near * ");
397 strcat (line, "unknown * ");
399 strcat (line, nounName(sym->etype));
401 strcat (line, sym->name);
404 sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
407 strcat (line, sym->regs[0]->name);
410 strcat (line, sym->regs[1]->name);
415 sprintf (line+strlen(line), "stack%+d", sym->stack);
418 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
419 strcat (line, "far");
422 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
423 strcat (line, "bit");
426 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
427 strcat (line, "dir");
430 strcat (line, "unknown");
432 } else if (IS_VALOP(op)) {
433 opRegName(op, 0, line);
434 } else if (IS_TYPOP(op)) {
437 if (DCL_TYPE(optype)==FPOINTER)
438 strcat (line, "far * ");
439 else if (DCL_TYPE(optype)==CPOINTER)
440 strcat (line, "code * ");
441 else if (DCL_TYPE(optype)==GPOINTER)
442 strcat (line, "gen * ");
443 else if (DCL_TYPE(optype)==POINTER)
444 strcat (line, "near * ");
446 strcat (line, "unknown * ");
448 // forget about static, volatile, ... for now
449 if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
450 if (SPEC_LONG(operandType(op))) strcat (line, "long ");
451 strcat (line, nounName(operandType(op)));
454 bailOut("printOp: unexpected operand type");
459 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
462 sprintf (line, "%s(%d)", op, ic->lineno);
464 strcat (line, " result=");
465 strcat (line, printOp (IC_RESULT(ic)));
468 strcat (line, " left=");
469 strcat (line, printOp (IC_LEFT(ic)));
472 strcat (line, " right=");
473 strcat (line, printOp (IC_RIGHT(ic)));
475 emitcode (";", line);
478 /*-----------------------------------------------------------------*/
479 /* toBoolean - return carry for operand!=0 */
480 /*-----------------------------------------------------------------*/
481 static char *toBoolean (operand * op) {
482 switch (AOP_SIZE(op))
486 emitcode ("cmp", "%s,#0", AOP_NAME(op));
487 emitcode ("mov", "c,z");
491 bailOut("toBoolean: unknown size");
495 /*-----------------------------------------------------------------*/
496 /* regsInCommon - two operands have some registers in common */
497 /*-----------------------------------------------------------------*/
498 static bool regsInCommon (operand * op1, operand * op2) {
502 /* if they have registers in common */
503 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
506 sym1 = OP_SYMBOL (op1);
507 sym2 = OP_SYMBOL (op2);
509 if (sym1->nRegs == 0 || sym2->nRegs == 0)
512 for (i = 0; i < sym1->nRegs; i++)
518 for (j = 0; j < sym2->nRegs; j++)
523 if (sym2->regs[j] == sym1->regs[i])
531 /*-----------------------------------------------------------------*/
532 /* resultRemat - result is rematerializable */
533 /*-----------------------------------------------------------------*/
534 static int resultRemat (iCode * ic) {
535 if (SKIP_IC (ic) || ic->op == IFX)
538 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
540 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
541 if (sym->remat && !POINTER_SET (ic))
548 /*-----------------------------------------------------------------*/
549 /* genNot - generate code for ! operation */
550 /*-----------------------------------------------------------------*/
551 static void genNot (iCode * ic) {
552 printIc("genNot:", ic, 1,1,0);
555 /*-----------------------------------------------------------------*/
556 /* genCpl - generate code for complement */
557 /*-----------------------------------------------------------------*/
558 static void genCpl (iCode * ic) {
559 printIc("genCpl", ic, 1,1,0);
562 /*-----------------------------------------------------------------*/
563 /* genUminus - unary minus code generation */
564 /*-----------------------------------------------------------------*/
565 static void genUminus (iCode * ic) {
566 printIc("genUminus", ic, 1,1,0);
569 /*-----------------------------------------------------------------*/
570 /* genIpush - genrate code for pushing this gets a little complex */
571 /*-----------------------------------------------------------------*/
572 static void genIpush (iCode * ic) {
573 printIc ("genIpush", ic, 0,1,0);
576 /*-----------------------------------------------------------------*/
577 /* genIpop - recover the registers: can happen only for spilling */
578 /*-----------------------------------------------------------------*/
579 static void genIpop (iCode * ic) {
580 printIc ("genIpop", ic, 0,1,0);
583 /*-----------------------------------------------------------------*/
584 /* genCall - generates a call statement */
585 /*-----------------------------------------------------------------*/
586 static void genCall (iCode * ic) {
587 emitcode (";", "genCall %s result=%s", OP_SYMBOL(IC_LEFT(ic))->name,
588 printOp (IC_RESULT(ic)));
591 /*-----------------------------------------------------------------*/
592 /* genPcall - generates a call by pointer statement */
593 /*-----------------------------------------------------------------*/
595 genPcall (iCode * ic)
597 emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
600 /*-----------------------------------------------------------------*/
601 /* genFunction - generated code for function entry */
602 /*-----------------------------------------------------------------*/
603 static void genFunction (iCode * ic) {
604 symbol *sym=OP_SYMBOL(IC_LEFT(ic));
605 sym_link *type=sym->type;
607 emitcode (";", "-----------------------------------------");
608 emitcode (";", " function %s", sym->name);
609 emitcode (";", "-----------------------------------------");
611 emitcode ("", "%s:", sym->rname);
613 if (IFFUNC_ISNAKED(type))
615 emitcode(";", "naked function: no prologue.");
619 /* if critical function then turn interrupts off */
620 if (IFFUNC_ISCRITICAL (type))
621 emitcode ("clr", "ea");
625 /*-----------------------------------------------------------------*/
626 /* genEndFunction - generates epilogue for functions */
627 /*-----------------------------------------------------------------*/
629 genEndFunction (iCode * ic)
631 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
633 if (IFFUNC_ISNAKED(sym->type))
635 emitcode(";", "naked function: no epilogue.");
639 printIc ("genEndFunction", ic, 0,0,0);
642 /*-----------------------------------------------------------------*/
643 /* genRet - generate code for return statement */
644 /*-----------------------------------------------------------------*/
645 static void genRet (iCode * ic) {
647 printIc ("genRet", ic, 0,1,0);
649 aopOp(IC_LEFT(ic),FALSE);
651 switch (AOP_SIZE(IC_LEFT(ic)))
654 emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
655 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
658 emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
661 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
664 emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
670 /*-----------------------------------------------------------------*/
671 /* genLabel - generates a label */
672 /*-----------------------------------------------------------------*/
673 static void genLabel (iCode * ic) {
674 /* special case never generate */
675 if (IC_LABEL (ic) == entryLabel)
678 emitcode (";", "genLabel %s", IC_LABEL(ic)->name);
679 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
682 /*-----------------------------------------------------------------*/
683 /* genGoto - generates a jmp */
684 /*-----------------------------------------------------------------*/
685 static void genGoto (iCode * ic) {
686 emitcode (";", "genGoto %s", IC_LABEL(ic)->name);
687 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
690 /*-----------------------------------------------------------------*/
691 /* genPlus - generates code for addition */
692 /*-----------------------------------------------------------------*/
693 static void genPlus (iCode * ic) {
694 printIc ("genPlus", ic, 1,1,1);
697 /*-----------------------------------------------------------------*/
698 /* genMinus - generates code for subtraction */
699 /*-----------------------------------------------------------------*/
700 static void genMinus (iCode * ic) {
701 printIc ("genMinus", ic, 1,1,1);
705 /*-----------------------------------------------------------------*/
706 /* genMult - generates code for multiplication */
707 /*-----------------------------------------------------------------*/
708 static void genMult (iCode * ic) {
709 printIc ("genMult", ic, 1,1,1);
712 /*-----------------------------------------------------------------*/
713 /* genDiv - generates code for division */
714 /*-----------------------------------------------------------------*/
715 static void genDiv (iCode * ic) {
716 printIc ("genDiv", ic, 1,1,1);
719 /*-----------------------------------------------------------------*/
720 /* genMod - generates code for division */
721 /*-----------------------------------------------------------------*/
722 static void genMod (iCode * ic) {
723 printIc ("genMod", ic, 1,1,1);
726 /*-----------------------------------------------------------------*/
727 /* genCmpGt :- greater than comparison */
728 /*-----------------------------------------------------------------*/
729 static void genCmpGt (iCode * ic) {
730 printIc ("genCmpGt", ic, 1,1,1);
732 /*-----------------------------------------------------------------*/
733 /* genCmpGt :- greater than comparison */
734 /*-----------------------------------------------------------------*/
735 static void genCmpLe (iCode * ic) {
736 printIc ("genCmpGt", ic, 1,1,1);
738 /*-----------------------------------------------------------------*/
739 /* genCmpGt :- greater than comparison */
740 /*-----------------------------------------------------------------*/
741 static void genCmpGe (iCode * ic) {
742 printIc ("genCmpGt", ic, 1,1,1);
744 /*-----------------------------------------------------------------*/
745 /* genCmpGt :- greater than comparison */
746 /*-----------------------------------------------------------------*/
747 static void genCmpNe (iCode * ic) {
748 printIc ("genCmpGt", ic, 1,1,1);
750 /*-----------------------------------------------------------------*/
751 /* genCmpLt - less than comparisons */
752 /*-----------------------------------------------------------------*/
753 static void genCmpLt (iCode * ic) {
754 printIc ("genCmpLt", ic, 1,1,1);
756 /*-----------------------------------------------------------------*/
757 /* genCmpEq - generates code for equal to */
758 /*-----------------------------------------------------------------*/
759 static void genCmpEq (iCode * ic) {
760 printIc ("genCmpEq", ic, 1,1,1);
763 /*-----------------------------------------------------------------*/
764 /* ifxForOp - returns the icode containing the ifx for operand */
765 /*-----------------------------------------------------------------*/
766 static iCode *ifxForOp (operand * op, iCode * ic) {
767 /* if true symbol then needs to be assigned */
768 if (IS_TRUE_SYMOP (op))
771 /* if this has register type condition and
772 the next instruction is ifx with the same operand
773 and live to of the operand is upto the ifx only then */
775 ic->next->op == IFX &&
776 IC_COND (ic->next)->key == op->key &&
777 OP_SYMBOL (op)->liveTo <= ic->next->seq)
783 /*-----------------------------------------------------------------*/
784 /* hasInc - operand is incremented before any other use */
785 /*-----------------------------------------------------------------*/
786 static iCode *hasInc (operand *op, iCode *ic, int osize) {
787 sym_link *type = operandType(op);
788 sym_link *retype = getSpec (type);
789 iCode *lic = ic->next;
792 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
793 if (!IS_SYMOP(op)) return NULL;
795 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
796 if (IS_AGGREGATE(type->next)) return NULL;
797 if (osize != (isize = getSize(type->next))) return NULL;
800 /* if operand of the form op = op + <sizeof *op> */
801 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
802 isOperandEqual(IC_RESULT(lic),op) &&
803 isOperandLiteral(IC_RIGHT(lic)) &&
804 operandLitValue(IC_RIGHT(lic)) == isize) {
807 /* if the operand used or deffed */
808 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
812 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
818 /*-----------------------------------------------------------------*/
819 /* genAndOp - for && operation */
820 /*-----------------------------------------------------------------*/
821 static void genAndOp (iCode * ic) {
822 printIc ("genAndOp(&&)", ic, 1,1,1);
825 /*-----------------------------------------------------------------*/
826 /* genOrOp - for || operation */
827 /*-----------------------------------------------------------------*/
828 static void genOrOp (iCode * ic) {
829 printIc ("genOrOp(||)", ic, 1,1,1);
832 /*-----------------------------------------------------------------*/
833 /* genAnd - code for and */
834 /*-----------------------------------------------------------------*/
835 static void genAnd (iCode * ic, iCode * ifx) {
836 printIc ("genAnd", ic, 1,1,1);
839 /*-----------------------------------------------------------------*/
840 /* genOr - code for or */
841 /*-----------------------------------------------------------------*/
842 static void genOr (iCode * ic, iCode * ifx) {
843 printIc ("genOr", ic, 1,1,1);
846 /*-----------------------------------------------------------------*/
847 /* genXor - code for xclusive or */
848 /*-----------------------------------------------------------------*/
849 static void genXor (iCode * ic, iCode * ifx) {
850 printIc ("genXor", ic, 1,1,1);
853 /*-----------------------------------------------------------------*/
854 /* genInline - write the inline code out */
855 /*-----------------------------------------------------------------*/
856 static void genInline (iCode * ic) {
857 printIc ("genInline", ic, 0,0,0);
860 /*-----------------------------------------------------------------*/
861 /* genRRC - rotate right with carry */
862 /*-----------------------------------------------------------------*/
863 static void genRRC (iCode * ic) {
864 printIc ("genRRC", ic, 1,1,0);
867 /*-----------------------------------------------------------------*/
868 /* genRLC - generate code for rotate left with carry */
869 /*-----------------------------------------------------------------*/
870 static void genRLC (iCode * ic) {
871 printIc ("genRLC", ic, 1,1,0);
874 /*-----------------------------------------------------------------*/
875 /* genGetHbit - generates code get highest order bit */
876 /*-----------------------------------------------------------------*/
877 static void genGetHbit (iCode * ic) {
878 printIc ("genGetHbit", ic, 1,1,0);
881 /*-----------------------------------------------------------------*/
882 /* genLeftShift - generates code for left shifting */
883 /*-----------------------------------------------------------------*/
884 static void genLeftShift (iCode * ic) {
885 printIc ("genLeftShift", ic, 1,1,1);
888 /*-----------------------------------------------------------------*/
889 /* genRightShift - generate code for right shifting */
890 /*-----------------------------------------------------------------*/
891 static void genRightShift (iCode * ic) {
892 printIc ("genRightShift", ic, 1,1,1);
895 /*-----------------------------------------------------------------*/
896 /* genPointerGet - generate code for pointer get */
897 /*-----------------------------------------------------------------*/
898 static void genPointerGet (iCode * ic, iCode *pi) {
901 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
903 printIc ("genPointerGet", ic, 1,1,0);
905 if (!IS_PTR(operandType(left))) {
906 bailOut ("genPointerGet: pointer required");
912 if (IS_GENPTR(operandType(left))) {
913 emitcode (";", "INLINE\t_gptrget ; %s %s = [%s %s]",
914 AOP_NAME(result)[0], AOP_NAME(result)[1],
915 AOP_NAME(left)[0], AOP_NAME(left)[1]);
919 switch (AOP_TYPE(left))
922 if (AOP_SIZE(result)==1) {
927 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
928 if (AOP_SIZE(result) > 2) {
929 if (AOP_SIZE(result)==3) {
934 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
938 if (AOP_SIZE(result)==1) {
943 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
944 if (AOP_SIZE(result) > 2) {
945 if (AOP_SIZE(result)==3) {
950 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
954 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
955 if (AOP_SIZE(result) > 2) {
956 emitcode (instr, "%s,%s+2", AOP_NAME(result)[1], AOP_NAME(left)[0]);
960 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
961 if (AOP_SIZE(result) > 2) {
962 // result is generic pointer
963 sym_link *optype=operandType(left);
964 sym_link *opetype=getSpec(optype);
965 if (IS_PTR(optype) && !IS_GENPTR(optype)) {
966 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(result)[1],
967 PTR_TYPE(SPEC_OCLS(opetype)));
969 emitcode (instr, "%s,[%s]", AOP_NAME(result)[1], AOP_NAME(left)[1]);
975 if (AOP_TYPE(result)==AOP_STK) {
976 if (AOP_SIZE(result)==1) {
977 emitcode ("mov", "r0l,%s", AOP_NAME(left)[0]);
978 emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
980 emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
981 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
984 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
986 if (AOP_SIZE(result) > 2) {
987 if (AOP_TYPE(result)==AOP_STK) {
988 if (AOP_SIZE(result)==3) {
989 emitcode ("mov", "r0l,%s", AOP_NAME(left)[1]);
990 emitcode ("mov", "%s,r0l", AOP_NAME(result)[1]);
992 emitcode ("mov", "r0,%s", AOP_NAME(left)[1]);
993 emitcode ("mov", "%s,r0", AOP_NAME(result)[1]);
996 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1001 bailOut ("genPointerGet: unknown pointer");
1004 /*-----------------------------------------------------------------*/
1005 /* genPointerSet - stores the value into a pointer location */
1006 /*-----------------------------------------------------------------*/
1007 static void genPointerSet (iCode * ic, iCode *pi) {
1010 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1012 printIc ("genPointerSet", ic, 1,0,1);
1014 if (!IS_PTR(operandType(result))) {
1015 bailOut ("genPointerSet: pointer required");
1021 if (IS_GENPTR(operandType(result))) {
1022 emitcode (";", "INLINE _gptrset ; [%s %s]= %s %s",
1023 AOP_NAME(result)[0], AOP_NAME(result)[1],
1024 AOP_NAME(right)[0], AOP_NAME(right)[1]);
1028 switch (AOP_TYPE(result))
1034 if (AOP_SIZE(result)==1) {
1039 emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1040 if (AOP_SIZE(result) > 2) {
1041 if (AOP_SIZE(result)==3) {
1046 emitcode (instr, "[%s],%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1050 bailOut ("genPointerSet: unknown pointer");
1053 /*-----------------------------------------------------------------*/
1054 /* genIfx - generate code for Ifx statement */
1055 /*-----------------------------------------------------------------*/
1056 static void genIfx (iCode * ic, iCode * popIc) {
1059 symbol *jlbl, *tlbl;
1060 operand *cond=IC_COND(ic);
1062 emitcode (";", "genIfx cond=%s trueLabel:%s falseLabel:%s",
1064 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1065 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1077 switch (AOP_TYPE(cond) )
1080 emitcode (trueOrFalse ? "jb" : "jbc", "%s,%05d$",
1081 AOP_NAME(cond)[0], jlbl->key+100);
1087 tlbl=newiTempLabel(NULL);
1088 if (AOP_SIZE(cond)==1) {
1093 emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1094 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1095 if (AOP_SIZE(cond) > 2) {
1096 if (AOP_SIZE(cond)==3) {
1101 emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1102 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1104 emitcode ("jmp", "%05d$", jlbl->key+100);
1105 emitcode ("", "%05d$:", tlbl->key+100);
1111 /*-----------------------------------------------------------------*/
1112 /* genAddrOf - generates code for address of */
1113 /*-----------------------------------------------------------------*/
1114 static void genAddrOf (iCode * ic) {
1115 operand *left=IC_LEFT(ic);
1117 printIc ("genAddrOf", ic, 1,1,0);
1119 aopOp (IC_RESULT(ic),TRUE);
1121 if (isOperandOnStack(left)) {
1122 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1123 getStackOffset(OP_SYMBOL(left)->stack));
1124 if (AOP_SIZE(IC_RESULT(ic)) > 2) {
1125 // this must be a generic pointer
1126 emitcode ("mov", "%s,#0x01", AOP_NAME(IC_RESULT(ic))[1]);
1131 if (isOperandInDirSpace(left) ||
1132 isOperandInFarSpace(left) ||
1133 isOperandInCodeSpace(left)) {
1134 emitcode ("mov", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1136 if (AOP_SIZE(IC_RESULT(ic)) > 2) {
1137 // this must be a generic pointer
1138 int space=0; // dir space
1139 if (isOperandInFarSpace(left)) {
1141 } else if (isOperandInCodeSpace(left)) {
1144 emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1149 bailOut("genAddrOf");
1152 /*-----------------------------------------------------------------*/
1153 /* genAssign - generate code for assignment */
1154 /*-----------------------------------------------------------------*/
1155 static void genAssign (iCode * ic) {
1156 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1160 printIc ("genAssign", ic, 1,0,1);
1162 if (!IS_SYMOP(result)) {
1163 bailOut("genAssign: result is not a symbol");
1166 aopOp(right, FALSE);
1167 aopOp(result, TRUE);
1168 size=AOP_SIZE(result);
1170 if (result->aop->type==AOP_REG ||
1171 right->aop->type==AOP_REG ||
1172 right->aop->type==AOP_LIT ||
1173 right->aop->type==AOP_STK ||
1174 right->aop->type==AOP_IMMD) {
1175 // everything will do
1177 // they have to match
1178 if (result->aop->type != right->aop->type) {
1179 fprintf (stderr, "genAssign: types don't match (%s!=%s)\n",
1180 aopTypeName(result->aop), aopTypeName(right->aop));
1185 /* if result is a bit */
1186 if (AOP_TYPE(result) == AOP_CRY) {
1187 /* if right is literal, we know what the value is */
1188 if (AOP_TYPE(right) == AOP_LIT) {
1189 if (operandLitValue(right)) {
1190 emitcode ("setb", AOP_NAME(result)[0]);
1192 emitcode ("clr", AOP_NAME(result)[0]);
1196 /* if right is also a bit */
1197 if (AOP_TYPE(right) == AOP_CRY) {
1198 emitcode ("mov", "c,%s", AOP_NAME(right));
1199 emitcode ("mov", "%s,c", AOP_NAME(result));
1203 emitcode ("mov", "%s,%s", AOP_NAME(result), toBoolean(right));
1213 emitcode (instr, "%s,%s",
1214 result->aop->name[0], right->aop->name[0]);
1215 if (AOP_SIZE(result) > 2) {
1221 emitcode (instr, "%s,%s",
1222 result->aop->name[1], right->aop->name[1]);
1227 /*-----------------------------------------------------------------*/
1228 /* genJumpTab - genrates code for jump table */
1229 /*-----------------------------------------------------------------*/
1230 static void genJumpTab (iCode * ic) {
1231 printIc ("genJumpTab", ic, 0,0,0);
1234 /*-----------------------------------------------------------------*/
1235 /* genCast - gen code for casting */
1236 /*-----------------------------------------------------------------*/
1237 static void genCast (iCode * ic) {
1238 printIc ("genCast", ic, 1,1,1);
1241 /*-----------------------------------------------------------------*/
1242 /* genDjnz - generate decrement & jump if not zero instrucion */
1243 /*-----------------------------------------------------------------*/
1244 static bool genDjnz (iCode * ic, iCode * ifx) {
1250 /* if the if condition has a false label
1251 then we cannot save */
1255 /* if the minus is not of the form
1257 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1258 !IS_OP_LITERAL (IC_RIGHT (ic)))
1261 if (operandLitValue (IC_RIGHT (ic)) != 1)
1264 /* if the size of this greater than two then no
1266 if (getSize (operandType (IC_RESULT (ic))) > 2)
1269 printIc ("genDjnz", ic, 1,1,1);
1271 /* otherwise we can save BIG */
1272 lbl = newiTempLabel (NULL);
1273 lbl1 = newiTempLabel (NULL);
1275 aopOp (IC_RESULT (ic), TRUE);
1277 if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1278 emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1279 emitcode ("bra", "%05d$", lbl1->key + 100);
1280 emitcode ("", "%05d$:", lbl->key + 100);
1281 emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1282 emitcode ("", "%05d$:", lbl1->key + 100);
1285 bailOut("genDjnz: aop type");
1289 /*-----------------------------------------------------------------*/
1290 /* genReceive - generate code for a receive iCode */
1291 /*-----------------------------------------------------------------*/
1292 static void genReceive (iCode * ic) {
1293 printIc ("genReceive", ic, 1,0,0);
1296 /*-----------------------------------------------------------------*/
1297 /* gen51Code - generate code for 8051 based controllers */
1298 /*-----------------------------------------------------------------*/
1299 void genXA51Code (iCode * lic) {
1303 fprintf (stderr, "genXA51Code\n");
1304 lineHead = lineCurr = NULL;
1306 /* print the allocation information */
1308 printAllocInfo (currFunc, codeOutFile);
1310 /* if debug information required */
1311 if (options.debug && currFunc)
1313 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1315 if (IS_STATIC (currFunc->etype))
1316 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1318 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1322 for (ic = lic; ic; ic = ic->next) {
1323 if (cln != ic->lineno) {
1324 if (options.debug) {
1326 emitcode ("", "C$%s$%d$%d$%d ==.",
1327 FileBaseName (ic->filename), ic->lineno,
1328 ic->level, ic->block);
1331 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1332 printCLine(ic->filename, ic->lineno));
1335 /* if the result is marked as
1336 spilt and rematerializable or code for
1337 this has already been generated then
1339 if (resultRemat (ic) || ic->generated)
1342 /* depending on the operation */
1362 /* IPOP happens only when trying to restore a
1363 spilt live range, if there is an ifx statement
1364 following this pop then the if statement might
1365 be using some of the registers being popped which
1366 would destory the contents of the register so
1367 we need to check for this condition and handle it */
1369 ic->next->op == IFX &&
1370 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1371 genIfx (ic->next, ic);
1389 genEndFunction (ic);
1409 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1458 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1462 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1466 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1493 case GET_VALUE_AT_ADDRESS:
1494 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_LEFT(ic)))));
1498 if (POINTER_SET (ic))
1499 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1525 addSet (&_G.sendSet, ic);
1534 /* now we are ready to call the
1535 peep hole optimizer */
1536 if (!options.nopeep)
1537 peepHole (&lineHead);
1539 /* now do the actual printing */
1540 printLine (lineHead, codeOutFile);