📄 ip2k.c
字号:
enum rtx_code code; rtx dest;{#define operands ip2k_compare_operands enum machine_mode mode; operands[2] = dest; mode = GET_MODE (operands[0]); if ((mode != QImode) && (mode != HImode) && (mode != SImode) && (mode != DImode)) mode = GET_MODE (operands[1]); /* We have a fast path for a specific type of QImode compare. We ought to extend this for larger cases too but that wins less frequently and introduces a lot of complexity. */ if (mode == QImode && !rtx_equal_p (operands[0], operands[2]) && !rtx_equal_p (operands[1], operands[2]) && (! REG_P (operands[2]) || (ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[2]), 1) && ip2k_xexp_not_uses_reg_p (operands[1], REGNO (operands[2]), 1)))) { OUT_AS1 (clr, %2); if (immediate_operand (operands[1], QImode) && ((INTVAL (operands[1]) & 0xff) == 0xff)) { if (code == EQ) OUT_AS2 (incsnz, w, %0); else OUT_AS2 (incsz, w, %0); } else if (immediate_operand (operands[1], QImode) && ((INTVAL (operands[1]) & 0xff) == 0x01)) { if (code == EQ) OUT_AS2 (decsnz, w, %0); else OUT_AS2 (decsz, w, %0); } else if (ip2k_compare_operands[1] == const0_rtx) { OUT_AS2 (mov, w, %0); if (code == EQ) OUT_AS1 (snz,); else OUT_AS1 (sz,); } else { OUT_AS2 (mov, w, %0); if (code == EQ) OUT_AS2 (csne, w, %1); else OUT_AS2 (cse, w, %1); } OUT_AS1 (inc, %2); } else { if (ip2k_compare_operands[1] == const0_rtx) { switch (mode) { case QImode: OUT_AS2 (mov, w, %0); break; case HImode: OUT_AS2 (mov, w, %H0); OUT_AS2 (or, w, %L0); break; case SImode: OUT_AS2 (mov, w, %A0); OUT_AS2 (or, w, %B0); OUT_AS2 (or, w, %C0); OUT_AS2 (or, w, %D0); break; case DImode: OUT_AS2 (mov, w, %S0); OUT_AS2 (or, w, %T0); OUT_AS2 (or, w, %U0); OUT_AS2 (or, w, %V0); OUT_AS2 (or, w, %W0); OUT_AS2 (or, w, %X0); OUT_AS2 (or, w, %Y0); OUT_AS2 (or, w, %Z0); break; default: abort (); } } else { switch (mode) { case QImode: OUT_AS2 (mov, w, %1); OUT_AS2 (cmp, w, %0); break; case HImode: OUT_AS2 (mov, w, %H1); OUT_AS2 (cmp, w, %H0); OUT_AS1 (sz,); OUT_AS1 (page, 2f); OUT_AS1 (jmp, 2f); OUT_AS2 (mov, w, %L1); OUT_AS2 (cmp, w, %L0); OUT_AS1 (2:,); break; case SImode: if (code == EQ) { OUT_AS2 (mov, w, #1); OUT_AS2 (mov, mulh, w); } else OUT_AS1 (clr, mulh); OUT_AS2 (mov, w, %A1); OUT_AS2 (cse, w, %A0); OUT_AS1 (page, 2f); OUT_AS1 (jmp, 2f); OUT_AS2 (mov, w, %B1); OUT_AS2 (cse, w, %B0); OUT_AS1 (page, 2f); OUT_AS1 (jmp, 2f); OUT_AS2 (mov, w, %C1); OUT_AS2 (cse, w, %C0); OUT_AS1 (page, 2f); OUT_AS1 (jmp, 2f); OUT_AS2 (mov, w, %D1); OUT_AS2 (cse, w, %D0); OUT_AS1 (2:,); if (code == EQ) OUT_AS1 (dec, mulh); else OUT_AS1 (inc, mulh); OUT_AS2 (mov, w, mulh); OUT_AS2 (mov, %2, w); return ""; case DImode: if (code == EQ) { OUT_AS2 (mov, w, #1); OUT_AS2 (mov, mulh, w); } else OUT_AS1 (clr, mulh); OUT_AS2 (mov, w, %S1); OUT_AS2 (cse, w, %S0); OUT_AS1 (page, 2f); OUT_AS1 (jmp, 2f); OUT_AS2 (mov, w, %T1); OUT_AS2 (cse, w, %T0); OUT_AS1 (page, 2f); OUT_AS1 (jmp, 2f); OUT_AS2 (mov, w, %U1); OUT_AS2 (cse, w, %U0); OUT_AS1 (page, 2f); OUT_AS1 (jmp, 2f); OUT_AS2 (mov, w, %V1); OUT_AS2 (cse, w, %V0); OUT_AS1 (page, 2f); OUT_AS1 (jmp, 2f); OUT_AS2 (mov, w, %W1); OUT_AS2 (cse, w, %W0); OUT_AS1 (page, 2f); OUT_AS1 (jmp, 2f); OUT_AS2 (mov, w, %X1); OUT_AS2 (cse, w, %X0); OUT_AS1 (page, 2f); OUT_AS1 (jmp, 2f); OUT_AS2 (mov, w, %Y1); OUT_AS2 (cse, w, %Y0); OUT_AS1 (page, 2f); OUT_AS1 (jmp, 2f); OUT_AS2 (mov, w, %Z1); OUT_AS2 (cse, w, %Z0); OUT_AS1 (2:,); if (code == EQ) OUT_AS1 (dec, mulh); else OUT_AS1 (inc, mulh); OUT_AS2 (mov, w, mulh); OUT_AS2 (mov, %2, w); return ""; default: abort (); } } OUT_AS2 (mov, w, #0); if (code == EQ) OUT_AS1 (snz,); else OUT_AS1 (sz,); OUT_AS1 (inc, wreg); OUT_AS2 (mov, %2, w); } return "";#undef operands}const char *ip2k_gen_signed_comp_branch (insn, code, label) rtx insn; enum rtx_code code; rtx label;{#define operands ip2k_compare_operands enum machine_mode mode; int can_use_skip = 0; rtx ninsn; operands[2] = label; mode = GET_MODE (operands[0]); if ((mode != QImode) && (mode != HImode) && (mode != SImode) && (mode != DImode)) mode = GET_MODE (operands[1]); /* Look for situations where we can just skip the next instruction instead of skipping and then branching! */ ninsn = next_real_insn (insn); if (ninsn && (recog_memoized (ninsn) >= 0) && get_attr_skip (ninsn) == SKIP_YES) { rtx skip_tgt = next_nonnote_insn (next_real_insn (insn)); /* The first situation is where the target of the jump is one insn after the jump insn and the insn being jumped is only one machine opcode long. */ if (label == skip_tgt) can_use_skip = 1; else { /* If our skip target is in fact a code label then we ignore the label and move onto the next useful instruction. Nothing we do here has any effect on the use of skipping instructions. */ if (GET_CODE (skip_tgt) == CODE_LABEL) skip_tgt = next_nonnote_insn (skip_tgt); /* The second situation is where we have something of the form: test_condition skip_conditional page/jump label optional_label (this may or may not exist): skippable_insn page/jump label In this case we can eliminate the first "page/jump label". */ if (GET_CODE (skip_tgt) == JUMP_INSN) { rtx set = single_set (skip_tgt); if (GET_CODE (XEXP (set, 0)) == PC && GET_CODE (XEXP (set, 1)) == LABEL_REF && label == JUMP_LABEL (skip_tgt)) can_use_skip = 2; } } } /* gcc is a little braindead and does some rather stateful things while inspecting attributes - we have to put this state back to what it's supposed to be. */ extract_constrain_insn_cached (insn); if (ip2k_compare_operands[1] == const0_rtx) /* These are easier. */ { switch (code) { case LT: if (can_use_skip) { OUT_AS2 (sb, %0, 7); } else { OUT_AS2 (snb, %0, 7); OUT_AS1 (page, %2); OUT_AS1 (jmp, %2); } break; case GT: switch (mode) { case DImode: OUT_AS2 (rl, w, %S0); OUT_AS2 (mov, w, %S0); OUT_AS2 (or, w, %T0); OUT_AS2 (or, w, %U0); OUT_AS2 (or, w, %V0); OUT_AS2 (or, w, %W0); OUT_AS2 (or, w, %X0); OUT_AS2 (or, w, %Y0); OUT_AS2 (or, w, %Z0); OUT_AS1 (snz, ); OUT_AS2 (setb, status, 0); OUT_AS2 (sb, status, 0); OUT_AS1 (page, %2); OUT_AS1 (jmp, %2); break; case SImode: OUT_AS2 (rl, w, %A0); OUT_AS2 (mov, w, %A0); OUT_AS2 (or, w, %B0); OUT_AS2 (or, w, %C0); OUT_AS2 (or, w, %D0); OUT_AS1 (snz, ); OUT_AS2 (setb, status, 0); OUT_AS2 (sb, status, 0); OUT_AS1 (page, %2); OUT_AS1 (jmp, %2); break; case HImode: OUT_AS2 (rl, w, %H0); OUT_AS2 (mov, w, %H0); OUT_AS2 (or, w, %L0); OUT_AS1 (snz, ); OUT_AS2 (setb, status, 0); OUT_AS2 (sb, status, 0); OUT_AS1 (page, %2); OUT_AS1 (jmp, %2); break; case QImode: OUT_AS2 (mov, w, %0); /* Will just do "sb w, 7". */ OUT_AS1 (snz, ); OUT_AS2 (setb, wreg, 7); OUT_AS2 (sb, wreg, 7); OUT_AS1 (page, %2); OUT_AS1 (jmp, %2); break; default: abort (); } break; case LE: switch (mode) { case DImode: OUT_AS2 (mov, w, %S0); OUT_AS2 (or, w, %T0); OUT_AS2 (or, w, %U0); OUT_AS2 (or, w, %V0); OUT_AS2 (or, w, %W0); OUT_AS2 (or, w, %X0); OUT_AS2 (or, w, %Y0); OUT_AS2 (or, w, %Z0); /* Z is correct. */ OUT_AS1 (sz, ); OUT_AS2 (snb, %S0, 7); OUT_AS1 (page, %2); OUT_AS1 (jmp, %2); break; case SImode: OUT_AS2 (mov, w, %A0); OUT_AS2 (or, w, %B0); OUT_AS2 (or, w, %C0); OUT_AS2 (or, w, %D0); /* Z is correct. */ OUT_AS1 (sz, ); OUT_AS2 (snb, %A0, 7); OUT_AS1 (page, %2); OUT_AS1 (jmp, %2); break; case HImode: OUT_AS2 (mov, w, %H0); OUT_AS2 (or, w, %L0); OUT_AS1 (sz, ); OUT_AS2 (snb, %H0, 7); OUT_AS1 (page, %2); OUT_AS1 (jmp, %2); break; case QImode: OUT_AS2 (mov, w, %0); /* Will just do "sb w, 7". */ OUT_AS1 (sz, ); OUT_AS2 (snb, wreg, 7); OUT_AS1 (page, %2); OUT_AS1 (jmp, %2); break; default: abort (); } break; case GE: if (can_use_skip) { OUT_AS2 (snb, %0, 7); } else { OUT_AS2 (sb, %0, 7); OUT_AS1 (page, %2); OUT_AS1 (jmp, %2); } break; default: abort (); } return ""; } /* signed compares are out of line because we can't get the hardware to compute the overflow for us. */ switch (mode) { case QImode: OUT_AS1 (push, %1%<); OUT_AS1 (push, %0%>); OUT_AS1 (page, __cmpqi2); OUT_AS1 (call, __cmpqi2); break; case HImode: OUT_AS1 (push, %L1%<); OUT_AS1 (push, %H1%<); OUT_AS1 (push, %L0%<); OUT_AS1 (push, %H0%>%>%>); OUT_AS1 (page, __cmphi2); OUT_AS1 (call, __cmphi2); break; case SImode: OUT_AS1 (push, %D1%<); OUT_AS1 (push, %C1%<); OUT_AS1 (push, %B1%<); OUT_AS1 (push, %A1%<); OUT_AS1 (push, %D0%<); OUT_AS1 (push, %C0%<); OUT_AS1 (push, %B0%<); OUT_AS1 (push, %A0%>%>%>%>%>%>%>); OUT_AS1 (page, __cmpsi2); OUT_AS1 (call, __cmpsi2); break; case DImode: if (GET_CODE (operands[0]) == MEM && true_regnum (XEXP (operands[0], 0)) == REG_DP) { OUT_AS1 (push, %Z1%<); OUT_AS1 (push, %Y1%<); OUT_AS1 (push, %X1%<); OUT_AS1 (push, %W1%<); OUT_AS1 (push, %V1%<); OUT_AS1 (push, %U1%<); OUT_AS1 (push, %T1%<); OUT_AS1 (push, %S1%>%>%>%>%>%>%>); OUT_AS1 (page, __cmpdi2_dp); OUT_AS1 (call, __cmpdi2_dp); } else { OUT_AS1 (push, %Z1%<); OUT_AS1 (push, %Y1%<); OUT_AS1 (push, %X1%<); OUT_AS1 (push, %W1%<); OUT_AS1 (push, %V1%<); OUT_AS1 (push, %U1%<); OUT_AS1 (push, %T1%<); OUT_AS1 (push, %S1%<); OUT_AS1 (push, %Z0%<); OUT_AS1 (push, %Y0%<); OUT_AS1 (push, %X0%<); OUT_AS1 (push, %W0%<); OUT_AS1 (push, %V0%<); OUT_AS1 (push, %U0%<); OUT_AS1 (push, %T0%<); OUT_AS1 (push, %S0%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>); OUT_AS1 (page, __cmpdi2); OUT_AS1 (call, __cmpdi2); } break; default: abort (); } switch (code) { case LT: if (can_use_skip) { OUT_AS2 (cse, w, #0); } else { OUT_AS2 (csne, w, #0); OUT_AS1 (page, %2); OUT_AS1 (jmp, %2); } break; case GT: if (can_use_skip) { OUT_AS2 (cse, w, #2); } else { OUT_AS2 (csne, w, #2); OUT_AS1 (page, %2); OUT_AS1 (jmp, %2); } break; case LE: if (can_use_skip) { OUT_AS2 (snb, wreg, 1); } else { OUT_AS2 (sb, wreg, 1); OUT_AS1 (page, %2); OUT_AS1 (jmp, %2); } break; case GE: if (can_use_skip) { OUT_AS2 (csne, w, #0); } else { OUT_AS2 (cse, w, #0); OUT_AS1 (page, %2); OUT_AS1 (jmp, %2); } break; default:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -