📄 mt.md
字号:
;; Machine description for MorphoRISC1;; Copyright (C) 2005 Free Software Foundation, Inc.;; Contributed by Red Hat, Inc.;; This file is part of GCC.;; GCC is free software; you can redistribute it and/or modify;; it under the terms of the GNU General Public License as published by;; the Free Software Foundation; either version 2, or (at your option);; any later version.;; GCC is distributed in the hope that it will be useful,;; but WITHOUT ANY WARRANTY; without even the implied warranty of;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the;; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License;; along with GCC; see the file COPYING. If not, write to the Free;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA;; 02110-1301, USA.;; UNSPECs(define_constants [ (UNSPEC_BLOCKAGE 0) (UNSPEC_EI 1) (UNSPEC_DI 2) ]);; Attributes(define_attr "type" "branch,call,load,store,io,arith,complex,unknown" (const_string "unknown") );; If the attribute takes numeric values, no `enum' type will be defined and;; the function to obtain the attribute's value will return `int'.(define_attr "length" "" (const_int 4));; DFA scheduler.(define_automaton "other")(define_cpu_unit "decode_unit" "other")(define_cpu_unit "memory_unit" "other")(define_cpu_unit "branch_unit" "other")(define_insn_reservation "mem_access" 2 (ior (eq_attr "type" "load") (eq_attr "type" "store")) "decode_unit+memory_unit*2")(define_insn_reservation "io_access" 2 (eq_attr "type" "io") "decode_unit+memory_unit*2")(define_insn_reservation "branch_access" 2 (ior (eq_attr "type" "branch") (eq_attr "type" "call")) "decode_unit+branch_unit*2")(define_insn_reservation "arith_access" 1 (eq_attr "type" "arith") "decode_unit")(define_bypass 2 "arith_access" "branch_access")(define_bypass 3 "mem_access" "branch_access")(define_bypass 3 "io_access" "branch_access");; Delay Slots;; The mt does not allow branches in the delay slot.;; The mt does not allow back to back memory or io instruction.;; The compiler does not know what the type of instruction is at;; the destination of the branch. Thus, only type that will be acceptable;; (safe) is the arith type.(define_delay (ior (eq_attr "type" "branch") (eq_attr "type" "call")) [(eq_attr "type" "arith") (nil) (nil)])(define_insn "decrement_and_branch_until_zero" [(set (pc) (if_then_else (ne (match_operand:SI 0 "nonimmediate_operand" "+r,*m") (const_int 0)) (label_ref (match_operand 1 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1))) (clobber (match_scratch:SI 2 "=X,&r")) (clobber (match_scratch:SI 3 "=X,&r"))] "TARGET_MS1_16_003 || TARGET_MS2" "@ dbnz\t%0, %l1%# #" [(set_attr "length" "4,16") (set_attr "type" "branch,unknown")]);; Split the above to handle the case where operand 0 is in memory;; (a register that couldn't get a hard register).(define_split [(set (pc) (if_then_else (ne (match_operand:SI 0 "memory_operand" "") (const_int 0)) (label_ref (match_operand 1 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1))) (clobber (match_scratch:SI 2 "")) (clobber (match_scratch:SI 3 ""))] "TARGET_MS1_16_003 || TARGET_MS2" [(set (match_dup 2) (match_dup 0)) (set (match_dup 3) (plus:SI (match_dup 2) (const_int -1))) (set (match_dup 0) (match_dup 3)) (set (pc) (if_then_else (ne (match_dup 2) (const_int 0)) (label_ref (match_dup 1)) (pc)))] "");; This peephole is defined in the vain hope that it might actually trigger one;; day, although I have yet to find a test case that matches it. The normal;; problem is that GCC likes to move the loading of the constant value -1 out;; of the loop, so it is not here to be matched.(define_peephole2 [(set (match_operand:SI 0 "register_operand" "") (plus:SI (match_dup 0) (const_int -1))) (set (match_operand:SI 1 "register_operand" "") (const_int -1)) (set (pc) (if_then_else (ne (match_dup 0) (match_dup 1)) (label_ref (match_operand 2 "" "")) (pc)))] "TARGET_MS1_16_003 || TARGET_MS2" [(parallel [(set (pc) (if_then_else (ne (match_dup 0) (const_int 0)) (label_ref (match_dup 2)) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1))) (clobber (reg:SI 0)) (clobber (reg:SI 0))])] "");; Moves(define_expand "loadqi" [ ;; compute shift (set (match_operand:SI 2 "register_operand" "") (and:SI (match_dup 1) (const_int 3))) (set (match_dup 2) (xor:SI (match_dup 2) (const_int 3))) (set (match_dup 2 ) (ashift:SI (match_dup 2) (const_int 3))) ;; get word that contains byte (set (match_operand:SI 0 "register_operand" "") (mem:SI (and:SI (match_operand:SI 1 "register_operand" "") (const_int -3)))) ;; align byte (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2))) ] "" "");; storeqi;; operand 0 byte value to store;; operand 1 address;; operand 2 temp, word containing byte;; operand 3 temp, shift count;; operand 4 temp, mask, aligned and masked byte;; operand 5 (unused)(define_expand "storeqi" [ ;; compute shift (set (match_operand:SI 3 "register_operand" "") (and:SI (match_operand:SI 1 "register_operand" "") (const_int 3))) (set (match_dup 3) (xor:SI (match_dup 3) (const_int 3))) (set (match_dup 3) (ashift:SI (match_dup 3) (const_int 3))) ;; get word that contains byte (set (match_operand:SI 2 "register_operand" "") (mem:SI (and:SI (match_dup 1) (const_int -3)))) ;; generate mask (set (match_operand:SI 4 "register_operand" "") (const_int 255)) (set (match_dup 4) (ashift:SI (match_dup 4) (match_dup 3))) (set (match_dup 4) (not:SI (match_dup 4))) ;; clear appropriate bits (set (match_dup 2) (and:SI (match_dup 2) (match_dup 4))) ;; align byte (set (match_dup 4) (and:SI (match_operand:SI 0 "register_operand" "") (const_int 255))) (set (match_dup 4) (ashift:SI (match_dup 4) (match_dup 3))) ;; combine (set (match_dup 2) (ior:SI (match_dup 4) (match_dup 2))) ;; store updated word (set (mem:SI (and:SI (match_dup 1) (const_int -3))) (match_dup 2)) ] "" "")(define_expand "movqi" [(set (match_operand:QI 0 "general_operand" "") (match_operand:QI 1 "general_operand" ""))] "" "{ if (!reload_in_progress && !reload_completed && GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) operands[1] = copy_to_mode_reg (QImode, operands[1]); if ( (! TARGET_BYTE_ACCESS) && GET_CODE (operands[0]) == MEM) { rtx scratch1 = gen_reg_rtx (SImode); rtx scratch2 = gen_reg_rtx (SImode); rtx scratch3 = gen_reg_rtx (SImode); rtx data = operands[1]; rtx address = XEXP (operands[0], 0); rtx seq; if ( GET_CODE (data) != REG ) data = copy_to_mode_reg (QImode, data); if ( GET_CODE (address) != REG ) address = copy_to_mode_reg (SImode, address); start_sequence (); emit_insn (gen_storeqi (gen_lowpart (SImode, data), address, scratch1, scratch2, scratch3)); mt_set_memflags (operands[0]); seq = get_insns (); end_sequence (); emit_insn (seq); DONE; } if ( (! TARGET_BYTE_ACCESS) && GET_CODE (operands[1]) == MEM) { rtx scratch1 = gen_reg_rtx (SImode); rtx data = operands[0]; rtx address = XEXP (operands[1], 0); rtx seq; if ( GET_CODE (address) != REG ) address = copy_to_mode_reg (SImode, address); start_sequence (); emit_insn (gen_loadqi (gen_lowpart (SImode, data), address, scratch1)); mt_set_memflags (operands[1]); seq = get_insns (); end_sequence (); emit_insn (seq); DONE; } /* If the load is a pseudo register in a stack slot, some simplification can be made because the loads are aligned */ if ( (! TARGET_BYTE_ACCESS) && (reload_in_progress && GET_CODE (operands[1]) == SUBREG && GET_CODE (SUBREG_REG (operands[1])) == REG && REGNO (SUBREG_REG (operands[1])) >= FIRST_PSEUDO_REGISTER)) { rtx data = operands[0]; rtx address = XEXP (operands[1], 0); rtx seq; start_sequence (); emit_insn (gen_movsi (gen_lowpart (SImode, data), address)); mt_set_memflags (operands[1]); seq = get_insns (); end_sequence (); emit_insn (seq); DONE; }}")(define_insn "*movqi_internal" [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,r") (match_operand:QI 1 "general_operand" "r,m,r,I"))] "TARGET_BYTE_ACCESS && (!memory_operand (operands[0], QImode) || !memory_operand (operands[1], QImode))" "@ or %0, %1, %1 ldb %0, %1 stb %1, %0 addi %0, r0, %1" [(set_attr "length" "4,4,4,4") (set_attr "type" "arith,load,store,arith")])(define_insn "*movqi_internal_nobyte" [(set (match_operand:QI 0 "register_operand" "=r,r") (match_operand:QI 1 "arith_operand" "r,I"))] "!TARGET_BYTE_ACCESS && (!memory_operand (operands[0], QImode) || !memory_operand (operands[1], QImode))" "@ or %0, %1, %1 addi %0, r0, %1" [(set_attr "length" "4,4") (set_attr "type" "arith,arith")]);; The MorphoRISC does not have 16-bit loads and stores.;; These operations must be synthesized. Note that the code;; for loadhi and storehi assumes that the least significant bits;; is ignored.;; loadhi;; operand 0 location of result;; operand 1 memory address;; operand 2 temp(define_expand "loadhi" [ ;; compute shift (set (match_operand:SI 2 "register_operand" "") (and:SI (match_dup 1) (const_int 2))) (set (match_dup 2) (xor:SI (match_dup 2) (const_int 2))) (set (match_dup 2 ) (ashift:SI (match_dup 2) (const_int 3))) ;; get word that contains the 16-bits (set (match_operand:SI 0 "register_operand" "") (mem:SI (and:SI (match_operand:SI 1 "register_operand" "") (const_int -3)))) ;; align 16-bit value (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2))) ] "" "");; storehi;; operand 0 byte value to store;; operand 1 address;; operand 2 temp, word containing byte;; operand 3 temp, shift count;; operand 4 temp, mask, aligned and masked byte;; operand 5 (unused)(define_expand "storehi" [ ;; compute shift (set (match_operand:SI 3 "register_operand" "") (and:SI (match_operand:SI 1 "register_operand" "") (const_int 2))) (set (match_dup 3) (xor:SI (match_dup 3) (const_int 2))) (set (match_dup 3) (ashift:SI (match_dup 3) (const_int 3))) ;; get word that contains the 16-bits (set (match_operand:SI 2 "register_operand" "") (mem:SI (and:SI (match_dup 1) (const_int -3)))) ;; generate mask (set (match_operand:SI 4 "register_operand" "") (const_int 65535)) (set (match_dup 4) (ashift:SI (match_dup 4) (match_dup 3))) (set (match_dup 4) (not:SI (match_dup 4))) ;; clear appropriate bits (set (match_dup 2) (and:SI (match_dup 2) (match_dup 4))) ;; align 16-bit value (set (match_dup 4) (and:SI (match_operand:SI 0 "register_operand" "") (const_int 65535))) (set (match_dup 4) (ashift:SI (match_dup 4) (match_dup 3))) ;; combine (set (match_dup 2) (ior:SI (match_dup 4) (match_dup 2))) ;; store updated word (set (mem:SI (and:SI (match_dup 1) (const_int -3))) (match_dup 2)) ] "" "")(define_expand "movhi" [(set (match_operand:HI 0 "general_operand" "") (match_operand:HI 1 "general_operand" ""))] "" "{ if (!reload_in_progress && !reload_completed && GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) operands[1] = copy_to_mode_reg (HImode, operands[1]); if ( GET_CODE (operands[0]) == MEM) { rtx scratch1 = gen_reg_rtx (SImode); rtx scratch2 = gen_reg_rtx (SImode); rtx scratch3 = gen_reg_rtx (SImode); rtx data = operands[1]; rtx address = XEXP (operands[0], 0); rtx seq; if (GET_CODE (data) != REG) data = copy_to_mode_reg (HImode, data); if (GET_CODE (address) != REG) address = copy_to_mode_reg (SImode, address); start_sequence (); emit_insn (gen_storehi (gen_lowpart (SImode, data), address, scratch1, scratch2, scratch3)); mt_set_memflags (operands[0]); seq = get_insns (); end_sequence (); emit_insn (seq); DONE; } if ( GET_CODE (operands[1]) == MEM) { rtx scratch1 = gen_reg_rtx (SImode); rtx data = operands[0]; rtx address = XEXP (operands[1], 0); rtx seq; if (GET_CODE (address) != REG) address = copy_to_mode_reg (SImode, address); start_sequence (); emit_insn (gen_loadhi (gen_lowpart (SImode, data), address, scratch1)); mt_set_memflags (operands[1]); seq = get_insns (); end_sequence (); emit_insn (seq); DONE; } /* If the load is a pseudo register in a stack slot, some simplification can be made because the loads are aligned */ if ( (reload_in_progress && GET_CODE (operands[1]) == SUBREG && GET_CODE (SUBREG_REG (operands[1])) == REG && REGNO (SUBREG_REG (operands[1])) >= FIRST_PSEUDO_REGISTER)) { rtx data = operands[0]; rtx address = XEXP (operands[1], 0); rtx seq; start_sequence (); emit_insn (gen_movsi (gen_lowpart (SImode, data), address)); mt_set_memflags (operands[1]); seq = get_insns (); end_sequence (); emit_insn (seq); DONE; }}")(define_insn "*movhi_internal" [(set (match_operand:HI 0 "register_operand" "=r,r") (match_operand:HI 1 "arith_operand" "r,I"))] "!memory_operand (operands[0], HImode) || !memory_operand (operands[1], HImode)" "@ or %0, %1, %1 addi %0, r0, %1" [(set_attr "length" "4,4") (set_attr "type" "arith,arith")])(define_expand "movsi" [(set (match_operand:SI 0 "nonimmediate_operand" "") (match_operand:SI 1 "general_operand" ""))] "" "{ if (!reload_in_progress && !reload_completed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -