📄 romp.md
字号:
;; If the output is a register and the input is memory, we have to be careful;; and see which word needs to be loaded first. We also cannot to the;; split if the input is a constant because it would result in invalid;; insns. When the output is a MEM, we must put a CLOBBER on each of the;; resulting insn, when it is not a MEM, we must not.(define_split [(set (match_operand:DF 0 "memory_operand" "") (match_operand:DF 1 "register_operand" "")) (clobber (reg:SI 0)) (clobber (reg:SI 15))] "GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 15" [(parallel [(set (match_dup 2) (match_dup 3)) (clobber (match_dup 6))]) (parallel [(set (match_dup 4) (match_dup 5)) (clobber (match_dup 7))])] "{ operands[2] = operand_subword (operands[0], 0, 0, DFmode); operands[3] = operand_subword (operands[1], 0, 0, DFmode); operands[4] = operand_subword (operands[0], 1, 0, DFmode); operands[5] = operand_subword (operands[1], 1, 0, DFmode); if (operands[2] == 0 || operands[3] == 0 || operands[4] == 0 || operands[5] == 0) FAIL; if (reload_completed) operands[6] = operands[7] = gen_rtx_REG (SImode, 15); else { operands[6] = gen_rtx_SCRATCH (SImode); operands[7] = gen_rtx_SCRATCH (SImode); }}")(define_split [(set (match_operand:DF 0 "nonmemory_operand" "") (match_operand:DF 1 "general_operand" "")) (clobber (reg:SI 0)) (clobber (reg:SI 15))] "! symbolic_memory_operand (operands[1], DFmode) && GET_CODE (operands[1]) != CONST_DOUBLE && (GET_CODE (operands[0]) != REG || REGNO (operands[0]) < 15) && (GET_CODE (operands[1]) != REG || REGNO (operands[1]) < 15) && (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG) && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG && ! reload_completed && reg_overlap_mentioned_p (operands[0], operands[1]))" [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))] "{ if (GET_CODE (operands[0]) != REG || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, operands[1], 0)) { operands[2] = operand_subword (operands[0], 0, 0, DFmode); operands[3] = operand_subword (operands[1], 0, 0, DFmode); operands[4] = operand_subword (operands[0], 1, 0, DFmode); operands[5] = operand_subword (operands[1], 1, 0, DFmode); } else { operands[2] = operand_subword (operands[0], 1, 0, DFmode); operands[3] = operand_subword (operands[1], 1, 0, DFmode); operands[4] = operand_subword (operands[0], 0, 0, DFmode); operands[5] = operand_subword (operands[1], 0, 0, DFmode); } if (operands[2] == 0 || operands[3] == 0 || operands[4] == 0 || operands[5] == 0) FAIL;}");; Conversions from one integer mode to another.;; It is possible sometimes to sign- or zero-extend while fetching from memory.;;;; First, sign-extensions:(define_expand "extendhisi2" [(set (match_operand:SI 0 "register_operand" "") (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] "" "")(define_insn "" [(set (match_operand:SI 0 "register_operand" "=b") (sign_extend:SI (match_operand:HI 1 "symbolic_memory_operand" "m")))] "" "loadha %0,%1" [(set_attr "type" "load")])(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r,r,b") (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Q,m")))] "" "@ exts %0,%1 lha%M1 %0,%1 loadha %0,%1" [(set_attr "type" "arith,load,load") (set_attr "length" "2,*,*")])(define_expand "extendqisi2" [(set (match_dup 2) (ashift:SI (match_operand:QI 1 "register_operand" "") (const_int 24))) (set (match_operand:SI 0 "register_operand" "") (ashiftrt:SI (match_dup 2) (const_int 24)))] "" "{ operands[1] = gen_lowpart (SImode, operands[1]); operands[2] = gen_reg_rtx (SImode); }")(define_expand "extendqihi2" [(set (match_dup 2) (ashift:SI (match_operand:QI 1 "register_operand" "") (const_int 24))) (set (match_operand:HI 0 "register_operand" "") (ashiftrt:SI (match_dup 2) (const_int 24)))] "" "{ operands[0] = gen_lowpart (SImode, operands[0]); operands[1] = gen_lowpart (SImode, operands[1]); operands[2] = gen_reg_rtx (SImode); }");; Define peepholes to eliminate an instruction when we are doing a sign;; extension but cannot clobber the input.;;;; In this case we will shift left 24 bits, but need a copy first. The shift;; can be replaced by a "mc03" instruction, but this can only be done if;; followed by the right shift of 24 or more bits.(define_peephole [(set (match_operand:SI 0 "register_operand" "") (subreg:SI (match_operand:QI 1 "register_operand" "") 0)) (set (match_dup 0) (ashift:SI (match_dup 0) (const_int 24))) (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_operand:SI 2 "const_int_operand" "")))] "INTVAL (operands[2]) >= 24" "mc03 %0,%1\;sari16 %0,%S2" [(set_attr "type" "multi") (set_attr "length" "4") (set_attr "cc" "sets")]);; Now zero extensions:(define_expand "zero_extendhisi2" [(set (match_operand:SI 0 "register_operand" "") (zero_extend:SI (match_operand:HI 1 "register_operand" "")))] "" "")(define_insn "" [(set (match_operand:SI 0 "register_operand" "=b") (zero_extend:SI (match_operand:HI 1 "symbolic_memory_operand" "m")))] "" "loadh %0,%1" [(set_attr "type" "load")])(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r,r,b") (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Q,m")))] "" "@ nilz %0,%1,65535 lh%N1 %0,%1 loadh %0,%1" [(set_attr "type" "arith,loadz,load")])(define_expand "zero_extendqisi2" [(set (match_operand:SI 0 "register_operand" "") (zero_extend:SI (match_operand:QI 1 "register_operand" "")))] "" "")(define_insn "" [(set (match_operand:SI 0 "register_operand" "=b") (zero_extend:SI (match_operand:QI 1 "symbolic_memory_operand" "m")))] "" "loadc %0,%1" [(set_attr "type" "load")])(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r,r,b") (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Q,m")))] "" "@ nilz %0,%1,255 lc%M1 %0,%1 loadc %0,%1" [(set_attr "type" "arith,load,load")])(define_expand "zero_extendqihi2" [(set (match_operand:HI 0 "register_operand" "") (zero_extend:HI (match_operand:QI 1 "register_operand" "")))] "" "")(define_insn "" [(set (match_operand:HI 0 "register_operand" "=b") (zero_extend:HI (match_operand:QI 1 "symbolic_memory_operand" "m")))] "" "loadc %0,%1" [(set_attr "type" "load")])(define_insn "" [(set (match_operand:HI 0 "register_operand" "=r,r,b") (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,Q,m")))] "" "@ nilz %0,%1,255 lc%M1 %0,%1 loadc %0,%1" [(set_attr "type" "arith,load,load")]);; Various extract and insertion operations.(define_expand "extzv" [(set (match_operand:SI 0 "register_operand" "") (zero_extract:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "const_int_operand" "") (match_operand:SI 3 "const_int_operand" "")))] "" "{ if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 8) FAIL; if (GET_CODE (operands[3]) != CONST_INT) FAIL; if (INTVAL (operands[3]) != 0 && INTVAL (operands[3]) != 8 && INTVAL (operands[3]) != 16 && INTVAL (operands[3]) != 24) FAIL;}")(define_insn "" [(set (match_operand:SI 0 "register_operand" "=&r") (zero_extract:SI (match_operand:SI 1 "register_operand" "r") (const_int 8) (match_operand:SI 2 "const_int_operand" "n")))] "(INTVAL (operands[2]) & 7) == 0" "lis %0,0\;mc3%B2 %0,%1" [(set_attr "type" "multi") (set_attr "cc" "change0")])(define_split [(set (match_operand:SI 0 "register_operand" "=&r") (zero_extract:SI (match_operand:SI 1 "register_operand" "r") (const_int 8) (match_operand:SI 2 "const_int_operand" "n")))] "(INTVAL (operands[2]) & 7) == 0" [(set (match_dup 0) (const_int 0)) (set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 24)) (zero_extract:SI (match_dup 1) (const_int 8) (match_dup 2)))] "")(define_insn "" [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") (const_int 8) (const_int 24)) (zero_extract:SI (match_operand:SI 1 "register_operand" "r") (const_int 8) (match_operand:SI 2 "const_int_operand" "n")))] "(INTVAL (operands[2]) & 7) == 0" "mc3%B2 %0,%1" [(set_attr "type" "address") (set_attr "length" "2")])(define_expand "insv" [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "") (match_operand:SI 1 "const_int_operand" "") (match_operand:SI 2 "const_int_operand" "")) (match_operand:SI 3 "register_operand" ""))] "" "{ if (GET_CODE (operands[2]) != CONST_INT) FAIL; if (GET_CODE (operands[1]) != CONST_INT) FAIL; if (INTVAL (operands[1]) == 1) { emit_insn (gen_bit_insv (operands[0], operands[1], operands[2], operands[3])); DONE; } else if (INTVAL (operands[1]) == 8 && (INTVAL (operands[2]) % 8 == 0)) ; /* Accept aligned byte-wide field. */ else FAIL;}");; For a single-bit insert, it is better to explicitly generate references;; to the T bit. We will call the T bit "CC0" because it can be clobbered;; by some CC0 sets (single-bit tests).(define_expand "bit_insv" [(set (cc0) (zero_extract:SI (match_operand:SI 3 "register_operand" "") (const_int 1) (const_int 31))) (parallel [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "") (match_operand:SI 1 "const_int_operand" "") (match_operand:SI 2 "const_int_operand" "")) (ne (cc0) (const_int 0))) (clobber (match_scratch:SI 4 ""))])] "" "") (define_insn "" [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") (const_int 8) (match_operand:SI 1 "const_int_operand" "n")) (match_operand:SI 2 "register_operand" "r"))] "(INTVAL (operands[1]) & 7) == 0" "mc%B1%.3 %0,%2" [(set_attr "type" "address") (set_attr "length" "2")]);; This pattern cannot have any input reloads since if references CC0.;; So we have to add code to support memory, which is the only other;; thing that a "register_operand" can become. There is still a problem;; if the address isn't valid and *it* needs a reload, but there is no;; way to solve that problem, so let's hope it never happens.(define_insn "" [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r,m") (const_int 1) (match_operand:SI 1 "const_int_operand" "n,m")) (ne (cc0) (const_int 0))) (clobber (match_scratch:SI 2 "=X,b"))] "" "@ mftbi%t1 %0,%S1 l%M0 %2,%0\;mftb%t1 %2,%S1\;st%M0 %2,%0" [(set_attr "type" "*,multi") (set_attr "cc" "none,none") (set_attr "length" "2,10")]);; Arithmetic instructions. First, add and subtract.;;;; It may be that the second input is either large or small enough that;; the operation cannot be done in a single insn. In that case, emit two.(define_expand "addsi3" [(set (match_operand:SI 0 "register_operand" "") (plus:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "nonmemory_operand" "")))] "" "{ if (GET_CODE (operands[2]) == CONST_INT && (unsigned) (INTVAL (operands[2]) + 0x8000) >= 0x10000 && (INTVAL (operands[2]) & 0xffff) != 0) { int low = INTVAL (operands[2]) & 0xffff; int high = (unsigned) INTVAL (operands[2]) >> 16; if (low & 0x8000) high++, low |= 0xffff0000; emit_insn (gen_addsi3 (operands[0], operands[1], GEN_INT (high << 16))); operands[1] = operands[0]; operands[2] = GEN_INT (low); }}");; Put the insn to add a symbolic constant to a register separately to;; improve register allocation since it has different register requirements.(define_insn "" [(set (match_operand:SI 0 "register_operand" "=b") (plus:SI (match_operand:SI 1 "register_operand" "%b") (match_operand:SI 2 "romp_symbolic_operand" "s")))] "" "get %0,$%2(%1)" [(set_attr "type" "address") (set_attr "length" "8")])(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,b") (plus:SI (match_operand:SI 1 "reg_or_add_operand" "%0,0,r,b,0,r,b") (match_operand:SI 2 "reg_or_add_operand" "I,J,K,M,r,b,s")))] "register_operand (operands[1], SImode) || register_operand (operands[2], SImode)" "@ ais %0,%2 sis %0,%n2 ail %0,%1,%2 cau %0,%H2(%1) a %0,%2 cas %0,%1,%2 get %0,$%2(%1)" [(set_attr "type" "arith,arith,arith,address,arith,address,misc") (set_attr "length" "2,2,4,4,2,2,8")]);; Now subtract.;;;; 1. If third operand is constant integer, convert it to add of the negative;; of that integer.;; 2. If the second operand is not a valid constant integer, force it into a;; register.(define_expand "subsi3" [(set (match_operand:SI 0 "register_operand" "") (minus:SI (match_operand:SI 1 "reg_or_any_cint_operand" "") (match_operand:SI 2 "reg_or_any_cint_operand" "")))] "" "{ if (GET_CODE (operands [2]) == CONST_INT) { emit_insn (gen_addsi3 (operands[0], operands[1], GEN_INT (- INTVAL (operands[2])))); DONE; } else operands[2] = force_reg (SImode, operands[2]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -