|  | ; OpenRISC 1000 architecture.  -*- Scheme -*- | 
|  | ; Copyright 2000-2019 Free Software Foundation, Inc. | 
|  | ; Contributed by Peter Gavin, pgavin@gmail.com | 
|  | ; Modified by Andrey Bacherov, avbacherov@opencores.org | 
|  | ; | 
|  | ; This program 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 3 of the License, or | 
|  | ; (at your option) any later version. | 
|  | ; | 
|  | ; This program 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 this program; if not, see <http://www.gnu.org/licenses/> | 
|  |  | 
|  | ; Initial ORFPX32 instruction set | 
|  |  | 
|  | ; I'm not sure how CGEN handles rounding in FP operations, except for | 
|  | ; in conversions to/from integers.  So lf.add, lf.sub, lf.mul, and | 
|  | ; lf.div do not round according to the FPCSR RM field. | 
|  | ; NaN, overflow, and underflow are not yet handled either. | 
|  |  | 
|  | (define-normal-insn-enum insn-opcode-float-regreg | 
|  | "floating point reg/reg insn opcode enums" () | 
|  | OPC_FLOAT_REGREG_ f-op-7-8 | 
|  | (("ADD_S"  #x00) | 
|  | ("SUB_S"  #x01) | 
|  | ("MUL_S"  #x02) | 
|  | ("DIV_S"  #x03) | 
|  | ("ITOF_S" #x04) | 
|  | ("FTOI_S" #x05) | 
|  | ("REM_S"  #x06) | 
|  | ("MADD_S" #x07) | 
|  | ("SFEQ_S" #x08) | 
|  | ("SFNE_S" #x09) | 
|  | ("SFGT_S" #x0a) | 
|  | ("SFGE_S" #x0b) | 
|  | ("SFLT_S" #x0c) | 
|  | ("SFLE_S" #x0d) | 
|  | ("ADD_D"  #x10) | 
|  | ("SUB_D"  #x11) | 
|  | ("MUL_D"  #x12) | 
|  | ("DIV_D"  #x13) | 
|  | ("ITOF_D" #x14) | 
|  | ("FTOI_D" #x15) | 
|  | ("REM_D"  #x16) | 
|  | ("MADD_D" #x17) | 
|  | ("SFEQ_D" #x18) | 
|  | ("SFNE_D" #x19) | 
|  | ("SFGT_D" #x1a) | 
|  | ("SFGE_D" #x1b) | 
|  | ("SFLT_D" #x1c) | 
|  | ("SFLE_D" #x1d) | 
|  | ("SFUEQ_S" #x28) | 
|  | ("SFUNE_S" #x29) | 
|  | ("SFUGT_S" #x2a) | 
|  | ("SFUGE_S" #x2b) | 
|  | ("SFULT_S" #x2c) | 
|  | ("SFULE_S" #x2d) | 
|  | ("SFUN_S" #x2e) | 
|  | ("SFUEQ_D" #x38) | 
|  | ("SFUNE_D" #x39) | 
|  | ("SFUGT_D" #x3a) | 
|  | ("SFUGE_D" #x3b) | 
|  | ("SFULT_D" #x3c) | 
|  | ("SFULE_D" #x3d) | 
|  | ("SFUN_D" #x3e) | 
|  | ("CUST1_S" #xd0) | 
|  | ("CUST1_D" #xe0) | 
|  | ) | 
|  | ) | 
|  |  | 
|  | ; Register offset flags, if set offset is 2 otherwise offset is 1 | 
|  | (dnf f-rdoff-10-1   "destination register pair offset flag" ((MACH ORFPX64A32-MACHS)) 10 1) | 
|  | (dnf f-raoff-9-1    "source register A pair offset flag"    ((MACH ORFPX64A32-MACHS)) 9 1) | 
|  | (dnf f-rboff-8-1    "source register B pair offset flag"    ((MACH ORFPX64A32-MACHS)) 8 1) | 
|  |  | 
|  | (dsh h-roff1        "1-bit offset flag"                     () (register BI)) | 
|  |  | 
|  | (dnop rDSF "destination register (single floating point mode)" ((MACH ORFPX32-MACHS)) h-fsr f-r1) | 
|  | (dnop rASF "source register A (single floating point mode)"    ((MACH ORFPX32-MACHS)) h-fsr f-r2) | 
|  | (dnop rBSF "source register B (single floating point mode)"    ((MACH ORFPX32-MACHS)) h-fsr f-r3) | 
|  |  | 
|  | (define-pmacro (double-field-and-ops mnemonic reg offbit op-comment) | 
|  | (begin | 
|  | (define-multi-ifield | 
|  | (name (.sym "f-r" (.downcase mnemonic) "d32")) | 
|  | (comment op-comment) | 
|  | (attrs (MACH ORFPX64A32-MACHS)) | 
|  | (mode SI) | 
|  | (subfields reg offbit) | 
|  | ; From the multi-ifield insert the bits into subfields | 
|  | (insert (sequence | 
|  | () | 
|  | (set (ifield reg) | 
|  | (and (ifield (.sym "f-r" (.downcase mnemonic) "d32")) | 
|  | (const #x1f)) | 
|  | ) | 
|  | (set (ifield offbit) | 
|  | (and (sra (ifield (.sym "f-r" (.downcase mnemonic) "d32")) | 
|  | (const 5)) | 
|  | (const 1)) | 
|  | ) | 
|  | ) | 
|  | ) | 
|  | ; Extract the multi-ifield from the subfield bits | 
|  | (extract | 
|  | (set (ifield (.sym "f-r" (.downcase mnemonic) "d32")) | 
|  | (or (ifield reg) | 
|  | (sll (ifield offbit) | 
|  | (const 5))) | 
|  | ) | 
|  | ) | 
|  | ) | 
|  | (define-operand | 
|  | (name (.sym "r" (.upcase mnemonic) "D32F")) | 
|  | (comment (.str op-comment " (double floating point pair)")) | 
|  | (attrs (MACH ORFPX64A32-MACHS)) | 
|  | (type h-fd32r) | 
|  | (index (.sym "f-r" (.downcase mnemonic) "d32")) | 
|  | (handlers (parse "regpair") (print "regpair")) | 
|  | ) | 
|  | (define-operand | 
|  | (name (.sym "r" (.upcase mnemonic) "DI")) | 
|  | (comment (.str op-comment " (double integer pair)")) | 
|  | (attrs (MACH ORFPX64A32-MACHS)) | 
|  | (type h-i64r) | 
|  | (index (.sym "f-r" (.downcase mnemonic) "d32")) | 
|  | (handlers (parse "regpair") (print "regpair")) | 
|  | ) | 
|  | ) | 
|  | ) | 
|  |  | 
|  | (double-field-and-ops D f-r1 f-rdoff-10-1 "destination register") | 
|  | (double-field-and-ops A f-r2 f-raoff-9-1  "source register A") | 
|  | (double-field-and-ops B f-r3 f-rboff-8-1  "source register B") | 
|  |  | 
|  | (define-pmacro (float-regreg-insn mnemonic) | 
|  | (begin | 
|  | (dni (.sym lf- mnemonic -s) | 
|  | (.str "lf." mnemonic ".s reg/reg/reg") | 
|  | ((MACH ORFPX32-MACHS)) | 
|  | (.str "lf." mnemonic ".s $rDSF,$rASF,$rBSF") | 
|  | (+ OPC_FLOAT rDSF rASF rBSF (f-resv-10-3 0) (.sym OPC_FLOAT_REGREG_ (.upcase mnemonic) _S)) | 
|  | (set SF rDSF (mnemonic SF rASF rBSF)) | 
|  | () | 
|  | ) | 
|  | (dni (.sym lf- mnemonic -d32) | 
|  | (.str "lf." mnemonic ".d regpair/regpair/regpair") | 
|  | ((MACH ORFPX64A32-MACHS)) | 
|  | (.str "lf." mnemonic ".d $rDD32F,$rAD32F,$rBD32F") | 
|  | (+ OPC_FLOAT rDD32F rAD32F rBD32F (.sym OPC_FLOAT_REGREG_ (.upcase mnemonic) _D)) | 
|  | (set DF rDD32F (mnemonic DF rAD32F rBD32F)) | 
|  | () | 
|  | ) | 
|  | ) | 
|  | ) | 
|  |  | 
|  | (float-regreg-insn add) | 
|  | (float-regreg-insn sub) | 
|  | (float-regreg-insn mul) | 
|  | (float-regreg-insn div) | 
|  |  | 
|  | (dni lf-rem-s | 
|  | "lf.rem.s reg/reg/reg" | 
|  | ((MACH ORFPX32-MACHS)) | 
|  | "lf.rem.s $rDSF,$rASF,$rBSF" | 
|  | (+ OPC_FLOAT rDSF rASF rBSF (f-resv-10-3 0) OPC_FLOAT_REGREG_REM_S) | 
|  | (set SF rDSF (rem SF rASF rBSF)) | 
|  | () | 
|  | ) | 
|  |  | 
|  | (dni lf-rem-d32 | 
|  | "lf.rem.d regpair/regpair/regpair" | 
|  | ((MACH ORFPX64A32-MACHS)) | 
|  | "lf.rem.d $rDD32F,$rAD32F,$rBD32F" | 
|  | (+ OPC_FLOAT rDD32F rAD32F rBD32F OPC_FLOAT_REGREG_REM_D) | 
|  | (set DF rDD32F (rem DF rAD32F rBD32F)) | 
|  | () | 
|  | ) | 
|  |  | 
|  | (define-pmacro (get-rounding-mode) | 
|  | (case INT sys-fpcsr-rm | 
|  | ((0) 1) ; TIES-TO-EVEN -- I'm assuming this is what is meant by "round to nearest" | 
|  | ((1) 3) ; TOWARD-ZERO | 
|  | ((2) 4) ; TOWARD-POSITIVE | 
|  | (else 5) ; TOWARD-NEGATIVE | 
|  | ) | 
|  | ) | 
|  |  | 
|  | (dni lf-itof-s | 
|  | "lf.itof.s reg/reg" | 
|  | ((MACH ORFPX32-MACHS)) | 
|  | "lf.itof.s $rDSF,$rA" | 
|  | (+ OPC_FLOAT rDSF rA (f-r3 0) (f-resv-10-3 0) OPC_FLOAT_REGREG_ITOF_S) | 
|  | (set SF rDSF (float SF (get-rounding-mode) (trunc SI rA))) | 
|  | () | 
|  | ) | 
|  |  | 
|  | (dni lf-itof-d32 | 
|  | "lf.itof.d regpair/regpair" | 
|  | ((MACH ORFPX64A32-MACHS)) | 
|  | "lf.itof.d $rDD32F,$rADI" | 
|  | (+ OPC_FLOAT rDD32F rADI (f-r3 0) (f-resv-8-1 0) OPC_FLOAT_REGREG_ITOF_D) | 
|  | (set DF rDD32F (float DF (get-rounding-mode) rADI)) | 
|  | () | 
|  | ) | 
|  |  | 
|  | (dni lf-ftoi-s | 
|  | "lf.ftoi.s reg/reg" | 
|  | ((MACH ORFPX32-MACHS)) | 
|  | "lf.ftoi.s $rD,$rASF" | 
|  | (+ OPC_FLOAT rD rASF (f-r3 0) (f-resv-10-3 0) OPC_FLOAT_REGREG_FTOI_S) | 
|  | (set WI rD (ext WI (fix SI (get-rounding-mode) rASF))) | 
|  | () | 
|  | ) | 
|  |  | 
|  | (dni lf-ftoi-d32 | 
|  | "lf.ftoi.d regpair/regpair" | 
|  | ((MACH ORFPX64A32-MACHS)) | 
|  | "lf.ftoi.d $rDDI,$rAD32F" | 
|  | (+ OPC_FLOAT rDDI rAD32F (f-r3 0) (f-resv-8-1 0) OPC_FLOAT_REGREG_FTOI_D) | 
|  | (set DI rDDI (fix DI (get-rounding-mode) rAD32F)) | 
|  | () | 
|  | ) | 
|  |  | 
|  | (define-pmacro (float-setflag-insn-base mnemonic rtx-mnemonic symantics) | 
|  | (begin | 
|  | (dni (.sym lf-sf mnemonic -s) | 
|  | (.str "lf.sf" mnemonic ".s reg/reg") | 
|  | ((MACH ORFPX32-MACHS)) | 
|  | (.str "lf.sf" mnemonic ".s $rASF,$rBSF") | 
|  | (+ OPC_FLOAT (f-r1 0) rASF rBSF (f-resv-10-3 0) (.sym OPC_FLOAT_REGREG_SF (.upcase mnemonic) _S)) | 
|  | (symantics rtx-mnemonic SF rASF rBSF) | 
|  | () | 
|  | ) | 
|  | (dni (.sym lf-sf mnemonic -d32) | 
|  | (.str "lf.sf" mnemonic ".d regpair/regpair") | 
|  | ((MACH ORFPX64A32-MACHS)) | 
|  | (.str "lf.sf" mnemonic ".d $rAD32F,$rBD32F") | 
|  | (+ OPC_FLOAT (f-r1 0) rAD32F rBD32F (f-resv-10-1 0) (.sym OPC_FLOAT_REGREG_SF (.upcase mnemonic) _D)) | 
|  | (symantics rtx-mnemonic DF rAD32F rBD32F) | 
|  | () | 
|  | ) | 
|  | ) | 
|  | ) | 
|  |  | 
|  | (define-pmacro (float-setflag-symantics mnemonic mode r1 r2) | 
|  | (set BI sys-sr-f (mnemonic mode r1 r2))) | 
|  |  | 
|  | (define-pmacro (float-setflag-insn mnemonic) | 
|  | (float-setflag-insn-base mnemonic mnemonic float-setflag-symantics)) | 
|  |  | 
|  | (define-pmacro (float-setflag-unordered-cmp-symantics mnemonic mode r1 r2) | 
|  | (set BI sys-sr-f (or (unordered mode r1 r2) | 
|  | (mnemonic mode r1 r2)))) | 
|  |  | 
|  | (define-pmacro (float-setflag-unordered-symantics mnemonic mode r1 r2) | 
|  | (set BI sys-sr-f (unordered mode r1 r2))) | 
|  |  | 
|  | (define-pmacro (float-setflag-unordered-insn mnemonic) | 
|  | (float-setflag-insn-base (.str "u" mnemonic) | 
|  | mnemonic | 
|  | float-setflag-unordered-cmp-symantics)) | 
|  |  | 
|  | (float-setflag-insn eq) | 
|  | (float-setflag-insn ne) | 
|  | (float-setflag-insn ge) | 
|  | (float-setflag-insn gt) | 
|  | (float-setflag-insn lt) | 
|  | (float-setflag-insn le) | 
|  | (float-setflag-unordered-insn eq) | 
|  | (float-setflag-unordered-insn ne) | 
|  | (float-setflag-unordered-insn gt) | 
|  | (float-setflag-unordered-insn ge) | 
|  | (float-setflag-unordered-insn lt) | 
|  | (float-setflag-unordered-insn le) | 
|  | (float-setflag-insn-base un () float-setflag-unordered-symantics) | 
|  |  | 
|  | (dni lf-madd-s | 
|  | "lf.madd.s reg/reg/reg" | 
|  | ((MACH ORFPX32-MACHS)) | 
|  | "lf.madd.s $rDSF,$rASF,$rBSF" | 
|  | (+ OPC_FLOAT rDSF rASF rBSF (f-resv-10-3 0) OPC_FLOAT_REGREG_MADD_S) | 
|  | (set SF rDSF (add SF (mul SF rASF rBSF) rDSF)) | 
|  | () | 
|  | ) | 
|  |  | 
|  | (dni lf-madd-d32 | 
|  | "lf.madd.d regpair/regpair/regpair" | 
|  | ((MACH ORFPX64A32-MACHS)) | 
|  | "lf.madd.d $rDD32F,$rAD32F,$rBD32F" | 
|  | (+ OPC_FLOAT rDD32F rAD32F rBD32F OPC_FLOAT_REGREG_MADD_D) | 
|  | (set DF rDD32F (add DF (mul DF rAD32F rBD32F) rDD32F)) | 
|  | () | 
|  | ) | 
|  |  | 
|  | (define-pmacro (float-cust-insn cust-num) | 
|  | (begin | 
|  | (dni (.sym "lf-cust" cust-num "-s") | 
|  | (.str "lf.cust" cust-num ".s") | 
|  | ((MACH ORFPX32-MACHS)) | 
|  | (.str "lf.cust" cust-num ".s $rASF,$rBSF") | 
|  | (+ OPC_FLOAT (f-resv-25-5 0) rASF rBSF (f-resv-10-3 0) (.sym "OPC_FLOAT_REGREG_CUST" cust-num "_S")) | 
|  | (nop) | 
|  | () | 
|  | ) | 
|  | (dni (.sym "lf-cust" cust-num "-d32") | 
|  | (.str "lf.cust" cust-num ".d") | 
|  | ((MACH ORFPX64A32-MACHS)) | 
|  | (.str "lf.cust" cust-num ".d") | 
|  | (+ OPC_FLOAT (f-resv-25-5 0) rAD32F rBD32F (f-resv-10-1 0) (.sym "OPC_FLOAT_REGREG_CUST" cust-num "_D")) | 
|  | (nop) | 
|  | () | 
|  | ) | 
|  | ) | 
|  | ) | 
|  |  | 
|  | (float-cust-insn "1") |