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] ;aopForSym:stack:1", getStackOffset(sym->stack));
209 sprintf (aop->name[0], "r0l");
212 emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:2", getStackOffset(sym->stack));
213 sprintf (aop->name[0], "r0");
216 emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:3.w", getStackOffset(sym->stack));
217 sprintf (aop->name[0], "r0");
218 emitcode ("mov.b", "r1l,[%s] ;aopForSym:stack:3.b", getStackOffset(sym->stack+2));
219 sprintf (aop->name[1], "r1l");
222 emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:4", getStackOffset(sym->stack));
223 sprintf (aop->name[0], "r0");
224 emitcode ("mov.w", "r1,[%s] ;aopForSym:stack:4", 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, "r0,[r0+]");
278 sprintf (aop->name[1], "r0");
279 emitcode (MOV, "r1l,[r0+]");
280 sprintf (aop->name[0], "r1l");
283 emitcode (MOV, "r0,#%s", sym->rname);
284 emitcode (MOVC, "r1,[r0+]");
285 emitcode (MOVC, "r0,[r0+]");
286 emitcode ("xch", "r0,r1");
287 sprintf (aop->name[0], "r0");
288 sprintf (aop->name[1], "r1");
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.w", "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 (bool printToStderr,
587 char *op, iCode * ic, bool result, bool left, bool right) {
590 sprintf (line, "%s(%d)", op, ic->lineno);
592 strcat (line, " result=");
593 strcat (line, printOp (IC_RESULT(ic)));
596 strcat (line, " left=");
597 strcat (line, printOp (IC_LEFT(ic)));
600 strcat (line, " right=");
601 strcat (line, printOp (IC_RIGHT(ic)));
603 emitcode (";", line);
605 fprintf (stderr, "%s\n", line);
609 /*-----------------------------------------------------------------*/
610 /* toBoolean - return carry for operand!=0 */
611 /*-----------------------------------------------------------------*/
612 static char *toBoolean (operand * op) {
613 symbol *tlbl=newiTempLabel(NULL);
615 switch (AOP_SIZE(op))
619 emitcode ("cjne", "%s,#1,%05d$; %s", AOP_NAME(op), tlbl->key+100,
620 "This needs a second thought");
622 emitcode ("", "%05d$:", tlbl->key+100);
626 bailOut("toBoolean: unknown size");
630 /*-----------------------------------------------------------------*/
631 /* regsInCommon - two operands have some registers in common */
632 /*-----------------------------------------------------------------*/
633 static bool regsInCommon (operand * op1, operand * op2) {
637 /* if they have registers in common */
638 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
641 sym1 = OP_SYMBOL (op1);
642 sym2 = OP_SYMBOL (op2);
644 if (sym1->nRegs == 0 || sym2->nRegs == 0)
647 for (i = 0; i < sym1->nRegs; i++)
653 for (j = 0; j < sym2->nRegs; j++)
658 if (sym2->regs[j] == sym1->regs[i])
666 /*-----------------------------------------------------------------*/
667 /* resultRemat - result is rematerializable */
668 /*-----------------------------------------------------------------*/
669 static int resultRemat (iCode * ic) {
670 if (SKIP_IC (ic) || ic->op == IFX)
673 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
675 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
676 if (sym->remat && !POINTER_SET (ic))
683 /*-----------------------------------------------------------------*/
684 /* genNot - generate code for ! operation */
685 /*-----------------------------------------------------------------*/
686 static void genNot (iCode * ic) {
687 printIc (0, "genNot:", ic, 1,1,0);
690 /*-----------------------------------------------------------------*/
691 /* genCpl - generate code for complement */
692 /*-----------------------------------------------------------------*/
693 static void genCpl (iCode * ic) {
694 printIc (0, "genCpl", ic, 1,1,0);
697 /*-----------------------------------------------------------------*/
698 /* genUminus - unary minus code generation */
699 /*-----------------------------------------------------------------*/
700 static void genUminus (iCode * ic) {
701 printIc (0, "genUminus", ic, 1,1,0);
704 /*-----------------------------------------------------------------*/
705 /* genIpush - generate code for pushing */
706 /*-----------------------------------------------------------------*/
707 static void genIpush (iCode * ic) {
708 operand *left=IC_LEFT(ic);
710 printIc (0, "genIpush", ic, 0,1,0);
711 aopOp(left,FALSE,FALSE);
714 if (AOP_TYPE(left)==AOP_LIT) {
715 switch (AOP_SIZE(left))
718 emitcode ("mov", "r1l,%s", AOP_NAME(left)[0]);
719 emitcode ("push", "r1l");
723 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
724 emitcode ("push", "r1");
728 emitcode ("mov", "r1l,%s", AOP_NAME(left)[1]);
729 emitcode ("push", "r1l");
730 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
731 emitcode ("push", "r1");
735 emitcode ("mov", "r1,%s", AOP_NAME(left)[1]);
736 emitcode ("push", "r1");
737 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
738 emitcode ("push", "r1");
743 if (AOP_SIZE(left)>2) {
744 emitcode ("push", "%s", AOP_NAME(left)[1]);
747 emitcode ("push", "%s", AOP_NAME(left)[0]);
752 /*-----------------------------------------------------------------*/
753 /* genIpop - recover the registers: can happen only for spilling */
754 /*-----------------------------------------------------------------*/
755 static void genIpop (iCode * ic) {
756 printIc (0, "genIpop", ic, 0,1,0);
759 /*-----------------------------------------------------------------*/
760 /* genCall - generates a call statement */
761 /*-----------------------------------------------------------------*/
762 static void genCall (iCode * ic) {
763 operand *result=IC_RESULT(ic);
765 emitcode (";", "genCall(%d) %s result=%s", ic->lineno,
766 OP_SYMBOL(IC_LEFT(ic))->name,
767 printOp (IC_RESULT(ic)));
768 emitcode ("call", "%s", OP_SYMBOL(IC_LEFT(ic))->rname);
770 /* readjust the stack if we have pushed some parms */
771 if (_G.parmsPushed) {
772 emitcode ("add", "r7,#0x%02x", _G.parmsPushed*2);
776 /* if we need to assign a result value */
777 if (IS_ITEMP (IC_RESULT(ic)) &&
778 OP_SYMBOL (IC_RESULT (ic))->nRegs) {
779 aopOp(result,FALSE,FALSE);
780 switch (AOP_SIZE(result))
783 emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
786 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
790 emitcode ("mov", "%s,r1l", AOP_NAME(result)[1]);
791 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
794 emitcode ("mov", "%s,r1", AOP_NAME(result)[1]);
795 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
802 /*-----------------------------------------------------------------*/
803 /* genPcall - generates a call by pointer statement */
804 /*-----------------------------------------------------------------*/
806 genPcall (iCode * ic)
808 emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
811 /*-----------------------------------------------------------------*/
812 /* genFunction - generated code for function entry */
813 /*-----------------------------------------------------------------*/
814 static void genFunction (iCode * ic) {
815 symbol *sym=OP_SYMBOL(IC_LEFT(ic));
816 sym_link *type=sym->type;
818 emitcode (";", "genFunction %s", sym->rname);
820 /* print the allocation information */
821 printAllocInfo (currFunc, codeOutFile);
823 emitcode ("", "%s:", sym->rname);
825 if (IFFUNC_ISNAKED(type))
827 emitcode(";", "naked function: no prologue.");
831 /* adjust the stack for locals used in this function */
833 emitcode ("sub", "r7,#%d\t; create stack space for locals", sym->stack);
837 /*-----------------------------------------------------------------*/
838 /* genEndFunction - generates epilogue for functions */
839 /*-----------------------------------------------------------------*/
841 genEndFunction (iCode * ic)
843 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
845 printIc (0, "genEndFunction", ic, 0,0,0);
847 if (IFFUNC_ISNAKED(sym->type)) {
848 emitcode(";", "naked function: no epilogue.");
852 /* readjust the stock for locals used in this function */
854 emitcode ("add", "r7,#%d\t; release stack space for locals", sym->stack);
857 if (IFFUNC_ISISR(sym->type)) {
858 emitcode ("reti", "");
860 emitcode ("ret", "");
864 /*-----------------------------------------------------------------*/
865 /* genRet - generate code for return statement */
866 /*-----------------------------------------------------------------*/
867 static void genRet (iCode * ic) {
870 printIc (0, "genRet", ic, 0, 0, 0);
872 printIc (0, "genRet", ic, 0, 1, 0);
873 aopOp(IC_LEFT(ic), TRUE, TRUE);
874 switch (AOP_SIZE(IC_LEFT(ic)))
877 emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
878 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
881 emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
884 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
887 emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
894 emitcode ("jmp", "%05d$", returnLabel->key+100);
897 /*-----------------------------------------------------------------*/
898 /* genLabel - generates a label */
899 /*-----------------------------------------------------------------*/
900 static void genLabel (iCode * ic) {
901 /* special case never generate */
902 if (IC_LABEL (ic) == entryLabel)
905 emitcode (";", "genLabel(%d) %s", ic->lineno, IC_LABEL(ic)->name);
906 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
909 /*-----------------------------------------------------------------*/
910 /* genGoto - generates a jmp */
911 /*-----------------------------------------------------------------*/
912 static void genGoto (iCode * ic) {
913 emitcode (";", "genGoto(%d) %s", ic->lineno, IC_LABEL(ic)->name);
914 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
917 /*-----------------------------------------------------------------*/
918 /* genPlus - generates code for addition */
919 /*-----------------------------------------------------------------*/
920 static void genPlus (iCode * ic) {
921 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
925 printIc (0, "genPlus", ic, 1,1,1);
927 size=aopOp(result, TRUE, TRUE);
929 /* if left is a literal, then exchange them */
930 if (IS_LITERAL(operandType(left))) {
931 operand *tmp = right;
936 if (aopIsBit(result)) {
937 if (IS_LITERAL(operandType(right))) {
938 if (operandLitValue(right)) {
939 emitcode ("setb", AOP_NAME(result)[0]);
942 aopOp(left, TRUE, TRUE);
943 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
946 bailOut("genPlus: unfinished genPlus bit");
949 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
950 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
952 // special case for "* = * + char", needs a closer look
953 // heck, this shouldn't have come here but bug-223113 does
954 if (size==3 && AOP_SIZE(right)==1) {
955 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
956 emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
957 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
958 emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
959 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
963 // special case for "xdata * = xdata * + char", needs a closer look
964 // heck, this shouldn't have come here but bug-441448 does
965 if (size==2 && AOP_SIZE(right)==1) {
966 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
967 emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
968 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
969 emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
978 if (!aopEqual(result->aop, left->aop, 0)) {
979 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
981 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
983 if (!aopEqual(result->aop, left->aop, 1)) {
984 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
989 emitcode ("addc.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
995 /*-----------------------------------------------------------------*/
996 /* genMinus - generates code for subtraction */
997 /*-----------------------------------------------------------------*/
998 static void genMinus (iCode * ic) {
999 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1003 printIc (0, "genMinus", ic, 1,1,1);
1005 size=aopOp(result, TRUE, TRUE);
1007 /* if left is a literal, then exchange them */
1008 if (IS_LITERAL(operandType(left))) {
1009 operand *tmp = right;
1014 if (aopIsBit(result)) {
1015 if (IS_LITERAL(operandType(right))) {
1016 if (operandLitValue(right)) {
1017 emitcode ("clr", AOP_NAME(result)[0]);
1020 aopOp(left, TRUE, TRUE);
1021 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1024 bailOut("genPlus: unfinished genPlus bit");
1027 if (isOperandEqual(result,left)) {
1028 left->aop=result->aop;
1030 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1032 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1039 if (!aopEqual(result->aop, left->aop, 0)) {
1040 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1042 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1044 if (!aopEqual(result->aop, left->aop, 1)) {
1045 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1050 emitcode ("subb.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1056 /*-----------------------------------------------------------------*/
1057 /* genMult - generates code for multiplication */
1058 /*-----------------------------------------------------------------*/
1059 static void genMult (iCode * ic) {
1060 printIc (0, "genMult", ic, 1,1,1);
1063 /*-----------------------------------------------------------------*/
1064 /* genDiv - generates code for division */
1065 /*-----------------------------------------------------------------*/
1066 static void genDiv (iCode * ic) {
1067 printIc (0, "genDiv", ic, 1,1,1);
1070 /*-----------------------------------------------------------------*/
1071 /* genMod - generates code for division */
1072 /*-----------------------------------------------------------------*/
1073 static void genMod (iCode * ic) {
1074 printIc (0, "genMod", ic, 1,1,1);
1077 /*-----------------------------------------------------------------*/
1078 /* ifxForOp - returns the icode containing the ifx for operand */
1079 /*-----------------------------------------------------------------*/
1080 static iCode *ifxForOp (operand * op, iCode * ic) {
1081 /* if true symbol then needs to be assigned */
1082 if (IS_TRUE_SYMOP (op))
1085 /* if this has register type condition and
1086 the next instruction is ifx with the same operand
1087 and live to of the operand is upto the ifx only then */
1089 ic->next->op == IFX &&
1090 IC_COND (ic->next)->key == op->key &&
1091 OP_SYMBOL (op)->liveTo <= ic->next->seq)
1097 /*-----------------------------------------------------------------*/
1098 /* genCmp - compares whatever */
1099 /*-----------------------------------------------------------------*/
1100 static void genCmp (iCode * ic, char *trueInstr, char *falseInstr) {
1101 iCode *ifx=ifxForOp(IC_RESULT(ic),ic);
1102 operand *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1109 size=aopOp(left, TRUE, TRUE);
1110 aopOp(right, !aopIsPtr(left), TRUE);
1120 jlbl=IC_TRUE(ifx)->key+100;
1123 jlbl=IC_FALSE(ifx)->key+100;
1127 aopOp(IC_RESULT(ic), !aopIsPtr(left), TRUE);
1128 jlbl=newiTempLabel(NULL)->key+100;
1129 emitcode("mov", "%s,#-1", AOP_NAME(IC_RESULT(ic))[0]);
1130 emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]);
1131 emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl);
1132 emitcode("cpl", "%s", AOP_NAME(IC_RESULT(ic))[0]);
1133 emitcode("", "%05d$:", jlbl);
1135 emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]);
1136 emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl);
1141 bailOut("genCmp: size > 2");
1146 /*-----------------------------------------------------------------*/
1147 /* genCmpEq :- generates code for equal to */
1148 /*-----------------------------------------------------------------*/
1149 static void genCmpEq (iCode * ic) {
1150 printIc (0, "genCmpEq", ic, 0,1,1);
1151 genCmp(ic, "beq", "bne"); // no sign
1154 /*-----------------------------------------------------------------*/
1155 /* genCmpGt :- greater than comparison */
1156 /*-----------------------------------------------------------------*/
1157 static void genCmpGt (iCode * ic) {
1158 printIc (0, "genCmpGt", ic, 0,1,1);
1159 if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1160 SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1161 genCmp(ic, "bg", "bl"); // unsigned
1163 genCmp(ic, "bgt", "ble"); // signed
1167 /*-----------------------------------------------------------------*/
1168 /* genCmpLt - less than comparisons */
1169 /*-----------------------------------------------------------------*/
1170 static void genCmpLt (iCode * ic) {
1171 printIc (0, "genCmpLt", ic, 0,1,1);
1172 if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1173 SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1174 genCmp(ic, "bcs", "bcc"); // unsigned
1176 genCmp(ic, "blt", "bge"); // signed
1180 /*-----------------------------------------------------------------*/
1181 /* hasInc - operand is incremented before any other use */
1182 /*-----------------------------------------------------------------*/
1183 static iCode *hasInc (operand *op, iCode *ic, int osize) {
1184 sym_link *type = operandType(op);
1185 sym_link *retype = getSpec (type);
1186 iCode *lic = ic->next;
1189 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
1190 if (!IS_SYMOP(op)) return NULL;
1192 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
1193 if (IS_AGGREGATE(type->next)) return NULL;
1194 if (osize != (isize = getSize(type->next))) return NULL;
1197 /* if operand of the form op = op + <sizeof *op> */
1198 if (lic->op == '+') {
1199 if (isOperandEqual(IC_LEFT(lic),op) &&
1200 //isOperandEqual(IC_RESULT(lic),op) &&
1201 isOperandLiteral(IC_RIGHT(lic)) &&
1202 operandLitValue(IC_RIGHT(lic)) == isize) {
1203 emitcode (";", "Found hasInc");
1207 /* if the operand used or deffed */
1208 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
1211 /* if GOTO or IFX */
1212 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1218 /*-----------------------------------------------------------------*/
1219 /* genAndOp - for && operation */
1220 /*-----------------------------------------------------------------*/
1221 static void genAndOp (iCode * ic) {
1222 printIc (0, "genAndOp(&&)", ic, 1,1,1);
1225 /*-----------------------------------------------------------------*/
1226 /* genOrOp - for || operation */
1227 /*-----------------------------------------------------------------*/
1228 static void genOrOp (iCode * ic) {
1229 printIc (0, "genOrOp(||)", ic, 1,1,1);
1232 /*-----------------------------------------------------------------*/
1233 /* genAnd - code for and */
1234 /*-----------------------------------------------------------------*/
1235 static void genAnd (iCode * ic, iCode * ifx) {
1236 printIc (0, "genAnd", ic, 1,1,1);
1239 /*-----------------------------------------------------------------*/
1240 /* genOr - code for or */
1241 /*-----------------------------------------------------------------*/
1242 static void genOr (iCode * ic, iCode * ifx) {
1243 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1247 printIc (0, "genOr", ic, 1,1,1);
1249 size=aopOp(result, TRUE, TRUE);
1251 /* if left is a literal, then exchange them */
1252 if (IS_LITERAL(operandType(left))) {
1253 operand *tmp = right;
1258 if (aopIsBit(result)) {
1259 if (IS_LITERAL(operandType(right))) {
1260 if (operandLitValue(right)) {
1261 emitcode ("setb", AOP_NAME(result)[0]);
1264 aopOp(left, TRUE, TRUE);
1265 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1270 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1271 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1278 if (!aopEqual(result->aop, left->aop, 0)) {
1279 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1281 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1283 if (!aopEqual(result->aop, left->aop, 1)) {
1284 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1286 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1291 /*-----------------------------------------------------------------*/
1292 /* genXor - code for xclusive or */
1293 /*-----------------------------------------------------------------*/
1294 static void genXor (iCode * ic, iCode * ifx) {
1295 printIc (0, "genXor", ic, 1,1,1);
1298 /*-----------------------------------------------------------------*/
1299 /* genInline - write the inline code out */
1300 /*-----------------------------------------------------------------*/
1301 static void genInline (iCode * ic) {
1303 printIc (0, "genInline", ic, 0,0,0);
1305 emitcode ("", IC_INLINE(ic));
1308 /*-----------------------------------------------------------------*/
1309 /* genRRC - rotate right with carry */
1310 /*-----------------------------------------------------------------*/
1311 static void genRRC (iCode * ic) {
1312 printIc (0, "genRRC", ic, 1,1,0);
1315 /*-----------------------------------------------------------------*/
1316 /* genRLC - generate code for rotate left with carry */
1317 /*-----------------------------------------------------------------*/
1318 static void genRLC (iCode * ic) {
1319 printIc (0, "genRLC", ic, 1,1,0);
1322 /*-----------------------------------------------------------------*/
1323 /* genGetHbit - generates code get highest order bit */
1324 /*-----------------------------------------------------------------*/
1325 static void genGetHbit (iCode * ic) {
1326 printIc (0, "genGetHbit", ic, 1,1,0);
1329 /*-----------------------------------------------------------------*/
1330 /* genLeftShift - generates code for left shifting */
1331 /*-----------------------------------------------------------------*/
1332 static void genLeftShift (iCode * ic) {
1333 printIc (0, "genLeftShift", ic, 1,1,1);
1336 /*-----------------------------------------------------------------*/
1337 /* genRightShift - generate code for right shifting */
1338 /*-----------------------------------------------------------------*/
1339 static void genRightShift (iCode * ic) {
1340 printIc (0, "genRightShift", ic, 1,1,1);
1343 /*-----------------------------------------------------------------*/
1344 /* genPointerGet - generate code for pointer get */
1345 /*-----------------------------------------------------------------*/
1346 static void genPointerGet (iCode * ic, iCode *pi) {
1347 char *instr, *scratchReg;
1348 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1349 bool codePointer=IS_CODEPTR(operandType(left));
1353 printIc (0, "genPointerGet pi", ic, 1,1,0);
1355 printIc (0, "genPointerGet", ic, 1,1,0);
1358 if (!IS_PTR(operandType(left))) {
1359 bailOut ("genPointerGet: pointer required");
1362 aopOp(left,FALSE,FALSE);
1363 size=aopOp(result,TRUE,aopIsDir(left));
1365 if (IS_GENPTR(operandType(left))) {
1366 symbol *tlbl1=newiTempLabel(NULL);
1367 symbol *tlbl2=newiTempLabel(NULL);
1368 emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1369 emitcode ("beq", "%05d$", tlbl1->key+100);
1372 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1375 emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1379 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1381 emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1384 emitcode ("br", "%05d$", tlbl2->key+100);
1385 emitcode ("", "%05d$:", tlbl1->key+100);
1388 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1391 emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1392 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1396 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1398 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1401 emitcode ("", "%05d$:", tlbl2->key+100);
1405 switch (AOP_TYPE(left))
1408 emitcode("mov","r1,%s", AOP_NAME(left)[0]);
1409 sprintf (AOP_NAME(left)[0], "r1");
1427 if (AOP_TYPE(result)==AOP_STK) {
1428 emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1429 emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1432 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0],
1437 emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1438 emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1440 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0],
1454 if (AOP_TYPE(result)==AOP_STK) {
1455 emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1456 emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1459 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1],
1463 emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1465 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1],
1473 bailOut ("genPointerGet");
1476 /*-----------------------------------------------------------------*/
1477 /* genPointerSet - stores the value into a pointer location */
1478 /*-----------------------------------------------------------------*/
1479 static void genPointerSet (iCode * ic, iCode *pi) {
1481 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1484 printIc (0, "genPointerSet", ic, 1,0,1);
1486 if (!IS_PTR(operandType(result))) {
1487 bailOut ("genPointerSet: pointer required");
1490 aopOp(result,FALSE,FALSE);
1491 size=aopOp(right,FALSE, FALSE);
1493 if (IS_GENPTR(operandType(result))) {
1494 emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s",
1495 AOP_NAME(result)[0], AOP_NAME(result)[1],
1496 AOP_NAME(right)[0], AOP_NAME(right)[1]);
1500 switch (AOP_TYPE(right))
1510 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1513 emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1520 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0],
1521 AOP_NAME(right)[1]);
1523 emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0],
1524 AOP_NAME(right)[1]);
1529 bailOut ("genPointerSet");
1532 /*-----------------------------------------------------------------*/
1533 /* genIfx - generate code for Ifx statement */
1534 /*-----------------------------------------------------------------*/
1535 static void genIfx (iCode * ic, iCode * popIc) {
1539 symbol *jlbl, *tlbl=newiTempLabel(NULL);
1540 operand *cond=IC_COND(ic);
1542 emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s",
1543 ic->lineno, printOp(cond),
1544 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1545 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1547 size=aopOp(cond,TRUE,TRUE);
1557 switch (AOP_TYPE(cond) )
1560 emitcode (trueOrFalse ? "jnb" : "jb", "%s,%05d$",
1561 AOP_NAME(cond)[0], tlbl->key+100);
1562 emitcode ("jmp", "%05d$", jlbl->key+100);
1563 emitcode ("", "%05d$:", tlbl->key+100);
1574 emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1575 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1578 // generic pointer, forget the generic part
1580 emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1581 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1584 emitcode ("jmp", "%05d$", jlbl->key+100);
1585 emitcode ("", "%05d$:", tlbl->key+100);
1591 /*-----------------------------------------------------------------*/
1592 /* genAddrOf - generates code for address of */
1593 /*-----------------------------------------------------------------*/
1594 static void genAddrOf (iCode * ic) {
1596 operand *left=IC_LEFT(ic);
1598 printIc (0, "genAddrOf", ic, 1,1,0);
1600 size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1602 if (isOperandOnStack(left)) {
1603 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1604 getStackOffset(OP_SYMBOL(left)->stack));
1606 // this must be a generic pointer
1607 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1612 if (isOperandInDirSpace(left) ||
1613 isOperandInFarSpace(left) ||
1614 isOperandInCodeSpace(left)) {
1615 emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1616 OP_SYMBOL(left)->rname);
1618 // this must be a generic pointer
1619 int space=0; // dir space
1620 if (isOperandInFarSpace(left)) {
1622 } else if (isOperandInCodeSpace(left)) {
1625 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1630 bailOut("genAddrOf");
1633 /*-----------------------------------------------------------------*/
1634 /* genAssign - generate code for assignment */
1635 /*-----------------------------------------------------------------*/
1636 static void genAssign (iCode * ic) {
1637 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1641 printIc (0, "genAssign", ic, 1,0,1);
1643 if (!IS_SYMOP(result)) {
1644 bailOut("genAssign: result is not a symbol");
1647 aopOp(result, TRUE, TRUE);
1648 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1649 size=AOP_SIZE(result);
1651 /* if result is a bit */
1652 if (AOP_TYPE(result) == AOP_BIT) {
1653 /* if right is literal, we know what the value is */
1654 if (AOP_TYPE(right) == AOP_LIT) {
1655 if (operandLitValue(right)) {
1656 emitcode ("setb", AOP_NAME(result)[0]);
1658 emitcode ("clr", AOP_NAME(result)[0]);
1662 /* if right is also a bit */
1663 if (AOP_TYPE(right) == AOP_BIT) {
1664 emitcode ("mov", "c,%s", AOP_NAME(right));
1665 emitcode ("mov", "%s,c", AOP_NAME(result));
1669 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1673 // TODO: if (-8 >= right==lit <= 7) instr=MOVS
1680 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1687 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1692 /*-----------------------------------------------------------------*/
1693 /* genJumpTab - genrates code for jump table */
1694 /*-----------------------------------------------------------------*/
1695 static void genJumpTab (iCode * ic) {
1696 printIc (0, "genJumpTab", ic, 0,0,0);
1699 /*-----------------------------------------------------------------*/
1700 /* genCast - gen code for casting */
1701 /*-----------------------------------------------------------------*/
1702 static void genCast (iCode * ic) {
1704 operand *result=IC_RESULT(ic);
1705 operand *right=IC_RIGHT(ic);
1706 sym_link *ctype=operandType(IC_LEFT(ic));
1707 sym_link *rtype=operandType(IC_RIGHT(ic));
1708 sym_link *etype=getSpec(rtype);
1709 short ptrType, signedness;
1711 printIc (0, "genCast", ic, 1,1,1);
1713 aopOp(result, TRUE, TRUE);
1714 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1715 size=AOP_SIZE(result);
1717 /* if result is a bit */
1718 if (AOP_TYPE(result) == AOP_BIT) {
1719 /* if right is literal, we know what the value is */
1720 if (AOP_TYPE(right) == AOP_LIT) {
1721 if (operandLitValue(right)) {
1722 emitcode ("setb", AOP_NAME(result)[0]);
1724 emitcode ("clr", AOP_NAME(result)[0]);
1728 /* if right is also a bit */
1729 if (AOP_TYPE(right) == AOP_BIT) {
1730 emitcode ("mov", "c,%s", AOP_NAME(right));
1731 emitcode ("mov", "%s,c", AOP_NAME(result));
1735 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1739 /* if right is a bit */
1740 if (AOP_TYPE(right)==AOP_BIT) {
1741 emitcode ("mov", "c,%s", AOP_NAME(right));
1742 emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
1743 emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
1745 emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
1750 /* if the result is of type pointer */
1751 if (IS_PTR (ctype)) {
1753 if (AOP_SIZE(right)>1) {
1754 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1756 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
1757 emitcode ("sext", "r1h");
1758 emitcode ("mov", "%s,r1", AOP_NAME(result)[0]);
1761 /* if pointer to generic pointer */
1762 if (IS_GENPTR (ctype)) {
1764 if (IS_GENPTR (rtype)) {
1765 bailOut("genCast: gptr -> gptr");
1768 if (IS_PTR (rtype)) {
1769 ptrType = DCL_TYPE (rtype);
1771 /* we have to go by the storage class */
1772 if (!SPEC_OCLS(etype)) {
1773 ptrType=0; // hush the compiler
1774 bailOut("genCast: unknown storage class");
1776 ptrType = PTR_TYPE (SPEC_OCLS (etype));
1780 /* the generic part depends on the type */
1784 emitcode ("mov.b", "%s,#0x00", AOP_NAME(result)[1]);
1787 emitcode ("mov.b", "%s,#0x01", AOP_NAME(result)[1]);
1790 emitcode ("mov.b", "%s,#0x02", AOP_NAME(result)[1]);
1793 bailOut("genCast: got unknown storage class");
1799 /* do we have to sign extend? */
1800 signedness = SPEC_USIGN(rtype);
1802 /* now depending on the size */
1803 switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
1807 emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1812 emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1815 emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1817 emitcode("sext", "%s", AOP_NAME(result)[1]);
1819 emitcode("mov", "%s,#0", AOP_NAME(result)[1]);
1824 emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
1826 emitcode("sext", "r1h");
1828 emitcode("mov", "r1h,#0");
1830 emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
1833 // fall through: case 0x41
1835 emitcode("sext", "r1");
1837 emitcode("mov", "r1,#0");
1839 emitcode("mov", "%s,r1", AOP_NAME(result)[1]);
1843 emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
1844 emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
1847 fprintf(stderr, "genCast: unknown size: %d:%d\n",
1848 AOP_SIZE(result), AOP_SIZE(right));
1849 bailOut("genCast: unknown size");
1853 /*-----------------------------------------------------------------*/
1854 /* genDjnz - generate decrement & jump if not zero instrucion */
1855 /*-----------------------------------------------------------------*/
1856 static bool genDjnz (iCode * ic, iCode * ifx) {
1862 /* if the if condition has a false label
1863 then we cannot save */
1867 /* if the minus is not of the form
1869 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1870 !IS_OP_LITERAL (IC_RIGHT (ic)))
1873 if (operandLitValue (IC_RIGHT (ic)) != 1)
1876 /* if the size of this greater than two then no
1878 if (getSize (operandType (IC_RESULT (ic))) > 2)
1881 printIc (0, "genDjnz", ic, 1,1,1);
1883 /* otherwise we can save BIG */
1884 lbl = newiTempLabel (NULL);
1885 lbl1 = newiTempLabel (NULL);
1887 aopOp (IC_RESULT (ic), FALSE, TRUE);
1889 if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1890 emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1891 emitcode ("br", "%05d$", lbl1->key + 100);
1892 emitcode ("", "%05d$:", lbl->key + 100);
1893 emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1894 emitcode ("", "%05d$:", lbl1->key + 100);
1898 bailOut("genDjnz: aop type");
1902 /*-----------------------------------------------------------------*/
1903 /* genReceive - generate code for a receive iCode */
1904 /*-----------------------------------------------------------------*/
1905 static void genReceive (iCode * ic) {
1906 printIc (0, "genReceive", ic, 1,0,0);
1909 /*-----------------------------------------------------------------*/
1910 /* gen51Code - generate code for 8051 based controllers */
1911 /*-----------------------------------------------------------------*/
1912 void genXA51Code (iCode * lic) {
1916 lineHead = lineCurr = NULL;
1918 /* if debug information required */
1919 if (options.debug && currFunc)
1921 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1923 if (IS_STATIC (currFunc->etype))
1924 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1926 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1930 for (ic = lic; ic; ic = ic->next) {
1931 if (ic->lineno && cln != ic->lineno) {
1932 if (options.debug) {
1934 emitcode ("", "C$%s$%d$%d$%d ==.",
1935 FileBaseName (ic->filename), ic->lineno,
1936 ic->level, ic->block);
1939 if (!options.noCcodeInAsm) {
1940 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1941 printCLine(ic->filename, ic->lineno));
1945 if (options.iCodeInAsm) {
1946 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
1949 /* if the result is marked as
1950 spilt and rematerializable or code for
1951 this has already been generated then
1953 if (resultRemat (ic) || ic->generated)
1956 /* depending on the operation */
1976 /* IPOP happens only when trying to restore a
1977 spilt live range, if there is an ifx statement
1978 following this pop then the if statement might
1979 be using some of the registers being popped which
1980 would destory the contents of the register so
1981 we need to check for this condition and handle it */
1983 ic->next->op == IFX &&
1984 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1985 genIfx (ic->next, ic);
2003 genEndFunction (ic);
2023 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
2051 /* note these two are xlated by algebraic equivalence
2052 during parsing SDCC.y */
2053 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2054 "got '>=' or '<=' shouldn't have come here");
2070 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
2074 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
2078 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
2105 case GET_VALUE_AT_ADDRESS:
2106 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
2110 if (POINTER_SET (ic))
2111 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
2137 addSet (&_G.sendSet, ic);
2146 /* now we are ready to call the
2147 peep hole optimizer */
2148 if (!options.nopeep)
2149 peepHole (&lineHead);
2151 /* now do the actual printing */
2152 printLine (lineHead, codeOutFile);