📄 mmix.md
字号:
= mmix_gen_compare_reg (GE, mmix_compare_op0, mmix_compare_op1); /* The head comment of optabs.c:can_compare_p says we're required to implement this, so we have to clean up the mess here. */ if (operands[1] == NULL_RTX) { /* FIXME: Watch out for sharing/unsharing of rtx:es. */ emit_jump_insn ((*bcc_gen_fctn[(int) GT]) (operands[0])); emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (operands[0])); DONE; }}")(define_expand "blt" [(set (pc) (if_then_else (lt (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ operands[1] = mmix_gen_compare_reg (LT, mmix_compare_op0, mmix_compare_op1);}")(define_expand "bgtu" [(set (pc) (if_then_else (gtu (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ operands[1] = mmix_gen_compare_reg (GTU, mmix_compare_op0, mmix_compare_op1);}")(define_expand "bleu" [(set (pc) (if_then_else (leu (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ operands[1] = mmix_gen_compare_reg (LEU, mmix_compare_op0, mmix_compare_op1);}")(define_expand "bgeu" [(set (pc) (if_then_else (geu (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ operands[1] = mmix_gen_compare_reg (GEU, mmix_compare_op0, mmix_compare_op1);}")(define_expand "bltu" [(set (pc) (if_then_else (ltu (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ operands[1] = mmix_gen_compare_reg (LTU, mmix_compare_op0, mmix_compare_op1);}")(define_expand "bunordered" [(set (pc) (if_then_else (unordered (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ operands[1] = mmix_gen_compare_reg (UNORDERED, mmix_compare_op0, mmix_compare_op1); if (operands[1] == NULL_RTX) FAIL;}")(define_expand "bordered" [(set (pc) (if_then_else (ordered (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ operands[1] = mmix_gen_compare_reg (ORDERED, mmix_compare_op0, mmix_compare_op1);}");; FIXME: we can emit an unordered-or-*not*-equal compare in one insn, but;; there's no RTL code for it. Maybe revisit in future.;; FIXME: Odd/Even matchers?(define_insn "*bCC_foldable" [(set (pc) (if_then_else (match_operator 1 "mmix_foldable_comparison_operator" [(match_operand 2 "register_operand" "r") (const_int 0)]) (label_ref (match_operand 0 "" "")) (pc)))] "" "%+B%d1 %2,%0")(define_insn "*bCC" [(set (pc) (if_then_else (match_operator 1 "mmix_comparison_operator" [(match_operand 2 "mmix_reg_cc_operand" "r") (const_int 0)]) (label_ref (match_operand 0 "" "")) (pc)))] "" "%+B%d1 %2,%0")(define_insn "*bCC_inverted_foldable" [(set (pc) (if_then_else (match_operator 1 "mmix_foldable_comparison_operator" [(match_operand 2 "register_operand" "r") (const_int 0)]) (pc) (label_ref (match_operand 0 "" ""))))];; REVERSIBLE_CC_MODE is checked by mmix_foldable_comparison_operator. "" "%+B%D1 %2,%0")(define_insn "*bCC_inverted" [(set (pc) (if_then_else (match_operator 1 "mmix_comparison_operator" [(match_operand 2 "mmix_reg_cc_operand" "r") (const_int 0)]) (pc) (label_ref (match_operand 0 "" ""))))] "REVERSIBLE_CC_MODE (GET_MODE (operands[2]))" "%+B%D1 %2,%0")(define_expand "call" [(parallel [(call (match_operand:QI 0 "memory_operand" "") (match_operand 1 "general_operand" "")) (use (match_operand 2 "general_operand" "")) (clobber (match_dup 4))]) (set (match_dup 4) (match_dup 3))] "" "{ /* Since the epilogue 'uses' the return address, and it is clobbered in the call, and we set it back after every call (all but one setting will be optimized away), integrity is maintained. */ operands[3] = mmix_get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM); /* FIXME: There's a bug in gcc which causes NULL to be passed as operand[2] when we get out of registers, which later confuses gcc. Work around it by replacing it with const_int 0. Possibly documentation error too. */ if (operands[2] == NULL_RTX) operands[2] = const0_rtx; operands[4] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);}")(define_expand "call_value" [(parallel [(set (match_operand 0 "" "") (call (match_operand:QI 1 "memory_operand" "") (match_operand 2 "general_operand" ""))) (use (match_operand 3 "general_operand" "")) (clobber (match_dup 5))]) (set (match_dup 5) (match_dup 4))] "" "{ /* Since the epilogue 'uses' the return address, and it is clobbered in the call, and we set it back after every call (all but one setting will be optimized away), integrity is maintained. */ operands[4] = mmix_get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM); /* FIXME: See 'call'. */ if (operands[3] == NULL_RTX) operands[3] = const0_rtx; /* FIXME: Documentation bug: operands[3] (operands[2] for 'call') is the *next* argument register, not the number of arguments in registers. (There used to be code here where that mattered.) */ operands[5] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);}");; Don't use 'p' here. A 'p' must stand first in constraints, or reload;; messes up, not registering the address for reload. Several C++;; test-cases, including g++.brendan/crash40.C. FIXME: This is arguably a;; bug in gcc. Note line ~2612 in reload.c, that does things on the;; condition <<else if (constraints[i][0] == 'p')>> and the comment on;; ~3017 that says:;; << case 'p':;; /* All necessary reloads for an address_operand;; were handled in find_reloads_address. */>>;; Sorry, I have not dug deeper. If symbolic addresses are used;; rarely compared to addresses in registers, disparaging the;; first ("p") alternative by adding ? in the first operand;; might do the trick. We define 'U' as a synonym to 'p', but without the;; caveats (and very small advantages) of 'p'.(define_insn "*call_real" [(call (mem:QI (match_operand:DI 0 "mmix_symbolic_or_address_operand" "s,rU")) (match_operand 1 "" "")) (use (match_operand 2 "" "")) (clobber (reg:DI MMIX_rJ_REGNUM))] "" "@ PUSHJ $%p2,%0 PUSHGO $%p2,%a0")(define_insn "*call_value_real" [(set (match_operand 0 "register_operand" "=r,r") (call (mem:QI (match_operand:DI 1 "mmix_symbolic_or_address_operand" "s,rU")) (match_operand 2 "" ""))) (use (match_operand 3 "" "")) (clobber (reg:DI MMIX_rJ_REGNUM))] "" "@ PUSHJ $%p3,%1 PUSHGO $%p3,%a1");; I hope untyped_call and untyped_return are not needed for MMIX.;; Users of Objective-C will notice.; Generated by GCC.(define_expand "return" [(return)] "mmix_use_simple_return ()" ""); Generated by the epilogue expander.(define_insn "*expanded_return" [(return)] "" "POP %.,0")(define_expand "prologue" [(const_int 0)] "" "mmix_expand_prologue (); DONE;"); Note that the (return) from the expander itself is always the last insn; in the epilogue.(define_expand "epilogue" [(return)] "" "mmix_expand_epilogue ();")(define_insn "nop" [(const_int 0)] "" "SWYM 0,0,0")(define_insn "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" "JMP %0")(define_insn "indirect_jump" [(set (pc) (match_operand 0 "address_operand" "p"))] "" "GO $255,%a0");; FIXME: This is just a jump, and should be expanded to one.(define_insn "tablejump" [(set (pc) (match_operand:DI 0 "address_operand" "p")) (use (label_ref (match_operand 1 "" "")))] "" "GO $255,%a0");; The only peculiar thing is that the register stack has to be unwound at;; nonlocal_goto_receiver. At each function that has a nonlocal label, we;; save at function entry the location of the "alpha" register stack;; pointer, rO, in a stack slot known to that function (right below where;; the frame-pointer would be located).;; In the nonlocal goto receiver, we unwind the register stack by a series;; of "pop 0,0" until rO equals the saved value. (If it goes lower, we;; should call abort.)(define_expand "nonlocal_goto_receiver" [(parallel [(unspec_volatile [(const_int 0)] 1) (clobber (scratch:DI)) (clobber (reg:DI MMIX_rJ_REGNUM))]) (set (reg:DI MMIX_rJ_REGNUM) (match_dup 0))] "" "{ operands[0] = mmix_get_hard_reg_initial_val (Pmode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM); /* Mark this function as containing a landing-pad. */ cfun->machine->has_landing_pad = 1;}");; GCC can insist on using saved registers to keep the slot address in;; "across" the exception, or (perhaps) to use saved registers in the;; address and re-use them after the register stack unwind, so it's best;; to form the address ourselves.(define_insn "*nonlocal_goto_receiver_expanded" [(unspec_volatile [(const_int 0)] 1) (clobber (match_scratch:DI 0 "=&r")) (clobber (reg:DI MMIX_rJ_REGNUM))] ""{ rtx temp_reg = operands[0]; rtx my_operands[2]; HOST_WIDEST_INT offs; const char *my_template = "GETA $255,0f\;PUT rJ,$255\;LDOU $255,%a0\n\0:\;GET %1,rO\;CMPU %1,%1,$255\;BNP %1,1f\;POP 0,0\n1:"; my_operands[1] = temp_reg; /* If we have a frame-pointer (hence unknown stack-pointer offset), just use the frame-pointer and the known offset. */ if (frame_pointer_needed) { my_operands[0] = GEN_INT (-MMIX_fp_rO_OFFSET); output_asm_insn ("NEGU %1,0,%0", my_operands); my_operands[0] = gen_rtx_PLUS (Pmode, frame_pointer_rtx, temp_reg); } else { /* We know the fp-based offset, so "eliminate" it to be sp-based. */ offs = (mmix_initial_elimination_offset (MMIX_FRAME_POINTER_REGNUM, MMIX_STACK_POINTER_REGNUM) + MMIX_fp_rO_OFFSET); if (offs >= 0 && offs <= 255) my_operands[0] = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offs)); else { mmix_output_register_setting (asm_out_file, REGNO (temp_reg), offs, 1); my_operands[0] = gen_rtx_PLUS (Pmode, stack_pointer_rtx, temp_reg); } } output_asm_insn (my_template, my_operands); return "";})(define_insn "*Naddu" [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "const_int_operand" "n")) (match_operand:DI 3 "mmix_reg_or_8bit_operand" "rI")))] "GET_CODE (operands[2]) == CONST_INT && (INTVAL (operands[2]) == 2 || INTVAL (operands[2]) == 4 || INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)" "%2ADDU %0,%1,%3")(define_insn "*andn" [(set (match_operand:DI 0 "register_operand" "=r") (and:DI (not:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")) (match_operand:DI 2 "register_operand" "r")))] "" "ANDN %0,%2,%1")(define_insn "*nand" [(set (match_operand:DI 0 "register_operand" "=r") (ior:DI (not:DI (match_operand:DI 1 "register_operand" "%r")) (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))] "" "NAND %0,%1,%2")(define_insn "*nor" [(set (match_operand:DI 0 "register_operand" "=r") (and:DI (not:DI (match_operand:DI 1 "register_operand" "%r")) (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))] "" "NOR %0,%1,%2")(define_insn "*nxor" [(set (match_operand:DI 0 "register_operand" "=r") (not:DI (xor:DI (match_operand:DI 1 "register_operand" "%r") (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))] "" "NXOR %0,%1,%2")(define_insn "sync_icache" [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m") (match_operand:DI 1 "const_int_operand" "I")] 0)] "" "SYNCID %1,%0");; Local Variables:;; mode: lisp;; indent-tabs-mode: t;; End:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -