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 void bailOut (char *mesg) {
106 fprintf (stderr, "%s: bailing out\n", mesg);
110 /*-----------------------------------------------------------------*/
111 /* emitcode - writes the code into a file : for now it is simple */
112 /*-----------------------------------------------------------------*/
113 static void emitcode (char *inst, char *fmt,...) {
115 char lb[INITIAL_INLINEASM];
123 sprintf (lb, "%s\t", inst);
125 sprintf (lb, "%s", inst);
126 vsprintf (lb + (strlen (lb)), fmt, ap);
129 vsprintf (lb, fmt, ap);
131 while (isspace ((int)*lbp))
135 lineCurr = (lineCurr ?
136 connectLine (lineCurr, newLineNode (lb)) :
137 (lineHead = newLineNode (lb)));
138 lineCurr->isInline = _G.inLine;
139 lineCurr->isDebug = _G.debugLine;
143 char *getStackOffset(int stack) {
144 static char gsoBuf[1024];
145 sprintf (gsoBuf, "r7%+d+0%+d%+d", stack,
146 FUNC_ISISR(currFunc->type) ?
147 port->stack.isr_overhead : port->stack.call_overhead,
152 /*-----------------------------------------------------------------*/
153 /* newAsmop - creates a new asmOp */
154 /*-----------------------------------------------------------------*/
156 newAsmop (short type)
160 aop = Safe_calloc (1, sizeof (asmop));
165 char *aopTypeName(asmop *aop) {
168 case AOP_LIT: return "lit";
169 case AOP_REG: return "reg";
170 case AOP_DIR: return "dir";
171 case AOP_FAR: return "far";
172 case AOP_CODE: return "code";
173 case AOP_STK: return "stack";
174 case AOP_IMMD: return "imm";
175 case AOP_CRY: return "bit";
180 /*-----------------------------------------------------------------*/
181 /* aopForSym - for a true symbol */
182 /*-----------------------------------------------------------------*/
183 static asmop *aopForSym(symbol *sym, bool result) {
187 sym->aop = aop = newAsmop(0);
188 size=aop->size=getSize(sym->type);
190 // if the sym has registers
191 if (sym->nRegs && sym->regs[0]) {
193 sprintf (aop->name[0], sym->regs[0]->name);
195 sprintf (aop->name[1], sym->regs[1]->name);
203 sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
205 sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
210 // if it has a spillLoc
211 if (sym->usl.spillLoc) {
212 return aopForSym (sym->usl.spillLoc, result);
216 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
218 sprintf (aop->name[0], sym->rname);
222 // if in direct space
223 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
225 sprintf (aop->name[0], sym->rname);
227 sprintf (aop->name[0], "%s+2", sym->rname);
233 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
235 bailOut("aopForSym: result can not be in code space");
238 emitcode ("mov", "r0,#%s", sym->rname);
239 sprintf (aop->name[0], "[r0]");
241 sprintf (aop->name[1], "[r0+1]");
247 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
249 emitcode ("mov", "r0,#%s", sym->rname);
250 sprintf (aop->name[0], "[r0]");
252 sprintf (aop->name[1], "[r0+1]");
257 bailOut("aopForSym");
261 /*-----------------------------------------------------------------*/
262 /* aopForVal - for a value */
263 /*-----------------------------------------------------------------*/
264 static asmop *aopForVal(operand *op) {
266 long v=(long long)floatFromVal(OP_VALUE(op));
268 if (IS_OP_LITERAL(op)) {
269 op->aop = aop = newAsmop (AOP_LIT);
270 switch ((aop->size=getSize(operandType(op))))
273 sprintf (aop->name[0], "#0x%02lx", v);
276 sprintf (aop->name[0], "#0x%04lx", v);
279 sprintf (aop->name[0], "#(0x%08lx >> 16)", v);
280 sprintf (aop->name[1], "#(0x%08lx & 0xffff)", v);
283 bailOut("aopForVal");
290 op->aop = aop = newAsmop (AOP_IMMD);
291 switch ((aop->size=getSize(OP_SYMBOL(op)->type)))
295 sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
297 case 3: // generic pointer
298 sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
299 sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
303 bailOut ("aopForVal: unknown type");
307 static void aopOp(operand *op, bool result) {
310 op->aop=aopForSym (OP_SYMBOL(op), result);
315 bailOut("aopOp: result can not be a value");
321 bailOut("aopOp: unexpected operand");
324 char *opRegName(operand *op, int offset, char *opName) {
327 if (OP_SYMBOL(op)->onStack) {
328 sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
331 if (IS_TRUE_SYMOP(op))
332 return OP_SYMBOL(op)->rname;
333 else if (OP_SYMBOL(op)->regs[offset])
334 return OP_SYMBOL(op)->regs[offset]->name;
336 bailOut("opRegName: unknown regs");
340 switch (SPEC_NOUN(OP_VALUE(op)->type)) {
343 if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
344 SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
345 bailOut("opRegName: invalid bit value");
349 sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
352 if (SPEC_LONG(OP_VALUE(op)->type)) {
353 sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
355 sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
359 sprintf (opName, "#%f", SPEC_CVAL(OP_VALUE(op)->type).v_float);
362 bailOut("opRegName: unexpected noun");
366 bailOut("opRegName: unexpected operand type");
370 char * printOp (operand *op) {
371 static char line[132];
372 sym_link *optype=operandType(op);
373 bool isPtr = IS_PTR(optype);
376 symbol *sym=OP_SYMBOL(op);
377 if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
378 sym=SYM_SPIL_LOC(sym);
382 if (DCL_TYPE(optype)==FPOINTER)
383 strcat (line, "far * ");
384 else if (DCL_TYPE(optype)==CPOINTER)
385 strcat (line, "code * ");
386 else if (DCL_TYPE(optype)==GPOINTER)
387 strcat (line, "gen * ");
388 else if (DCL_TYPE(optype)==POINTER)
389 strcat (line, "near * ");
391 strcat (line, "unknown * ");
393 strcat (line, nounName(sym->etype));
395 strcat (line, sym->name);
398 sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
401 strcat (line, sym->regs[0]->name);
404 strcat (line, sym->regs[1]->name);
409 sprintf (line+strlen(line), "stack%+d", sym->stack);
412 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
413 strcat (line, "far");
416 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
417 strcat (line, "bit");
420 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
421 strcat (line, "dir");
424 strcat (line, "unknown");
426 } else if (IS_VALOP(op)) {
427 opRegName(op, 0, line);
428 } else if (IS_TYPOP(op)) {
431 if (DCL_TYPE(optype)==FPOINTER)
432 strcat (line, "far * ");
433 else if (DCL_TYPE(optype)==CPOINTER)
434 strcat (line, "code * ");
435 else if (DCL_TYPE(optype)==GPOINTER)
436 strcat (line, "gen * ");
437 else if (DCL_TYPE(optype)==POINTER)
438 strcat (line, "near * ");
440 strcat (line, "unknown * ");
442 // forget about static, volatile, ... for now
443 if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
444 if (SPEC_LONG(operandType(op))) strcat (line, "long ");
445 strcat (line, nounName(operandType(op)));
448 bailOut("printOp: unexpected operand type");
453 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
456 sprintf (line, "%s(%d)", op, ic->lineno);
458 strcat (line, " result=");
459 strcat (line, printOp (IC_RESULT(ic)));
462 strcat (line, " left=");
463 strcat (line, printOp (IC_LEFT(ic)));
466 strcat (line, " right=");
467 strcat (line, printOp (IC_RIGHT(ic)));
469 emitcode (";", line);
472 /*-----------------------------------------------------------------*/
473 /* toBoolean - return bit for operand!=0 */
474 /*-----------------------------------------------------------------*/
475 static char *toBoolean (operand * op) {
476 switch (AOP_SIZE(op))
480 emitcode ("cmp", "%s,#0", AOP_NAME(op));
484 bailOut("toBoolean: unknown size");
488 /*-----------------------------------------------------------------*/
489 /* regsInCommon - two operands have some registers in common */
490 /*-----------------------------------------------------------------*/
491 static bool regsInCommon (operand * op1, operand * op2) {
495 /* if they have registers in common */
496 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
499 sym1 = OP_SYMBOL (op1);
500 sym2 = OP_SYMBOL (op2);
502 if (sym1->nRegs == 0 || sym2->nRegs == 0)
505 for (i = 0; i < sym1->nRegs; i++)
511 for (j = 0; j < sym2->nRegs; j++)
516 if (sym2->regs[j] == sym1->regs[i])
524 /*-----------------------------------------------------------------*/
525 /* resultRemat - result is rematerializable */
526 /*-----------------------------------------------------------------*/
527 static int resultRemat (iCode * ic) {
528 if (SKIP_IC (ic) || ic->op == IFX)
531 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
533 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
534 if (sym->remat && !POINTER_SET (ic))
541 /*-----------------------------------------------------------------*/
542 /* genNot - generate code for ! operation */
543 /*-----------------------------------------------------------------*/
544 static void genNot (iCode * ic) {
545 printIc("genNot:", ic, 1,1,0);
548 /*-----------------------------------------------------------------*/
549 /* genCpl - generate code for complement */
550 /*-----------------------------------------------------------------*/
551 static void genCpl (iCode * ic) {
552 printIc("genCpl", ic, 1,1,0);
555 /*-----------------------------------------------------------------*/
556 /* genUminus - unary minus code generation */
557 /*-----------------------------------------------------------------*/
558 static void genUminus (iCode * ic) {
559 printIc("genUminus", ic, 1,1,0);
562 /*-----------------------------------------------------------------*/
563 /* genIpush - genrate code for pushing this gets a little complex */
564 /*-----------------------------------------------------------------*/
565 static void genIpush (iCode * ic) {
566 printIc ("genIpush", ic, 0,1,0);
569 /*-----------------------------------------------------------------*/
570 /* genIpop - recover the registers: can happen only for spilling */
571 /*-----------------------------------------------------------------*/
572 static void genIpop (iCode * ic) {
573 printIc ("genIpop", ic, 0,1,0);
576 /*-----------------------------------------------------------------*/
577 /* genCall - generates a call statement */
578 /*-----------------------------------------------------------------*/
579 static void genCall (iCode * ic) {
580 emitcode (";", "genCall %s result=%s", OP_SYMBOL(IC_LEFT(ic))->name,
581 printOp (IC_RESULT(ic)));
584 /*-----------------------------------------------------------------*/
585 /* genPcall - generates a call by pointer statement */
586 /*-----------------------------------------------------------------*/
588 genPcall (iCode * ic)
590 emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
593 /*-----------------------------------------------------------------*/
594 /* genFunction - generated code for function entry */
595 /*-----------------------------------------------------------------*/
596 static void genFunction (iCode * ic) {
597 symbol *sym=OP_SYMBOL(IC_LEFT(ic));
598 sym_link *type=sym->type;
600 emitcode (";", "-----------------------------------------");
601 emitcode (";", " function %s", sym->name);
602 emitcode (";", "-----------------------------------------");
604 emitcode ("", "%s:", sym->rname);
606 if (IFFUNC_ISNAKED(type))
608 emitcode(";", "naked function: no prologue.");
612 /* if critical function then turn interrupts off */
613 if (IFFUNC_ISCRITICAL (type))
614 emitcode ("clr", "ea");
618 /*-----------------------------------------------------------------*/
619 /* genEndFunction - generates epilogue for functions */
620 /*-----------------------------------------------------------------*/
622 genEndFunction (iCode * ic)
624 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
626 if (IFFUNC_ISNAKED(sym->type))
628 emitcode(";", "naked function: no epilogue.");
632 printIc ("genEndFunction", ic, 0,0,0);
635 /*-----------------------------------------------------------------*/
636 /* genRet - generate code for return statement */
637 /*-----------------------------------------------------------------*/
638 static void genRet (iCode * ic) {
640 printIc ("genRet", ic, 0,1,0);
642 aopOp(IC_LEFT(ic),FALSE);
644 switch (AOP_SIZE(IC_LEFT(ic)))
647 emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
648 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
651 emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
654 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
657 emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
663 /*-----------------------------------------------------------------*/
664 /* genLabel - generates a label */
665 /*-----------------------------------------------------------------*/
666 static void genLabel (iCode * ic) {
667 /* special case never generate */
668 if (IC_LABEL (ic) == entryLabel)
671 emitcode (";", "genLabel %s", IC_LABEL(ic)->name);
672 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
675 /*-----------------------------------------------------------------*/
676 /* genGoto - generates a ljmp */
677 /*-----------------------------------------------------------------*/
678 static void genGoto (iCode * ic) {
679 emitcode (";", "genGoto %s", IC_LABEL(ic)->name);
680 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
683 /*-----------------------------------------------------------------*/
684 /* genPlus - generates code for addition */
685 /*-----------------------------------------------------------------*/
686 static void genPlus (iCode * ic) {
687 printIc ("genPlus", ic, 1,1,1);
690 /*-----------------------------------------------------------------*/
691 /* genMinus - generates code for subtraction */
692 /*-----------------------------------------------------------------*/
693 static void genMinus (iCode * ic) {
694 printIc ("genMinus", ic, 1,1,1);
698 /*-----------------------------------------------------------------*/
699 /* genMult - generates code for multiplication */
700 /*-----------------------------------------------------------------*/
701 static void genMult (iCode * ic) {
702 printIc ("genMult", ic, 1,1,1);
705 /*-----------------------------------------------------------------*/
706 /* genDiv - generates code for division */
707 /*-----------------------------------------------------------------*/
708 static void genDiv (iCode * ic) {
709 printIc ("genDiv", ic, 1,1,1);
712 /*-----------------------------------------------------------------*/
713 /* genMod - generates code for division */
714 /*-----------------------------------------------------------------*/
715 static void genMod (iCode * ic) {
716 printIc ("genMod", ic, 1,1,1);
719 /*-----------------------------------------------------------------*/
720 /* genCmpGt :- greater than comparison */
721 /*-----------------------------------------------------------------*/
722 static void genCmpGt (iCode * ic) {
723 printIc ("genCmpGt", ic, 1,1,1);
725 /*-----------------------------------------------------------------*/
726 /* genCmpGt :- greater than comparison */
727 /*-----------------------------------------------------------------*/
728 static void genCmpLe (iCode * ic) {
729 printIc ("genCmpGt", ic, 1,1,1);
731 /*-----------------------------------------------------------------*/
732 /* genCmpGt :- greater than comparison */
733 /*-----------------------------------------------------------------*/
734 static void genCmpGe (iCode * ic) {
735 printIc ("genCmpGt", ic, 1,1,1);
737 /*-----------------------------------------------------------------*/
738 /* genCmpGt :- greater than comparison */
739 /*-----------------------------------------------------------------*/
740 static void genCmpNe (iCode * ic) {
741 printIc ("genCmpGt", ic, 1,1,1);
743 /*-----------------------------------------------------------------*/
744 /* genCmpLt - less than comparisons */
745 /*-----------------------------------------------------------------*/
746 static void genCmpLt (iCode * ic) {
747 printIc ("genCmpLt", ic, 1,1,1);
749 /*-----------------------------------------------------------------*/
750 /* genCmpEq - generates code for equal to */
751 /*-----------------------------------------------------------------*/
752 static void genCmpEq (iCode * ic) {
753 printIc ("genCmpEq", ic, 1,1,1);
756 /*-----------------------------------------------------------------*/
757 /* ifxForOp - returns the icode containing the ifx for operand */
758 /*-----------------------------------------------------------------*/
759 static iCode *ifxForOp (operand * op, iCode * ic) {
760 /* if true symbol then needs to be assigned */
761 if (IS_TRUE_SYMOP (op))
764 /* if this has register type condition and
765 the next instruction is ifx with the same operand
766 and live to of the operand is upto the ifx only then */
768 ic->next->op == IFX &&
769 IC_COND (ic->next)->key == op->key &&
770 OP_SYMBOL (op)->liveTo <= ic->next->seq)
776 /*-----------------------------------------------------------------*/
777 /* hasInc - operand is incremented before any other use */
778 /*-----------------------------------------------------------------*/
779 static iCode *hasInc (operand *op, iCode *ic, int osize) {
780 sym_link *type = operandType(op);
781 sym_link *retype = getSpec (type);
782 iCode *lic = ic->next;
785 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
786 if (!IS_SYMOP(op)) return NULL;
788 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
789 if (IS_AGGREGATE(type->next)) return NULL;
790 if (osize != (isize = getSize(type->next))) return NULL;
793 /* if operand of the form op = op + <sizeof *op> */
794 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
795 isOperandEqual(IC_RESULT(lic),op) &&
796 isOperandLiteral(IC_RIGHT(lic)) &&
797 operandLitValue(IC_RIGHT(lic)) == isize) {
800 /* if the operand used or deffed */
801 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
805 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
811 /*-----------------------------------------------------------------*/
812 /* genAndOp - for && operation */
813 /*-----------------------------------------------------------------*/
814 static void genAndOp (iCode * ic) {
815 printIc ("genAndOp(&&)", ic, 1,1,1);
818 /*-----------------------------------------------------------------*/
819 /* genOrOp - for || operation */
820 /*-----------------------------------------------------------------*/
821 static void genOrOp (iCode * ic) {
822 printIc ("genOrOp(||)", ic, 1,1,1);
825 /*-----------------------------------------------------------------*/
826 /* genAnd - code for and */
827 /*-----------------------------------------------------------------*/
828 static void genAnd (iCode * ic, iCode * ifx) {
829 printIc ("genAnd", ic, 1,1,1);
832 /*-----------------------------------------------------------------*/
833 /* genOr - code for or */
834 /*-----------------------------------------------------------------*/
835 static void genOr (iCode * ic, iCode * ifx) {
836 printIc ("genOr", ic, 1,1,1);
839 /*-----------------------------------------------------------------*/
840 /* genXor - code for xclusive or */
841 /*-----------------------------------------------------------------*/
842 static void genXor (iCode * ic, iCode * ifx) {
843 printIc ("genXor", ic, 1,1,1);
846 /*-----------------------------------------------------------------*/
847 /* genInline - write the inline code out */
848 /*-----------------------------------------------------------------*/
849 static void genInline (iCode * ic) {
850 printIc ("genInline", ic, 0,0,0);
853 /*-----------------------------------------------------------------*/
854 /* genRRC - rotate right with carry */
855 /*-----------------------------------------------------------------*/
856 static void genRRC (iCode * ic) {
857 printIc ("genRRC", ic, 1,1,0);
860 /*-----------------------------------------------------------------*/
861 /* genRLC - generate code for rotate left with carry */
862 /*-----------------------------------------------------------------*/
863 static void genRLC (iCode * ic) {
864 printIc ("genRLC", ic, 1,1,0);
867 /*-----------------------------------------------------------------*/
868 /* genGetHbit - generates code get highest order bit */
869 /*-----------------------------------------------------------------*/
870 static void genGetHbit (iCode * ic) {
871 printIc ("genGetHbit", ic, 1,1,0);
874 /*-----------------------------------------------------------------*/
875 /* genLeftShift - generates code for left shifting */
876 /*-----------------------------------------------------------------*/
877 static void genLeftShift (iCode * ic) {
878 printIc ("genLeftShift", ic, 1,1,1);
881 /*-----------------------------------------------------------------*/
882 /* genRightShift - generate code for right shifting */
883 /*-----------------------------------------------------------------*/
884 static void genRightShift (iCode * ic) {
885 printIc ("genRightShift", ic, 1,1,1);
888 /*-----------------------------------------------------------------*/
889 /* genPointerGet - generate code for pointer get */
890 /*-----------------------------------------------------------------*/
891 static void genPointerGet (iCode * ic, iCode *pi) {
894 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
896 printIc ("genPointerGet", ic, 1,1,0);
898 if (!IS_PTR(operandType(left))) {
899 bailOut ("genPointerGet: pointer required");
905 if (IS_GENPTR(operandType(left))) {
906 emitcode ("INLINE", "_gptrget %s %s = [%s %s]",
907 AOP_NAME(result)[0], AOP_NAME(result)[1],
908 AOP_NAME(left)[0], AOP_NAME(left)[1]);
912 switch (AOP_TYPE(left))
918 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
919 if (AOP_SIZE(result) > 2) {
920 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
924 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
925 if (AOP_SIZE(result) > 2) {
926 emitcode (instr, "%s,%s+2", AOP_NAME(result)[1], AOP_NAME(left)[0]);
930 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
931 if (AOP_SIZE(result) > 2) {
932 emitcode (instr, "%s,[%s]", AOP_NAME(result)[1], AOP_NAME(left)[1]);
936 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
937 if (AOP_SIZE(result) > 2) {
938 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
942 bailOut ("genPointerGet: unknown pointer");
945 /*-----------------------------------------------------------------*/
946 /* genPointerSet - stores the value into a pointer location */
947 /*-----------------------------------------------------------------*/
948 static void genPointerSet (iCode * ic, iCode *pi) {
951 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
953 printIc ("genPointerSet", ic, 1,0,1);
955 if (!IS_PTR(operandType(result))) {
956 bailOut ("genPointerSet: pointer required");
962 if (IS_GENPTR(operandType(result))) {
963 emitcode ("INLINE", "_gptrset [%s %s]= %s %s",
964 AOP_NAME(result)[0], AOP_NAME(result)[1],
965 AOP_NAME(right)[0], AOP_NAME(right)[1]);
969 switch (AOP_TYPE(result))
978 emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
979 if (AOP_SIZE(result) > 2) {
980 emitcode (instr, "[%s],%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
985 bailOut ("genPointerSet: unknown pointer");
988 /*-----------------------------------------------------------------*/
989 /* genIfx - generate code for Ifx statement */
990 /*-----------------------------------------------------------------*/
991 static void genIfx (iCode * ic, iCode * popIc) {
994 operand *cond=IC_COND(ic);
996 emitcode (";", "genIfx cond=%s trueLabel:%s falseLabel:%s",
998 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
999 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1011 switch (AOP_TYPE(cond) )
1014 emitcode (trueOrFalse ? "jb" : "jbc", "%s,%05d$",
1015 AOP_NAME(cond)[0], jlbl->key+100);
1021 tlbl=newiTempLabel(NULL);
1022 emitcode ("cmp", "%s,#0", AOP_NAME(cond)[0]);
1023 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1024 if (AOP_SIZE(cond) > 2) {
1025 emitcode ("cmp", "%s,#0", AOP_NAME(cond)[1]);
1026 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1028 emitcode ("jmp", "%05d$", jlbl->key+100);
1029 emitcode ("", "%05d$:", tlbl->key+100);
1035 /*-----------------------------------------------------------------*/
1036 /* genAddrOf - generates code for address of */
1037 /*-----------------------------------------------------------------*/
1038 static void genAddrOf (iCode * ic) {
1039 operand *left=IC_LEFT(ic);
1041 printIc ("genAddrOf", ic, 1,1,0);
1043 aopOp (IC_RESULT(ic),TRUE);
1045 if (isOperandOnStack(left)) {
1046 aopOp (IC_LEFT(ic),FALSE);
1047 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1048 AOP_NAME(IC_LEFT(ic))[0]);
1049 if (AOP_SIZE(IC_RESULT(ic)) > 2) {
1050 // this must be a generic pointer
1051 emitcode ("mov", "%s,#0x01", AOP_NAME(IC_RESULT(ic))[1]);
1056 if (isOperandInDirSpace(left) ||
1057 isOperandInFarSpace(left) ||
1058 isOperandInCodeSpace(left)) {
1059 emitcode ("mov", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1061 if (AOP_SIZE(IC_RESULT(ic)) > 2) {
1062 // this must be a generic pointer
1063 int space=0; // dir space
1064 if (isOperandInFarSpace(left)) {
1066 } else if (isOperandInCodeSpace(left)) {
1069 emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1074 bailOut("genAddrOf");
1077 /*-----------------------------------------------------------------*/
1078 /* genAssign - generate code for assignment */
1079 /*-----------------------------------------------------------------*/
1080 static void genAssign (iCode * ic) {
1081 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1083 printIc ("genAssign", ic, 1,0,1);
1085 if (!IS_SYMOP(result)) {
1086 bailOut("genAssign: result is not a symbol");
1089 aopOp(right, FALSE);
1090 aopOp(result, TRUE);
1092 if (result->aop->type==AOP_REG ||
1093 right->aop->type==AOP_REG ||
1094 right->aop->type==AOP_LIT ||
1095 right->aop->type==AOP_STK ||
1096 right->aop->type==AOP_IMMD) {
1097 // everything will do
1099 // they have to match
1100 if (result->aop->type != right->aop->type) {
1101 fprintf (stderr, "genAssign: types don't match (%s!=%s)\n",
1102 aopTypeName(result->aop), aopTypeName(right->aop));
1107 /* if result is a bit */
1108 if (AOP_TYPE(result) == AOP_CRY) {
1109 /* if right is literal, we know what the value is */
1110 if (AOP_TYPE(right) == AOP_LIT) {
1111 if (operandLitValue(right)) {
1112 emitcode ("setb", AOP_NAME(result)[0]);
1114 emitcode ("clr", AOP_NAME(result)[0]);
1118 /* if right is also a bit */
1119 if (AOP_TYPE(right) == AOP_CRY) {
1120 emitcode ("mov", "c,%s", AOP_NAME(right));
1121 emitcode ("mov", "%s,c", AOP_NAME(result));
1125 emitcode ("mov", "%s,%s", AOP_NAME(result), toBoolean(right));
1130 emitcode ("mov", "%s,%s",
1131 result->aop->name[0], right->aop->name[0]);
1132 if (AOP_SIZE(result) > 2) {
1133 emitcode ("mov", "%s,%s",
1134 result->aop->name[1], right->aop->name[1]);
1139 /*-----------------------------------------------------------------*/
1140 /* genJumpTab - genrates code for jump table */
1141 /*-----------------------------------------------------------------*/
1142 static void genJumpTab (iCode * ic) {
1143 printIc ("genJumpTab", ic, 0,0,0);
1146 /*-----------------------------------------------------------------*/
1147 /* genCast - gen code for casting */
1148 /*-----------------------------------------------------------------*/
1149 static void genCast (iCode * ic) {
1150 printIc ("genCast", ic, 1,1,1);
1153 /*-----------------------------------------------------------------*/
1154 /* genDjnz - generate decrement & jump if not zero instrucion */
1155 /*-----------------------------------------------------------------*/
1156 static bool genDjnz (iCode * ic, iCode * ifx) {
1162 /* if the if condition has a false label
1163 then we cannot save */
1167 /* if the minus is not of the form
1169 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1170 !IS_OP_LITERAL (IC_RIGHT (ic)))
1173 if (operandLitValue (IC_RIGHT (ic)) != 1)
1176 /* if the size of this greater than two then no
1178 if (getSize (operandType (IC_RESULT (ic))) > 2)
1181 printIc ("genDjnz", ic, 1,1,1);
1183 /* otherwise we can save BIG */
1184 lbl = newiTempLabel (NULL);
1185 lbl1 = newiTempLabel (NULL);
1187 aopOp (IC_RESULT (ic), TRUE);
1189 if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1190 emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1191 emitcode ("bra", "%05d$", lbl1->key + 100);
1192 emitcode ("", "%05d$:", lbl->key + 100);
1193 emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1194 emitcode ("", "%05d$:", lbl1->key + 100);
1197 bailOut("genDjnz: aop type");
1201 /*-----------------------------------------------------------------*/
1202 /* genReceive - generate code for a receive iCode */
1203 /*-----------------------------------------------------------------*/
1204 static void genReceive (iCode * ic) {
1205 printIc ("genReceive", ic, 1,0,0);
1208 /*-----------------------------------------------------------------*/
1209 /* gen51Code - generate code for 8051 based controllers */
1210 /*-----------------------------------------------------------------*/
1211 void genXA51Code (iCode * lic) {
1215 fprintf (stderr, "genXA51Code\n");
1216 lineHead = lineCurr = NULL;
1218 /* print the allocation information */
1220 printAllocInfo (currFunc, codeOutFile);
1222 /* if debug information required */
1223 if (options.debug && currFunc)
1225 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1227 if (IS_STATIC (currFunc->etype))
1228 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1230 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1234 for (ic = lic; ic; ic = ic->next) {
1235 if (cln != ic->lineno) {
1236 if (options.debug) {
1238 emitcode ("", "C$%s$%d$%d$%d ==.",
1239 FileBaseName (ic->filename), ic->lineno,
1240 ic->level, ic->block);
1243 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1244 printCLine(ic->filename, ic->lineno));
1247 /* if the result is marked as
1248 spilt and rematerializable or code for
1249 this has already been generated then
1251 if (resultRemat (ic) || ic->generated)
1254 /* depending on the operation */
1274 /* IPOP happens only when trying to restore a
1275 spilt live range, if there is an ifx statement
1276 following this pop then the if statement might
1277 be using some of the registers being popped which
1278 would destory the contents of the register so
1279 we need to check for this condition and handle it */
1281 ic->next->op == IFX &&
1282 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1283 genIfx (ic->next, ic);
1301 genEndFunction (ic);
1321 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1370 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1374 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1378 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1405 case GET_VALUE_AT_ADDRESS:
1406 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_LEFT(ic)))));
1410 if (POINTER_SET (ic))
1411 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1437 addSet (&_G.sendSet, ic);
1446 /* now we are ready to call the
1447 peep hole optimizer */
1448 if (!options.nopeep)
1449 peepHole (&lineHead);
1451 /* now do the actual printing */
1452 printLine (lineHead, codeOutFile);