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 */
84 extern int xa51_ptrRegReq;
85 extern int xa51_nRegs;
86 extern FILE *codeOutFile;
88 static lineNode *lineHead = NULL;
89 static lineNode *lineCurr = NULL;
96 static char *MOV="mov";
97 static char *MOVB="mov.b";
98 static char *MOVW="mov.w";
99 static char *MOVC="movc";
100 static char *MOVCB="movc.b";
101 static char *MOVCW="movc.w";
103 static char *R1L="r1l";
104 static char *R1="r1";
106 void bailOut (char *mesg) {
107 fprintf (stderr, "%s: bailing out\n", mesg);
111 /*-----------------------------------------------------------------*/
112 /* emitcode - writes the code into a file : for now it is simple */
113 /*-----------------------------------------------------------------*/
114 static void emitcode (char *inst, char *fmt,...) {
116 char lb[INITIAL_INLINEASM];
124 sprintf (lb, "%s\t", inst);
126 sprintf (lb, "%s", inst);
127 vsprintf (lb + (strlen (lb)), fmt, ap);
130 vsprintf (lb, fmt, ap);
132 while (isspace ((int)*lbp))
136 lineCurr = (lineCurr ?
137 connectLine (lineCurr, newLineNode (lb)) :
138 (lineHead = newLineNode (lb)));
139 lineCurr->isInline = _G.inLine;
140 lineCurr->isDebug = _G.debugLine;
144 char *getStackOffset(int stack) {
145 static char gsoBuf[1024];
146 sprintf (gsoBuf, "r7+(%d%+d%+d)", stack,
147 currFunc->stack, _G.nRegsSaved);
151 /*-----------------------------------------------------------------*/
152 /* newAsmop - creates a new asmOp */
153 /*-----------------------------------------------------------------*/
155 newAsmop (short type)
159 aop = Safe_calloc (1, sizeof (asmop));
164 char *aopTypeName(asmop *aop) {
167 case AOP_LIT: return "lit";
168 case AOP_REG: return "reg";
169 case AOP_DIR: return "dir";
170 case AOP_FAR: return "far";
171 case AOP_CODE: return "code";
172 case AOP_GPTR: return "gptr";
173 case AOP_STK: return "stack";
174 case AOP_IMMD: return "imm";
175 case AOP_BIT: return "bit";
180 /*-----------------------------------------------------------------*/
181 /* aopForSym - for a true symbol */
182 /*-----------------------------------------------------------------*/
183 static asmop *aopForSym(symbol *sym,
184 bool canUsePointer, bool canUseOffset) {
188 sym->aop = aop = newAsmop(0);
189 size=aop->size=getSize(sym->type);
191 // if the sym has registers
192 if (sym->nRegs && sym->regs[0]) {
194 sprintf (aop->name[0], sym->regs[0]->name);
196 sprintf (aop->name[1], sym->regs[1]->name);
203 if (!canUsePointer || !canUseOffset) {
208 emitcode ("mov.b", "r0l,[%s]", getStackOffset(sym->stack));
209 sprintf (aop->name[0], "r0l");
212 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
213 sprintf (aop->name[0], "r0");
216 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
217 sprintf (aop->name[0], "r0");
218 emitcode ("mov.b", "r1l,[%s]", getStackOffset(sym->stack+2));
219 sprintf (aop->name[1], "r1l");
222 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
223 sprintf (aop->name[0], "r0");
224 emitcode ("mov.w", "r1,[%s]", getStackOffset(sym->stack+2));
225 sprintf (aop->name[1], "r1");
230 sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
232 sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
237 // if it has a spillLoc
238 if (sym->usl.spillLoc) {
239 return aopForSym (sym->usl.spillLoc, canUsePointer, canUseOffset);
243 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
245 sprintf (aop->name[0], sym->rname);
249 // if in direct space
250 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
252 sprintf (aop->name[0], sym->rname);
254 sprintf (aop->name[1], "%s+2", sym->rname);
260 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
261 if (!canUsePointer) {
266 emitcode (MOV, "r0,#%s", sym->rname);
267 emitcode (MOVC, "r0l,[r0]");
268 sprintf (aop->name[0], "r0l");
271 emitcode (MOV, "r0,#%s", sym->rname);
272 emitcode (MOVC, "r0,[r0]");
273 sprintf (aop->name[0], "r0");
276 emitcode (MOV, "r0,#%s", sym->rname);
277 emitcode (MOVC, "r1l,[r0+2]");
278 sprintf (aop->name[1], "r1l");
279 emitcode (MOV, "r0,[r0]");
280 sprintf (aop->name[0], "r0");
283 emitcode (MOV, "r0,#%s", sym->rname);
284 emitcode (MOVC, "r1,[r0+2]");
285 sprintf (aop->name[1], "r1");
286 emitcode (MOVC, "r0,[r0]");
287 sprintf (aop->name[0], "r0");
293 emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
294 sprintf (aop->name[0], "[r0]");
296 sprintf (aop->name[1], "[r0+2]");
303 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
304 if (!canUsePointer) {
309 emitcode (MOV, "r0,#%s", sym->rname);
310 emitcode (MOV, "r0l,[r0]");
311 sprintf (aop->name[0], "r0l");
314 emitcode (MOV, "r0,#%s", sym->rname);
315 emitcode (MOV, "r0,[r0]");
316 sprintf (aop->name[0], "r0");
319 emitcode (MOV, "r0,#%s", sym->rname);
320 emitcode (MOV, "r1l,[r0+2]");
321 sprintf (aop->name[1], "r1l");
322 emitcode (MOV, "r0,[r0]");
323 sprintf (aop->name[0], "r0");
326 emitcode (MOV, "r0,#%s", sym->rname);
327 emitcode (MOV, "r1,[r0+2]");
328 sprintf (aop->name[1], "r1");
329 emitcode (MOV, "r0,[r0]");
330 sprintf (aop->name[0], "r0");
335 emitcode ("mov.w", "r0,#%s ; aopForSym:far", sym->rname);
336 sprintf (aop->name[0], "[r0]");
338 sprintf (aop->name[1], "[r0+2]");
344 bailOut("aopForSym");
348 /*-----------------------------------------------------------------*/
349 /* aopForVal - for a value */
350 /*-----------------------------------------------------------------*/
351 static asmop *aopForVal(operand *op) {
354 if (IS_OP_LITERAL(op)) {
355 op->aop = aop = newAsmop (AOP_LIT);
356 switch ((aop->size=getSize(operandType(op))))
359 sprintf (aop->name[0], "#0x%02x",
360 SPEC_CVAL(operandType(op)).v_int & 0xff);
361 sprintf (aop->name[1], "#0");
364 sprintf (aop->name[0], "#0x%04x",
365 SPEC_CVAL(operandType(op)).v_int & 0xffff);
366 sprintf (aop->name[1], "#0");
369 // must be a generic pointer, can only be zero
370 // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
371 sprintf (aop->name[0], "#0x%04x",
372 SPEC_CVAL(operandType(op)).v_uint & 0xffff);
373 sprintf (aop->name[1], "#0");
376 sprintf (aop->name[0], "#0x%04lx",
377 SPEC_CVAL(operandType(op)).v_ulong & 0xffff);
378 sprintf (aop->name[1], "#0x%04lx",
379 SPEC_CVAL(operandType(op)).v_ulong >> 16);
382 bailOut("aopForVal");
389 op->aop = aop = newAsmop (AOP_IMMD);
390 switch ((aop->size=getSize(OP_SYMBOL(op)->type)))
394 sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
396 case 3: // generic pointer
397 sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
398 sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
403 bailOut ("aopForVal: unknown type");
407 static int aopOp(operand *op,
408 bool canUsePointer, bool canUseOffset) {
411 op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset);
415 op->aop=aopForVal (op);
419 bailOut("aopOp: unexpected operand");
423 bool aopEqual(asmop *aop1, asmop *aop2, int offset) {
424 if (strcmp(aop1->name[offset], aop2->name[offset])) {
430 bool aopIsDir(operand *op) {
431 return AOP_TYPE(op)==AOP_DIR;
434 bool aopIsBit(operand *op) {
435 return AOP_TYPE(op)==AOP_BIT;
438 bool aopIsPtr(operand *op) {
439 if (AOP_TYPE(op)==AOP_STK ||
440 AOP_TYPE(op)==AOP_CODE ||
441 AOP_TYPE(op)==AOP_FAR) {
448 char *opRegName(operand *op, int offset, char *opName, bool decorate) {
451 if (OP_SYMBOL(op)->onStack) {
452 sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
455 if (IS_TRUE_SYMOP(op))
456 return OP_SYMBOL(op)->rname;
457 else if (OP_SYMBOL(op)->regs[offset])
458 return OP_SYMBOL(op)->regs[offset]->name;
460 bailOut("opRegName: unknown regs");
464 switch (SPEC_NOUN(OP_VALUE(op)->type)) {
467 if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
468 SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
469 bailOut("opRegName: invalid bit value");
473 sprintf (opName, "#%s0x%02x", decorate?"(char)":"",
474 SPEC_CVAL(OP_VALUE(op)->type).v_int);
477 if (SPEC_LONG(OP_VALUE(op)->type)) {
478 sprintf (opName, "#%s0x%02lx", decorate?"(long)":"",
479 SPEC_CVAL(OP_VALUE(op)->type).v_long);
481 sprintf (opName, "#%s0x%02x", decorate?"(int)":"",
482 SPEC_CVAL(OP_VALUE(op)->type).v_int);
486 sprintf (opName, "#%s%f", decorate?"(float)":"",
487 SPEC_CVAL(OP_VALUE(op)->type).v_float);
490 bailOut("opRegName: unexpected noun");
494 bailOut("opRegName: unexpected operand type");
498 char * printOp (operand *op) {
499 static char line[132];
500 sym_link *optype=operandType(op);
501 bool isPtr = IS_PTR(optype);
504 symbol *sym=OP_SYMBOL(op);
505 if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
506 sym=SYM_SPIL_LOC(sym);
510 if (DCL_TYPE(optype)==FPOINTER)
511 strcat (line, "far * ");
512 else if (DCL_TYPE(optype)==CPOINTER)
513 strcat (line, "code * ");
514 else if (DCL_TYPE(optype)==GPOINTER)
515 strcat (line, "gen * ");
516 else if (DCL_TYPE(optype)==POINTER)
517 strcat (line, "near * ");
519 strcat (line, "unknown * ");
521 strcat (line, nounName(sym->etype));
523 strcat (line, sym->name);
526 sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
529 strcat (line, sym->regs[0]->name);
532 strcat (line, sym->regs[1]->name);
537 sprintf (line+strlen(line), "stack%+d", sym->stack);
540 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
541 strcat (line, "code");
544 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
545 strcat (line, "far");
548 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
549 strcat (line, "bit");
552 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
553 strcat (line, "dir");
556 strcat (line, "unknown");
558 } else if (IS_VALOP(op)) {
559 opRegName(op, 0, line, 1);
560 } else if (IS_TYPOP(op)) {
563 if (DCL_TYPE(optype)==FPOINTER)
564 strcat (line, "far * ");
565 else if (DCL_TYPE(optype)==CPOINTER)
566 strcat (line, "code * ");
567 else if (DCL_TYPE(optype)==GPOINTER)
568 strcat (line, "gen * ");
569 else if (DCL_TYPE(optype)==POINTER)
570 strcat (line, "near * ");
572 strcat (line, "unknown * ");
574 // forget about static, volatile, ... for now
575 if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
576 if (SPEC_LONG(operandType(op))) strcat (line, "long ");
577 strcat (line, nounName(operandType(op)));
580 bailOut("printOp: unexpected operand type");
585 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
588 sprintf (line, "%s(%d)", op, ic->lineno);
590 strcat (line, " result=");
591 strcat (line, printOp (IC_RESULT(ic)));
594 strcat (line, " left=");
595 strcat (line, printOp (IC_LEFT(ic)));
598 strcat (line, " right=");
599 strcat (line, printOp (IC_RIGHT(ic)));
601 emitcode (";", line);
604 /*-----------------------------------------------------------------*/
605 /* toBoolean - return carry for operand!=0 */
606 /*-----------------------------------------------------------------*/
607 static char *toBoolean (operand * op) {
608 symbol *tlbl=newiTempLabel(NULL);
610 switch (AOP_SIZE(op))
614 emitcode ("cjne", "%s,#1,%05d$; %s", AOP_NAME(op), tlbl->key+100,
615 "This needs a second thought");
617 emitcode ("", "%05d$:", tlbl->key+100);
621 bailOut("toBoolean: unknown size");
625 /*-----------------------------------------------------------------*/
626 /* regsInCommon - two operands have some registers in common */
627 /*-----------------------------------------------------------------*/
628 static bool regsInCommon (operand * op1, operand * op2) {
632 /* if they have registers in common */
633 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
636 sym1 = OP_SYMBOL (op1);
637 sym2 = OP_SYMBOL (op2);
639 if (sym1->nRegs == 0 || sym2->nRegs == 0)
642 for (i = 0; i < sym1->nRegs; i++)
648 for (j = 0; j < sym2->nRegs; j++)
653 if (sym2->regs[j] == sym1->regs[i])
661 /*-----------------------------------------------------------------*/
662 /* resultRemat - result is rematerializable */
663 /*-----------------------------------------------------------------*/
664 static int resultRemat (iCode * ic) {
665 if (SKIP_IC (ic) || ic->op == IFX)
668 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
670 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
671 if (sym->remat && !POINTER_SET (ic))
678 /*-----------------------------------------------------------------*/
679 /* genNot - generate code for ! operation */
680 /*-----------------------------------------------------------------*/
681 static void genNot (iCode * ic) {
682 printIc("genNot:", ic, 1,1,0);
685 /*-----------------------------------------------------------------*/
686 /* genCpl - generate code for complement */
687 /*-----------------------------------------------------------------*/
688 static void genCpl (iCode * ic) {
689 printIc("genCpl", ic, 1,1,0);
692 /*-----------------------------------------------------------------*/
693 /* genUminus - unary minus code generation */
694 /*-----------------------------------------------------------------*/
695 static void genUminus (iCode * ic) {
696 printIc("genUminus", ic, 1,1,0);
699 /*-----------------------------------------------------------------*/
700 /* genIpush - generate code for pushing */
701 /*-----------------------------------------------------------------*/
702 static void genIpush (iCode * ic) {
703 operand *left=IC_LEFT(ic);
705 printIc ("genIpush", ic, 0,1,0);
706 aopOp(left,FALSE,FALSE);
709 if (AOP_TYPE(left)==AOP_LIT) {
710 switch (AOP_SIZE(left))
713 emitcode ("mov", "r1l,%s", AOP_NAME(left)[0]);
714 emitcode ("push", "r1l");
718 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
719 emitcode ("push", "r1");
723 emitcode ("mov", "r1l,%s", AOP_NAME(left)[1]);
724 emitcode ("push", "r1l");
725 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
726 emitcode ("push", "r1");
730 emitcode ("mov", "r1,%s", AOP_NAME(left)[1]);
731 emitcode ("push", "r1");
732 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
733 emitcode ("push", "r1");
738 if (AOP_SIZE(left)>2) {
739 emitcode ("push", "%s", AOP_NAME(left)[1]);
742 emitcode ("push", "%s", AOP_NAME(left)[0]);
747 /*-----------------------------------------------------------------*/
748 /* genIpop - recover the registers: can happen only for spilling */
749 /*-----------------------------------------------------------------*/
750 static void genIpop (iCode * ic) {
751 printIc ("genIpop", ic, 0,1,0);
754 /*-----------------------------------------------------------------*/
755 /* genCall - generates a call statement */
756 /*-----------------------------------------------------------------*/
757 static void genCall (iCode * ic) {
758 operand *result=IC_RESULT(ic);
760 emitcode (";", "genCall(%d) %s result=%s", ic->lineno,
761 OP_SYMBOL(IC_LEFT(ic))->name,
762 printOp (IC_RESULT(ic)));
763 emitcode ("call", "%s", OP_SYMBOL(IC_LEFT(ic))->rname);
765 /* readjust the stack if we have pushed some parms */
766 if (_G.parmsPushed) {
767 emitcode ("add", "r7,#0x%02x", _G.parmsPushed*2);
771 /* if we need to assign a result value */
772 if (IS_ITEMP (IC_RESULT(ic)) &&
773 OP_SYMBOL (IC_RESULT (ic))->nRegs) {
774 aopOp(result,FALSE,FALSE);
775 switch (AOP_SIZE(result))
778 emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
781 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
785 emitcode ("mov", "%s,r1l", AOP_NAME(result)[1]);
786 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
789 emitcode ("mov", "%s,r1", AOP_NAME(result)[1]);
790 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
797 /*-----------------------------------------------------------------*/
798 /* genPcall - generates a call by pointer statement */
799 /*-----------------------------------------------------------------*/
801 genPcall (iCode * ic)
803 emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
806 /*-----------------------------------------------------------------*/
807 /* genFunction - generated code for function entry */
808 /*-----------------------------------------------------------------*/
809 static void genFunction (iCode * ic) {
810 symbol *sym=OP_SYMBOL(IC_LEFT(ic));
811 sym_link *type=sym->type;
813 emitcode (";", "genFunction %s", sym->rname);
815 /* print the allocation information */
816 printAllocInfo (currFunc, codeOutFile);
818 emitcode ("", "%s:", sym->rname);
820 if (IFFUNC_ISNAKED(type))
822 emitcode(";", "naked function: no prologue.");
826 /* adjust the stack for locals used in this function */
828 emitcode ("sub", "r7,#%d\t; create stack space for locals", sym->stack);
832 /*-----------------------------------------------------------------*/
833 /* genEndFunction - generates epilogue for functions */
834 /*-----------------------------------------------------------------*/
836 genEndFunction (iCode * ic)
838 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
840 printIc ("genEndFunction", ic, 0,0,0);
842 if (IFFUNC_ISNAKED(sym->type)) {
843 emitcode(";", "naked function: no epilogue.");
847 /* readjust the stock for locals used in this function */
849 emitcode ("add", "r7,#%d\t; release stack space for locals", sym->stack);
852 if (IFFUNC_ISISR(sym->type)) {
853 emitcode ("reti", "");
855 emitcode ("ret", "");
859 /*-----------------------------------------------------------------*/
860 /* genRet - generate code for return statement */
861 /*-----------------------------------------------------------------*/
862 static void genRet (iCode * ic) {
864 printIc ("genRet", ic, 0,1,0);
866 aopOp(IC_LEFT(ic), TRUE, TRUE);
868 switch (AOP_SIZE(IC_LEFT(ic)))
871 emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
872 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
875 emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
878 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
881 emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
886 emitcode ("jmp", "%05d$", returnLabel->key+100);
889 /*-----------------------------------------------------------------*/
890 /* genLabel - generates a label */
891 /*-----------------------------------------------------------------*/
892 static void genLabel (iCode * ic) {
893 /* special case never generate */
894 if (IC_LABEL (ic) == entryLabel)
897 emitcode (";", "genLabel(%d) %s", ic->lineno, IC_LABEL(ic)->name);
898 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
901 /*-----------------------------------------------------------------*/
902 /* genGoto - generates a jmp */
903 /*-----------------------------------------------------------------*/
904 static void genGoto (iCode * ic) {
905 emitcode (";", "genGoto(%d) %s", ic->lineno, IC_LABEL(ic)->name);
906 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
909 /*-----------------------------------------------------------------*/
910 /* genPlus - generates code for addition */
911 /*-----------------------------------------------------------------*/
912 static void genPlus (iCode * ic) {
913 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
917 printIc ("genPlus", ic, 1,1,1);
919 size=aopOp(result, TRUE, TRUE);
921 /* if left is a literal, then exchange them */
922 if (IS_LITERAL(operandType(left))) {
923 operand *tmp = right;
928 if (aopIsBit(result)) {
929 if (IS_LITERAL(operandType(right))) {
930 if (operandLitValue(right)) {
931 emitcode ("setb", AOP_NAME(result)[0]);
934 aopOp(left, TRUE, TRUE);
935 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
938 bailOut("genPlus: unfinished genPlus bit");
941 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
942 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
949 if (!aopEqual(result->aop, left->aop, 0)) {
950 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
952 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
954 if (!aopEqual(result->aop, left->aop, 1)) {
955 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
960 emitcode ("addc.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
966 /*-----------------------------------------------------------------*/
967 /* genMinus - generates code for subtraction */
968 /*-----------------------------------------------------------------*/
969 static void genMinus (iCode * ic) {
970 printIc ("genMinus", ic, 1,1,1);
974 /*-----------------------------------------------------------------*/
975 /* genMult - generates code for multiplication */
976 /*-----------------------------------------------------------------*/
977 static void genMult (iCode * ic) {
978 printIc ("genMult", ic, 1,1,1);
981 /*-----------------------------------------------------------------*/
982 /* genDiv - generates code for division */
983 /*-----------------------------------------------------------------*/
984 static void genDiv (iCode * ic) {
985 printIc ("genDiv", ic, 1,1,1);
988 /*-----------------------------------------------------------------*/
989 /* genMod - generates code for division */
990 /*-----------------------------------------------------------------*/
991 static void genMod (iCode * ic) {
992 printIc ("genMod", ic, 1,1,1);
995 /*-----------------------------------------------------------------*/
996 /* genCmpGt :- greater than comparison */
997 /*-----------------------------------------------------------------*/
998 static void genCmpGt (iCode * ic) {
999 printIc ("genCmpGt", ic, 1,1,1);
1001 /*-----------------------------------------------------------------*/
1002 /* genCmpGt :- greater than comparison */
1003 /*-----------------------------------------------------------------*/
1004 static void genCmpLe (iCode * ic) {
1005 printIc ("genCmpLe", ic, 1,1,1);
1007 /*-----------------------------------------------------------------*/
1008 /* genCmpGt :- greater than comparison */
1009 /*-----------------------------------------------------------------*/
1010 static void genCmpGe (iCode * ic) {
1011 printIc ("genCmpGe", ic, 1,1,1);
1013 /*-----------------------------------------------------------------*/
1014 /* genCmpGt :- greater than comparison */
1015 /*-----------------------------------------------------------------*/
1016 static void genCmpNe (iCode * ic) {
1017 printIc ("genCmpNe", ic, 1,1,1);
1019 /*-----------------------------------------------------------------*/
1020 /* genCmpLt - less than comparisons */
1021 /*-----------------------------------------------------------------*/
1022 static void genCmpLt (iCode * ic) {
1023 printIc ("genCmpLt", ic, 1,1,1);
1025 /*-----------------------------------------------------------------*/
1026 /* genCmpEq - generates code for equal to */
1027 /*-----------------------------------------------------------------*/
1028 static void genCmpEq (iCode * ic) {
1029 printIc ("genCmpEq", ic, 1,1,1);
1032 /*-----------------------------------------------------------------*/
1033 /* ifxForOp - returns the icode containing the ifx for operand */
1034 /*-----------------------------------------------------------------*/
1035 static iCode *ifxForOp (operand * op, iCode * ic) {
1036 /* if true symbol then needs to be assigned */
1037 if (IS_TRUE_SYMOP (op))
1040 /* if this has register type condition and
1041 the next instruction is ifx with the same operand
1042 and live to of the operand is upto the ifx only then */
1044 ic->next->op == IFX &&
1045 IC_COND (ic->next)->key == op->key &&
1046 OP_SYMBOL (op)->liveTo <= ic->next->seq)
1052 /*-----------------------------------------------------------------*/
1053 /* hasInc - operand is incremented before any other use */
1054 /*-----------------------------------------------------------------*/
1055 static iCode *hasInc (operand *op, iCode *ic, int osize) {
1056 sym_link *type = operandType(op);
1057 sym_link *retype = getSpec (type);
1058 iCode *lic = ic->next;
1061 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
1062 if (!IS_SYMOP(op)) return NULL;
1064 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
1065 if (IS_AGGREGATE(type->next)) return NULL;
1066 if (osize != (isize = getSize(type->next))) return NULL;
1069 /* if operand of the form op = op + <sizeof *op> */
1070 if (lic->op == '+') {
1071 if (isOperandEqual(IC_LEFT(lic),op) &&
1072 //isOperandEqual(IC_RESULT(lic),op) &&
1073 isOperandLiteral(IC_RIGHT(lic)) &&
1074 operandLitValue(IC_RIGHT(lic)) == isize) {
1075 emitcode (";", "Found hasInc");
1079 /* if the operand used or deffed */
1080 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
1083 /* if GOTO or IFX */
1084 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1090 /*-----------------------------------------------------------------*/
1091 /* genAndOp - for && operation */
1092 /*-----------------------------------------------------------------*/
1093 static void genAndOp (iCode * ic) {
1094 printIc ("genAndOp(&&)", ic, 1,1,1);
1097 /*-----------------------------------------------------------------*/
1098 /* genOrOp - for || operation */
1099 /*-----------------------------------------------------------------*/
1100 static void genOrOp (iCode * ic) {
1101 printIc ("genOrOp(||)", ic, 1,1,1);
1104 /*-----------------------------------------------------------------*/
1105 /* genAnd - code for and */
1106 /*-----------------------------------------------------------------*/
1107 static void genAnd (iCode * ic, iCode * ifx) {
1108 printIc ("genAnd", ic, 1,1,1);
1111 /*-----------------------------------------------------------------*/
1112 /* genOr - code for or */
1113 /*-----------------------------------------------------------------*/
1114 static void genOr (iCode * ic, iCode * ifx) {
1115 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1119 printIc ("genOr", ic, 1,1,1);
1121 size=aopOp(result, TRUE, TRUE);
1123 /* if left is a literal, then exchange them */
1124 if (IS_LITERAL(operandType(left))) {
1125 operand *tmp = right;
1130 if (aopIsBit(result)) {
1131 if (IS_LITERAL(operandType(right))) {
1132 if (operandLitValue(right)) {
1133 emitcode ("setb", AOP_NAME(result)[0]);
1136 aopOp(left, TRUE, TRUE);
1137 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1142 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1143 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1150 if (!aopEqual(result->aop, left->aop, 0)) {
1151 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1153 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1155 if (!aopEqual(result->aop, left->aop, 1)) {
1156 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1158 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1163 /*-----------------------------------------------------------------*/
1164 /* genXor - code for xclusive or */
1165 /*-----------------------------------------------------------------*/
1166 static void genXor (iCode * ic, iCode * ifx) {
1167 printIc ("genXor", ic, 1,1,1);
1170 /*-----------------------------------------------------------------*/
1171 /* genInline - write the inline code out */
1172 /*-----------------------------------------------------------------*/
1173 static void genInline (iCode * ic) {
1175 printIc ("genInline", ic, 0,0,0);
1177 emitcode ("", IC_INLINE(ic));
1180 /*-----------------------------------------------------------------*/
1181 /* genRRC - rotate right with carry */
1182 /*-----------------------------------------------------------------*/
1183 static void genRRC (iCode * ic) {
1184 printIc ("genRRC", ic, 1,1,0);
1187 /*-----------------------------------------------------------------*/
1188 /* genRLC - generate code for rotate left with carry */
1189 /*-----------------------------------------------------------------*/
1190 static void genRLC (iCode * ic) {
1191 printIc ("genRLC", ic, 1,1,0);
1194 /*-----------------------------------------------------------------*/
1195 /* genGetHbit - generates code get highest order bit */
1196 /*-----------------------------------------------------------------*/
1197 static void genGetHbit (iCode * ic) {
1198 printIc ("genGetHbit", ic, 1,1,0);
1201 /*-----------------------------------------------------------------*/
1202 /* genLeftShift - generates code for left shifting */
1203 /*-----------------------------------------------------------------*/
1204 static void genLeftShift (iCode * ic) {
1205 printIc ("genLeftShift", ic, 1,1,1);
1208 /*-----------------------------------------------------------------*/
1209 /* genRightShift - generate code for right shifting */
1210 /*-----------------------------------------------------------------*/
1211 static void genRightShift (iCode * ic) {
1212 printIc ("genRightShift", ic, 1,1,1);
1215 /*-----------------------------------------------------------------*/
1216 /* genPointerGet - generate code for pointer get */
1217 /*-----------------------------------------------------------------*/
1218 static void genPointerGet (iCode * ic, iCode *pi) {
1219 char *instr, *scratchReg;
1220 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1221 bool codePointer=IS_CODEPTR(operandType(left));
1225 printIc ("genPointerGet pi", ic, 1,1,0);
1227 printIc ("genPointerGet", ic, 1,1,0);
1230 if (!IS_PTR(operandType(left))) {
1231 bailOut ("genPointerGet: pointer required");
1234 aopOp(left,FALSE,FALSE);
1235 size=aopOp(result,TRUE,aopIsDir(left));
1237 if (IS_GENPTR(operandType(left))) {
1238 symbol *tlbl1=newiTempLabel(NULL);
1239 symbol *tlbl2=newiTempLabel(NULL);
1240 emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1241 emitcode ("beq", "%05d$", tlbl1->key+100);
1244 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1247 emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1251 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1253 emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1256 emitcode ("br", "%05d$", tlbl2->key+100);
1257 emitcode ("", "%05d$:", tlbl1->key+100);
1260 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1263 emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1264 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1268 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1270 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1273 emitcode ("", "%05d$:", tlbl2->key+100);
1277 switch (AOP_TYPE(left))
1295 if (AOP_TYPE(result)==AOP_STK) {
1296 emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1297 emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1300 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0],
1305 emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1306 emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1308 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0],
1322 if (AOP_TYPE(result)==AOP_STK) {
1323 emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1324 emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1327 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1],
1331 emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1333 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1],
1341 bailOut ("genPointerGet");
1344 /*-----------------------------------------------------------------*/
1345 /* genPointerSet - stores the value into a pointer location */
1346 /*-----------------------------------------------------------------*/
1347 static void genPointerSet (iCode * ic, iCode *pi) {
1349 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1352 printIc ("genPointerSet", ic, 1,0,1);
1354 if (!IS_PTR(operandType(result))) {
1355 bailOut ("genPointerSet: pointer required");
1358 aopOp(result,FALSE,FALSE);
1359 size=aopOp(right,FALSE, FALSE);
1361 if (IS_GENPTR(operandType(result))) {
1362 emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s",
1363 AOP_NAME(result)[0], AOP_NAME(result)[1],
1364 AOP_NAME(right)[0], AOP_NAME(right)[1]);
1368 switch (AOP_TYPE(right))
1378 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1381 emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1388 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0],
1389 AOP_NAME(right)[1]);
1391 emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0],
1392 AOP_NAME(right)[1]);
1397 bailOut ("genPointerSet");
1400 /*-----------------------------------------------------------------*/
1401 /* genIfx - generate code for Ifx statement */
1402 /*-----------------------------------------------------------------*/
1403 static void genIfx (iCode * ic, iCode * popIc) {
1407 symbol *jlbl, *tlbl=newiTempLabel(NULL);
1408 operand *cond=IC_COND(ic);
1410 emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s",
1411 ic->lineno, printOp(cond),
1412 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1413 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1415 size=aopOp(cond,TRUE,TRUE);
1425 switch (AOP_TYPE(cond) )
1428 emitcode (trueOrFalse ? "jnb" : "jb", "%s,%05d$",
1429 AOP_NAME(cond)[0], tlbl->key+100);
1430 emitcode ("jmp", "%05d$", jlbl->key+100);
1431 emitcode ("", "%05d$:", tlbl->key+100);
1442 emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1443 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1446 // generic pointer, forget the generic part
1448 emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1449 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1452 emitcode ("jmp", "%05d$", jlbl->key+100);
1453 emitcode ("", "%05d$:", tlbl->key+100);
1459 /*-----------------------------------------------------------------*/
1460 /* genAddrOf - generates code for address of */
1461 /*-----------------------------------------------------------------*/
1462 static void genAddrOf (iCode * ic) {
1464 operand *left=IC_LEFT(ic);
1466 printIc ("genAddrOf", ic, 1,1,0);
1468 size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1470 if (isOperandOnStack(left)) {
1471 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1472 getStackOffset(OP_SYMBOL(left)->stack));
1474 // this must be a generic pointer
1475 emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1480 if (isOperandInDirSpace(left) ||
1481 isOperandInFarSpace(left) ||
1482 isOperandInCodeSpace(left)) {
1483 emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1484 OP_SYMBOL(left)->rname);
1486 // this must be a generic pointer
1487 int space=0; // dir space
1488 if (isOperandInFarSpace(left)) {
1490 } else if (isOperandInCodeSpace(left)) {
1493 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1498 bailOut("genAddrOf");
1501 /*-----------------------------------------------------------------*/
1502 /* genAssign - generate code for assignment */
1503 /*-----------------------------------------------------------------*/
1504 static void genAssign (iCode * ic) {
1505 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1509 printIc ("genAssign", ic, 1,0,1);
1511 if (!IS_SYMOP(result)) {
1512 bailOut("genAssign: result is not a symbol");
1515 aopOp(result, TRUE, TRUE);
1516 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1517 size=AOP_SIZE(result);
1519 /* if result is a bit */
1520 if (AOP_TYPE(result) == AOP_BIT) {
1521 /* if right is literal, we know what the value is */
1522 if (AOP_TYPE(right) == AOP_LIT) {
1523 if (operandLitValue(right)) {
1524 emitcode ("setb", AOP_NAME(result)[0]);
1526 emitcode ("clr", AOP_NAME(result)[0]);
1530 /* if right is also a bit */
1531 if (AOP_TYPE(right) == AOP_BIT) {
1532 emitcode ("mov", "c,%s", AOP_NAME(right));
1533 emitcode ("mov", "%s,c", AOP_NAME(result));
1537 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1547 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1554 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1559 /*-----------------------------------------------------------------*/
1560 /* genJumpTab - genrates code for jump table */
1561 /*-----------------------------------------------------------------*/
1562 static void genJumpTab (iCode * ic) {
1563 printIc ("genJumpTab", ic, 0,0,0);
1566 /*-----------------------------------------------------------------*/
1567 /* genCast - gen code for casting */
1568 /*-----------------------------------------------------------------*/
1569 static void genCast (iCode * ic) {
1571 operand *result=IC_RESULT(ic);
1572 operand *right=IC_RIGHT(ic);
1573 sym_link *ctype=operandType(IC_LEFT(ic));
1574 sym_link *rtype=operandType(IC_RIGHT(ic));
1575 sym_link *etype=getSpec(rtype);
1576 short ptrType, signedness;
1578 printIc ("genCast", ic, 1,1,1);
1580 aopOp(result, TRUE, TRUE);
1581 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1582 size=AOP_SIZE(result);
1584 /* if result is a bit */
1585 if (AOP_TYPE(result) == AOP_BIT) {
1586 /* if right is literal, we know what the value is */
1587 if (AOP_TYPE(right) == AOP_LIT) {
1588 if (operandLitValue(right)) {
1589 emitcode ("setb", AOP_NAME(result)[0]);
1591 emitcode ("clr", AOP_NAME(result)[0]);
1595 /* if right is also a bit */
1596 if (AOP_TYPE(right) == AOP_BIT) {
1597 emitcode ("mov", "c,%s", AOP_NAME(right));
1598 emitcode ("mov", "%s,c", AOP_NAME(result));
1602 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1606 /* if right is a bit */
1607 if (AOP_TYPE(right)==AOP_BIT) {
1608 emitcode ("mov", "c,%s", AOP_NAME(right));
1609 emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
1610 emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
1612 emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
1617 /* if the result is of type pointer */
1618 if (IS_PTR (ctype)) {
1620 if (AOP_SIZE(right)>1) {
1621 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1623 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
1624 emitcode ("sext", "r1h");
1625 emitcode ("mov", "%s,r1", AOP_NAME(result)[0]);
1628 /* if pointer to generic pointer */
1629 if (IS_GENPTR (ctype)) {
1631 if (IS_GENPTR (rtype)) {
1632 bailOut("genCast: gptr -> gptr");
1635 if (IS_PTR (rtype)) {
1636 ptrType = DCL_TYPE (rtype);
1638 /* we have to go by the storage class */
1639 if (!SPEC_OCLS(etype)) {
1640 ptrType=0; // hush the compiler
1641 bailOut("genCast: unknown storage class");
1643 ptrType = PTR_TYPE (SPEC_OCLS (etype));
1647 /* the generic part depends on the type */
1651 emitcode ("mov", "%s,#0x00", AOP_NAME(result)[1]);
1654 emitcode ("mov", "%s,#0x01", AOP_NAME(result)[1]);
1657 emitcode ("mov", "%s,#0x02", AOP_NAME(result)[1]);
1660 bailOut("genCast: got unknown storage class");
1666 /* do we have to sign extend? */
1667 signedness = SPEC_USIGN(rtype);
1669 /* now depending on the size */
1670 switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
1674 emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1679 emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1682 emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1684 emitcode("sext", "%s", AOP_NAME(result)[1]);
1686 emitcode("mov", "%s,#0", AOP_NAME(result)[1]);
1691 emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
1693 emitcode("sext", "r1h");
1695 emitcode("mov", "r1h,#0");
1697 emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
1700 // fall through: case 0x41
1702 emitcode("sext", "r1");
1704 emitcode("mov", "r1,#0");
1706 emitcode("mov", "%s,r1", AOP_NAME(result)[1]);
1710 emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
1711 emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
1714 fprintf(stderr, "genCast: unknown size: %d:%d\n",
1715 AOP_SIZE(result), AOP_SIZE(right));
1716 bailOut("genCast: unknown size");
1720 /*-----------------------------------------------------------------*/
1721 /* genDjnz - generate decrement & jump if not zero instrucion */
1722 /*-----------------------------------------------------------------*/
1723 static bool genDjnz (iCode * ic, iCode * ifx) {
1729 /* if the if condition has a false label
1730 then we cannot save */
1734 /* if the minus is not of the form
1736 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1737 !IS_OP_LITERAL (IC_RIGHT (ic)))
1740 if (operandLitValue (IC_RIGHT (ic)) != 1)
1743 /* if the size of this greater than two then no
1745 if (getSize (operandType (IC_RESULT (ic))) > 2)
1748 printIc ("genDjnz", ic, 1,1,1);
1750 /* otherwise we can save BIG */
1751 lbl = newiTempLabel (NULL);
1752 lbl1 = newiTempLabel (NULL);
1754 aopOp (IC_RESULT (ic), FALSE, TRUE);
1756 if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1757 emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1758 emitcode ("br", "%05d$", lbl1->key + 100);
1759 emitcode ("", "%05d$:", lbl->key + 100);
1760 emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1761 emitcode ("", "%05d$:", lbl1->key + 100);
1765 bailOut("genDjnz: aop type");
1769 /*-----------------------------------------------------------------*/
1770 /* genReceive - generate code for a receive iCode */
1771 /*-----------------------------------------------------------------*/
1772 static void genReceive (iCode * ic) {
1773 printIc ("genReceive", ic, 1,0,0);
1776 /*-----------------------------------------------------------------*/
1777 /* gen51Code - generate code for 8051 based controllers */
1778 /*-----------------------------------------------------------------*/
1779 void genXA51Code (iCode * lic) {
1783 lineHead = lineCurr = NULL;
1785 /* if debug information required */
1786 if (options.debug && currFunc)
1788 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1790 if (IS_STATIC (currFunc->etype))
1791 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1793 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1797 for (ic = lic; ic; ic = ic->next) {
1798 if (ic->lineno && cln != ic->lineno) {
1799 if (options.debug) {
1801 emitcode ("", "C$%s$%d$%d$%d ==.",
1802 FileBaseName (ic->filename), ic->lineno,
1803 ic->level, ic->block);
1806 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1807 printCLine(ic->filename, ic->lineno));
1810 /* if the result is marked as
1811 spilt and rematerializable or code for
1812 this has already been generated then
1814 if (resultRemat (ic) || ic->generated)
1817 /* depending on the operation */
1837 /* IPOP happens only when trying to restore a
1838 spilt live range, if there is an ifx statement
1839 following this pop then the if statement might
1840 be using some of the registers being popped which
1841 would destory the contents of the register so
1842 we need to check for this condition and handle it */
1844 ic->next->op == IFX &&
1845 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1846 genIfx (ic->next, ic);
1864 genEndFunction (ic);
1884 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1933 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1937 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1941 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1968 case GET_VALUE_AT_ADDRESS:
1969 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
1973 if (POINTER_SET (ic))
1974 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
2000 addSet (&_G.sendSet, ic);
2009 /* now we are ready to call the
2010 peep hole optimizer */
2011 if (!options.nopeep)
2012 peepHole (&lineHead);
2014 /* now do the actual printing */
2015 printLine (lineHead, codeOutFile);