1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
41 #ifdef HAVE_MACHINE_ENDIAN_H
42 #include <machine/endian.h>
47 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
48 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
49 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
56 #include "SDCCpeeph.h"
60 #if defined(__BORLANDC__) || defined(_MSC_VER)
61 #define STRCASECMP stricmp
63 #define STRCASECMP strcasecmp
68 /* this is the down and dirty file with all kinds of
69 kludgy & hacky stuff. This is what it is all about
70 CODE GENERATION for a specific MCU . some of the
71 routines may be reusable, will have to see */
83 extern int xa51_ptrRegReq;
84 extern int xa51_nRegs;
85 extern FILE *codeOutFile;
87 static lineNode *lineHead = NULL;
88 static lineNode *lineCurr = NULL;
95 static char *MOV="mov";
96 static char *MOVB="mov.b";
97 static char *MOVW="mov.w";
98 static char *MOVC="movc";
99 static char *MOVCB="movc.b";
100 static char *MOVCW="movc.w";
102 static char *R1L="r1l";
103 static char *R1="r1";
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%+d%+d%+d)", stack,
146 FUNC_ISISR(currFunc->type) ?
147 port->stack.isr_overhead : port->stack.call_overhead,
148 currFunc->stack, _G.nRegsSaved);
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_GPTR: return "gptr";
174 case AOP_STK: return "stack";
175 case AOP_IMMD: return "imm";
176 case AOP_BIT: return "bit";
181 /*-----------------------------------------------------------------*/
182 /* aopForSym - for a true symbol */
183 /*-----------------------------------------------------------------*/
184 static asmop *aopForSym(symbol *sym,
185 bool canUsePointer, bool canUseOffset) {
189 sym->aop = aop = newAsmop(0);
190 size=aop->size=getSize(sym->type);
192 // if the sym has registers
193 if (sym->nRegs && sym->regs[0]) {
195 sprintf (aop->name[0], sym->regs[0]->name);
197 sprintf (aop->name[1], sym->regs[1]->name);
204 if (!canUsePointer || !canUseOffset) {
209 emitcode ("mov.b", "r0l,[%s]", getStackOffset(sym->stack));
210 sprintf (aop->name[0], "r0l");
213 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
214 sprintf (aop->name[0], "r0");
217 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
218 sprintf (aop->name[0], "r0");
219 emitcode ("mov.b", "r1l,[%s]", getStackOffset(sym->stack+2));
220 sprintf (aop->name[1], "r1l");
223 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
224 sprintf (aop->name[0], "r0");
225 emitcode ("mov.w", "r1,[%s]", getStackOffset(sym->stack+2));
226 sprintf (aop->name[1], "r1");
231 sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
233 sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
238 // if it has a spillLoc
239 if (sym->usl.spillLoc) {
240 return aopForSym (sym->usl.spillLoc, canUsePointer, canUseOffset);
244 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
246 sprintf (aop->name[0], sym->rname);
250 // if in direct space
251 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
253 sprintf (aop->name[0], sym->rname);
255 sprintf (aop->name[1], "%s+2", sym->rname);
261 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
262 if (!canUsePointer) {
267 emitcode (MOV, "r0,#%s", sym->rname);
268 emitcode (MOVC, "r0l,[r0]");
269 sprintf (aop->name[0], "r0l");
272 emitcode (MOV, "r0,#%s", sym->rname);
273 emitcode (MOVC, "r0,[r0]");
274 sprintf (aop->name[0], "r0");
277 emitcode (MOV, "r0,#%s", sym->rname);
278 emitcode (MOVC, "r1l,[r0+2]");
279 sprintf (aop->name[1], "r1l");
280 emitcode (MOV, "r0,[r0]");
281 sprintf (aop->name[0], "r0");
284 emitcode (MOV, "r0,#%s", sym->rname);
285 emitcode (MOVC, "r1,[r0+2]");
286 sprintf (aop->name[1], "r1");
287 emitcode (MOVC, "r0,[r0]");
288 sprintf (aop->name[0], "r0");
294 emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
295 sprintf (aop->name[0], "[r0]");
297 sprintf (aop->name[1], "[r0+2]");
304 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
305 if (!canUsePointer) {
310 emitcode (MOV, "r0,#%s", sym->rname);
311 emitcode (MOV, "r0l,[r0]");
312 sprintf (aop->name[0], "r0l");
315 emitcode (MOV, "r0,#%s", sym->rname);
316 emitcode (MOV, "r0,[r0]");
317 sprintf (aop->name[0], "r0");
320 emitcode (MOV, "r0,#%s", sym->rname);
321 emitcode (MOV, "r1l,[r0+2]");
322 sprintf (aop->name[1], "r1l");
323 emitcode (MOV, "r0,[r0]");
324 sprintf (aop->name[0], "r0");
327 emitcode (MOV, "r0,#%s", sym->rname);
328 emitcode (MOV, "r1,[r0+2]");
329 sprintf (aop->name[1], "r1");
330 emitcode (MOV, "r0,[r0]");
331 sprintf (aop->name[0], "r0");
336 emitcode ("mov", "r0,#%s ; aopForSym:far", sym->rname);
337 sprintf (aop->name[0], "[r0]");
339 sprintf (aop->name[1], "[r0+2]");
345 bailOut("aopForSym");
349 /*-----------------------------------------------------------------*/
350 /* aopForVal - for a value */
351 /*-----------------------------------------------------------------*/
352 static asmop *aopForVal(operand *op) {
355 if (IS_OP_LITERAL(op)) {
356 op->aop = aop = newAsmop (AOP_LIT);
357 switch ((aop->size=getSize(operandType(op))))
360 sprintf (aop->name[0], "#0x%02x",
361 SPEC_CVAL(operandType(op)).v_int & 0xff);
362 sprintf (aop->name[1], "#0");
365 sprintf (aop->name[0], "#0x%04x",
366 SPEC_CVAL(operandType(op)).v_int & 0xffff);
367 sprintf (aop->name[1], "#0");
370 // must be a generic pointer, can only be zero
371 // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
372 sprintf (aop->name[0], "#0x%04x",
373 SPEC_CVAL(operandType(op)).v_uint & 0xffff);
374 sprintf (aop->name[1], "#0");
377 sprintf (aop->name[0], "#0x%04lx",
378 SPEC_CVAL(operandType(op)).v_ulong & 0xffff);
379 sprintf (aop->name[1], "#0x%04lx",
380 SPEC_CVAL(operandType(op)).v_ulong >> 16);
383 bailOut("aopForVal");
390 op->aop = aop = newAsmop (AOP_IMMD);
391 switch ((aop->size=getSize(OP_SYMBOL(op)->type)))
395 sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
397 case 3: // generic pointer
398 sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
399 sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
404 bailOut ("aopForVal: unknown type");
408 static int aopOp(operand *op,
409 bool canUsePointer, bool canUseOffset) {
412 op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset);
416 op->aop=aopForVal (op);
420 bailOut("aopOp: unexpected operand");
424 bool aopEqual(asmop *aop1, asmop *aop2, int offset) {
425 if (strcmp(aop1->name[offset], aop2->name[offset])) {
431 bool aopIsDir(operand *op) {
432 return AOP_TYPE(op)==AOP_DIR;
435 bool aopIsBit(operand *op) {
436 return AOP_TYPE(op)==AOP_BIT;
439 bool aopIsPtr(operand *op) {
440 if (AOP_TYPE(op)==AOP_STK ||
441 AOP_TYPE(op)==AOP_CODE ||
442 AOP_TYPE(op)==AOP_FAR) {
449 char *opRegName(operand *op, int offset, char *opName, bool decorate) {
452 if (OP_SYMBOL(op)->onStack) {
453 sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
456 if (IS_TRUE_SYMOP(op))
457 return OP_SYMBOL(op)->rname;
458 else if (OP_SYMBOL(op)->regs[offset])
459 return OP_SYMBOL(op)->regs[offset]->name;
461 bailOut("opRegName: unknown regs");
465 switch (SPEC_NOUN(OP_VALUE(op)->type)) {
468 if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
469 SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
470 bailOut("opRegName: invalid bit value");
474 sprintf (opName, "#%s0x%02x", decorate?"(char)":"",
475 SPEC_CVAL(OP_VALUE(op)->type).v_int);
478 if (SPEC_LONG(OP_VALUE(op)->type)) {
479 sprintf (opName, "#%s0x%02lx", decorate?"(long)":"",
480 SPEC_CVAL(OP_VALUE(op)->type).v_long);
482 sprintf (opName, "#%s0x%02x", decorate?"(int)":"",
483 SPEC_CVAL(OP_VALUE(op)->type).v_int);
487 sprintf (opName, "#%s%f", decorate?"(float)":"",
488 SPEC_CVAL(OP_VALUE(op)->type).v_float);
491 bailOut("opRegName: unexpected noun");
495 bailOut("opRegName: unexpected operand type");
499 char * printOp (operand *op) {
500 static char line[132];
501 sym_link *optype=operandType(op);
502 bool isPtr = IS_PTR(optype);
505 symbol *sym=OP_SYMBOL(op);
506 if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
507 sym=SYM_SPIL_LOC(sym);
511 if (DCL_TYPE(optype)==FPOINTER)
512 strcat (line, "far * ");
513 else if (DCL_TYPE(optype)==CPOINTER)
514 strcat (line, "code * ");
515 else if (DCL_TYPE(optype)==GPOINTER)
516 strcat (line, "gen * ");
517 else if (DCL_TYPE(optype)==POINTER)
518 strcat (line, "near * ");
520 strcat (line, "unknown * ");
522 strcat (line, nounName(sym->etype));
524 strcat (line, sym->name);
527 sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
530 strcat (line, sym->regs[0]->name);
533 strcat (line, sym->regs[1]->name);
538 sprintf (line+strlen(line), "stack%+d", sym->stack);
541 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
542 strcat (line, "code");
545 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
546 strcat (line, "far");
549 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
550 strcat (line, "bit");
553 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
554 strcat (line, "dir");
557 strcat (line, "unknown");
559 } else if (IS_VALOP(op)) {
560 opRegName(op, 0, line, 1);
561 } else if (IS_TYPOP(op)) {
564 if (DCL_TYPE(optype)==FPOINTER)
565 strcat (line, "far * ");
566 else if (DCL_TYPE(optype)==CPOINTER)
567 strcat (line, "code * ");
568 else if (DCL_TYPE(optype)==GPOINTER)
569 strcat (line, "gen * ");
570 else if (DCL_TYPE(optype)==POINTER)
571 strcat (line, "near * ");
573 strcat (line, "unknown * ");
575 // forget about static, volatile, ... for now
576 if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
577 if (SPEC_LONG(operandType(op))) strcat (line, "long ");
578 strcat (line, nounName(operandType(op)));
581 bailOut("printOp: unexpected operand type");
586 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
589 sprintf (line, "%s(%d)", op, ic->lineno);
591 strcat (line, " result=");
592 strcat (line, printOp (IC_RESULT(ic)));
595 strcat (line, " left=");
596 strcat (line, printOp (IC_LEFT(ic)));
599 strcat (line, " right=");
600 strcat (line, printOp (IC_RIGHT(ic)));
602 emitcode (";", line);
605 /*-----------------------------------------------------------------*/
606 /* toBoolean - return carry for operand!=0 */
607 /*-----------------------------------------------------------------*/
608 static char *toBoolean (operand * op) {
609 symbol *tlbl=newiTempLabel(NULL);
611 switch (AOP_SIZE(op))
615 emitcode ("cjne", "%s,#1,%05d$; %s", AOP_NAME(op), tlbl->key+100,
616 "This needs a second thought");
618 emitcode ("", "%05d$:", tlbl->key+100);
622 bailOut("toBoolean: unknown size");
626 /*-----------------------------------------------------------------*/
627 /* regsInCommon - two operands have some registers in common */
628 /*-----------------------------------------------------------------*/
629 static bool regsInCommon (operand * op1, operand * op2) {
633 /* if they have registers in common */
634 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
637 sym1 = OP_SYMBOL (op1);
638 sym2 = OP_SYMBOL (op2);
640 if (sym1->nRegs == 0 || sym2->nRegs == 0)
643 for (i = 0; i < sym1->nRegs; i++)
649 for (j = 0; j < sym2->nRegs; j++)
654 if (sym2->regs[j] == sym1->regs[i])
662 /*-----------------------------------------------------------------*/
663 /* resultRemat - result is rematerializable */
664 /*-----------------------------------------------------------------*/
665 static int resultRemat (iCode * ic) {
666 if (SKIP_IC (ic) || ic->op == IFX)
669 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
671 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
672 if (sym->remat && !POINTER_SET (ic))
679 /*-----------------------------------------------------------------*/
680 /* genNot - generate code for ! operation */
681 /*-----------------------------------------------------------------*/
682 static void genNot (iCode * ic) {
683 printIc("genNot:", ic, 1,1,0);
686 /*-----------------------------------------------------------------*/
687 /* genCpl - generate code for complement */
688 /*-----------------------------------------------------------------*/
689 static void genCpl (iCode * ic) {
690 printIc("genCpl", ic, 1,1,0);
693 /*-----------------------------------------------------------------*/
694 /* genUminus - unary minus code generation */
695 /*-----------------------------------------------------------------*/
696 static void genUminus (iCode * ic) {
697 printIc("genUminus", ic, 1,1,0);
700 /*-----------------------------------------------------------------*/
701 /* genIpush - generate code for pushing */
702 /*-----------------------------------------------------------------*/
703 static void genIpush (iCode * ic) {
704 operand *left=IC_LEFT(ic);
706 printIc ("genIpush", ic, 0,1,0);
707 aopOp(left,FALSE,FALSE);
708 if (AOP_TYPE(left)==AOP_LIT) {
709 switch (AOP_SIZE(left))
712 emitcode ("mov", "r1l,%s", AOP_NAME(left)[0]);
713 emitcode ("push", "r1l");
716 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
717 emitcode ("push", "r1");
720 emitcode ("mov", "r1l,%s", AOP_NAME(left)[1]);
721 emitcode ("push", "r1l");
722 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
723 emitcode ("push", "r1");
726 emitcode ("mov", "r1,%s", AOP_NAME(left)[1]);
727 emitcode ("push", "r1");
728 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
729 emitcode ("push", "r1");
733 if (AOP_SIZE(left)>2) {
734 emitcode ("push", "%s", AOP_NAME(left)[1]);
736 emitcode ("push", "%s", AOP_NAME(left)[0]);
740 /*-----------------------------------------------------------------*/
741 /* genIpop - recover the registers: can happen only for spilling */
742 /*-----------------------------------------------------------------*/
743 static void genIpop (iCode * ic) {
744 printIc ("genIpop", ic, 0,1,0);
747 /*-----------------------------------------------------------------*/
748 /* genCall - generates a call statement */
749 /*-----------------------------------------------------------------*/
750 static void genCall (iCode * ic) {
751 operand *result=IC_RESULT(ic);
753 emitcode (";", "genCall(%d) %s result=%s", ic->lineno,
754 OP_SYMBOL(IC_LEFT(ic))->name,
755 printOp (IC_RESULT(ic)));
756 emitcode ("call", "%s", OP_SYMBOL(IC_LEFT(ic))->rname);
758 /* if we need to assign a result value */
759 if (IS_ITEMP (IC_RESULT(ic)) &&
760 OP_SYMBOL (IC_RESULT (ic))->nRegs) {
761 aopOp(result,FALSE,FALSE);
762 switch (AOP_SIZE(result))
765 emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
768 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
772 emitcode ("mov", "%s,r1l", AOP_NAME(result)[1]);
773 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
776 emitcode ("mov", "%s,r1", AOP_NAME(result)[1]);
777 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
784 /*-----------------------------------------------------------------*/
785 /* genPcall - generates a call by pointer statement */
786 /*-----------------------------------------------------------------*/
788 genPcall (iCode * ic)
790 emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
793 /*-----------------------------------------------------------------*/
794 /* genFunction - generated code for function entry */
795 /*-----------------------------------------------------------------*/
796 static void genFunction (iCode * ic) {
797 symbol *sym=OP_SYMBOL(IC_LEFT(ic));
798 sym_link *type=sym->type;
800 emitcode (";", "genFunction %s", sym->rname);
802 /* print the allocation information */
803 printAllocInfo (currFunc, codeOutFile);
805 emitcode ("", "%s:", sym->rname);
807 if (IFFUNC_ISNAKED(type))
809 emitcode(";", "naked function: no prologue.");
813 /* adjust the stack for locals used in this function */
815 emitcode ("sub", "r7,#%d\t; create stack space for locals", sym->stack);
819 /*-----------------------------------------------------------------*/
820 /* genEndFunction - generates epilogue for functions */
821 /*-----------------------------------------------------------------*/
823 genEndFunction (iCode * ic)
825 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
827 printIc ("genEndFunction", ic, 0,0,0);
829 if (IFFUNC_ISNAKED(sym->type)) {
830 emitcode(";", "naked function: no epilogue.");
834 /* readjust the stock for locals used in this function */
836 emitcode ("add", "r7,#%d\t; release stack space for locals", sym->stack);
839 if (IFFUNC_ISISR(sym->type)) {
840 emitcode ("reti", "");
842 emitcode ("ret", "");
846 /*-----------------------------------------------------------------*/
847 /* genRet - generate code for return statement */
848 /*-----------------------------------------------------------------*/
849 static void genRet (iCode * ic) {
851 printIc ("genRet", ic, 0,1,0);
853 aopOp(IC_LEFT(ic), TRUE, TRUE);
855 switch (AOP_SIZE(IC_LEFT(ic)))
858 emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
859 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
862 emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
865 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
868 emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
874 /*-----------------------------------------------------------------*/
875 /* genLabel - generates a label */
876 /*-----------------------------------------------------------------*/
877 static void genLabel (iCode * ic) {
878 /* special case never generate */
879 if (IC_LABEL (ic) == entryLabel)
882 emitcode (";", "genLabel %s", IC_LABEL(ic)->name);
883 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
886 /*-----------------------------------------------------------------*/
887 /* genGoto - generates a jmp */
888 /*-----------------------------------------------------------------*/
889 static void genGoto (iCode * ic) {
890 emitcode (";", "genGoto %s", IC_LABEL(ic)->name);
891 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
894 /*-----------------------------------------------------------------*/
895 /* genPlus - generates code for addition */
896 /*-----------------------------------------------------------------*/
897 static void genPlus (iCode * ic) {
898 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
902 printIc ("genPlus", ic, 1,1,1);
904 size=aopOp(result, TRUE, TRUE);
906 /* if left is a literal, then exchange them */
907 if (IS_LITERAL(operandType(left))) {
908 operand *tmp = right;
913 if (aopIsBit(result)) {
914 if (IS_LITERAL(operandType(right))) {
915 if (operandLitValue(right)) {
916 emitcode ("setb", AOP_NAME(result)[0]);
919 aopOp(left, TRUE, TRUE);
920 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
923 bailOut("genPlus: unfinished genPlus bit");
926 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
927 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
934 if (!aopEqual(result->aop, left->aop, 0)) {
935 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
937 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
939 if (!aopEqual(result->aop, left->aop, 1)) {
940 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
945 emitcode ("addc.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
951 /*-----------------------------------------------------------------*/
952 /* genMinus - generates code for subtraction */
953 /*-----------------------------------------------------------------*/
954 static void genMinus (iCode * ic) {
955 printIc ("genMinus", ic, 1,1,1);
959 /*-----------------------------------------------------------------*/
960 /* genMult - generates code for multiplication */
961 /*-----------------------------------------------------------------*/
962 static void genMult (iCode * ic) {
963 printIc ("genMult", ic, 1,1,1);
966 /*-----------------------------------------------------------------*/
967 /* genDiv - generates code for division */
968 /*-----------------------------------------------------------------*/
969 static void genDiv (iCode * ic) {
970 printIc ("genDiv", ic, 1,1,1);
973 /*-----------------------------------------------------------------*/
974 /* genMod - generates code for division */
975 /*-----------------------------------------------------------------*/
976 static void genMod (iCode * ic) {
977 printIc ("genMod", ic, 1,1,1);
980 /*-----------------------------------------------------------------*/
981 /* genCmpGt :- greater than comparison */
982 /*-----------------------------------------------------------------*/
983 static void genCmpGt (iCode * ic) {
984 printIc ("genCmpGt", ic, 1,1,1);
986 /*-----------------------------------------------------------------*/
987 /* genCmpGt :- greater than comparison */
988 /*-----------------------------------------------------------------*/
989 static void genCmpLe (iCode * ic) {
990 printIc ("genCmpLe", ic, 1,1,1);
992 /*-----------------------------------------------------------------*/
993 /* genCmpGt :- greater than comparison */
994 /*-----------------------------------------------------------------*/
995 static void genCmpGe (iCode * ic) {
996 printIc ("genCmpGe", ic, 1,1,1);
998 /*-----------------------------------------------------------------*/
999 /* genCmpGt :- greater than comparison */
1000 /*-----------------------------------------------------------------*/
1001 static void genCmpNe (iCode * ic) {
1002 printIc ("genCmpNe", ic, 1,1,1);
1004 /*-----------------------------------------------------------------*/
1005 /* genCmpLt - less than comparisons */
1006 /*-----------------------------------------------------------------*/
1007 static void genCmpLt (iCode * ic) {
1008 printIc ("genCmpLt", ic, 1,1,1);
1010 /*-----------------------------------------------------------------*/
1011 /* genCmpEq - generates code for equal to */
1012 /*-----------------------------------------------------------------*/
1013 static void genCmpEq (iCode * ic) {
1014 printIc ("genCmpEq", ic, 1,1,1);
1017 /*-----------------------------------------------------------------*/
1018 /* ifxForOp - returns the icode containing the ifx for operand */
1019 /*-----------------------------------------------------------------*/
1020 static iCode *ifxForOp (operand * op, iCode * ic) {
1021 /* if true symbol then needs to be assigned */
1022 if (IS_TRUE_SYMOP (op))
1025 /* if this has register type condition and
1026 the next instruction is ifx with the same operand
1027 and live to of the operand is upto the ifx only then */
1029 ic->next->op == IFX &&
1030 IC_COND (ic->next)->key == op->key &&
1031 OP_SYMBOL (op)->liveTo <= ic->next->seq)
1037 /*-----------------------------------------------------------------*/
1038 /* hasInc - operand is incremented before any other use */
1039 /*-----------------------------------------------------------------*/
1040 static iCode *hasInc (operand *op, iCode *ic, int osize) {
1041 sym_link *type = operandType(op);
1042 sym_link *retype = getSpec (type);
1043 iCode *lic = ic->next;
1046 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
1047 if (!IS_SYMOP(op)) return NULL;
1049 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
1050 if (IS_AGGREGATE(type->next)) return NULL;
1051 if (osize != (isize = getSize(type->next))) return NULL;
1054 /* if operand of the form op = op + <sizeof *op> */
1055 if (lic->op == '+') {
1056 if (isOperandEqual(IC_LEFT(lic),op) &&
1057 //isOperandEqual(IC_RESULT(lic),op) &&
1058 isOperandLiteral(IC_RIGHT(lic)) &&
1059 operandLitValue(IC_RIGHT(lic)) == isize) {
1060 emitcode (";", "Found hasInc");
1064 /* if the operand used or deffed */
1065 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
1068 /* if GOTO or IFX */
1069 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1075 /*-----------------------------------------------------------------*/
1076 /* genAndOp - for && operation */
1077 /*-----------------------------------------------------------------*/
1078 static void genAndOp (iCode * ic) {
1079 printIc ("genAndOp(&&)", ic, 1,1,1);
1082 /*-----------------------------------------------------------------*/
1083 /* genOrOp - for || operation */
1084 /*-----------------------------------------------------------------*/
1085 static void genOrOp (iCode * ic) {
1086 printIc ("genOrOp(||)", ic, 1,1,1);
1089 /*-----------------------------------------------------------------*/
1090 /* genAnd - code for and */
1091 /*-----------------------------------------------------------------*/
1092 static void genAnd (iCode * ic, iCode * ifx) {
1093 printIc ("genAnd", ic, 1,1,1);
1096 /*-----------------------------------------------------------------*/
1097 /* genOr - code for or */
1098 /*-----------------------------------------------------------------*/
1099 static void genOr (iCode * ic, iCode * ifx) {
1100 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1104 printIc ("genOr", ic, 1,1,1);
1106 size=aopOp(result, TRUE, TRUE);
1108 /* if left is a literal, then exchange them */
1109 if (IS_LITERAL(operandType(left))) {
1110 operand *tmp = right;
1115 if (aopIsBit(result)) {
1116 if (IS_LITERAL(operandType(right))) {
1117 if (operandLitValue(right)) {
1118 emitcode ("setb", AOP_NAME(result)[0]);
1121 aopOp(left, TRUE, TRUE);
1122 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1127 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1128 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1135 if (!aopEqual(result->aop, left->aop, 0)) {
1136 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1138 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1140 if (!aopEqual(result->aop, left->aop, 1)) {
1141 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1143 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1148 /*-----------------------------------------------------------------*/
1149 /* genXor - code for xclusive or */
1150 /*-----------------------------------------------------------------*/
1151 static void genXor (iCode * ic, iCode * ifx) {
1152 printIc ("genXor", ic, 1,1,1);
1155 /*-----------------------------------------------------------------*/
1156 /* genInline - write the inline code out */
1157 /*-----------------------------------------------------------------*/
1158 static void genInline (iCode * ic) {
1160 printIc ("genInline", ic, 0,0,0);
1162 emitcode ("", IC_INLINE(ic));
1165 /*-----------------------------------------------------------------*/
1166 /* genRRC - rotate right with carry */
1167 /*-----------------------------------------------------------------*/
1168 static void genRRC (iCode * ic) {
1169 printIc ("genRRC", ic, 1,1,0);
1172 /*-----------------------------------------------------------------*/
1173 /* genRLC - generate code for rotate left with carry */
1174 /*-----------------------------------------------------------------*/
1175 static void genRLC (iCode * ic) {
1176 printIc ("genRLC", ic, 1,1,0);
1179 /*-----------------------------------------------------------------*/
1180 /* genGetHbit - generates code get highest order bit */
1181 /*-----------------------------------------------------------------*/
1182 static void genGetHbit (iCode * ic) {
1183 printIc ("genGetHbit", ic, 1,1,0);
1186 /*-----------------------------------------------------------------*/
1187 /* genLeftShift - generates code for left shifting */
1188 /*-----------------------------------------------------------------*/
1189 static void genLeftShift (iCode * ic) {
1190 printIc ("genLeftShift", ic, 1,1,1);
1193 /*-----------------------------------------------------------------*/
1194 /* genRightShift - generate code for right shifting */
1195 /*-----------------------------------------------------------------*/
1196 static void genRightShift (iCode * ic) {
1197 printIc ("genRightShift", ic, 1,1,1);
1200 /*-----------------------------------------------------------------*/
1201 /* genPointerGet - generate code for pointer get */
1202 /*-----------------------------------------------------------------*/
1203 static void genPointerGet (iCode * ic, iCode *pi) {
1204 char *instr, *scratchReg;
1205 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1206 bool codePointer=IS_CODEPTR(operandType(left));
1209 printIc ("genPointerGet", ic, 1,1,0);
1211 if (!IS_PTR(operandType(left))) {
1212 bailOut ("genPointerGet: pointer required");
1215 aopOp(left,FALSE,FALSE);
1216 size=aopOp(result,TRUE,aopIsDir(left));
1218 if (IS_GENPTR(operandType(left))) {
1219 symbol *tlbl1=newiTempLabel(NULL);
1220 symbol *tlbl2=newiTempLabel(NULL);
1221 emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1222 emitcode ("bne", "%05d$", tlbl1->key+100);
1225 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1228 emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1232 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1234 emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1237 emitcode ("br", "%05d$", tlbl2->key+100);
1238 emitcode ("", "%05d$:", tlbl1->key+100);
1241 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1244 emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1245 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1249 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1251 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1254 emitcode ("", "%05d$:", tlbl2->key+100);
1258 switch (AOP_TYPE(left))
1276 if (AOP_TYPE(result)==AOP_STK) {
1277 emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1278 emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1281 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0],
1286 emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1287 emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1289 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0],
1303 if (AOP_TYPE(result)==AOP_STK) {
1304 emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1305 emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1308 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1],
1312 emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1314 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1],
1322 bailOut ("genPointerGet");
1325 /*-----------------------------------------------------------------*/
1326 /* genPointerSet - stores the value into a pointer location */
1327 /*-----------------------------------------------------------------*/
1328 static void genPointerSet (iCode * ic, iCode *pi) {
1330 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1333 printIc ("genPointerSet", ic, 1,0,1);
1335 if (!IS_PTR(operandType(result))) {
1336 bailOut ("genPointerSet: pointer required");
1339 aopOp(result,FALSE,FALSE);
1340 size=aopOp(right,FALSE, FALSE);
1342 if (IS_GENPTR(operandType(result))) {
1343 emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s",
1344 AOP_NAME(result)[0], AOP_NAME(result)[1],
1345 AOP_NAME(right)[0], AOP_NAME(right)[1]);
1349 switch (AOP_TYPE(right))
1359 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1362 emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1369 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0],
1370 AOP_NAME(right)[1]);
1372 emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0],
1373 AOP_NAME(right)[1]);
1378 bailOut ("genPointerSet");
1381 /*-----------------------------------------------------------------*/
1382 /* genIfx - generate code for Ifx statement */
1383 /*-----------------------------------------------------------------*/
1384 static void genIfx (iCode * ic, iCode * popIc) {
1388 symbol *jlbl, *tlbl;
1389 operand *cond=IC_COND(ic);
1391 emitcode (";", "genIfx cond=%s trueLabel:%s falseLabel:%s",
1393 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1394 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1396 size=aopOp(cond,TRUE,TRUE);
1406 switch (AOP_TYPE(cond) )
1409 emitcode (trueOrFalse ? "jb" : "jbc", "%s,%05d$",
1410 AOP_NAME(cond)[0], jlbl->key+100);
1416 tlbl=newiTempLabel(NULL);
1422 emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1423 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1426 // generic pointer, forget the generic part
1428 emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1429 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1432 emitcode ("jmp", "%05d$", jlbl->key+100);
1433 emitcode ("", "%05d$:", tlbl->key+100);
1439 /*-----------------------------------------------------------------*/
1440 /* genAddrOf - generates code for address of */
1441 /*-----------------------------------------------------------------*/
1442 static void genAddrOf (iCode * ic) {
1444 operand *left=IC_LEFT(ic);
1446 printIc ("genAddrOf", ic, 1,1,0);
1448 size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1450 if (isOperandOnStack(left)) {
1451 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1452 getStackOffset(OP_SYMBOL(left)->stack));
1454 // this must be a generic pointer
1455 emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1460 if (isOperandInDirSpace(left) ||
1461 isOperandInFarSpace(left) ||
1462 isOperandInCodeSpace(left)) {
1463 emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1464 OP_SYMBOL(left)->rname);
1466 // this must be a generic pointer
1467 int space=0; // dir space
1468 if (isOperandInFarSpace(left)) {
1470 } else if (isOperandInCodeSpace(left)) {
1473 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1478 bailOut("genAddrOf");
1481 /*-----------------------------------------------------------------*/
1482 /* genAssign - generate code for assignment */
1483 /*-----------------------------------------------------------------*/
1484 static void genAssign (iCode * ic) {
1485 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1489 printIc ("genAssign", ic, 1,0,1);
1491 if (!IS_SYMOP(result)) {
1492 bailOut("genAssign: result is not a symbol");
1495 aopOp(result, TRUE, TRUE);
1496 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1497 size=AOP_SIZE(result);
1499 /* if result is a bit */
1500 if (AOP_TYPE(result) == AOP_BIT) {
1501 /* if right is literal, we know what the value is */
1502 if (AOP_TYPE(right) == AOP_LIT) {
1503 if (operandLitValue(right)) {
1504 emitcode ("setb", AOP_NAME(result)[0]);
1506 emitcode ("clr", AOP_NAME(result)[0]);
1510 /* if right is also a bit */
1511 if (AOP_TYPE(right) == AOP_BIT) {
1512 emitcode ("mov", "c,%s", AOP_NAME(right));
1513 emitcode ("mov", "%s,c", AOP_NAME(result));
1517 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1527 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1534 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1539 /*-----------------------------------------------------------------*/
1540 /* genJumpTab - genrates code for jump table */
1541 /*-----------------------------------------------------------------*/
1542 static void genJumpTab (iCode * ic) {
1543 printIc ("genJumpTab", ic, 0,0,0);
1546 /*-----------------------------------------------------------------*/
1547 /* genCast - gen code for casting */
1548 /*-----------------------------------------------------------------*/
1549 static void genCast (iCode * ic) {
1550 printIc ("genCast", ic, 1,1,1);
1553 /*-----------------------------------------------------------------*/
1554 /* genDjnz - generate decrement & jump if not zero instrucion */
1555 /*-----------------------------------------------------------------*/
1556 static bool genDjnz (iCode * ic, iCode * ifx) {
1562 /* if the if condition has a false label
1563 then we cannot save */
1567 /* if the minus is not of the form
1569 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1570 !IS_OP_LITERAL (IC_RIGHT (ic)))
1573 if (operandLitValue (IC_RIGHT (ic)) != 1)
1576 /* if the size of this greater than two then no
1578 if (getSize (operandType (IC_RESULT (ic))) > 2)
1581 printIc ("genDjnz", ic, 1,1,1);
1583 /* otherwise we can save BIG */
1584 lbl = newiTempLabel (NULL);
1585 lbl1 = newiTempLabel (NULL);
1587 aopOp (IC_RESULT (ic), FALSE, TRUE);
1589 if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1590 emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1591 emitcode ("br", "%05d$", lbl1->key + 100);
1592 emitcode ("", "%05d$:", lbl->key + 100);
1593 emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1594 emitcode ("", "%05d$:", lbl1->key + 100);
1598 bailOut("genDjnz: aop type");
1602 /*-----------------------------------------------------------------*/
1603 /* genReceive - generate code for a receive iCode */
1604 /*-----------------------------------------------------------------*/
1605 static void genReceive (iCode * ic) {
1606 printIc ("genReceive", ic, 1,0,0);
1609 /*-----------------------------------------------------------------*/
1610 /* gen51Code - generate code for 8051 based controllers */
1611 /*-----------------------------------------------------------------*/
1612 void genXA51Code (iCode * lic) {
1616 lineHead = lineCurr = NULL;
1618 /* if debug information required */
1619 if (options.debug && currFunc)
1621 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1623 if (IS_STATIC (currFunc->etype))
1624 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1626 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1630 for (ic = lic; ic; ic = ic->next) {
1631 if (ic->lineno && cln != ic->lineno) {
1632 if (options.debug) {
1634 emitcode ("", "C$%s$%d$%d$%d ==.",
1635 FileBaseName (ic->filename), ic->lineno,
1636 ic->level, ic->block);
1639 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1640 printCLine(ic->filename, ic->lineno));
1643 /* if the result is marked as
1644 spilt and rematerializable or code for
1645 this has already been generated then
1647 if (resultRemat (ic) || ic->generated)
1650 /* depending on the operation */
1670 /* IPOP happens only when trying to restore a
1671 spilt live range, if there is an ifx statement
1672 following this pop then the if statement might
1673 be using some of the registers being popped which
1674 would destory the contents of the register so
1675 we need to check for this condition and handle it */
1677 ic->next->op == IFX &&
1678 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1679 genIfx (ic->next, ic);
1697 genEndFunction (ic);
1717 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1766 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1770 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1774 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1801 case GET_VALUE_AT_ADDRESS:
1802 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
1806 if (POINTER_SET (ic))
1807 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1833 addSet (&_G.sendSet, ic);
1842 /* now we are ready to call the
1843 peep hole optimizer */
1844 if (!options.nopeep)
1845 peepHole (&lineHead);
1847 /* now do the actual printing */
1848 printLine (lineHead, codeOutFile);