📄 ip2k.md
字号:
;; -*- Mode: Scheme -*-;; GCC machine description for Ubicom IP2022 Communications Controller.;; Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.;; Contributed by Red Hat, Inc and Ubicom, Inc.;;;; This file is part of GNU CC.;;;; GNU CC 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.;;;; GNU CC 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 GNU CC; see the file COPYING. If not, write to;; the Free Software Foundation, 59 Temple Place - Suite 330,;; Boston, MA 02111-1307, USA. */;; Default all instruction lengths to two bytes (one 16-bit instruction).;;(define_attr "length" "" (const_int 2));; Define if we can "skip" an insn or not(define_attr "skip" "no,yes" (const_string "no"));; Define an insn clobbers WREG or not(define_attr "clobberw" "no,yes" (const_string "yes"));; Performance Issues:;;;; With the IP2k only having one really useful pointer register we have to;; make most of our instruction patterns only match one offsettable address;; before addressing becomes strict whereas afterwards of course we can use;; any register details that have become fixed. As we've already committed;; any reloads at this point of course we're a little late so we have to use;; a number of peephole2 optimizations to remerge viable patterns. We can;; do a bit more tidying up in the machine-dependent reorg pass to try and;; make things better still. None of this is ideal, but it's *much* better;; than nothing.;; Constraints:;;;; I - -255..-1 - all other literal values have to be loaded;; J - 0..7 - valid bit number in a register;; K - 0..127 - valid offset for addressing mode;; L - 1..127 - positive count suitable for shift.;; M - -1 as a literal value;; N - +1 as a literal value;; O - zero;; P - 0..255;;;; a - DP or IP registers (general address);; f - IP register;; j - IPL register;; k - IPH register;; b - DP register;; y - DPH register;; z - DPL register;; q - SP register;; c - DP or SP registers (offsettable address);; d - non-pointer registers (not SP, DP, IP);; u - non-SP registers (everything except SP);;;; R - Indirect thru IP - Avoid this except for QI mode, since we;; can't access extra bytes.;; S - Short (stack/dp address). Pointer with 0..127 displacement;; Note that 0(SP) has undefined contents due to post-decrement push;; T - data-section immediate value. A CONST_INT or SYMBOL_REF into .data;; Special assembly-language format effectors:;;;; ABCD -;; Reference up to 4 big-endian registers - %A0 is Rn+0, while %D0 is Rn+3;; STUVWXYZ -;; Reference up to 8 big-endian registers - %S0 is Rn+0, while %Z0 is Rn+7;;;; H - High part of 16 bit address or literal %hi8data(v) or %hi8insn(v);; L - Low part of 16 bit address or literal %lo8data(v) or %lo8insn(v);; b - print a literal value with no punctuation (typically bit selector);; e - print 1 << v ('exponent');; n - print negative number;; x - print 16 bit hex number;; < - interior stack push; adjust any stack-relative operands accordingly;; > - interior stack pop; clear adjustment.;;;; Basic operations to move data in and out of fr's. Also extended to;; cover the loading of w with immediates;;(define_insn "*movqi_w_gen" [(set (reg:QI 10) (match_operand:QI 0 "general_operand" "rSi"))] "(ip2k_reorg_split_qimode)" "mov\\tw,%0" [(set_attr "skip" "yes")])(define_insn "*movqi_fr_w" [(set (match_operand:QI 0 "nonimmediate_operand" "=rS") (reg:QI 10))] "(ip2k_reorg_split_qimode)" "mov\\t%0,w" [(set_attr "skip" "yes") (set_attr "clobberw" "no")]);; Handle the cases where we get back to back redundant mov patterns issued. ;; This of course sounds somewhat absurd but is actually reasonably common;; because we aren't able to match certain patterns before registers are;; chosen. This is particularly true of memory to memory operations where;; we can't provide patterns that will guarantee to match every time because;; this would require reloads in the middle of instructions. If we;; discover a case that doesn't need a reload of course then this combiner;; operation will tidy up for us.;;;; Warning! Whilst it would be nice to match operand 0 as a general operand;; we mustn't do so because this doesn't work with the REG_DEAD check.;;(define_peephole2 [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") (match_operand 1 "ip2k_gen_operand" "")) (set (match_operand 2 "ip2k_split_dest_operand" "") (match_dup 0))] "(peep2_reg_dead_p (2, operands[0]) && ! (REG_P (operands[2]) && REGNO (operands[2]) == REG_SP) && (REG_P (operands[2]) || ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), GET_MODE_SIZE (GET_MODE (operands[0])))))" [(set (match_dup 2) (match_dup 1))] "")(define_peephole2 [(set (match_operand 0 "ip2k_nonsp_reg_operand" "") (match_operand 1 "immediate_operand" "")) (set (match_operand 2 "ip2k_gen_operand" "") (match_dup 0))] "(peep2_reg_dead_p (2, operands[0]) && ! (REG_P (operands[2]) && REGNO (operands[2]) == REG_SP) && ip2k_xexp_not_uses_reg_p (operands[2], REGNO (operands[0]), GET_MODE_SIZE (GET_MODE (operands[0]))))" [(set (match_dup 2) (match_dup 1))] "");;;; Move 8-bit integers.;;(define_expand "movqi" [(set (match_operand:QI 0 "" "") (match_operand:QI 1 "" ""))] "" "")(define_insn "*pushqi" [(set (match_operand:QI 0 "push_operand" "=<") (match_operand:QI 1 "general_operand" "g"))] "" "push\\t%1" [(set_attr "skip" "yes") (set_attr "clobberw" "no")]);; IP isn't offsettable but we can fake this behavior here and win if we would;; otherwise use DP and require a reload from IP. This instruction is only;; matched by peephole2 operations.;;(define_insn "*movqi_to_ip_plus_offs" [(set (mem:QI (plus:HI (reg:HI 4) (match_operand 0 "const_int_operand" "P,P"))) (match_operand:QI 1 "general_operand" "O,g"))] "reload_completed && (INTVAL (operands[0]) < 0x100)" "*{ if (INTVAL (operands[0]) == 1) OUT_AS1 (inc, ipl); else { OUT_AS2 (mov, w, %0); OUT_AS2 (add, ipl, w); } switch (which_alternative) { case 0: OUT_AS1 (clr, (IP)); break; case 1: OUT_AS1 (push, %1%<); OUT_AS1 (pop, (IP)%>); break; } if (!find_regno_note (insn, REG_DEAD, REG_IP)) { if (INTVAL (operands[0]) == 1) OUT_AS1 (dec, ipl); else OUT_AS2 (sub, ipl, w); } return \"\"; }");; IP isn't offsettable but we can fake this behavior here and win if we would;; otherwise use DP and require a reload from IP. This instruction is only;; matched by peephole2 operations.;;(define_insn "*movqi_from_ip_plus_offs" [(set (match_operand:QI 0 "nonimmediate_operand" "=g") (mem:QI (plus:HI (reg:HI 4) (match_operand 1 "const_int_operand" "P"))))] "reload_completed && (INTVAL (operands[1]) < 0x100)" "*{ if (INTVAL (operands[1]) == 1) OUT_AS1 (inc, ipl); else { OUT_AS2 (mov, w, %1); OUT_AS2 (add, ipl, w); } OUT_AS1 (push, (IP)%<); OUT_AS1 (pop, %0%>); if (!find_regno_note (insn, REG_DEAD, REG_IP) && ip2k_xexp_not_uses_reg_p (operands[0], REG_IP, 2)) { if (INTVAL (operands[1]) == 1) OUT_AS1 (dec, ipl); else OUT_AS2 (sub, ipl, w); } return \"\"; }")(define_insn_and_split "*movqi" [(set (match_operand:QI 0 "nonimmediate_operand" "=roR,roR,r, rS,roR") (match_operand:QI 1 "general_operand" " O, ri,o,rioR,rSi"))] "" "@ clr\\t%0 # # # #" "(ip2k_reorg_split_qimode && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0))" [(set (reg:QI 10) (match_dup 1)) (set (match_dup 0) (reg:QI 10))] "" [(set_attr "skip" "yes,no,no,no,no") (set_attr "clobberw" "no,yes,yes,yes,yes")])(define_peephole2 [(set (reg:HI 12) (reg:HI 4)) (set (match_operand:QI 0 "nonimmediate_operand" "") (mem:QI (plus:HI (reg:HI 12) (match_operand 1 "const_int_operand" ""))))] "((ip2k_reorg_in_progress || ip2k_reorg_completed) && peep2_regno_dead_p (2, REG_DP) && ip2k_xexp_not_uses_reg_p (operands[0], REG_DP, 2) && (INTVAL (operands[1]) < 0x100))" [(set (match_dup 0) (mem:QI (plus:HI (reg:HI 4) (match_dup 1))))] "")(define_peephole2 [(set (reg:HI 12) (reg:HI 4)) (set (mem:QI (plus:HI (reg:HI 12) (match_operand 0 "const_int_operand" ""))) (match_operand:QI 1 "general_operand" ""))] "((ip2k_reorg_in_progress || ip2k_reorg_completed) && peep2_regno_dead_p (2, REG_DP) && ip2k_xexp_not_uses_reg_p (operands[0], REG_DP, 2) && (INTVAL (operands[0]) < 0x100))" [(set (mem:QI (plus:HI (reg:HI 4) (match_dup 0))) (match_dup 1))] "")(define_peephole2 [(set (match_operand:QI 0 "register_operand" "") (mem:QI (plus:HI (reg:HI 4) (match_operand 1 "const_int_operand" "")))) (set (match_operand:QI 2 "nonimmediate_operand" "") (match_dup 0))] "((ip2k_reorg_in_progress || ip2k_reorg_completed) && peep2_reg_dead_p (2, operands[0]))" [(set (match_dup 2) (mem:QI (plus:HI (reg:HI 4) (match_dup 1))))] "");; We sometimes want to copy a value twice, usually when we copy a value into;; both a structure slot and into a temporary register. We can win here;; because gcc doesn't know about ways of reusing w while we're copying.;;(define_insn_and_split "*movqi_twice" [(set (match_operand:QI 0 "nonimmediate_operand" "=g") (match_operand:QI 1 "general_operand" "g")) (set (match_operand:QI 2 "nonimmediate_operand" "=g") (match_dup 1))] "ip2k_reorg_merge_qimode" "mov\\tw,%1\;mov\\t%0,w\;mov\\t%2,w" "(ip2k_reorg_split_qimode)" [(set (reg:QI 10) (match_dup 1)) (set (match_dup 0) (reg:QI 10)) (set (match_dup 2) (reg:QI 10))] "");; Don't try to match until we've removed redundant reloads. Often this;; simplification will remove the need to do two moves!;;(define_peephole2 [(set (match_operand:QI 0 "nonimmediate_operand" "") (match_operand:QI 1 "general_operand" "")) (set (match_operand:QI 2 "nonimmediate_operand" "") (match_dup 0))] "(ip2k_reorg_merge_qimode && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0))" [(parallel [(set (match_dup 0) (match_dup 1)) (set (match_dup 2) (match_dup 1))])] "");; Don't try to match until we've removed redundant reloads. Often this;; simplification will remove the need to do two moves!;;(define_peephole2 [(set (match_operand:QI 0 "nonimmediate_operand" "") (match_operand:QI 1 "general_operand" "")) (set (match_operand:QI 2 "nonimmediate_operand" "") (match_dup 1))] "(ip2k_reorg_merge_qimode && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0))" [(parallel [(set (match_dup 0) (match_dup 1)) (set (match_dup 2) (match_dup 1))])] "");;;; Move 16-bit integers.;;(define_expand "movhi" [(set (match_operand:HI 0 "" "") (match_operand:HI 1 "" ""))] "" "")(define_insn "*pushhi_ip" [(set (match_operand:HI 0 "push_operand" "=<") (mem:HI (reg:HI 4)))] "reload_completed" "inc\\tipl\;push\\t(IP)\;dec\\tipl\;push\\t(IP)" [(set_attr "clobberw" "no")])(define_insn "*movhi_to_ip" [(set (mem:HI (reg:HI 4)) (match_operand:HI 0 "general_operand" "O,roi"))] "reload_completed" "*{ switch (which_alternative) { case 0: OUT_AS1 (clr, (IP)); OUT_AS1 (inc, ipl); OUT_AS1 (clr, (IP)); if (!find_regno_note (insn, REG_DEAD, REG_IP)) OUT_AS1 (dec, ipl); return \"\"; case 1: OUT_AS2 (mov, w, %H0); OUT_AS2 (mov, (IP), w); OUT_AS2 (mov, w, %L0); OUT_AS1 (inc, ipl); OUT_AS2 (mov, (IP), w); if (!find_regno_note (insn, REG_DEAD, REG_IP)) OUT_AS1 (dec, ipl); return \"\"; default: abort (); } }")(define_insn "*movhi_from_ip" [(set (match_operand:HI 0 "nonimmediate_operand" "=f,bqdo") (mem:HI (reg:HI 4)))] "reload_completed" "*{ switch (which_alternative) { case 0: OUT_AS1 (push, (IP)); OUT_AS1 (inc, ipl); OUT_AS2 (mov, w, (IP));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -