📄 romp.md
字号:
if (GET_CODE (operands[1]) != CONST_INT || (unsigned) (INTVAL (operands[1]) + 0x8000) >= 0x10000) operands[1] = force_reg (SImode, operands[1]);}")(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (minus:SI (match_operand:SI 1 "reg_or_D_operand" "K,0,r") (match_operand:SI 2 "register_operand" "r,r,0")))] "" "@ sfi %0,%2,%1 s %0,%2 sf %0,%1" [(set_attr "length" "4,2,2")]);; Multiply either calls a special RT routine or is done in-line, depending;; on the value of a -m flag.;;;; First define the way we call the subroutine.(define_expand "mulsi3_subr" [(set (reg:SI 2) (match_operand:SI 1 "register_operand" "")) (set (reg:SI 3) (match_operand:SI 2 "register_operand" "")) (parallel [(set (reg:SI 2) (mult:SI (reg:SI 2) (reg:SI 3))) (clobber (reg:SI 0)) (clobber (reg:SI 15))]) (set (match_operand:SI 0 "register_operand" "") (reg:SI 2))] "" "")(define_expand "mulsi3" [(set (match_operand:SI 0 "register_operand" "") (mult:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "register_operand" "")))] "" "{ if (! TARGET_IN_LINE_MUL) { emit_insn (gen_mulsi3_subr (operands[0], operands[1], operands[2])); DONE; }}");; Define the patterns to match.;; We would like to provide a delay slot for the insns that call internal;; routines, but doing so is risky since reorg will think that the use of;; r2 and r3 is completed in the insn needing the delay slot. Also, it;; won't know that the cc will be clobbered. So take the safe approach;; and don't give them delay slots.(define_insn "" [(set (reg:SI 2) (mult:SI (reg:SI 2) (reg:SI 3))) (clobber (reg:SI 0)) (clobber (reg:SI 15))] "! TARGET_IN_LINE_MUL" "bali%# r15,lmul$$" [(set_attr "type" "misc") (set_attr "in_delay_slot" "no")])(define_insn "" [(set (match_operand:SI 0 "register_operand" "=&r") (mult:SI (match_operand:SI 1 "register_operand" "%r") (match_operand:SI 2 "register_operand" "r")))] "TARGET_IN_LINE_MUL" "*{ return output_in_line_mul (); }" [(set_attr "length" "38") (set_attr "type" "multi")]);; Handle divide and modulus. The same function returns both values,;; so use divmodsi4. This divides arg 1 by arg 2 with quotient to go;; into arg 0 and remainder in arg 3.;;;; We want to put REG_EQUAL notes for the two outputs. So we need a;; function to do everything else.(define_expand "divmodsi4_doit" [(set (reg:SI 2) (match_operand:SI 0 "register_operand" "")) (set (reg:SI 3) (match_operand:SI 1 "register_operand" "")) (parallel [(set (reg:SI 2) (div:SI (reg:SI 2) (reg:SI 3))) (set (reg:SI 3) (mod:SI (reg:SI 2) (reg:SI 3))) (clobber (reg:SI 0)) (clobber (reg:SI 15))])] "" "")(define_expand "divmodsi4" [(parallel [(set (match_operand:SI 0 "register_operand" "") (div:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "register_operand" ""))) (set (match_operand:SI 3 "register_operand" "") (mod:SI (match_dup 1) (match_dup 2)))])] "" "{ rtx insn; emit_insn (gen_divmodsi4_doit (operands[1], operands[2])); insn = emit_move_insn (operands[0], gen_rtx_REG (SImode, 2)); REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, gen_rtx_DIV (SImode, operands[1], operands[2]), REG_NOTES (insn)); insn = emit_move_insn (operands[3], gen_rtx_REG (SImode, 3)); REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, gen_rtx_MOD (SImode, operands[1], operands[2]), REG_NOTES (insn)); DONE;}")(define_insn "" [(set (reg:SI 2) (div:SI (reg:SI 2) (reg:SI 3))) (set (reg:SI 3) (mod:SI (reg:SI 2) (reg:SI 3))) (clobber (reg:SI 0)) (clobber (reg:SI 15))] "" "bali%# r15,ldiv$$" [(set_attr "type" "misc") (set_attr "in_delay_slot" "no")]);; Similarly for unsigned divide.(define_expand "udivmodsi4_doit" [(set (reg:SI 2) (match_operand:SI 0 "register_operand" "")) (set (reg:SI 3) (match_operand:SI 1 "register_operand" "")) (parallel [(set (reg:SI 2) (udiv:SI (reg:SI 2) (reg:SI 3))) (set (reg:SI 3) (umod:SI (reg:SI 2) (reg:SI 3))) (clobber (reg:SI 0)) (clobber (reg:SI 15))])] "" "")(define_expand "udivmodsi4" [(parallel [(set (match_operand:SI 0 "register_operand" "") (udiv:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "register_operand" ""))) (set (match_operand:SI 3 "register_operand" "") (umod:SI (match_dup 1) (match_dup 2)))])] "" "{ rtx insn; emit_insn (gen_udivmodsi4_doit (operands[1], operands[2])); insn = emit_move_insn (operands[0], gen_rtx_REG (SImode, 2)); REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, gen_rtx_UDIV (SImode, operands[1], operands[2]), REG_NOTES (insn)); insn = emit_move_insn (operands[3], gen_rtx_REG (SImode, 3)); REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, gen_rtx_UMOD (SImode, operands[1], operands[2]), REG_NOTES (insn)); DONE;}")(define_insn "" [(set (reg:SI 2) (udiv:SI (reg:SI 2) (reg:SI 3))) (set (reg:SI 3) (umod:SI (reg:SI 2) (reg:SI 3))) (clobber (reg:SI 0)) (clobber (reg:SI 15))] "" "bali%# r15,uldiv$$" [(set_attr "type" "misc") (set_attr "in_delay_slot" "no")]);; Define DImode arithmetic operations.;;;; It is possible to do certain adds and subtracts with constants in a single;; insn, but it doesn't seem worth the trouble.;;;; Don't use DEFINE_SPLIT on these because the dependency on CC can't be;; easily tracked in that case!(define_insn "adddi3" [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (match_operand:DI 1 "register_operand" "%0") (match_operand:DI 2 "register_operand" "r")))] "" "a %O0,%O2\;ae %0,%2" [(set_attr "type" "multi")])(define_insn "subdi3" [(set (match_operand:DI 0 "register_operand" "=r") (minus:DI (match_operand:DI 1 "register_operand" "0") (match_operand:DI 2 "register_operand" "r")))] "" "s %O0,%O2\;se %0,%2" [(set_attr "type" "multi")])(define_insn "negdi2" [(set (match_operand:DI 0 "register_operand" "=r,&r") (neg:DI (match_operand:DI 1 "register_operand" "0,r")))] "" "twoc %O0,%O1\;onec %0,%1\;aei %0,%0,0" [(set_attr "type" "multi") (set_attr "length" "8")]);; Unary arithmetic operations.(define_insn "abssi2" [(set (match_operand:SI 0 "register_operand" "=r") (abs:SI (match_operand:SI 1 "register_operand" "r")))] "" "abs %0,%1" [(set_attr "length" "2")])(define_insn "negsi2" [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (match_operand:SI 1 "register_operand" "r")))] "" "twoc %0,%1" [(set_attr "length" "2")])(define_insn "one_cmplsi2" [(set (match_operand:SI 0 "register_operand" "=r") (not:SI (match_operand:SI 1 "register_operand" "r")))] "" "onec %0,%1" [(set_attr "length" "2")]);; Logical insns: AND, IOR, and XOR;;;; If the operation is being performed on a 32-bit constant such that;; it cannot be done in one insn, do it in two. We may lose a bit on;; CSE in pathological cases, but it seems better doing it this way.(define_expand "andsi3" [(set (match_operand:SI 0 "register_operand" "") (and:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "reg_or_any_cint_operand" "")))] "" "{ if (GET_CODE (operands[2]) == CONST_INT) { int top = (unsigned) INTVAL (operands[2]) >> 16; int bottom = INTVAL (operands[2]) & 0xffff; if (top != 0 && top != 0xffff && bottom != 0 && bottom != 0xffff) { emit_insn (gen_andsi3 (operands[0], operands[1], GEN_INT ((top << 16) | 0xffff))); operands[1] = operands[0]; operands[2] = GEN_INT (0xffff0000 | bottom); } }}");(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (and:SI (match_operand:SI 1 "reg_or_and_operand" "%0,r,0") (match_operand:SI 2 "reg_or_and_operand" "P,LMO,r")))] "register_operand (operands[1], SImode) || register_operand (operands[2], SImode)" "@ clrb%k2 %0,%b2 ni%z2 %0,%1,%Z2 n %0,%2" [(set_attr "length" "2,4,2")]);; logical OR (IOR)(define_expand "iorsi3" [(set (match_operand:SI 0 "register_operand" "") (ior:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "reg_or_any_cint_operand" "")))] "" "{ if (GET_CODE (operands[2]) == CONST_INT) { int top = (unsigned) INTVAL (operands[2]) >> 16; int bottom = INTVAL (operands[2]) & 0xffff; if (top != 0 && bottom != 0) { emit_insn (gen_iorsi3 (operands[0], operands[1], GEN_INT (top << 16))); operands[1] = operands[0]; operands[2] = GEN_INT (bottom); } }}");(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (ior:SI (match_operand:SI 1 "reg_or_cint_operand" "%0,r,0") (match_operand:SI 2 "reg_or_cint_operand" "N,LM,r")))] "register_operand (operands[1], SImode) || register_operand (operands[2], SImode)" "@ setb%h2 %0,%b2 oi%h2 %0,%1,%H2 o %0,%2" [(set_attr "length" "2,4,2")]);; exclusive-or (XOR)(define_expand "xorsi3" [(set (match_operand:SI 0 "register_operand" "") (xor:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "reg_or_any_cint_operand" "")))] "" "{ if (GET_CODE (operands[2]) == CONST_INT) { int top = (unsigned) INTVAL (operands[2]) >> 16; int bottom = INTVAL (operands[2]) & 0xffff; if (top == 0xffff && bottom == 0xffff) { emit_insn (gen_one_cmplsi2 (operands[0], operands[1])); DONE; } else if (top != 0 && bottom != 0) { emit_insn (gen_xorsi3 (operands[0], operands[1], GEN_INT (top << 16))); operands[1] = operands[0]; operands[2] = GEN_INT (bottom); } }}");(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r,r") (xor:SI (match_operand:SI 1 "reg_or_cint_operand" "%r,0") (match_operand:SI 2 "reg_or_cint_operand" "LM,r")))] "register_operand (operands[1], SImode) || register_operand (operands[2], SImode)" "@ xi%h2 %0,%1,%H2 x %0,%2" [(set_attr "length" "4,2")]);; Various shift insns(define_insn "ashrsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0") (match_operand:SI 2 "reg_or_cint_operand" "r,n")))] "" "@ sar %0,%2 sari%s2 %0,%S2" [(set_attr "length" "2")])(define_insn "lshrsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0") (match_operand:SI 2 "reg_or_cint_operand" "r,n")))] "" "@ sr %0,%2 sri%s2 %0,%S2" [(set_attr "length" "2")])(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (ashift:SI (match_operand:SI 1 "register_operand" "b") (const_int 1)))] "" "cas %0,%1,%1" [(set_attr "length" "2") (set_attr "type" "address")])(define_insn "ashlsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") (ashift:SI (match_operand:SI 1 "register_operand" "0,0") (match_operand:SI 2 "reg_or_cint_operand" "r,n")))] "" "@ sl %0,%2 sli%s2 %0,%S2" [(set_attr "length" "2")]);; Function call insns:;;;; On the ROMP, &fcn is actually a pointer to the data area, which is passed;; to the function in r0. &.fcn is the actual starting address of the;; function. Also, the word at &fcn contains &.fcn.;;;; For both functions that do and don't return values, there are two cases:;; where the function's address is a constant, and where it isn't.;;;; Operand 1 (2 for `call_value') is the number of arguments and is not used.(define_expand "call" [(use (match_operand:SI 0 "address_operand" "")) (use (match_operand 1 "" ""))] "" "{ rtx reg0 = gen_rtx_REG (SImode, 0); rtx call_insn; if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != CONST_INT) abort(); operands[0] = XEXP (operands[0], 0); if (GET_CODE (operands[0]) == SYMBOL_REF) { char *real_fcnname = (char *) alloca (strlen (XSTR (operands[0], 0)) + 2); /* Copy the data area address to r0. */ emit_move_insn (reg0, force_reg (SImode, operands[0])); strcpy (real_fcnname, \".\"); strcat (real_fcnname, XSTR (operands[0], 0)); operands[0] = get_symref (real_fcnname); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -