📄 m32r.md
字号:
int shift; /* In all cases we will emit two instructions. However we try to use 2 byte instructions wherever possible. We can assume the constant isn't loadable with any of ldi, ld24, or seth. */ /* See if we can load a 24 bit unsigned value and invert it. */ if (UINT24_P (~ val)) { emit_insn (gen_movsi (operands[0], GEN_INT (~ val))); emit_insn (gen_one_cmplsi2 (operands[0], operands[0])); DONE; } /* See if we can load a 24 bit unsigned value and shift it into place. 0x01fffffe is just beyond ld24's range. */ for (shift = 1, tmp = 0x01fffffe; shift < 8; ++shift, tmp <<= 1) { if ((val & ~tmp) == 0) { emit_insn (gen_movsi (operands[0], GEN_INT (val >> shift))); emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (shift))); DONE; } } /* Can't use any two byte insn, fall back to seth/or3. Use ~0xffff instead of 0xffff0000, since the later fails on a 64-bit host. */ operands[2] = GEN_INT ((val) & ~0xffff); operands[3] = GEN_INT ((val) & 0xffff);}")(define_split [(set (match_operand:SI 0 "register_operand" "") (match_operand:SI 1 "seth_add3_operand" "i"))] "TARGET_ADDR32" [(set (match_dup 0) (high:SI (match_dup 1))) (set (match_dup 0) (lo_sum:SI (match_dup 0) (match_dup 1)))] "");; Small data area support.;; The address of _SDA_BASE_ is loaded into a register and all objects in;; the small data area are indexed off that. This is done for each reference;; but cse will clean things up for us. We let the compiler choose the;; register to use so we needn't allocate (and maybe even fix) a special;; register to use. Since the load and store insns have a 16 bit offset the;; total size of the data area can be 64K. However, if the data area lives;; above 16M (24 bits), _SDA_BASE_ will have to be loaded with seth/add3 which;; would then yield 3 instructions to reference an object [though there would;; be no net loss if two or more objects were referenced]. The 3 insns can be;; reduced back to 2 if the size of the small data area were reduced to 32K;; [then seth + ld/st would work for any object in the area]. Doing this;; would require special handling of _SDA_BASE_ (its value would be;; (.sdata + 32K) & 0xffff0000) and reloc computations would be different;; [I think]. What to do about this is deferred until later and for now we;; require .sdata to be in the first 16M.(define_expand "movsi_sda" [(set (match_dup 2) (unspec [(const_int 0)] 2)) (set (match_operand:SI 0 "register_operand" "") (lo_sum:SI (match_dup 2) (match_operand:SI 1 "small_data_operand" "")))] "" "{ if (reload_in_progress || reload_completed) operands[2] = operands[0]; else operands[2] = gen_reg_rtx (SImode);}")(define_insn "*load_sda_base" [(set (match_operand:SI 0 "register_operand" "=r") (unspec [(const_int 0)] 2))] "" "ld24 %0,#_SDA_BASE_" [(set_attr "type" "int4") (set_attr "length" "4")]);; 32 bit address support.(define_expand "movsi_addr32" [(set (match_dup 2) ; addr32_operand isn't used because it's too restrictive, ; seth_add3_operand is more general and thus safer. (high:SI (match_operand:SI 1 "seth_add3_operand" ""))) (set (match_operand:SI 0 "register_operand" "") (lo_sum:SI (match_dup 2) (match_dup 1)))] "" "{ if (reload_in_progress || reload_completed) operands[2] = operands[0]; else operands[2] = gen_reg_rtx (SImode);}")(define_insn "set_hi_si" [(set (match_operand:SI 0 "register_operand" "=r") (high:SI (match_operand 1 "symbolic_operand" "")))] "" "seth %0,%#shigh(%1)" [(set_attr "type" "int4") (set_attr "length" "4")])(define_insn "lo_sum_si" [(set (match_operand:SI 0 "register_operand" "=r") (lo_sum:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "immediate_operand" "in")))] "" "add3 %0,%1,%#%B2" [(set_attr "type" "int4") (set_attr "length" "4")])(define_expand "movdi" [(set (match_operand:DI 0 "general_operand" "") (match_operand:DI 1 "general_operand" ""))] "" "{ /* Everything except mem = const or mem = mem can be done easily. */ if (GET_CODE (operands[0]) == MEM) operands[1] = force_reg (DImode, operands[1]);}")(define_insn "*movdi_insn" [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,r,m") (match_operand:DI 1 "move_double_src_operand" "r,nG,F,m,r"))] "register_operand (operands[0], DImode) || register_operand (operands[1], DImode)" "#" [(set_attr "type" "multi,multi,multi,load8,store8") (set_attr "length" "4,4,16,6,6")])(define_split [(set (match_operand:DI 0 "move_dest_operand" "") (match_operand:DI 1 "move_double_src_operand" ""))] "reload_completed" [(match_dup 2)] "operands[2] = gen_split_move_double (operands);");; Floating point move insns.(define_expand "movsf" [(set (match_operand:SF 0 "general_operand" "") (match_operand:SF 1 "general_operand" ""))] "" "{ /* Everything except mem = const or mem = mem can be done easily. */ if (GET_CODE (operands[0]) == MEM) operands[1] = force_reg (SFmode, operands[1]);}")(define_insn "*movsf_insn" [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,r,r,T,S,m") (match_operand:SF 1 "move_src_operand" "r,F,U,S,m,r,r,r"))] "register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode)" "@ mv %0,%1 # ld %0,%1 ld %0,%1 ld %0,%1 st %1,%0 st %1,%0 st %1,%0" ;; ??? Length of alternative 1 is either 2, 4 or 8. [(set_attr "type" "int2,multi,load2,load2,load4,store2,store2,store4") (set_attr "length" "2,8,2,2,4,2,2,4")])(define_split [(set (match_operand:SF 0 "register_operand" "") (match_operand:SF 1 "const_double_operand" ""))] "reload_completed" [(set (match_dup 2) (match_dup 3))] "{ operands[2] = operand_subword (operands[0], 0, 0, SFmode); operands[3] = operand_subword (operands[1], 0, 0, SFmode);}")(define_expand "movdf" [(set (match_operand:DF 0 "general_operand" "") (match_operand:DF 1 "general_operand" ""))] "" "{ /* Everything except mem = const or mem = mem can be done easily. */ if (GET_CODE (operands[0]) == MEM) operands[1] = force_reg (DFmode, operands[1]);}")(define_insn "*movdf_insn" [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m") (match_operand:DF 1 "move_double_src_operand" "r,F,m,r"))] "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)" "#" [(set_attr "type" "multi,multi,load8,store8") (set_attr "length" "4,16,6,6")])(define_split [(set (match_operand:DF 0 "move_dest_operand" "") (match_operand:DF 1 "move_double_src_operand" ""))] "reload_completed" [(match_dup 2)] "operands[2] = gen_split_move_double (operands);");; Zero extension instructions.(define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r,r,r") (zero_extend:HI (match_operand:QI 1 "extend_operand" "r,T,m")))] "" "@ and3 %0,%1,%#255 ldub %0,%1 ldub %0,%1" [(set_attr "type" "int4,load2,load4") (set_attr "length" "4,2,4")])(define_insn "zero_extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (zero_extend:SI (match_operand:QI 1 "extend_operand" "r,T,m")))] "" "@ and3 %0,%1,%#255 ldub %0,%1 ldub %0,%1" [(set_attr "type" "int4,load2,load4") (set_attr "length" "4,2,4")])(define_insn "zero_extendhisi2" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (zero_extend:SI (match_operand:HI 1 "extend_operand" "r,T,m")))] "" "@ and3 %0,%1,%#65535 lduh %0,%1 lduh %0,%1" [(set_attr "type" "int4,load2,load4") (set_attr "length" "4,2,4")]);; Signed conversions from a smaller integer to a larger integer(define_insn "extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r,r,r") (sign_extend:HI (match_operand:QI 1 "extend_operand" "0,T,m")))] "" "@ # ldb %0,%1 ldb %0,%1" [(set_attr "type" "multi,load2,load4") (set_attr "length" "2,2,4")])(define_split [(set (match_operand:HI 0 "register_operand" "") (sign_extend:HI (match_operand:QI 1 "register_operand" "")))] "reload_completed" [(match_dup 2) (match_dup 3)] "{ rtx op0 = gen_lowpart (SImode, operands[0]); rtx shift = gen_rtx (CONST_INT, VOIDmode, 24); operands[2] = gen_ashlsi3 (op0, op0, shift); operands[3] = gen_ashrsi3 (op0, op0, shift);}")(define_insn "extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (sign_extend:SI (match_operand:QI 1 "extend_operand" "0,T,m")))] "" "@ # ldb %0,%1 ldb %0,%1" [(set_attr "type" "multi,load2,load4") (set_attr "length" "4,2,4")])(define_split [(set (match_operand:SI 0 "register_operand" "") (sign_extend:SI (match_operand:QI 1 "register_operand" "")))] "reload_completed" [(match_dup 2) (match_dup 3)] "{ rtx op0 = gen_lowpart (SImode, operands[0]); rtx shift = gen_rtx (CONST_INT, VOIDmode, 24); operands[2] = gen_ashlsi3 (op0, op0, shift); operands[3] = gen_ashrsi3 (op0, op0, shift);}")(define_insn "extendhisi2" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (sign_extend:SI (match_operand:HI 1 "extend_operand" "0,T,m")))] "" "@ # ldh %0,%1 ldh %0,%1" [(set_attr "type" "multi,load2,load4") (set_attr "length" "4,2,4")])(define_split [(set (match_operand:SI 0 "register_operand" "") (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] "reload_completed" [(match_dup 2) (match_dup 3)] "{ rtx op0 = gen_lowpart (SImode, operands[0]); rtx shift = gen_rtx (CONST_INT, VOIDmode, 16); operands[2] = gen_ashlsi3 (op0, op0, shift); operands[3] = gen_ashrsi3 (op0, op0, shift);}");; Arithmetic instructions.; ??? Adding an alternative to split add3 of small constants into two; insns yields better instruction packing but slower code. Adds of small; values is done a lot.(define_insn "addsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (plus:SI (match_operand:SI 1 "register_operand" "%0,0,r") (match_operand:SI 2 "nonmemory_operand" "r,I,J")))] "" "@ add %0,%2 addi %0,%#%2 add3 %0,%1,%#%2" [(set_attr "type" "int2,int2,int4") (set_attr "length" "2,2,4")]);(define_split; [(set (match_operand:SI 0 "register_operand" ""); (plus:SI (match_operand:SI 1 "register_operand" ""); (match_operand:SI 2 "int8_operand" "")))]; "reload_completed; && REGNO (operands[0]) != REGNO (operands[1]); && INT8_P (INTVAL (operands[2])); && INTVAL (operands[2]) != 0"; [(set (match_dup 0) (match_dup 1)); (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]; "")(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"))) (clobber (reg:SI 17))] "" "#" [(set_attr "type" "multi") (set_attr "length" "6")]);; ??? The cmp clears the condition bit. Can we speed up somehow?(define_split [(set (match_operand:DI 0 "register_operand" "") (plus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) (clobber (match_operand 3 "" ""))] "reload_completed" [(parallel [(set (match_dup 3) (const_int 0)) (use (match_dup 4))]) (parallel [(set (match_dup 4) (plus:SI (match_dup 4) (plus:SI (match_dup 5) (match_dup 3)))) (set (match_dup 3) (unspec [(const_int 0)] 3))]) (parallel [(set (match_dup 6) (plus:SI (match_dup 6) (plus:SI (match_dup 7) (match_dup 3)))) (set (match_dup 3) (unspec [(const_int 0)] 3))])] "{ operands[4] = operand_subword (operands[0], (WORDS_BIG_ENDIAN != 0), 0, DImode); operands[5] = operand_subword (operands[2], (WORDS_BIG_ENDIAN != 0), 0, DImode); operands[6] = operand_subword (operands[0], (WORDS_BIG_ENDIAN == 0), 0, DImode); operands[7] = operand_subword (operands[2], (WORDS_BIG_ENDIAN == 0), 0, DImode);}")(define_insn "*clear_c" [(set (reg:SI 17) (const_int 0)) (use (match_operand:SI 0 "register_operand" "r"))] "" "cmp %0,%0" [(set_attr "type" "int2") (set_attr "length" "2")])(define_insn "*add_carry" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_operand:SI 1 "register_operand" "%0") (plus:SI (match_operand:SI 2 "register_operand" "r") (reg:SI 17)))) (set (reg:SI 17) (unspec [(const_int 0)] 3))] "" "addx %0,%2" [(set_attr "type" "int2") (set_attr "length" "2")])(define_insn "subsi3" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "register_operand" "r")))] "" "sub %0,%2" [(set_attr "type" "int2") (set_attr "length" "2")])(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"))) (clobber (reg:SI 17))] "" "#" [(set_attr "type" "multi") (set_attr "length" "6")]);; ??? The cmp clears the condition bit. Can we speed up somehow?(define_split [(set (match_operand:DI 0 "register_operand" "") (minus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) (clobber (match_operand 3 "" ""))] "reload_completed" [(parallel [(set (match_dup 3) (const_int 0)) (use (match_dup 4))]) (parallel [(set (match_dup 4) (minus:SI (match_dup 4) (minus:SI (match_dup 5) (match_dup 3)))) (set (match_dup 3) (unspec [(const_int 0)] 3))]) (parallel [(set (match_dup 6) (minus:SI (match_dup 6) (minus:SI (match_dup 7) (match_dup 3)))) (set (match_dup 3) (unspec [(const_int 0)] 3))])]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -