📄 pa.md
字号:
;;- Machine description for HP PA-RISC architecture for GNU C compiler;; Copyright (C) 1992 Free Software Foundation, Inc.;; Contributed by the Center for Software Science at the University;; of Utah.;; 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, 675 Mass Ave, Cambridge, MA 02139, USA.;; This gcc Version 2 machine description is inspired by sparc.md and;; mips.md.;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.;; Insn type. Used to default other attribute values.;; type "unary" insns have one input operand (1) and one output operand (0);; type "binary" insns have two input operands (1,2) and one output (0)(define_attr "type" "move,unary,binary,compare,load,store,branch,cbranch,fbranch,call,dyncall,fpload,fpstore,fpalu,fpcc,fpmul,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,multi,misc,milli" (const_string "binary"));; Length (in # of insns).(define_attr "length" "" (cond [(eq_attr "type" "load,fpload") (if_then_else (match_operand 1 "symbolic_memory_operand" "") (const_int 2) (const_int 1)) (eq_attr "type" "store,fpstore") (if_then_else (match_operand 0 "symbolic_memory_operand" "") (const_int 2) (const_int 1)) (eq_attr "type" "binary") (if_then_else (match_operand 2 "arith_operand" "") (const_int 1) (const_int 3)) (eq_attr "type" "move,unary") (if_then_else (match_operand 1 "arith_operand" "") (const_int 1) (const_int 2))] (const_int 1)))(define_asm_attributes [(set_attr "length" "1") (set_attr "type" "multi")]);; Attributes for instruction and branch scheduling(define_attr "in_branch_delay" "false,true" (if_then_else (and (eq_attr "type" "!branch,cbranch,fbranch,call,dyncall,multi,milli") (eq_attr "length" "1")) (const_string "true") (const_string "false")));; Unconditional branch, call, and millicode call delay slot description.(define_delay (eq_attr "type" "branch,call,milli") [(eq_attr "in_branch_delay" "true") (nil) (nil)]);; Floating point conditional branch delay slot description.(define_delay (eq_attr "type" "fbranch") [(eq_attr "in_branch_delay" "true") (eq_attr "in_branch_delay" "true") (nil)]);; Integer conditional branch delay slot description.(define_delay (eq_attr "type" "cbranch") [(eq_attr "in_branch_delay" "true") (nil) (nil)]);; Function units of the HPPA. The following data is for the "Snake";; (Mustang CPU + Timex FPU) because that's what I have the docs for.;; Scheduling instructions for PA-83 machines according to the Snake;; constraints shouldn't hurt.;; (define_function_unit {name} {num-units} {n-users} {test};; {ready-delay} {issue-delay} [{conflict-list}]);; The integer ALU.;; (Noted only for documentation; units that take one cycle do not need to;; be specified.);; (define_function_unit "alu" 1 0;; (eq_attr "type" "unary,binary,move,address") 1 0);; Memory. Disregarding Cache misses, the Mustang memory times are:;; load: 2;; store, fpstore: 3, no D-cache operations should be scheduled.;; fpload: 3 (really 2 for flops, but I don't think we can specify that).(define_function_unit "memory" 1 1 (eq_attr "type" "load") 2 0)(define_function_unit "memory" 1 1 (eq_attr "type" "store,fpstore") 3 0)(define_function_unit "memory" 1 1 (eq_attr "type" "fpload") 3 0);; The Timex has two floating-point units: ALU, and MUL/DIV/SQRT unit.;; Timings:;; Instruction Time Unit Minimum Distance (unit contention);; fcpy 3 ALU 2;; fabs 3 ALU 2;; fadd 3 ALU 2;; fsub 3 ALU 2;; fcmp 3 ALU 2;; fcnv 3 ALU 2;; fmpyadd 3 ALU,MPY 2;; fmpysub 3 ALU,MPY 2;; fmpycfxt 3 ALU,MPY 2;; fmpy 3 MPY 2;; fmpyi 3 MPY 2;; fdiv,sgl 10 MPY 10;; fdiv,dbl 12 MPY 12;; fsqrt,sgl 14 MPY 14;; fsqrt,dbl 18 MPY 18(define_function_unit "fp_alu" 1 0 (eq_attr "type" "fpcc") 4 2)(define_function_unit "fp_alu" 1 0 (eq_attr "type" "fpalu") 3 2)(define_function_unit "fp_mpy" 1 0 (eq_attr "type" "fpmul") 3 2)(define_function_unit "fp_mpy" 1 0 (eq_attr "type" "fpdivsgl") 10 10)(define_function_unit "fp_mpy" 1 0 (eq_attr "type" "fpdivdbl") 12 12)(define_function_unit "fp_mpy" 1 0 (eq_attr "type" "fpsqrtsgl") 14 14)(define_function_unit "fp_mpy" 1 0 (eq_attr "type" "fpsqrtdbl") 18 18);; Compare instructions.;; This controls RTL generation and register allocation.;; We generate RTL for comparisons and branches by having the cmpxx;; patterns store away the operands. Then, the scc and bcc patterns;; emit RTL for both the compare and the branch.;;(define_expand "cmpsi" [(set (reg:CC 0) (compare:CC (match_operand:SI 0 "reg_or_0_operand" "") (match_operand:SI 1 "arith5_operand" "")))] "" "{ hppa_compare_op0 = operands[0]; hppa_compare_op1 = operands[1]; hppa_branch_type = CMP_SI; DONE;}")(define_expand "cmpsf" [(set (reg:CCFP 0) (compare:CCFP (match_operand:SF 0 "register_operand" "") (match_operand:SF 1 "register_operand" "")))] "" "{ hppa_compare_op0 = operands[0]; hppa_compare_op1 = operands[1]; hppa_branch_type = CMP_SF; DONE;}")(define_expand "cmpdf" [(set (reg:CCFP 0) (compare:CCFP (match_operand:DF 0 "register_operand" "") (match_operand:DF 1 "register_operand" "")))] "" "{ hppa_compare_op0 = operands[0]; hppa_compare_op1 = operands[1]; hppa_branch_type = CMP_DF; DONE;}")(define_insn "" [(set (reg:CCFP 0) (match_operator:CCFP 2 "comparison_operator" [(match_operand:SF 0 "register_operand" "fx") (match_operand:SF 1 "register_operand" "fx")]))] "" "fcmp,sgl,%Y2 %0,%1" [(set_attr "type" "fpcc")])(define_insn "" [(set (reg:CCFP 0) (match_operator:CCFP 2 "comparison_operator" [(match_operand:DF 0 "register_operand" "fx") (match_operand:DF 1 "register_operand" "fx")]))] "" "fcmp,dbl,%Y2 %0,%1" [(set_attr "type" "fpcc")]);; scc insns.(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (match_operator:CCFP 1 "comparison_operator" [(reg:CCFP 0) (const_int 0)]))] "" "copy 0,%0\;ftest\;ldi 1,%0" [(set_attr "type" "unary") (set_attr "length" "3")])(define_expand "seq" [(set (match_operand:SI 0 "register_operand" "") (eq:SI (match_dup 1) (match_dup 2)))] "" "{ if (hppa_branch_type != CMP_SI) { emit_insn (gen_cmp_fp (EQ, hppa_compare_op0, hppa_compare_op1)); emit_insn (gen_scond_fp (EQ, operands[0])); DONE; } /* set up operands from compare. */ operands[1] = hppa_compare_op0; operands[2] = hppa_compare_op1; /* fall through and generate default code */}")(define_expand "sne" [(set (match_operand:SI 0 "register_operand" "") (ne:SI (match_dup 1) (match_dup 2)))] "" "{ if (hppa_branch_type != CMP_SI) { emit_insn (gen_cmp_fp (NE, hppa_compare_op0, hppa_compare_op1)); emit_insn (gen_scond_fp (NE, operands[0])); DONE; } operands[1] = hppa_compare_op0; operands[2] = hppa_compare_op1;}")(define_expand "slt" [(set (match_operand:SI 0 "register_operand" "") (lt:SI (match_dup 1) (match_dup 2)))] "" "{ if (hppa_branch_type != CMP_SI) { emit_insn (gen_cmp_fp (LT, hppa_compare_op0, hppa_compare_op1)); emit_insn (gen_scond_fp (LT, operands[0])); DONE; } operands[1] = hppa_compare_op0; operands[2] = hppa_compare_op1;}")(define_expand "sgt" [(set (match_operand:SI 0 "register_operand" "") (gt:SI (match_dup 1) (match_dup 2)))] "" "{ if (hppa_branch_type != CMP_SI) { emit_insn (gen_cmp_fp (GT, hppa_compare_op0, hppa_compare_op1)); emit_insn (gen_scond_fp (GT, operands[0])); DONE; } operands[1] = hppa_compare_op0; operands[2] = hppa_compare_op1;}")(define_expand "sle" [(set (match_operand:SI 0 "register_operand" "") (le:SI (match_dup 1) (match_dup 2)))] "" "{ if (hppa_branch_type != CMP_SI) { emit_insn (gen_cmp_fp (LE, hppa_compare_op0, hppa_compare_op1)); emit_insn (gen_scond_fp (LE, operands[0])); DONE; } operands[1] = hppa_compare_op0; operands[2] = hppa_compare_op1;}")(define_expand "sge" [(set (match_operand:SI 0 "register_operand" "") (ge:SI (match_dup 1) (match_dup 2)))] "" "{ if (hppa_branch_type != CMP_SI) { emit_insn (gen_cmp_fp (GE, hppa_compare_op0, hppa_compare_op1)); emit_insn (gen_scond_fp (GE, operands[0])); DONE; } operands[1] = hppa_compare_op0; operands[2] = hppa_compare_op1;}")(define_expand "sltu" [(set (match_operand:SI 0 "register_operand" "") (ltu:SI (match_dup 1) (match_dup 2)))] "" "{ if (hppa_branch_type != CMP_SI) FAIL; operands[1] = hppa_compare_op0; operands[2] = hppa_compare_op1;}")(define_expand "sgtu" [(set (match_operand:SI 0 "register_operand" "") (gtu:SI (match_dup 1) (match_dup 2)))] "" "{ if (hppa_branch_type != CMP_SI) FAIL; operands[1] = hppa_compare_op0; operands[2] = hppa_compare_op1;}")(define_expand "sleu" [(set (match_operand:SI 0 "register_operand" "") (leu:SI (match_dup 1) (match_dup 2)))] "" "{ if (hppa_branch_type != CMP_SI) FAIL; operands[1] = hppa_compare_op0; operands[2] = hppa_compare_op1;}")(define_expand "sgeu" [(set (match_operand:SI 0 "register_operand" "") (geu:SI (match_dup 1) (match_dup 2)))] "" "{ if (hppa_branch_type != CMP_SI) FAIL; operands[1] = hppa_compare_op0; operands[2] = hppa_compare_op1;}");; Instruction canonicalization puts immediate operands second, which;; is the reverse of what we want.(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r,r") (match_operator:SI 3 "comparison_operator" [(match_operand:SI 1 "register_operand" "r,r") (match_operand:SI 2 "arith11_operand" "r,I")]))] "" "*{ if (which_alternative == 0) return \"comclr,%N3 %1,%2,%0\;ldi 1,%0\"; else { if (!(GET_CODE (operands[3]) == EQ || GET_CODE (operands[3]) == NE)) PUT_CODE (operands[3], reverse_relop (GET_CODE (operands[3]))); return \"comiclr,%N3 %2,%1,%0\;ldi 1,%0\"; }}" [(set_attr "type" "binary,binary") (set_attr "length" "2,2")]);; Conditionals(define_expand "beq" [(set (pc) (if_then_else (eq (match_dup 1) (match_dup 2)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ if (hppa_branch_type != CMP_SI) { emit_insn (gen_cmp_fp (EQ, hppa_compare_op0, hppa_compare_op1)); emit_bcond_fp (NE, operands[0]); DONE; } /* set up operands from compare. */ operands[1] = hppa_compare_op0; operands[2] = hppa_compare_op1; /* fall through and generate default code */}")(define_expand "bne" [(set (pc) (if_then_else (ne (match_dup 1) (match_dup 2)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ if (hppa_branch_type != CMP_SI) { emit_insn (gen_cmp_fp (NE, hppa_compare_op0, hppa_compare_op1)); emit_bcond_fp (NE, operands[0]); DONE; } operands[1] = hppa_compare_op0; operands[2] = hppa_compare_op1;}")(define_expand "bgt" [(set (pc) (if_then_else (gt (match_dup 1) (match_dup 2)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ if (hppa_branch_type != CMP_SI) { emit_insn (gen_cmp_fp (GT, hppa_compare_op0, hppa_compare_op1)); emit_bcond_fp (NE, operands[0]); DONE; } operands[1] = hppa_compare_op0; operands[2] = hppa_compare_op1;}")(define_expand "blt" [(set (pc) (if_then_else (lt (match_dup 1) (match_dup 2)) (label_ref (match_operand 0 "" "")) (pc)))] "" "{ if (hppa_branch_type != CMP_SI) { emit_insn (gen_cmp_fp (LT, hppa_compare_op0, hppa_compare_op1)); emit_bcond_fp (NE, operands[0]); DONE; } operands[1] = hppa_compare_op0; operands[2] = hppa_compare_op1;}")(define_expand "bge" [(set (pc)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -