📄 pdp11.c
字号:
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*/ } }int simple_memory_operand(op, mode) rtx op; enum machine_mode mode;{ 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 */ char *output_block_move(operands) 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 "";}/* for future use */intcomparison_operator_index(op) rtx op;{ switch (GET_CODE(op)) { case NE: return 0; case EQ: return 1; case GE: return 2; case GT: return 3; case LE: return 4; case LT: return 5; case GEU: return 6; case GTU: return 7; case LEU: return 8; case LTU: return 9; default: return -1; }} /* tests whether the rtx is a comparison operator */intcomp_operator (op, mode) rtx op; enum machine_mode mode;{ return comparison_operator_index(op) >= 0;} intlegitimate_address_p (mode, address) 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 */}/* 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, x) 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 (eg 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, ASM_OPEN_PAREN); output_addr_const_pdp11 (file, XEXP (x, 1)); fprintf (file, ASM_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"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -