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);
1119 aopOp(IC_RESULT(ic), !aopIsPtr(left), TRUE);
1120 jlbl=newiTempLabel(NULL)->key+100;
1121 emitcode("mov", "%s,#-1", AOP_NAME(IC_RESULT(ic))[0]);
1122 emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]);
1123 emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl);
1124 emitcode("cpl", "%s", AOP_NAME(IC_RESULT(ic))[0]);
1125 emitcode("", "%05d$:", jlbl);
1127 emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]);
1130 jlbl=IC_TRUE(ifx)->key+100;
1133 jlbl=IC_FALSE(ifx)->key+100;
1136 emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl);
1142 bailOut("genCmp: size > 2");
1147 /*-----------------------------------------------------------------*/
1148 /* genCmpEq :- generates code for equal to */
1149 /*-----------------------------------------------------------------*/
1150 static void genCmpEq (iCode * ic) {
1151 printIc (0, "genCmpEq", ic, 0,1,1);
1152 genCmp(ic, "beq", "bne"); // no sign
1155 /*-----------------------------------------------------------------*/
1156 /* genCmpGt :- greater than comparison */
1157 /*-----------------------------------------------------------------*/
1158 static void genCmpGt (iCode * ic) {
1159 printIc (0, "genCmpGt", ic, 0,1,1);
1160 if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1161 SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1162 genCmp(ic, "bg", "bl"); // unsigned
1164 genCmp(ic, "bgt", "ble"); // signed
1168 /*-----------------------------------------------------------------*/
1169 /* genCmpLt - less than comparisons */
1170 /*-----------------------------------------------------------------*/
1171 static void genCmpLt (iCode * ic) {
1172 printIc (0, "genCmpLt", ic, 0,1,1);
1173 if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1174 SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1175 genCmp(ic, "bcs", "bcc"); // unsigned
1177 genCmp(ic, "blt", "bge"); // signed
1181 /*-----------------------------------------------------------------*/
1182 /* hasInc - operand is incremented before any other use */
1183 /*-----------------------------------------------------------------*/
1184 static iCode *hasInc (operand *op, iCode *ic, int osize) {
1185 sym_link *type = operandType(op);
1186 sym_link *retype = getSpec (type);
1187 iCode *lic = ic->next;
1190 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
1191 if (!IS_SYMOP(op)) return NULL;
1193 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
1194 if (IS_AGGREGATE(type->next)) return NULL;
1195 if (osize != (isize = getSize(type->next))) return NULL;
1198 /* if operand of the form op = op + <sizeof *op> */
1199 if (lic->op == '+') {
1200 if (isOperandEqual(IC_LEFT(lic),op) &&
1201 //isOperandEqual(IC_RESULT(lic),op) &&
1202 isOperandLiteral(IC_RIGHT(lic)) &&
1203 operandLitValue(IC_RIGHT(lic)) == isize) {
1204 emitcode (";", "Found hasInc");
1208 /* if the operand used or deffed */
1209 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
1212 /* if GOTO or IFX */
1213 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1219 /*-----------------------------------------------------------------*/
1220 /* genAndOp - for && operation */
1221 /*-----------------------------------------------------------------*/
1222 static void genAndOp (iCode * ic) {
1223 printIc (0, "genAndOp(&&)", ic, 1,1,1);
1226 /*-----------------------------------------------------------------*/
1227 /* genOrOp - for || operation */
1228 /*-----------------------------------------------------------------*/
1229 static void genOrOp (iCode * ic) {
1230 printIc (0, "genOrOp(||)", ic, 1,1,1);
1233 /*-----------------------------------------------------------------*/
1234 /* genAnd - code for and */
1235 /*-----------------------------------------------------------------*/
1236 static void genAnd (iCode * ic, iCode * ifx) {
1237 printIc (0, "genAnd", ic, 1,1,1);
1240 /*-----------------------------------------------------------------*/
1241 /* genOr - code for or */
1242 /*-----------------------------------------------------------------*/
1243 static void genOr (iCode * ic, iCode * ifx) {
1244 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1248 printIc (0, "genOr", ic, 1,1,1);
1250 size=aopOp(result, TRUE, TRUE);
1252 /* if left is a literal, then exchange them */
1253 if (IS_LITERAL(operandType(left))) {
1254 operand *tmp = right;
1259 if (aopIsBit(result)) {
1260 if (IS_LITERAL(operandType(right))) {
1261 if (operandLitValue(right)) {
1262 emitcode ("setb", AOP_NAME(result)[0]);
1265 aopOp(left, TRUE, TRUE);
1266 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1271 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1272 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1279 if (!aopEqual(result->aop, left->aop, 0)) {
1280 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1282 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1284 if (!aopEqual(result->aop, left->aop, 1)) {
1285 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1287 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1292 /*-----------------------------------------------------------------*/
1293 /* genXor - code for xclusive or */
1294 /*-----------------------------------------------------------------*/
1295 static void genXor (iCode * ic, iCode * ifx) {
1296 printIc (0, "genXor", ic, 1,1,1);
1299 /*-----------------------------------------------------------------*/
1300 /* genInline - write the inline code out */
1301 /*-----------------------------------------------------------------*/
1302 static void genInline (iCode * ic) {
1304 printIc (0, "genInline", ic, 0,0,0);
1306 emitcode ("", IC_INLINE(ic));
1309 /*-----------------------------------------------------------------*/
1310 /* genRRC - rotate right with carry */
1311 /*-----------------------------------------------------------------*/
1312 static void genRRC (iCode * ic) {
1313 printIc (0, "genRRC", ic, 1,1,0);
1316 /*-----------------------------------------------------------------*/
1317 /* genRLC - generate code for rotate left with carry */
1318 /*-----------------------------------------------------------------*/
1319 static void genRLC (iCode * ic) {
1320 printIc (0, "genRLC", ic, 1,1,0);
1323 /*-----------------------------------------------------------------*/
1324 /* genGetHbit - generates code get highest order bit */
1325 /*-----------------------------------------------------------------*/
1326 static void genGetHbit (iCode * ic) {
1327 printIc (0, "genGetHbit", ic, 1,1,0);
1330 /*-----------------------------------------------------------------*/
1331 /* genLeftShift - generates code for left shifting */
1332 /*-----------------------------------------------------------------*/
1333 static void genLeftShift (iCode * ic) {
1334 printIc (0, "genLeftShift", ic, 1,1,1);
1337 /*-----------------------------------------------------------------*/
1338 /* genRightShift - generate code for right shifting */
1339 /*-----------------------------------------------------------------*/
1340 static void genRightShift (iCode * ic) {
1341 printIc (0, "genRightShift", ic, 1,1,1);
1344 /*-----------------------------------------------------------------*/
1345 /* genPointerGet - generate code for pointer get */
1346 /*-----------------------------------------------------------------*/
1347 static void genPointerGet (iCode * ic, iCode *pi) {
1348 char *instr, *scratchReg;
1349 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1350 bool codePointer=IS_CODEPTR(operandType(left));
1354 printIc (0, "genPointerGet pi", ic, 1,1,0);
1356 printIc (0, "genPointerGet", ic, 1,1,0);
1359 if (!IS_PTR(operandType(left))) {
1360 bailOut ("genPointerGet: pointer required");
1363 aopOp(left,FALSE,FALSE);
1364 size=aopOp(result,TRUE,aopIsDir(left));
1366 if (IS_GENPTR(operandType(left))) {
1367 symbol *tlbl1=newiTempLabel(NULL);
1368 symbol *tlbl2=newiTempLabel(NULL);
1369 emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1370 emitcode ("beq", "%05d$", tlbl1->key+100);
1373 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1376 emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1380 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1382 emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1385 emitcode ("br", "%05d$", tlbl2->key+100);
1386 emitcode ("", "%05d$:", tlbl1->key+100);
1389 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1392 emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1393 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1397 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1399 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1402 emitcode ("", "%05d$:", tlbl2->key+100);
1406 switch (AOP_TYPE(left))
1409 emitcode("mov","r1,%s", AOP_NAME(left)[0]);
1410 sprintf (AOP_NAME(left)[0], "r1");
1428 if (AOP_TYPE(result)==AOP_STK) {
1429 emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1430 emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1433 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0],
1438 emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1439 emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1441 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0],
1455 if (AOP_TYPE(result)==AOP_STK) {
1456 emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1457 emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1460 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1],
1464 emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1466 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1],
1474 bailOut ("genPointerGet");
1477 /*-----------------------------------------------------------------*/
1478 /* genPointerSet - stores the value into a pointer location */
1479 /*-----------------------------------------------------------------*/
1480 static void genPointerSet (iCode * ic, iCode *pi) {
1482 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1485 printIc (0, "genPointerSet", ic, 1,0,1);
1487 if (!IS_PTR(operandType(result))) {
1488 bailOut ("genPointerSet: pointer required");
1491 aopOp(result,FALSE,FALSE);
1492 size=aopOp(right,FALSE, FALSE);
1494 if (IS_GENPTR(operandType(result))) {
1495 emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s",
1496 AOP_NAME(result)[0], AOP_NAME(result)[1],
1497 AOP_NAME(right)[0], AOP_NAME(right)[1]);
1501 switch (AOP_TYPE(right))
1511 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1514 emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1521 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0],
1522 AOP_NAME(right)[1]);
1524 emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0],
1525 AOP_NAME(right)[1]);
1530 bailOut ("genPointerSet");
1533 /*-----------------------------------------------------------------*/
1534 /* genIfx - generate code for Ifx statement */
1535 /*-----------------------------------------------------------------*/
1536 static void genIfx (iCode * ic, iCode * popIc) {
1540 symbol *jlbl, *tlbl=newiTempLabel(NULL);
1541 operand *cond=IC_COND(ic);
1543 emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s",
1544 ic->lineno, printOp(cond),
1545 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1546 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1548 size=aopOp(cond,TRUE,TRUE);
1558 switch (AOP_TYPE(cond) )
1561 emitcode (trueOrFalse ? "jnb" : "jb", "%s,%05d$",
1562 AOP_NAME(cond)[0], tlbl->key+100);
1563 emitcode ("jmp", "%05d$", jlbl->key+100);
1564 emitcode ("", "%05d$:", tlbl->key+100);
1575 emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1576 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1579 // generic pointer, forget the generic part
1581 emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1582 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1585 emitcode ("jmp", "%05d$", jlbl->key+100);
1586 emitcode ("", "%05d$:", tlbl->key+100);
1592 /*-----------------------------------------------------------------*/
1593 /* genAddrOf - generates code for address of */
1594 /*-----------------------------------------------------------------*/
1595 static void genAddrOf (iCode * ic) {
1597 operand *left=IC_LEFT(ic);
1599 printIc (0, "genAddrOf", ic, 1,1,0);
1601 size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1603 if (isOperandOnStack(left)) {
1604 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1605 getStackOffset(OP_SYMBOL(left)->stack));
1607 // this must be a generic pointer
1608 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1613 if (isOperandInDirSpace(left) ||
1614 isOperandInFarSpace(left) ||
1615 isOperandInCodeSpace(left)) {
1616 emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1617 OP_SYMBOL(left)->rname);
1619 // this must be a generic pointer
1620 int space=0; // dir space
1621 if (isOperandInFarSpace(left)) {
1623 } else if (isOperandInCodeSpace(left)) {
1626 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1631 bailOut("genAddrOf");
1634 /*-----------------------------------------------------------------*/
1635 /* genAssign - generate code for assignment */
1636 /*-----------------------------------------------------------------*/
1637 static void genAssign (iCode * ic) {
1638 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1642 printIc (0, "genAssign", ic, 1,0,1);
1644 if (!IS_SYMOP(result)) {
1645 bailOut("genAssign: result is not a symbol");
1648 aopOp(result, TRUE, TRUE);
1649 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1650 size=AOP_SIZE(result);
1652 /* if result is a bit */
1653 if (AOP_TYPE(result) == AOP_BIT) {
1654 /* if right is literal, we know what the value is */
1655 if (AOP_TYPE(right) == AOP_LIT) {
1656 if (operandLitValue(right)) {
1657 emitcode ("setb", AOP_NAME(result)[0]);
1659 emitcode ("clr", AOP_NAME(result)[0]);
1663 /* if right is also a bit */
1664 if (AOP_TYPE(right) == AOP_BIT) {
1665 emitcode ("mov", "c,%s", AOP_NAME(right));
1666 emitcode ("mov", "%s,c", AOP_NAME(result));
1670 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1674 // TODO: if (-8 >= right==lit <= 7) instr=MOVS
1681 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1688 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1693 /*-----------------------------------------------------------------*/
1694 /* genJumpTab - genrates code for jump table */
1695 /*-----------------------------------------------------------------*/
1696 static void genJumpTab (iCode * ic) {
1697 printIc (0, "genJumpTab", ic, 0,0,0);
1700 /*-----------------------------------------------------------------*/
1701 /* genCast - gen code for casting */
1702 /*-----------------------------------------------------------------*/
1703 static void genCast (iCode * ic) {
1705 operand *result=IC_RESULT(ic);
1706 operand *right=IC_RIGHT(ic);
1707 sym_link *ctype=operandType(IC_LEFT(ic));
1708 sym_link *rtype=operandType(IC_RIGHT(ic));
1709 sym_link *etype=getSpec(rtype);
1710 short ptrType, signedness;
1712 printIc (0, "genCast", ic, 1,1,1);
1714 aopOp(result, TRUE, TRUE);
1715 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1716 size=AOP_SIZE(result);
1718 /* if result is a bit */
1719 if (AOP_TYPE(result) == AOP_BIT) {
1720 /* if right is literal, we know what the value is */
1721 if (AOP_TYPE(right) == AOP_LIT) {
1722 if (operandLitValue(right)) {
1723 emitcode ("setb", AOP_NAME(result)[0]);
1725 emitcode ("clr", AOP_NAME(result)[0]);
1729 /* if right is also a bit */
1730 if (AOP_TYPE(right) == AOP_BIT) {
1731 emitcode ("mov", "c,%s", AOP_NAME(right));
1732 emitcode ("mov", "%s,c", AOP_NAME(result));
1736 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1740 /* if right is a bit */
1741 if (AOP_TYPE(right)==AOP_BIT) {
1742 emitcode ("mov", "c,%s", AOP_NAME(right));
1743 emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
1744 emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
1746 emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
1751 /* if the result is of type pointer */
1752 if (IS_PTR (ctype)) {
1754 if (AOP_SIZE(right)>1) {
1755 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1757 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
1758 emitcode ("sext", "r1h");
1759 emitcode ("mov", "%s,r1", AOP_NAME(result)[0]);
1762 /* if pointer to generic pointer */
1763 if (IS_GENPTR (ctype)) {
1765 if (IS_GENPTR (rtype)) {
1766 bailOut("genCast: gptr -> gptr");
1769 if (IS_PTR (rtype)) {
1770 ptrType = DCL_TYPE (rtype);
1772 /* we have to go by the storage class */
1773 if (!SPEC_OCLS(etype)) {
1774 ptrType=0; // hush the compiler
1775 bailOut("genCast: unknown storage class");
1777 ptrType = PTR_TYPE (SPEC_OCLS (etype));
1781 /* the generic part depends on the type */
1785 emitcode ("mov.b", "%s,#0x00", AOP_NAME(result)[1]);
1788 emitcode ("mov.b", "%s,#0x01", AOP_NAME(result)[1]);
1791 emitcode ("mov.b", "%s,#0x02", AOP_NAME(result)[1]);
1794 bailOut("genCast: got unknown storage class");
1800 /* do we have to sign extend? */
1801 signedness = SPEC_USIGN(rtype);
1803 /* now depending on the size */
1804 switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
1808 emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1813 emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1816 emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1818 emitcode("sext", "%s", AOP_NAME(result)[1]);
1820 emitcode("mov", "%s,#0", AOP_NAME(result)[1]);
1825 emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
1827 emitcode("sext", "r1h");
1829 emitcode("mov", "r1h,#0");
1831 emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
1834 // fall through: case 0x41
1836 emitcode("sext", "r1");
1838 emitcode("mov", "r1,#0");
1840 emitcode("mov", "%s,r1", AOP_NAME(result)[1]);
1844 emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
1845 emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
1848 fprintf(stderr, "genCast: unknown size: %d:%d\n",
1849 AOP_SIZE(result), AOP_SIZE(right));
1850 bailOut("genCast: unknown size");
1854 /*-----------------------------------------------------------------*/
1855 /* genDjnz - generate decrement & jump if not zero instrucion */
1856 /*-----------------------------------------------------------------*/
1857 static bool genDjnz (iCode * ic, iCode * ifx) {
1863 /* if the if condition has a false label
1864 then we cannot save */
1868 /* if the minus is not of the form
1870 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1871 !IS_OP_LITERAL (IC_RIGHT (ic)))
1874 if (operandLitValue (IC_RIGHT (ic)) != 1)
1877 /* if the size of this greater than two then no
1879 if (getSize (operandType (IC_RESULT (ic))) > 2)
1882 printIc (0, "genDjnz", ic, 1,1,1);
1884 /* otherwise we can save BIG */
1885 lbl = newiTempLabel (NULL);
1886 lbl1 = newiTempLabel (NULL);
1888 aopOp (IC_RESULT (ic), FALSE, TRUE);
1890 if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1891 emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1892 emitcode ("br", "%05d$", lbl1->key + 100);
1893 emitcode ("", "%05d$:", lbl->key + 100);
1894 emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1895 emitcode ("", "%05d$:", lbl1->key + 100);
1899 bailOut("genDjnz: aop type");
1903 /*-----------------------------------------------------------------*/
1904 /* genReceive - generate code for a receive iCode */
1905 /*-----------------------------------------------------------------*/
1906 static void genReceive (iCode * ic) {
1907 printIc (0, "genReceive", ic, 1,0,0);
1910 /*-----------------------------------------------------------------*/
1911 /* gen51Code - generate code for 8051 based controllers */
1912 /*-----------------------------------------------------------------*/
1913 void genXA51Code (iCode * lic) {
1917 lineHead = lineCurr = NULL;
1919 /* if debug information required */
1920 if (options.debug && currFunc)
1922 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1924 if (IS_STATIC (currFunc->etype))
1925 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1927 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1931 for (ic = lic; ic; ic = ic->next) {
1932 if (ic->lineno && cln != ic->lineno) {
1933 if (options.debug) {
1935 emitcode ("", "C$%s$%d$%d$%d ==.",
1936 FileBaseName (ic->filename), ic->lineno,
1937 ic->level, ic->block);
1940 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1941 printCLine(ic->filename, ic->lineno));
1944 /* if the result is marked as
1945 spilt and rematerializable or code for
1946 this has already been generated then
1948 if (resultRemat (ic) || ic->generated)
1951 /* depending on the operation */
1971 /* IPOP happens only when trying to restore a
1972 spilt live range, if there is an ifx statement
1973 following this pop then the if statement might
1974 be using some of the registers being popped which
1975 would destory the contents of the register so
1976 we need to check for this condition and handle it */
1978 ic->next->op == IFX &&
1979 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1980 genIfx (ic->next, ic);
1998 genEndFunction (ic);
2018 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
2046 /* note these two are xlated by algebraic equivalence
2047 during parsing SDCC.y */
2048 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2049 "got '>=' or '<=' shouldn't have come here");
2065 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
2069 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
2073 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
2100 case GET_VALUE_AT_ADDRESS:
2101 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
2105 if (POINTER_SET (ic))
2106 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
2132 addSet (&_G.sendSet, ic);
2141 /* now we are ready to call the
2142 peep hole optimizer */
2143 if (!options.nopeep)
2144 peepHole (&lineHead);
2146 /* now do the actual printing */
2147 printLine (lineHead, codeOutFile);