URL
https://opencores.org/ocsvn/scarts/scarts/trunk
Subversion Repositories scarts
[/] [scarts/] [trunk/] [toolchain/] [scarts-binutils/] [binutils-2.19.1/] [cgen/] [cpu/] [sparcfpu.cpu] - Rev 6
Compare with Previous | Blame | View Log
; SPARC 32/64 FPU description. -*- Scheme -*-
; This file contains fpu instructions common to both sparc32/sparc64.
; It also contains sparc32/64 specific insns, but only when they are a variant
; of a collection of common ones (at least that's the current theory).
; Copyright (C) 2000 Red Hat, Inc.
; This file is part of CGEN.
; See file COPYING.CGEN for details.
; FP support is defined even for cpu's without an fpu as the instructions
; still have to be assembled and the simulator still has to recognize them
; so that the appropriate trap can be generated.
;
; The physical registers are stored as an array of SI values: here `SI'
; denotes "set of 32 bits" rather than "32 bit signed integer".
;
; wip: currently evaluating the various possibilities
; Floating point hardware.
; The description needs to know whether the fpu is present.
; Creating a utility register for this purposes seems reasonable.
; Might want an attribute to denote it as such.
(dsh h-fpu? "h/w fpu present?" () (register BI))
(dnop fpu? "h/w fpu present?" () h-fpu? f-nil)
(define-pmacro (build-freg-name n) ((.sym f n) n))
(define-hardware
(name h-fr32)
(semantic-name h-fr)
(comment "sparc32 floating point regs")
(attrs (MACH32))
(type register SI (32))
(indices keyword "%" (.map build-freg-name (.iota 32)))
)
(define-hardware
(name h-fr64)
(semantic-name h-fr)
(comment "sparc64 floating point regs")
(attrs (MACH64))
(type register SI (64))
(indices keyword "%" (.map build-freg-name (.iota 64)))
)
(define-hardware
(name h-frd32)
(semantic-name h-frd)
(comment "sparc32 double precision floating point regs")
(attrs VIRTUAL (MACH32))
(type register DI (16))
; ??? This works, but multiple copies of all the register names might be
; unpalatable. Another way is to specify a register table plus a constraint.
;(indices keyword "%" (.map build-freg-name (.iota 16 0 2)))
(get (index) (join DI SI
(reg h-fr index)
(reg h-fr (add index 1))))
(set (index newval)
(sequence ()
(set (reg h-fr index) (subword SI newval 0))
(set (reg h-fr (add index 1)) (subword SI newval 1))))
)
(define-hardware
(name h-frq32)
(semantic-name h-frq)
(comment "sparc32 quad precision floating point regs")
(attrs VIRTUAL (MACH32))
(type register TF (8))
(indices keyword "%" (.map build-freg-name (.iota 8 0 4)))
(get (index) (join TF SI
(reg h-fr index)
(reg h-fr (add index (const 1)))
(reg h-fr (add index (const 2)))
(reg h-fr (add index (const 3)))))
(set (index newval)
(sequence ()
(set (reg h-fr index) (subword SI newval 0))
(set (reg h-fr (add index (const 1))) (subword SI newval 1))
(set (reg h-fr (add index (const 2))) (subword SI newval 2))
(set (reg h-fr (add index (const 3))) (subword SI newval 3))))
)
(define-hardware
(name h-frd64)
(semantic-name h-frd)
(comment "sparc64 double precision floating point regs")
(attrs VIRTUAL (MACH64))
(type register DF (32))
(indices keyword "%" (.map build-freg-name (.iota 32 0 2)))
(get (index) (join DF SI
(reg h-fr index)
(reg h-fr (add index (const 1)))))
(set (index newval)
(sequence ()
(set (reg h-fr index) (subword SI newval 0))
(set (reg h-fr (add index (const 1))) (subword SI newval 1))))
)
(define-hardware
(name h-frq64)
(semantic-name h-frq)
(comment "sparc64 quad precision floating point regs")
(attrs VIRTUAL (MACH64))
(type register TF (16))
(indices keyword "%" (.map build-freg-name (.iota 16 0 4)))
(get (index) (join TF SI
(reg h-fr index)
(reg h-fr (add index (const 1)))
(reg h-fr (add index (const 2)))
(reg h-fr (add index (const 3)))))
(set (index newval)
(sequence ()
(set (reg h-fr index) (subword SI newval 0))
(set (reg h-fr (add index (const 1))) (subword SI newval 1))
(set (reg h-fr (add index (const 2))) (subword SI newval 2))
(set (reg h-fr (add index (const 3))) (subword SI newval 3))))
)
; fp condition codes
(dsh h-fcc0 "%fcc0" () (register (UINT 2)))
(dsh h-fcc1 "%fcc1" ((MACH64)) (register (UINT 2)))
(dsh h-fcc2 "%fcc2" ((MACH64)) (register (UINT 2)))
(dsh h-fcc3 "%fcc3" ((MACH64)) (register (UINT 2)))
; sparc64 fpu control regs
(dsh h-fsr-rd "fsr rounding direction" ((MACH64)) (register UQI))
(dsh h-fsr-tem "fsr trap enable mask" ((MACH64)) (register UQI))
(dsh h-fsr-ns "fsr nonstandard fp" ((MACH64)) (register BI))
(dsh h-fsr-ver "fsr version" ((MACH64)) (register UQI))
(dsh h-fsr-ftt "fsr fp trap type" ((MACH64)) (register UQI))
(dsh h-fsr-qne "fsr queue not empty" ((MACH64)) (register BI))
(dsh h-fsr-aexc "fsr accrued exception" ((MACH64)) (register UQI))
(dsh h-fsr-cexc "fsr current exception" ((MACH64)) (register UQI))
;(dsh h-fsr "floating point state" ((MACH64)) (register UDI))
(dsh h-fpsr-fef "fpsr enable fp" ((MACH64)) (register BI))
(dsh h-fpsr-du "fpsr dirty upper" ((MACH64)) (register BI))
(dsh h-fpsr-dl "fpsr dirty lower" ((MACH64)) (register BI))
(define-hardware
(name h-fpsr)
(comment "fp regs state")
(attrs VIRTUAL (MACH64))
(type register UQI)
(get () (const 0)) ; FIXME
(set (newval) (set (raw-reg UQI h-fpsr) (const 0))) ; FIXME
)
; Floating point operands.
(define-operand
(name frs1s)
(comment "single precision floating point source register 1")
(type h-fr)
(index f-rs1)
(mode SF)
)
(define-operand
(name frs2s)
(comment "single precision floating point source register 2")
(type h-fr)
(index f-rs2)
(mode SF)
)
(define-operand
(name frds)
(comment "single precision floating point dest'n register")
(type h-fr)
(index f-rd)
(mode SF)
)
(define-operand
(name frs1d)
(comment "double precision floating point source register 1")
(attrs (MACH32))
(type h-frd)
(index f-rs1)
(mode DF)
)
(define-operand
(name frs2d)
(comment "double precision floating point source register 2")
(attrs (MACH32))
(type h-frd)
(index f-rs2)
(mode DF)
)
(define-operand
(name frdd)
(comment "double precision floating point dest'n register")
(attrs (MACH32))
(type h-frd)
(index f-rd)
(mode DF)
)
(dnop frs1q "quad precision floating point source register 1" ((MACH32))
h-frq f-rs1)
(dnop frs2q "quad precision floating point source register 2" ((MACH32))
h-frq f-rs2)
(dnop frdq "quad precision floating point dest'n register" ((MACH32))
h-frq f-rd)
; Encoding/decoding of field for sparc64 requires extra effort.
; See v9 page 40: 5.1.4.1 Floating-Point Register Number Encoding.
(df f-frs1d-64 "rs1 field for sparc64 DF regs" ((MACH64)) 18 5 UINT
((value pc) (or INT (srl value (const 5)) (and value (const #x1e))))
((value pc) (or INT (sll (and value (const 1)) (const 5))
(and value (const #x1e))))
)
(df f-frs2d-64 "rs2 field for sparc64 DF regs" ((MACH64)) 4 5 UINT
((value pc) (or INT (srl value (const 5)) (and value (const #x1e))))
((value pc) (or INT (sll (and value (const 1)) (const 5))
(and value (const #x1e))))
)
(df f-frdd-64 "rd field for sparc64 DF regs" ((MACH64)) 29 5 UINT
((value pc) (or INT (srl value (const 5)) (and value (const #x1e))))
((value pc) (or INT (sll (and value (const 1)) (const 5))
(and value (const #x1e))))
)
(dnop frs1d "double precision floating point source register 1" ((MACH64))
h-frd f-frs1d-64)
(dnop frs2d "double precision floating point source register 2" ((MACH64))
h-frd f-frs2d-64)
(dnop frdd "double precision floating point dest'n register" ((MACH64))
h-frd f-frdd-64)
; Encoding/decoding of field for sparc64 requires extra effort.
; See v9 page 40: 5.1.4.1 Floating-Point Register Number Encoding.
(df f-frs1q-64 "rs1 field for sparc64 TF regs" ((MACH64)) 18 5 UINT
((value pc) (or INT (srl value (const 5)) (and value (const #x1e))))
((value pc) (or INT (sll (and value (const 1)) (const 5))
(and value (const #x1e))))
)
(df f-frs2q-64 "rs2 field for sparc64 TF regs" ((MACH64)) 4 5 UINT
((value pc) (or INT (srl value (const 5)) (and value (const #x1e))))
((value pc) (or INT (sll (and value (const 1)) (const 5))
(and value (const #x1e))))
)
(df f-frdq-64 "rd field for sparc64 TF regs" ((MACH64)) 29 5 UINT
((value pc) (or INT (srl value (const 5)) (and value (const #x1e))))
((value pc) (or INT (sll (and value (const 1)) (const 5))
(and value (const #x1e))))
)
(dnop frs1q "quad precision floating point source register 1" ((MACH64))
h-frq f-frs1q-64)
(dnop frs2q "quad precision floating point source register 2" ((MACH64))
h-frq f-frs2q-64)
(dnop frdq "quad precision floating point dest'n register" ((MACH64))
h-frq f-frdq-64)
(dnop fcc0 "%fcc0" () h-fcc0 f-nil)
; Misc. support macros.
; FIXME: TRAP32 wip
; FIXME: sparc32/sparc64 differences
; FIXME: trap handling in general (c-call's used until more thought invested)
; Check if fpu is present and enabled.
(define-pmacro (check-fp-enabled)
; FIXME: more things to check
(if (not fpu?)
(c-call VOID "@cpu@_hw_trap" pc (c-code INT "TRAP32_FP_DIS")))
)
; Return pointer to FPU.
; ??? wip. maybe move `snan?' to language proper?
(define-pmacro (current-fpu) (c-call PTR "CGEN_CPU_FPU"))
; Issue appropriate trap if x is an snan.
(define-pmacro (check-sf-snan x)
(if (c-raw-call BI "cgen_sf_snan_p" (current-fpu) x)
(c-call VOID "@cpu@_hw_trap" pc (c-code INT "TRAP32_FP_DIS"))) ; FIXME
)
(define-pmacro (check-df-snan x)
(if (c-raw-call BI "cgen_df_snan_p" (current-fpu) x)
(c-call VOID "@cpu@_hw_trap" pc (c-code INT "TRAP32_FP_DIS"))) ; FIXME
)
; Floating point memory ops.
; Note: the startup code uses a load to %f0 to see if an fpu is present.
; Other startup code tries to set the EF bit in the PSR.
(define-pmacro (fp-ld-op name comment op3 mode dest)
(begin
(dnmi (.sym name "f-reg") comment ()
(.str name " [$rs1],$" dest)
(emit (.sym name f-reg+reg) rs1 (rs2 0) dest))
(dnmi (.sym name "f-reg+0") comment ()
(.str name " [$rs1],$" dest)
(emit (.sym name f-reg+imm) rs1 (simm13 0) dest))
(dni (.sym name "f-reg+reg") comment ()
(.str name " [$rs1+$rs2],$" dest)
(+ OP_3 op3 dest rs1 (f-i 0) (f-res-asi 0) rs2)
(sequence ()
(check-fp-enabled)
(set dest (mem mode (add WI rs1 rs2))))
())
(dni (.sym name "f-reg+imm") comment ()
(.str name " [$rs1+$simm13],$" dest)
(+ OP_3 op3 dest rs1 (f-i 1) simm13)
(sequence ()
(check-fp-enabled)
(set dest (mem mode (add WI rs1 simm13))))
())
(dnmi (.sym name "f-reg/asi") comment ()
(.str name " [$rs1]$asi,$" dest)
(emit (.sym name f-reg+reg/asi) rs1 (rs2 0) asi dest))
(dni (.sym name "f-reg+reg/asi") comment ()
(.str name " [$rs1+$rs2]$asi,$" dest)
(+ OP_3 (.sym op3 A) dest rs1 (f-i 0) asi rs2)
(sequence ()
(check-fp-enabled)
(set dest (mem mode (add WI rs1 rs2))))
())
)
)
(fp-ld-op ld "fp SF load" OP3_LDF SF frds)
(fp-ld-op ldd "fp DF load" OP3_LDDF DF frdd)
(define-pmacro (fp-st-op name comment op3 mode src)
(begin
(dnmi (.sym name "f-reg") comment ()
(.str name " $" src ",[$rs1]")
(emit (.sym name f-reg+reg) rs1 (rs2 0) src))
(dnmi (.sym name "f-reg+0") comment ()
(.str name " $" src ",[$rs1]")
(emit (.sym name f-reg+imm) rs1 (simm13 0) src))
(dni (.sym name "f-reg+reg") comment ()
(.str name " $" src ",[$rs1+$rs2]")
(+ OP_3 op3 src rs1 (f-i 0) (f-res-asi 0) rs2)
(sequence ()
(check-fp-enabled)
(set (mem mode (add WI rs1 rs2)) src))
())
(dni (.sym name "f-reg+imm") comment ()
(.str name " $" src ",[$rs1+$simm13]")
(+ OP_3 op3 src rs1 (f-i 1) simm13)
(sequence ()
(check-fp-enabled)
(set (mem mode (add WI rs1 simm13)) src))
())
(dnmi (.sym name "f-reg/asi") comment ()
(.str name " $" src ",[$rs1]$asi")
(emit (.sym name -reg+reg/asi) rs1 (rs2 0) asi src))
(dni (.sym name "f-reg+reg/asi") comment ()
(.str name " $" src ",[$rs1+$rs2]$asi")
(+ OP_3 (.sym op3 A) src rs1 (f-i 0) asi rs2)
(sequence ()
(check-fp-enabled)
(set (mem mode (add WI rs1 rs2)) src))
())
)
)
(fp-st-op st "fp SF store" OP3_STF SF frds)
(fp-st-op std "fp DF store" OP3_STDF DF frdd)
; SF mode arithmetic ops.
(define-pmacro (sf-unary-op name comment op3 fpop1 fn)
(begin
(dni name comment ()
(.str name " $frs1s,$frds")
(+ OP_2 op3 fpop1 frds frs1s (f-rs2 0))
(sequence ()
(check-fp-enabled)
(set frds (fn frs1s))
; ??? dest is modified if snan, assign to tmp first?
; [grep for all check-*-snan's]
(check-sf-snan frds))
())
)
)
(define-pmacro (sf-binary-op name comment op3 fpop1 fn)
(begin
(dni name comment ()
(.str name " $frs1s,$frs2s,$frds")
(+ OP_2 op3 fpop1 frds frs1s frs2s)
(sequence ()
(check-fp-enabled)
(set frds (fn frs1s frs2s))
(check-sf-snan frds))
())
)
)
(sf-unary-op fnegs "32 bit fp neg" OP3_FPOPS1 FPOPS1_FNEGS neg)
(sf-unary-op fabss "32 bit fp abs" OP3_FPOPS1 FPOPS1_FABSS abs)
(sf-binary-op fadds "32 bit fp add" OP3_FPOPS1 FPOPS1_FADDS add)
(sf-binary-op fsubs "32 bit fp sub" OP3_FPOPS1 FPOPS1_FSUBS sub)
(sf-binary-op fmuls "32 bit fp mul" OP3_FPOPS1 FPOPS1_FMULS mul)
(sf-binary-op fdivs "32 bit fp div" OP3_FPOPS1 FPOPS1_FDIVS div)
; ??? floating point compares are wip
(dni fp-fcmps "32 bit compare" ()
"fcmps $frs1s,$frs2s"
(+ OP_2 OP3_FPOPS2 FPOPS2_FCMPS (f-rd 0) frs1s frs2s)
(sequence ()
(check-fp-enabled)
(set fcc0 (c-call UINT "SFCMP" frs1s frs2s)))
()
)
(dni fp-fcmpse "32 bit compare, signal if any nans" ()
"fcmpse $frs1s,$frs2s"
(+ OP_2 OP3_FPOPS2 FPOPS2_FCMPSE (f-rd 0) frs1s frs2s)
(sequence ()
(check-fp-enabled)
(check-sf-snan frs1s)
(check-sf-snan frs2s)
(set fcc0 (c-call UINT "SFCMP" frs1s frs2s)))
()
)
; DF mode arithmetic ops.
(define-pmacro (df-unary-op name comment op3 fpop1 fn)
(begin
(dni name comment ()
(.str name " $frs1d,$frdd")
(+ OP_2 op3 fpop1 frdd frs1d (f-rs2 0))
(sequence ()
(check-fp-enabled)
(set frdd (fn frs1d))
(check-df-snan frdd))
())
)
)
(define-pmacro (df-binary-op name comment op3 fpop1 fn)
(begin
(dni name comment ()
(.str name " $frs1d,$frs2d,$frdd")
(+ OP_2 op3 fpop1 frdd frs1d frs2d)
(sequence ()
(check-fp-enabled)
(set frdd (fn frs1d frs2d))
(check-df-snan frdd))
())
)
)
(df-unary-op fnegd "64 bit fp neg" OP3_FPOPS1 FPOPS1_FNEGD neg)
(df-unary-op fabsd "64 bit fp abs" OP3_FPOPS1 FPOPS1_FABSD abs)
(df-binary-op faddd "64 bit fp add" OP3_FPOPS1 FPOPS1_FADDD add)
(df-binary-op fsubd "64 bit fp sub" OP3_FPOPS1 FPOPS1_FSUBD sub)
(df-binary-op fmuld "64 bit fp mul" OP3_FPOPS1 FPOPS1_FMULD mul)
(df-binary-op fdivd "64 bit fp div" OP3_FPOPS1 FPOPS1_FDIVD div)
; ??? floating point compares are wip
(dni fp-fcmpd "64 bit compare" ()
"fcmpd $frs1d,$frs2d"
(+ OP_2 OP3_FPOPS2 FPOPS2_FCMPD (f-rd 0) frs1d frs2d)
(sequence ()
(check-fp-enabled)
(set fcc0 (c-call UINT "DFCMP" frs1d frs2d)))
()
)
(dni fp-fcmpde "64 bit compare, signal if any nans" ()
"fcmpde $frs1d,$frs2d"
(+ OP_2 OP3_FPOPS2 FPOPS2_FCMPDE (f-rd 0) frs1d frs2d)
(sequence ()
(check-fp-enabled)
(check-df-snan frs1d)
(check-df-snan frs2d)
(set fcc0 (c-call UINT "DFCMP" frs1d frs2d)))
()
)
; Branches
; CC is one of fcc0,fcc
(define-pmacro (ftest-u cc) (eq cc FCC_UN))
(define-pmacro (ftest-g cc) (eq cc FCC_GT))
(define-pmacro (ftest-ug cc) (orif (eq cc FCC_UN) (eq cc FCC_GT)))
(define-pmacro (ftest-l cc) (eq cc FCC_LT))
(define-pmacro (ftest-ul cc) (orif (eq cc FCC_UN) (eq cc FCC_LT)))
(define-pmacro (ftest-lg cc) (orif (eq cc FCC_LT) (eq cc FCC_GT)))
(define-pmacro (ftest-ne cc) (ne cc FCC_EQ))
(define-pmacro (ftest-e cc) (eq cc FCC_EQ))
(define-pmacro (ftest-ue cc) (orif (eq cc FCC_UN) (eq cc FCC_EQ)))
(define-pmacro (ftest-ge cc) (orif (eq cc FCC_GT) (eq cc FCC_EQ)))
(define-pmacro (ftest-uge cc) (ne cc FCC_LT))
(define-pmacro (ftest-le cc) (orif (eq cc FCC_LT) (eq cc FCC_EQ)))
(define-pmacro (ftest-ule cc) (ne cc FCC_GT))
(define-pmacro (ftest-o cc) (ne cc FCC_UN))
(define-pmacro (fbfcc-branch bname comment cond test br-sem)
(begin
(dni bname (.str "fp branch " comment) (V9-DEPRECATED)
(.str bname "$a $disp22")
(+ OP_0 a cond OP2_FBFCC disp22)
(br-sem test fcc0)
())
)
)
(fbfcc-branch fba "always" FCOND_A test-always uncond-br-sem)
(fbfcc-branch fbn "never" FCOND_N test-never uncond-br-sem)
(fbfcc-branch fbu "unordered" FCOND_U ftest-u cond-br-sem)
(fbfcc-branch fbg "greater" FCOND_G ftest-g cond-br-sem)
(fbfcc-branch fbug "unordered or greater" FCOND_UG ftest-ug cond-br-sem)
(fbfcc-branch fbl "less" FCOND_L ftest-l cond-br-sem)
(fbfcc-branch fbul "unordered or less" FCOND_UL ftest-ul cond-br-sem)
(fbfcc-branch fblg "less or greater" FCOND_LG ftest-lg cond-br-sem)
(fbfcc-branch fbne "not equal" FCOND_NE ftest-ne cond-br-sem)
(fbfcc-branch fbe "equal" FCOND_E ftest-e cond-br-sem)
(fbfcc-branch fbue "unordered or equal" FCOND_UE ftest-ue cond-br-sem)
(fbfcc-branch fbge "greater or equal" FCOND_GE ftest-ge cond-br-sem)
(fbfcc-branch fbuge "unordered or greater or equal" FCOND_UGE ftest-uge cond-br-sem)
(fbfcc-branch fble "less or equal" FCOND_LE ftest-le cond-br-sem)
(fbfcc-branch fbule "unordered or less or equal" FCOND_ULE ftest-ule cond-br-sem)
(fbfcc-branch fbo "ordered" FCOND_O ftest-o cond-br-sem)