📄 spur.md
字号:
; (match_operand:SI 1 "immediate_operand" "I")); (match_operand:QI 2 "register_operand" "r"))]; "GET_CODE (operands[1]) == CONST_INT; && INTVAL (operands[1]) % 8 == 0; && (unsigned) INTVAL (operands[1]) < 32"; "*;{; operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) / 8);; return \"wr_insert 0,0,%1\;insert %0,%0,%2\";;}");; The three define_expand patterns on this page;; serve as subroutines of "movhi".;; Generate code to fetch an aligned halfword from memory.;; Operand 0 is the destination register (HImode).;; Operand 1 is the memory address (SImode).;; Operand 2 is a temporary (SImode).;; Operand 3 is a temporary (SImode).;; Operand 4 is a temporary (QImode).;; Operand 5 is an internal temporary (HImode).(define_expand "loadhi" [(set (match_operand:SI 2 "register_operand" "") (mem:SI (match_operand:SI 1 "register_operand" ""))) ;; Extract the low byte. (set (subreg:SI (match_dup 5) 0) (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 1))) ;; Form address of high byte. (set (match_operand:SI 3 "register_operand" "") (plus:SI (match_dup 1) (const_int 1))) ;; Extract the high byte. (set (subreg:SI (match_operand:QI 4 "register_operand" "") 0) (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 3))) ;; Put the high byte in with the low one. (set (zero_extract:SI (match_dup 5) (const_int 8) (const_int 1)) (subreg:SI (match_dup 4) 0)) (set (match_operand:HI 0 "register_operand" "") (match_dup 5))] "" "operands[5] = gen_reg_rtx (HImode);");; Generate code to store an aligned halfword into memory.;; Operand 0 is the destination address (SImode).;; Operand 1 is the source register (HImode, not constant).;; Operand 2 is a temporary (SImode).;; Operand 3 is a temporary (SImode).;; Operand 4 is a temporary (QImode).;; Operand 5 is an internal variable made from operand 1.(define_expand "storehi" [(set (match_operand:SI 2 "register_operand" "") (mem:SI (match_operand:SI 0 "register_operand" ""))) ;; Insert the low byte. (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 0)) (match_dup 5)) ;; Form address of high byte. (set (match_operand:SI 3 "register_operand" "") (plus:SI (match_dup 0) (const_int 1))) ;; Extract the high byte from the source. (set (subreg:SI (match_operand:QI 4 "register_operand" "") 0) (zero_extract:SI (match_operand:HI 1 "register_operand" "") (const_int 8) (const_int 1))) ;; Store high byte into the memory word (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 3)) (subreg:SI (match_dup 4) 0)) ;; Put memory word back into memory. (set (mem:SI (match_dup 0)) (match_dup 2))] "" "{ if (GET_CODE (operands[1]) == SUBREG) operands[5] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]), SUBREG_WORD (operands[1])); else operands[5] = gen_rtx (SUBREG, SImode, operands[1], 0);}");; Like storehi but operands[1] is a CONST_INT.(define_expand "storeinthi" [(set (match_operand:SI 2 "register_operand" "") (mem:SI (match_operand:SI 0 "register_operand" ""))) ;; Insert the low byte. (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 0)) (match_dup 5)) ;; Form address of high byte. (set (match_operand:SI 3 "register_operand" "") (plus:SI (match_dup 0) (const_int 1))) ;; Store high byte into the memory word (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 3)) (match_dup 6)) ;; Put memory word back into memory. (set (mem:SI (match_dup 0)) (match_dup 2))] "" " operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 255); operands[6] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[1]) >> 8) & 255);");; Main entry for generating insns to move halfwords.(define_expand "movhi" [(set (match_operand:HI 0 "general_operand" "") (match_operand:HI 1 "general_operand" ""))] "" "{ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) operands[1] = copy_to_reg (operands[1]); if (GET_CODE (operands[1]) == MEM) { rtx insn = emit_insn (gen_loadhi (operands[0], force_reg (SImode, XEXP (operands[1], 0)), gen_reg_rtx (SImode), gen_reg_rtx (SImode), gen_reg_rtx (QImode))); /* Tell cse what value the loadhi produces, so it detect duplicates. */ REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, operands[1], REG_NOTES (insn)); } else if (GET_CODE (operands[0]) == MEM) { if (GET_CODE (operands[1]) == CONST_INT) emit_insn (gen_storeinthi (force_reg (SImode, XEXP (operands[0], 0)), operands[1], gen_reg_rtx (SImode), gen_reg_rtx (SImode), gen_reg_rtx (QImode))); else { if (CONSTANT_P (operands[1])) operands[1] = force_reg (HImode, operands[1]); emit_insn (gen_storehi (force_reg (SImode, XEXP (operands[0], 0)), operands[1], gen_reg_rtx (SImode), gen_reg_rtx (SImode), gen_reg_rtx (QImode))); } } else emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); DONE;}");; Recognize insns generated for moving halfwords.;; (Note that the extract and insert patterns for single-byte moves;; are also involved in recognizing some of the insns used for this purpose.)(define_insn "" [(set (match_operand:HI 0 "general_operand" "=r,m") (match_operand:HI 1 "general_operand" "rmi,r"))] "" "*{ if (GET_CODE (operands[0]) == MEM) return \"st_32 %1,%0\"; if (GET_CODE (operands[1]) == MEM) return \"ld_32 %0,%1\;nop\"; if (GET_CODE (operands[1]) == REG) return \"add_nt %0,%1,$0\"; return \"add_nt %0,r0,%1\";}")(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (zero_extract:SI (match_operand:HI 1 "register_operand" "r") (const_int 8) (match_operand:SI 2 "nonmemory_operand" "rI")))] "" "extract %0,%1,%2")(define_insn "" [(set (zero_extract:SI (match_operand:HI 0 "register_operand" "+r") (const_int 8) (match_operand:SI 1 "nonmemory_operand" "rI")) (match_operand:SI 2 "nonmemory_operand" "ri"))] "" "wr_insert %1\;insert %0,%0,%2");; Constant propagation can optimize the previous pattern into this pattern.;(define_insn ""; [(set (zero_extract:QI (match_operand:HI 0 "register_operand" "+r"); (const_int 8); (match_operand:SI 1 "immediate_operand" "I")); (match_operand:QI 2 "register_operand" "r"))]; "GET_CODE (operands[1]) == CONST_INT; && INTVAL (operands[1]) % 8 == 0; && (unsigned) INTVAL (operands[1]) < 32"; "*;{; operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) / 8);; return \"wr_insert 0,0,%1\;insert %0,%0,%2\";;}");; This pattern forces (set (reg:DF ...) (const_double ...));; to be reloaded by putting the constant into memory.;; It must come before the more general movdf pattern.(define_insn "" [(set (match_operand:DF 0 "general_operand" "=&r,f,&o") (match_operand:DF 1 "" "mG,m,G"))] "GET_CODE (operands[1]) == CONST_DOUBLE" "*{ if (FP_REG_P (operands[0])) return output_fp_move_double (operands); if (operands[1] == dconst0_rtx && GET_CODE (operands[0]) == REG) { operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); return \"add_nt %0,r0,$0\;add_nt %1,r0,$0\"; } if (operands[1] == dconst0_rtx && GET_CODE (operands[0]) == MEM) { operands[1] = adj_offsettable_operand (operands[0], 4); return \"st_32 r0,%0\;st_32 r0,%1\"; } return output_move_double (operands);}") (define_insn "movdf" [(set (match_operand:DF 0 "general_operand" "=r,&r,m,?f,?rm") (match_operand:DF 1 "general_operand" "r,m,r,rfm,f"))] "" "*{ if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) return output_fp_move_double (operands); return output_move_double (operands);}")(define_insn "movdi" [(set (match_operand:DI 0 "general_operand" "=r,&r,m,?f,?rm") (match_operand:DI 1 "general_operand" "r,m,r,rfm,f"))] "" "*{ if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) return output_fp_move_double (operands); return output_move_double (operands);}")(define_insn "movsf" [(set (match_operand:SF 0 "general_operand" "=rf,m") (match_operand:SF 1 "general_operand" "rfm,rf"))] "" "*{ if (FP_REG_P (operands[0])) { if (FP_REG_P (operands[1])) return \"fmov %0,%1\"; if (GET_CODE (operands[1]) == REG) { rtx xoperands[2]; int offset = - get_frame_size () - 8; xoperands[1] = operands[1]; xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset); output_asm_insn (\"st_32 %1,r25,%0\", xoperands); xoperands[1] = operands[0]; output_asm_insn (\"ld_sgl %1,r25,%0\;nop\", xoperands); return \"\"; } return \"ld_sgl %0,%1\;nop\"; } if (FP_REG_P (operands[1])) { if (GET_CODE (operands[0]) == REG) { rtx xoperands[2]; int offset = - get_frame_size () - 8; xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset); xoperands[1] = operands[1]; output_asm_insn (\"st_sgl %1,r25,%0\", xoperands); xoperands[1] = operands[0]; output_asm_insn (\"ld_32 %1,r25,%0\;nop\", xoperands); return \"\"; } return \"st_sgl %1,%0\"; } if (GET_CODE (operands[0]) == MEM) return \"st_32 %r1,%0\"; if (GET_CODE (operands[1]) == MEM) return \"ld_32 %0,%1\;nop\"; if (GET_CODE (operands[1]) == REG) return \"add_nt %0,%1,$0\"; return \"add_nt %0,r0,%1\";}");;- truncation instructions(define_insn "truncsiqi2" [(set (match_operand:QI 0 "register_operand" "=r") (truncate:QI (match_operand:SI 1 "register_operand" "r")))] "" "add_nt %0,%1,$0")(define_insn "trunchiqi2" [(set (match_operand:QI 0 "register_operand" "=r") (truncate:QI (match_operand:HI 1 "register_operand" "r")))] "" "add_nt %0,%1,$0")(define_insn "truncsihi2" [(set (match_operand:HI 0 "register_operand" "=r") (truncate:HI (match_operand:SI 1 "register_operand" "r")))] "" "add_nt %0,%1,$0");;- zero extension instructions;; Note that the one starting from HImode comes before those for QImode;; so that a constant operand will match HImode, not QImode.(define_expand "zero_extendhisi2" [(set (match_operand:SI 0 "register_operand" "") (and:SI (match_operand:HI 1 "register_operand" "") ;Changed to SI below ;; This constant is invalid, but reloading will handle it. ;; It's useless to generate here the insns to construct it ;; because constant propagation would simplify them anyway. (match_dup 2)))] "" "{ if (GET_CODE (operands[1]) == SUBREG) operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]), SUBREG_WORD (operands[1])); else operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0); operands[2] = force_reg (SImode, gen_rtx (CONST_INT, VOIDmode, 65535));}")(define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r") (zero_extend:HI (match_operand:QI 1 "register_operand" "r")))] "" "extract %0,%1,$0")(define_insn "zero_extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r") (zero_extend:SI (match_operand:QI 1 "register_operand" "r")))] "" "extract %0,%1,$0");;- sign extension instructions;; Note that the one starting from HImode comes before those for QImode;; so that a constant operand will match HImode, not QImode.(define_expand "extendhisi2" [(set (match_dup 2) (and:SI (match_operand:HI 1 "register_operand" "") ;Changed to SI below (match_dup 4))) (set (match_dup 3) (plus:SI (match_dup 2) (match_dup 5))) (set (match_operand:SI 0 "register_operand" "") (xor:SI (match_dup 3) (match_dup 5)))] "" "{ if (GET_CODE (operands[1]) == SUBREG) operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]), SUBREG_WORD (operands[1])); else operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0); operands[2] = gen_reg_rtx (SImode);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -