📄 pdp11.c
字号:
else /* worst case */ *total = COSTS_N_INSNS (18); } return false; default: return false; }}const char *output_jump(const char *pos, const char *neg, int length){ static int x = 0; static char buf[1000];#if 0/* currently we don't need this, because the tstdf and cmpdf copy the condition code immediately, and other float operations are not yet recognized as changing the FCC - if so, then the length-cost of all jump insns increases by one, because we have to potentially copy the FCC! */ if (cc_status.flags & CC_IN_FPU) output_asm_insn("cfcc", NULL);#endif switch (length) { case 1: strcpy(buf, pos); strcat(buf, " %l0"); return buf; case 3: sprintf(buf, "%s JMP_%d\n\tjmp %%l0\nJMP_%d:", neg, x, x); x++; return buf; default: abort(); } }voidnotice_update_cc_on_set(rtx exp, rtx insn ATTRIBUTE_UNUSED){ if (GET_CODE (SET_DEST (exp)) == CC0) { cc_status.flags = 0; cc_status.value1 = SET_DEST (exp); cc_status.value2 = SET_SRC (exp); /* if (GET_MODE(SET_SRC(exp)) == DFmode) cc_status.flags |= CC_IN_FPU;*/ } else if ((GET_CODE (SET_DEST (exp)) == REG || GET_CODE (SET_DEST (exp)) == MEM) && GET_CODE (SET_SRC (exp)) != PC && (GET_MODE (SET_DEST(exp)) == HImode || GET_MODE (SET_DEST(exp)) == QImode) && (GET_CODE (SET_SRC(exp)) == PLUS || GET_CODE (SET_SRC(exp)) == MINUS || GET_CODE (SET_SRC(exp)) == AND || GET_CODE (SET_SRC(exp)) == IOR || GET_CODE (SET_SRC(exp)) == XOR || GET_CODE (SET_SRC(exp)) == NOT || GET_CODE (SET_SRC(exp)) == NEG || GET_CODE (SET_SRC(exp)) == REG || GET_CODE (SET_SRC(exp)) == MEM)) { cc_status.flags = 0; cc_status.value1 = SET_SRC (exp); cc_status.value2 = SET_DEST (exp); if (cc_status.value1 && GET_CODE (cc_status.value1) == REG && cc_status.value2 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) cc_status.value2 = 0; if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM && cc_status.value2 && GET_CODE (cc_status.value2) == MEM) cc_status.value2 = 0; } else if (GET_CODE (SET_SRC (exp)) == CALL) { CC_STATUS_INIT; } else if (GET_CODE (SET_DEST (exp)) == REG) /* what's this ? */ { if ((cc_status.value1 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))) cc_status.value1 = 0; if ((cc_status.value2 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))) cc_status.value2 = 0; } else if (SET_DEST(exp) == pc_rtx) { /* jump */ } else /* if (GET_CODE (SET_DEST (exp)) == MEM) */ { /* the last else is a bit paranoiac, but since nearly all instructions play with condition codes, it's reasonable! */ CC_STATUS_INIT; /* paranoia*/ } }intsimple_memory_operand(rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){ rtx addr; /* Eliminate non-memory operations */ if (GET_CODE (op) != MEM) return FALSE;#if 0 /* dword operations really put out 2 instructions, so eliminate them. */ if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4)) return FALSE;#endif /* Decode the address now. */ indirection: addr = XEXP (op, 0); switch (GET_CODE (addr)) { case REG: /* (R0) - no extra cost */ return 1; case PRE_DEC: case POST_INC: /* -(R0), (R0)+ - cheap! */ return 0; case MEM: /* cheap - is encoded in addressing mode info! -- except for @(R0), which has to be @0(R0) !!! */ if (GET_CODE (XEXP (addr, 0)) == REG) return 0; op=addr; goto indirection; case CONST_INT: case LABEL_REF: case CONST: case SYMBOL_REF: /* @#address - extra cost */ return 0; case PLUS: /* X(R0) - extra cost */ return 0; default: break; } return FALSE;}/* * output a block move: * * operands[0] ... to * operands[1] ... from * operands[2] ... length * operands[3] ... alignment * operands[4] ... scratch register */ const char *output_block_move(rtx *operands){ static int count = 0; char buf[200]; if (GET_CODE(operands[2]) == CONST_INT && ! optimize_size) { if (INTVAL(operands[2]) < 16 && INTVAL(operands[3]) == 1) { register int i; for (i = 1; i <= INTVAL(operands[2]); i++) output_asm_insn("movb (%1)+, (%0)+", operands); return ""; } else if (INTVAL(operands[2]) < 32) { register int i; for (i = 1; i <= INTVAL(operands[2])/2; i++) output_asm_insn("mov (%1)+, (%0)+", operands); /* may I assume that moved quantity is multiple of alignment ??? I HOPE SO ! */ return ""; } /* can do other clever things, maybe... */ } if (CONSTANT_P(operands[2]) ) { /* just move count to scratch */ output_asm_insn("mov %2, %4", operands); } else { /* just clobber the register */ operands[4] = operands[2]; } /* switch over alignment */ switch (INTVAL(operands[3])) { case 1: /* x: movb (%1)+, (%0)+ if (TARGET_45) sob %4,x else dec %4 bgt x */ sprintf(buf, "\nmovestrhi%d:", count); output_asm_insn(buf, NULL); output_asm_insn("movb (%1)+, (%0)+", operands); if (TARGET_45) { sprintf(buf, "sob %%4, movestrhi%d", count); output_asm_insn(buf, operands); } else { output_asm_insn("dec %4", operands); sprintf(buf, "bgt movestrhi%d", count); output_asm_insn(buf, NULL); } count ++; break; case 2: /* asr %4 x: mov (%1)+, (%0)+ if (TARGET_45) sob %4, x else dec %4 bgt x */ generate_compact_code: output_asm_insn("asr %4", operands); sprintf(buf, "\nmovestrhi%d:", count); output_asm_insn(buf, NULL); output_asm_insn("mov (%1)+, (%0)+", operands); if (TARGET_45) { sprintf(buf, "sob %%4, movestrhi%d", count); output_asm_insn(buf, operands); } else { output_asm_insn("dec %4", operands); sprintf(buf, "bgt movestrhi%d", count); output_asm_insn(buf, NULL); } count ++; break; case 4: /* asr %4 asr %4 x: mov (%1)+, (%0)+ mov (%1)+, (%0)+ if (TARGET_45) sob %4, x else dec %4 bgt x */ if (optimize_size) goto generate_compact_code; output_asm_insn("asr %4", operands); output_asm_insn("asr %4", operands); sprintf(buf, "\nmovestrhi%d:", count); output_asm_insn(buf, NULL); output_asm_insn("mov (%1)+, (%0)+", operands); output_asm_insn("mov (%1)+, (%0)+", operands); if (TARGET_45) { sprintf(buf, "sob %%4, movestrhi%d", count); output_asm_insn(buf, operands); } else { output_asm_insn("dec %4", operands); sprintf(buf, "bgt movestrhi%d", count); output_asm_insn(buf, NULL); } count ++; break; default: /* asr %4 asr %4 asr %4 x: mov (%1)+, (%0)+ mov (%1)+, (%0)+ mov (%1)+, (%0)+ mov (%1)+, (%0)+ if (TARGET_45) sob %4, x else dec %4 bgt x */ if (optimize_size) goto generate_compact_code; output_asm_insn("asr %4", operands); output_asm_insn("asr %4", operands); output_asm_insn("asr %4", operands); sprintf(buf, "\nmovestrhi%d:", count); output_asm_insn(buf, NULL); output_asm_insn("mov (%1)+, (%0)+", operands); output_asm_insn("mov (%1)+, (%0)+", operands); output_asm_insn("mov (%1)+, (%0)+", operands); output_asm_insn("mov (%1)+, (%0)+", operands); if (TARGET_45) { sprintf(buf, "sob %%4, movestrhi%d", count); output_asm_insn(buf, operands); } else { output_asm_insn("dec %4", operands); sprintf(buf, "bgt movestrhi%d", count); output_asm_insn(buf, NULL); } count ++; break; ; } return "";}intlegitimate_address_p (enum machine_mode mode, rtx address){/* #define REG_OK_STRICT */ GO_IF_LEGITIMATE_ADDRESS(mode, address, win); return 0; win: return 1;/* #undef REG_OK_STRICT */}/* This function checks whether a real value can be encoded as a literal, i.e., addressing mode 27. In that mode, real values are one word values, so the remaining 48 bits have to be zero. */intlegitimate_const_double_p (rtx address){ REAL_VALUE_TYPE r; long sval[2]; REAL_VALUE_FROM_CONST_DOUBLE (r, address); REAL_VALUE_TO_TARGET_DOUBLE (r, sval); if ((sval[0] & 0xffff) == 0 && sval[1] == 0) return 1; return 0;}/* A copy of output_addr_const modified for pdp11 expression syntax. output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't use, and for debugging output, which we don't support with this port either. So this copy should get called whenever needed.*/voidoutput_addr_const_pdp11 (FILE *file, rtx x){ char buf[256]; restart: switch (GET_CODE (x)) { case PC: if (flag_pic) putc ('.', file); else abort (); break; case SYMBOL_REF: assemble_name (file, XSTR (x, 0)); break; case LABEL_REF: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0))); assemble_name (file, buf); break; case CODE_LABEL: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); assemble_name (file, buf); break; case CONST_INT: /* Should we check for constants which are too big? Maybe cutting them off to 16 bits is OK? */ fprintf (file, "%#ho", (unsigned short) INTVAL (x)); break; case CONST: /* This used to output parentheses around the expression, but that does not work on the 386 (either ATT or BSD assembler). */ output_addr_const_pdp11 (file, XEXP (x, 0)); break; case CONST_DOUBLE: if (GET_MODE (x) == VOIDmode) { /* We can use %o if the number is one word and positive. */ if (CONST_DOUBLE_HIGH (x)) abort (); /* Should we just silently drop the high part? */ else fprintf (file, "%#ho", (unsigned short) CONST_DOUBLE_LOW (x)); } else /* We can't handle floating point constants; PRINT_OPERAND must handle them. */ output_operand_lossage ("floating constant misused"); break; case PLUS: /* Some assemblers need integer constants to appear last (e.g. masm). */ if (GET_CODE (XEXP (x, 0)) == CONST_INT) { output_addr_const_pdp11 (file, XEXP (x, 1)); if (INTVAL (XEXP (x, 0)) >= 0) fprintf (file, "+"); output_addr_const_pdp11 (file, XEXP (x, 0)); } else { output_addr_const_pdp11 (file, XEXP (x, 0)); if (INTVAL (XEXP (x, 1)) >= 0) fprintf (file, "+"); output_addr_const_pdp11 (file, XEXP (x, 1)); } break; case MINUS: /* Avoid outputting things like x-x or x+5-x, since some assemblers can't handle that. */ x = simplify_subtraction (x); if (GET_CODE (x) != MINUS) goto restart; output_addr_const_pdp11 (file, XEXP (x, 0)); fprintf (file, "-"); if (GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) < 0) { fprintf (file, targetm.asm_out.open_paren); output_addr_const_pdp11 (file, XEXP (x, 1)); fprintf (file, targetm.asm_out.close_paren); } else output_addr_const_pdp11 (file, XEXP (x, 1)); break; case ZERO_EXTEND: case SIGN_EXTEND: output_addr_const_pdp11 (file, XEXP (x, 0)); break; default: output_operand_lossage ("invalid expression as operand"); }}/* Worker function for TARGET_RETURN_IN_MEMORY. */static boolpdp11_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED){ /* Should probably return DImode and DFmode in memory, lest we fill up all regs! have to, else we crash - exception: maybe return result in ac0 if DFmode and FPU present - compatibility problem with libraries for non-floating point.... */ return (TYPE_MODE (type) == DImode || (TYPE_MODE (type) == DFmode && ! TARGET_AC0));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -