📄 pdp11.md
字号:
;;- Machine description for the pdp11 for GNU C compiler;; Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001;; Free Software Foundation, Inc.;; Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).;; 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.;; HI is 16 bit;; QI is 8 bit ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code;;- updates for most instructions.;;- Operand classes for the register allocator:;; Compare instructions.;; currently we only support df floats, which saves us quite some;; hassle switching the FP mode! ;; we assume that CPU is always in long float mode, and ;; 16 bit integer mode - currently, the prologue for main does this,;; but maybe we should just set up a NEW crt0 properly, ;; -- and what about signal handling code?;; (we don't even let sf floats in the register file, so;; we only should have to worry about truncating and widening ;; when going to memory);; abort() call by g++ - must define libfunc for cmp_optab;; and ucmp_optab for mode SImode, because we don't have that!!!;; - yet since no libfunc is there, we abort ();; The only thing that remains to be done then is output ;; the floats in a way the assembler can handle it (and ;; if you're really into it, use a PDP11 float emulation;; library to do floating point constant folding - but ;; I guess you'll get reasonable results even when not;; doing this);; the last thing to do is fix the UPDATE_CC macro to check;; for floating point condition codes, and set cc_status;; properly, also setting the CC_IN_FCCR flag. ;; define attributes;; currently type is only fpu or arith or unknown, maybe branch later ?;; default is arith(define_attr "type" "unknown,arith,fp" (const_string "arith"));; length default is 1 word each(define_attr "length" "" (const_int 1));; a user's asm statement(define_asm_attributes [(set_attr "type" "unknown"); all bets are off how long it is - make it 256, forces long jumps ; whenever jumping around it !!! (set_attr "length" "256")]);; define function units;; arithmetic - values here immediately when next insn issued;; or does it mean the number of cycles after this insn was issued?;; how do I say that fpu insns use cpu also? (pre-interaction phase);(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0);(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0);; compare(define_insn "cmpdf" [(set (cc0) (compare (match_operand:DF 0 "general_operand" "fR,Q,F") (match_operand:DF 1 "register_operand" "a,a,a")))] "TARGET_FPU" "*{ cc_status.flags = CC_IN_FPU; return \"{cmpd|cmpf} %0, %1\;cfcc\";}" [(set_attr "length" "2,3,6")]);; a bit of brain damage, maybe inline later - ;; problem is - gcc seems to NEED SImode because ;; of the cmp weirdness - maybe change gcc to handle this?(define_expand "cmpsi" [(set (reg:SI 0) (match_operand:SI 0 "general_operand" "g")) (set (reg:SI 2) (match_operand:SI 1 "general_operand" "g")) (parallel [(set (cc0) (compare (reg:SI 0) (reg:SI 2))) (clobber (reg:SI 0))])] "0" ;; disable for test "");; check for next insn for branch code - does this still;; work in gcc 2.* ?(define_insn "" [(set (cc0) (compare (reg:SI 0) (reg:SI 2))) (clobber (reg:SI 0))] "" "*{ rtx br_insn = NEXT_INSN (insn); RTX_CODE br_code; if (GET_CODE (br_insn) != JUMP_INSN) abort(); br_code = GET_CODE (XEXP (XEXP (PATTERN (br_insn), 1), 0)); switch(br_code) { case GEU: case LTU: case GTU: case LEU: return \"jsr pc, ___ucmpsi\;cmp $1,r0\"; case GE: case LT: case GT: case LE: case EQ: case NE: return \"jsr pc, ___cmpsi\;tst r0\"; default: abort(); }}" [(set_attr "length" "4")])(define_insn "cmphi" [(set (cc0) (compare (match_operand:HI 0 "general_operand" "rR,rR,Qi,Qi") (match_operand:HI 1 "general_operand" "rR,Qi,rR,Qi")))] "" "cmp %0,%1" [(set_attr "length" "1,2,2,3")])(define_insn "cmpqi" [(set (cc0) (compare (match_operand:QI 0 "general_operand" "rR,rR,Qi,Qi") (match_operand:QI 1 "general_operand" "rR,Qi,rR,Qi")))] "" "cmpb %0,%1" [(set_attr "length" "1,2,2,3")]) ;; We have to have this because cse can optimize the previous pattern;; into this one.(define_insn "tstdf" [(set (cc0) (match_operand:DF 0 "general_operand" "fR,Q"))] "TARGET_FPU" "*{ cc_status.flags = CC_IN_FPU; return \"{tstd|tstf} %0\;cfcc\";}" [(set_attr "length" "2,3")])(define_expand "tstsi" [(set (reg:SI 0) (match_operand:SI 0 "general_operand" "g")) (parallel [(set (cc0) (reg:SI 0)) (clobber (reg:SI 0))])] "0" ;; disable for test "")(define_insn "" [(set (cc0) (reg:SI 0)) (clobber (reg:SI 0))] "" "jsr pc, ___tstsi\;tst r0" [(set_attr "length" "3")])(define_insn "tsthi" [(set (cc0) (match_operand:HI 0 "general_operand" "rR,Q"))] "" "tst %0" [(set_attr "length" "1,2")])(define_insn "tstqi" [(set (cc0) (match_operand:QI 0 "general_operand" "rR,Q"))] "" "tstb %0" [(set_attr "length" "1,2")]);; sob instruction - we need an assembler which can make this instruction;; valid under _all_ circumstances!(define_insn "" [(set (pc) (if_then_else (ne (plus:HI (match_operand:HI 0 "register_operand" "+r") (const_int -1)) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc))) (set (match_dup 0) (plus:HI (match_dup 0) (const_int -1)))] "TARGET_40_PLUS" "*{ static int labelcount = 0; static char buf[1000]; if (get_attr_length (insn) == 1) return \"sob %0, %l1\"; /* emulate sob */ output_asm_insn (\"dec %0\", operands); sprintf (buf, \"bge LONG_SOB%d\", labelcount); output_asm_insn (buf, NULL); output_asm_insn (\"jmp %l1\", operands); sprintf (buf, \"LONG_SOB%d:\", labelcount++); output_asm_insn (buf, NULL); return \"\";}" [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) (pc)) (const_int -256)) (ge (minus (match_dup 0) (pc)) (const_int 0))) (const_int 4) (const_int 1)))]);; These control RTL generation for conditional jump insns;; and match them for register allocation.;; problem with too short jump distance! we need an assembler which can ;; make this valid for all jump distances!;; e.g. gas!;; these must be changed to check for CC_IN_FCCR if float is to be ;; enabled(define_insn "beq" [(set (pc) (if_then_else (eq (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return output_jump(\"beq\", \"bne\", get_attr_length(insn));" [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) (pc)) (const_int -128)) (ge (minus (match_dup 0) (pc)) (const_int 128))) (const_int 3) (const_int 1)))])(define_insn "bne" [(set (pc) (if_then_else (ne (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return output_jump(\"bne\", \"beq\", get_attr_length(insn));" [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) (pc)) (const_int -128)) (ge (minus (match_dup 0) (pc)) (const_int 128))) (const_int 3) (const_int 1)))])(define_insn "bgt" [(set (pc) (if_then_else (gt (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return output_jump(\"bgt\", \"ble\", get_attr_length(insn));" [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) (pc)) (const_int -128)) (ge (minus (match_dup 0) (pc)) (const_int 128))) (const_int 3) (const_int 1)))])(define_insn "bgtu" [(set (pc) (if_then_else (gtu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return output_jump(\"bhi\", \"blos\", get_attr_length(insn));" [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) (pc)) (const_int -128)) (ge (minus (match_dup 0) (pc)) (const_int 128))) (const_int 3) (const_int 1)))])(define_insn "blt" [(set (pc) (if_then_else (lt (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return output_jump(\"blt\", \"bge\", get_attr_length(insn));" [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) (pc)) (const_int -128)) (ge (minus (match_dup 0) (pc)) (const_int 128))) (const_int 3) (const_int 1)))])(define_insn "bltu" [(set (pc) (if_then_else (ltu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return output_jump(\"blo\", \"bhis\", get_attr_length(insn));" [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) (pc)) (const_int -128)) (ge (minus (match_dup 0) (pc)) (const_int 128))) (const_int 3) (const_int 1)))])(define_insn "bge" [(set (pc) (if_then_else (ge (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return output_jump(\"bge\", \"blt\", get_attr_length(insn));" [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) (pc)) (const_int -128)) (ge (minus (match_dup 0) (pc)) (const_int 128))) (const_int 3) (const_int 1)))])(define_insn "bgeu" [(set (pc) (if_then_else (geu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return output_jump(\"bhis\", \"blo\", get_attr_length(insn));" [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) (pc)) (const_int -128)) (ge (minus (match_dup 0) (pc)) (const_int 128))) (const_int 3) (const_int 1)))])(define_insn "ble" [(set (pc) (if_then_else (le (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return output_jump(\"ble\", \"bgt\", get_attr_length(insn));" [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) (pc)) (const_int -128)) (ge (minus (match_dup 0) (pc)) (const_int 128))) (const_int 3) (const_int 1)))])(define_insn "bleu" [(set (pc) (if_then_else (leu (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "* return output_jump(\"blos\", \"bhi\", get_attr_length(insn));" [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) (pc)) (const_int -128)) (ge (minus (match_dup 0) (pc)) (const_int 128))) (const_int 3) (const_int 1)))]);; These match inverted jump insns for register allocation.(define_insn "" [(set (pc) (if_then_else (eq (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "* return output_jump(\"bne\", \"beq\", get_attr_length(insn));" [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0) (pc))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -