📄 bfin.md
字号:
;;- Machine description for Blackfin for GNU compiler;; Copyright 2005 Free Software Foundation, Inc.;; Contributed by Analog Devices.;; 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, 59 Temple Place - Suite 330,;; Boston, MA 02111-1307, USA.; operand punctuation marks:;; X -- integer value printed as log2; Y -- integer value printed as log2(~value) - for bitclear; h -- print half word register, low part; d -- print half word register, high part; D -- print operand as dregs pairs; w -- print operand as accumulator register word (a0w, a1w); H -- high part of double mode operand; T -- byte register representation Oct. 02 2001; constant operand classes;; J 2**N 5bit imm scaled; Ks7 -64 .. 63 signed 7bit imm; Ku5 0..31 unsigned 5bit imm; Ks4 -8 .. 7 signed 4bit imm; Ks3 -4 .. 3 signed 3bit imm; Ku3 0 .. 7 unsigned 3bit imm; Pn 0, 1, 2 constants 0, 1 or 2, corresponding to n;; register operands; d (r0..r7); a (p0..p5,fp,sp); e (a0, a1); b (i0..i3); f (m0..m3); B; c (i0..i3,m0..m3) CIRCREGS; C (CC) CCREGS;;; Define constants for hard registers.(define_constants [(REG_R0 0) (REG_R1 1) (REG_R2 2) (REG_R3 3) (REG_R4 4) (REG_R5 5) (REG_R6 6) (REG_R7 7) (REG_P0 8) (REG_P1 9) (REG_P2 10) (REG_P3 11) (REG_P4 12) (REG_P5 13) (REG_P6 14) (REG_P7 15) (REG_SP 14) (REG_FP 15) (REG_I0 16) (REG_B0 17) (REG_L0 18) (REG_I1 19) (REG_B1 20) (REG_L1 21) (REG_I2 22) (REG_B2 23) (REG_L2 24) (REG_I3 25) (REG_B3 26) (REG_L3 27) (REG_M0 28) (REG_M1 29) (REG_M2 30) (REG_M3 31) (REG_A0 32) (REG_A1 33) (REG_CC 34) (REG_RETS 35) (REG_RETI 36) (REG_RETX 37) (REG_RETN 38) (REG_RETE 39) (REG_ASTAT 40) (REG_SEQSTAT 41) (REG_USP 42) (REG_ARGP 43)]);; Constants used in UNSPECs and UNSPEC_VOLATILEs.(define_constants [(UNSPEC_CBRANCH_TAKEN 0) (UNSPEC_CBRANCH_NOPS 1) (UNSPEC_RETURN 2) (UNSPEC_MOVE_PIC 3) (UNSPEC_LIBRARY_OFFSET 4) (UNSPEC_PUSH_MULTIPLE 5)])(define_constants [(UNSPEC_VOLATILE_EH_RETURN 0)])(define_attr "type" "move,mvi,mcld,mcst,dsp32,mult,alu0,shft,brcc,br,call,misc,compare,dummy" (const_string "misc"));; Scheduling definitions(define_automaton "bfin")(define_cpu_unit "core" "bfin")(define_insn_reservation "alu" 1 (eq_attr "type" "move,mvi,mcst,dsp32,alu0,shft,brcc,br,call,misc,compare") "core")(define_insn_reservation "imul" 3 (eq_attr "type" "mult") "core*3")(define_insn_reservation "load" 1 (eq_attr "type" "mcld") "core");; Make sure genautomata knows about the maximum latency that can be produced;; by the adjust_cost function.(define_insn_reservation "dummy" 5 (eq_attr "type" "mcld") "core");; Operand and operator predicates(include "predicates.md");;; FRIO branches have been optimized for code density;;; this comes at a slight cost of complexity when;;; a compiler needs to generate branches in the general;;; case. In order to generate the correct branching;;; mechanisms the compiler needs keep track of instruction;;; lengths. The follow table describes how to count instructions;;; for the FRIO architecture.;;;;;; unconditional br are 12-bit imm pcrelative branches *2;;; conditional br are 10-bit imm pcrelative branches *2;;; brcc 10-bit:;;; 1024 10-bit imm *2 is 2048 (-1024..1022);;; br 12-bit :;;; 4096 12-bit imm *2 is 8192 (-4096..4094);;; NOTE : For brcc we generate instructions such as;;; if cc jmp; jump.[sl] offset;;; offset of jump.[sl] is from the jump instruction but;;; gcc calculates length from the if cc jmp instruction;;; furthermore gcc takes the end address of the branch instruction;;; as (pc) for a forward branch;;; hence our range is (-4094, 4092) instead of (-4096, 4094) for a br;;;;;; The way the (pc) rtx works in these calculations is somewhat odd;;;; for backward branches it's the address of the current instruction,;;; for forward branches it's the previously known address of the following;;; instruction - we have to take this into account by reducing the range;;; for a forward branch.;; Lengths for type "mvi" insns are always defined by the instructions;; themselves.(define_attr "length" "" (cond [(eq_attr "type" "mcld") (if_then_else (match_operand 1 "effective_address_32bit_p" "") (const_int 4) (const_int 2)) (eq_attr "type" "mcst") (if_then_else (match_operand 0 "effective_address_32bit_p" "") (const_int 4) (const_int 2)) (eq_attr "type" "move") (const_int 2) (eq_attr "type" "dsp32") (const_int 4) (eq_attr "type" "call") (const_int 4) (eq_attr "type" "br") (if_then_else (and (le (minus (match_dup 0) (pc)) (const_int 4092)) (ge (minus (match_dup 0) (pc)) (const_int -4096))) (const_int 2) (const_int 4)) (eq_attr "type" "brcc") (cond [(and (le (minus (match_dup 3) (pc)) (const_int 1020)) (ge (minus (match_dup 3) (pc)) (const_int -1024))) (const_int 2) (and (le (minus (match_dup 3) (pc)) (const_int 4092)) (ge (minus (match_dup 3) (pc)) (const_int -4094))) (const_int 4)] (const_int 6)) ] (const_int 2)));; Conditional moves(define_expand "movsicc" [(set (match_operand:SI 0 "validreg_operand" "") (if_then_else:SI (match_operand 1 "comparison_operator" "") (match_operand:SI 2 "validreg_operand" "") (match_operand:SI 3 "validreg_operand" "")))] ""{ operands[1] = bfin_gen_compare (operands[1], SImode);})(define_insn "*movsicc_insn1" [(set (match_operand:SI 0 "validreg_operand" "=da,da,da") (if_then_else:SI (eq:BI (match_operand:BI 3 "cc_operand" "C,C,C") (const_int 0)) (match_operand:SI 1 "validreg_operand" "da,0,da") (match_operand:SI 2 "validreg_operand" "0,da,da")))] "" "@ if !cc %0 =%1; /* movsicc-1a */ if cc %0 =%2; /* movsicc-1b */ if !cc %0 =%1; if cc %0=%2; /* movsicc-1 */" [(set_attr "length" "2,2,4") (set_attr "type" "move")])(define_insn "*movsicc_insn2" [(set (match_operand:SI 0 "validreg_operand" "=da,da,da") (if_then_else:SI (ne:BI (match_operand:BI 3 "cc_operand" "C,C,C") (const_int 0)) (match_operand:SI 1 "validreg_operand" "0,da,da") (match_operand:SI 2 "validreg_operand" "da,0,da")))] "" "@ if !cc %0 =%2; /* movsicc-2b */ if cc %0 =%1; /* movsicc-2a */ if cc %0 =%1; if !cc %0=%2; /* movsicc-1 */" [(set_attr "length" "2,2,4") (set_attr "type" "move")]);; Insns to load HIGH and LO_SUM(define_insn "movsi_high" [(set (match_operand:SI 0 "validreg_operand" "=x") (high:SI (match_operand:SI 1 "immediate_operand" "i")))] "reload_completed" "%d0 = %d1;" [(set_attr "type" "mvi") (set_attr "length" "4")])(define_insn "movstricthi_high" [(set (match_operand:SI 0 "validreg_operand" "+x") (ior:SI (and:SI (match_dup 0) (const_int 65535)) (match_operand:SI 1 "immediate_operand" "i")))] "reload_completed" "%d0 = %d1;" [(set_attr "type" "mvi") (set_attr "length" "4")])(define_insn "movsi_low" [(set (match_operand:SI 0 "validreg_operand" "=x") (lo_sum:SI (match_operand:SI 1 "validreg_operand" "0") (match_operand:SI 2 "immediate_operand" "i")))] "reload_completed" "%h0 = %h2;" [(set_attr "type" "mvi") (set_attr "length" "4")])(define_insn "movsi_high_pic" [(set (match_operand:SI 0 "validreg_operand" "=x") (high:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_MOVE_PIC)))] "" "%d0 = %1@GOT_LOW;" [(set_attr "type" "mvi") (set_attr "length" "4")])(define_insn "movsi_low_pic" [(set (match_operand:SI 0 "validreg_operand" "=x") (lo_sum:SI (match_operand:SI 1 "validreg_operand" "0") (unspec:SI [(match_operand:SI 2 "" "")] UNSPEC_MOVE_PIC)))] "" "%h0 = %h2@GOT_HIGH;" [(set_attr "type" "mvi") (set_attr "length" "4")]);;; Move instructions(define_insn_and_split "movdi_insn" [(set (match_operand:DI 0 "nonimmediate_operand" "=x,mx,r") (match_operand:DI 1 "general_operand" "iFx,r,mx"))] "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" "#" "reload_completed" [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))]{ rtx lo_half[2], hi_half[2]; split_di (operands, 2, lo_half, hi_half); if (reg_overlap_mentioned_p (lo_half[0], hi_half[1])) { operands[2] = hi_half[0]; operands[3] = hi_half[1]; operands[4] = lo_half[0]; operands[5] = lo_half[1]; } else { operands[2] = lo_half[0]; operands[3] = lo_half[1]; operands[4] = hi_half[0]; operands[5] = hi_half[1]; }})(define_insn "movbi" [(set (match_operand:BI 0 "nonimmediate_operand" "=x,x,d,mr,C,d") (match_operand:BI 1 "general_operand" "x,xKs3,mr,d,d,C"))] "" "@ %0 = %1; %0 = %1 (X); %0 = %1; %0 = %1; CC = %1; %0 = CC;" [(set_attr "type" "move,mvi,mcld,mcst,compare,compare") (set_attr "length" "2,2,*,*,2,2")])(define_insn "movpdi" [(set (match_operand:PDI 0 "nonimmediate_operand" "=e,<,e") (match_operand:PDI 1 "general_operand" " e,e,>"))] "" "@ %0 = %1; %0 = %x1; %0 = %w1; %w0 = %1; %x0 = %1;" [(set_attr "type" "move,mcst,mcld")])(define_insn "*pushsi_insn" [(set (mem:SI (pre_dec:SI (reg:SI REG_SP))) (match_operand:SI 0 "validreg_operand" "xy"))] "" "[--SP] = %0;" [(set_attr "type" "mcst") (set_attr "length" "2")])(define_insn "*popsi_insn" [(set (match_operand:SI 0 "validreg_operand" "=xy") (mem:SI (post_inc:SI (reg:SI REG_SP))))] "" "%0 = [SP++];" [(set_attr "type" "mcld") (set_attr "length" "2")]);; The first alternative is used to make reload choose a limited register;; class when faced with a movsi_insn that had its input operand replaced;; with a PLUS. We generally require fewer secondary reloads this way.(define_insn "*movsi_insn" [(set (match_operand:SI 0 "nonimmediate_operand" "=da,x*y,da,x,x,x,da,mr") (match_operand:SI 1 "general_operand" "da,x*y,xKs7,xKsh,xKuh,ix,mr,da"))] "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" "@ %0 = %1; %0 = %1; %0 = %1 (X); %0 = %1 (X); %0 = %1 (Z); # %0 = %1; %0 = %1;" [(set_attr "type" "move,move,mvi,mvi,mvi,*,mcld,mcst") (set_attr "length" "2,2,2,4,4,*,*,*")])(define_insn "*movv2hi_insn" [(set (match_operand:V2HI 0 "nonimmediate_operand" "=da,d,m") (match_operand:V2HI 1 "general_operand" "d,m,d"))] "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" "%0 = %1;" [(set_attr "type" "move,mcld,mcst") (set_attr "length" "2,*,*")])(define_insn "*movhi_insn" [(set (match_operand:HI 0 "nonimmediate_operand" "=x,da,x,d,mr") (match_operand:HI 1 "general_operand" "x,xKs7,xKsh,mr,d"))] "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" "@ %0 = %1; %0 = %1 (X); %0 = %1 (X); %0 = W %1 (X); W %0 = %1;" [(set_attr "type" "move,mvi,mvi,mcld,mcst") (set_attr "length" "2,2,4,*,*")])(define_insn "*movqi_insn" [(set (match_operand:QI 0 "nonimmediate_operand" "=x,da,x,d,mr") (match_operand:QI 1 "general_operand" "x,xKs7,xKsh,mr,d"))] "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" "@ %0 = %1; %0 = %1 (X); %0 = %1 (X); %0 = B %1 (X); B %0 = %1;" [(set_attr "type" "move,mvi,mvi,mcld,mcst") (set_attr "length" "2,2,4,*,*")])(define_insn "*movsf_insn" [(set (match_operand:SF 0 "nonimmediate_operand" "=x,x,da,mr") (match_operand:SF 1 "general_operand" "x,Fx,mr,da"))] "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" "@ %0 = %1; # %0 = %1; %0 = %1;" [(set_attr "type" "move,*,mcld,mcst")])(define_insn_and_split "movdf_insn" [(set (match_operand:DF 0 "nonimmediate_operand" "=x,mx,r") (match_operand:DF 1 "general_operand" "iFx,r,mx"))] "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" "#" "reload_completed" [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))]{ rtx lo_half[2], hi_half[2]; split_di (operands, 2, lo_half, hi_half); if (reg_overlap_mentioned_p (lo_half[0], hi_half[1])) { operands[2] = hi_half[0]; operands[3] = hi_half[1]; operands[4] = lo_half[0]; operands[5] = lo_half[1]; } else { operands[2] = lo_half[0]; operands[3] = lo_half[1]; operands[4] = hi_half[0]; operands[5] = hi_half[1]; }});; This is the main "hook" for PIC code. When generating
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -