aboutsummaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'cpu')
-rw-r--r--cpu/ChangeLog3
-rw-r--r--cpu/m32r.cpu2127
-rw-r--r--cpu/m32r.opc302
3 files changed, 2432 insertions, 0 deletions
diff --git a/cpu/ChangeLog b/cpu/ChangeLog
index f6ed0ba..9d0f3e2 100644
--- a/cpu/ChangeLog
+++ b/cpu/ChangeLog
@@ -1,5 +1,8 @@
2004-02-20 Andrew Cagney <cagney@redhat.com>
+ * m32r.opc, m32r.cpu: New files. Written by , Doug Evans, Nick
+ Clifton, Ben Elliston, Matthew Green, and Andrew Haley.
+
* sh.cpu, sh.opc, sh64-compact.cpu, sh64-media.cpu: New files, all
written by Ben Elliston.
diff --git a/cpu/m32r.cpu b/cpu/m32r.cpu
new file mode 100644
index 0000000..a2f94a8
--- /dev/null
+++ b/cpu/m32r.cpu
@@ -0,0 +1,2127 @@
+; Mitsubishi M32R CPU description. -*- Scheme -*-
+;
+; Copyright 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+;
+; Contributed by Red Hat Inc; developed under contract from Mitsubishi
+; Electric Corporation.
+;
+; This file is part of the GNU Binutils.
+;
+; 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 2 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, write to the Free Software
+; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+(include "simplify.inc")
+
+; FIXME: Delete sign extension of accumulator results.
+; Sign extension is done when accumulator is read.
+
+; define-arch must appear first
+
+(define-arch
+ (name m32r) ; name of cpu family
+ (comment "Mitsubishi M32R")
+ (default-alignment aligned)
+ (insn-lsb0? #f)
+ (machs m32r m32rx)
+ (isas m32r)
+)
+
+; Attributes.
+
+; An attribute to describe which pipeline an insn runs in.
+
+(define-attr
+ (for insn)
+ (type enum)
+ (name PIPE)
+ (comment "parallel execution pipeline selection")
+ (values NONE O S OS)
+)
+
+; A derived attribute that says which insns can be executed in parallel
+; with others. This is a required attribute for architectures with
+; parallel execution.
+
+(define-attr
+ (for insn)
+ (type enum)
+ (name PARALLEL)
+ (attrs META) ; do not define in any generated file for now
+ (values NO YES)
+ (default (if (eq-attr (current-insn) PIPE NONE) (symbol NO) (symbol YES)))
+)
+
+; Instruction set parameters.
+
+(define-isa
+ (name m32r)
+
+ ; This is 32 because 16 bit insns always appear as pairs.
+ ; ??? See if this can go away. It's only used by the disassembler (right?)
+ ; to decide how long an unknown insn is. One value isn't sufficient (e.g. if
+ ; on a 16 bit (and not 32 bit) boundary, will only want to advance pc by 16.)
+ (default-insn-bitsize 32)
+
+ ; Number of bytes of insn we can initially fetch.
+ ; The M32R is tricky in that insns are either two 16-bit insns
+ ; (executed sequentially or in parallel) or one 32-bit insn.
+ ; So on one hand the base insn size is 16 bits, but on another it's 32.
+ ; 32 is chosen because:
+ ; - if the chip were ever bi-endian it is believed that the byte order would
+ ; be based on 32 bit quantities
+ ; - 32 bit insns are always aligned on 32 bit boundaries
+ ; - the pc will never stop on a 16 bit (and not 32 bit) boundary
+ ; [well actually it can, but there are no branches to such places]
+ (base-insn-bitsize 32)
+
+ ; Used in computing bit numbers.
+ (default-insn-word-bitsize 32)
+
+ ; The m32r fetches 2 insns at a time.
+ (liw-insns 2)
+
+ ; While the m32r can execute insns in parallel, the base mach can't
+ ; (other than nop). The base mach is greatly handicapped by this, but
+ ; we still need to cleanly handle it.
+ (parallel-insns 2)
+
+ ; Initial bitnumbers to decode insns by.
+ (decode-assist (0 1 2 3 8 9 10 11))
+
+ ; Classification of instructions that fit in the various frames.
+ ; wip, not currently used
+ (insn-types (long ; name
+ 31 ; length
+ (eq-attr (current-insn) LENGTH 31) ; matching insns
+ (0 1 2 7 8 9 10) ; decode-assist
+ )
+ (short
+ 15
+ (eq-attr (current-insn) LENGTH 15) ; matching insns
+ (0 1 2 7 8 9 10)
+ )
+ )
+
+ ; Instruction framing.
+ ; Each m32r insn is either one 32 bit insn, two 16 bit insns executed
+ ; serially (left->right), or two 16 bit insns executed parallelly.
+ ; wip, not currently used
+ (frame long32 ; name
+ ((long)) ; list of insns in frame, plus constraint
+ "$0" ; assembler
+ (+ (1 1) (31 $0)) ; value
+ (sequence () (execute $0)) ; action
+ )
+ (frame serial2x16
+ ((short)
+ (short))
+ "$0 -> $1"
+ (+ (1 0) (15 $0) (1 0) (15 $1))
+ (sequence ()
+ (execute $0)
+ (execute $1))
+ )
+ (frame parallel2x16
+ ((short (eq-attr (current-insn) PIPE "O,BOTH"))
+ (short (eq-attr (current-insn) PIPE "S,BOTH")))
+ "$0 || $1"
+ (+ (1 0) (15 $0) (1 1) (15 $1))
+ (parallel ()
+ (execute $0)
+ (execute $1))
+ )
+)
+
+; Cpu family definitions.
+
+; ??? define-cpu-family [and in general "cpu-family"] might be clearer than
+; define-cpu.
+; ??? Have define-arch provide defaults for architecture that define-cpu can
+; then override [reduces duplication in define-cpu].
+; ??? Another way to go is to delete cpu-families entirely and have one mach
+; able to inherit things from another mach (would also need the ability to
+; not only override specific inherited things but also disable some,
+; e.g. if an insn wasn't supported).
+
+(define-cpu
+ ; cpu names must be distinct from the architecture name and machine names.
+ ; The "b" suffix stands for "base" and is the convention.
+ ; The "f" suffix stands for "family" and is the convention.
+ (name m32rbf)
+ (comment "Mitsubishi M32R base family")
+ (endian big)
+ (word-bitsize 32)
+ ; Override isa spec (??? keeps things simpler, though it was more true
+ ; in the early days and not so much now).
+ (parallel-insns 1)
+)
+
+(define-cpu
+ (name m32rxf)
+ (comment "Mitsubishi M32Rx family")
+ (endian big)
+ (word-bitsize 32)
+ ; Generated files have an "x" suffix.
+ (file-transform "x")
+)
+
+(define-mach
+ (name m32r)
+ (comment "Generic M32R cpu")
+ (cpu m32rbf)
+)
+
+(define-mach
+ (name m32rx)
+ (comment "M32RX cpu")
+ (cpu m32rxf)
+)
+
+; Model descriptions.
+
+; The meaning of this value is wip but at the moment it's intended to describe
+; the implementation (i.e. what -mtune=foo does in sparc gcc).
+;
+; Notes while wip:
+; - format of pipeline entry:
+; (pipeline name (stage1-name ...) (stage2-name ...) ...)
+; The contents of a stage description is wip.
+; - each mach must have at least one model
+; - the default model must be the first one
+;- maybe have `retire' support update total cycle count to handle current
+; parallel insn cycle counting problems
+
+(define-model
+ (name m32r/d) (comment "m32r/d") (attrs)
+ (mach m32r)
+
+ ;(prefetch)
+ ;(retire)
+
+ (pipeline p-non-mem "" () ((fetch) (decode) (execute) (writeback)))
+ (pipeline p-mem "" () ((fetch) (decode) (execute) (memory) (writeback)))
+
+ ; `state' is a list of variables for recording model state
+ (state
+ ; bit mask of h-gr registers, =1 means value being loaded from memory
+ (h-gr UINT)
+ )
+
+ (unit u-exec "Execution Unit" ()
+ 1 1 ; issue done
+ () ; state
+ ((sr INT -1) (dr INT -1)) ; inputs
+ ((dr INT -1)) ; outputs
+ () ; profile action (default)
+ )
+ (unit u-cmp "Compare Unit" ()
+ 1 1 ; issue done
+ () ; state
+ ((src1 INT -1) (src2 INT -1)) ; inputs
+ () ; outputs
+ () ; profile action (default)
+ )
+ (unit u-mac "Multiply/Accumulate Unit" ()
+ 1 1 ; issue done
+ () ; state
+ ((src1 INT -1) (src2 INT -1)) ; inputs
+ () ; outputs
+ () ; profile action (default)
+ )
+ (unit u-cti "Branch Unit" ()
+ 1 1 ; issue done
+ () ; state
+ ((sr INT -1)) ; inputs
+ ((pc)) ; outputs
+ () ; profile action (default)
+ )
+ (unit u-load "Memory Load Unit" ()
+ 1 1 ; issue done
+ () ; state
+ ((sr INT)
+ ;(ld-mem AI)
+ ) ; inputs
+ ((dr INT)) ; outputs
+ () ; profile action (default)
+ )
+ (unit u-store "Memory Store Unit" ()
+ 1 1 ; issue done
+ () ; state
+ ((src1 INT) (src2 INT)) ; inputs
+ () ; ((st-mem AI)) ; outputs
+ () ; profile action (default)
+ )
+)
+
+(define-model
+ (name test) (comment "test") (attrs)
+ (mach m32r)
+ (pipeline all "" () ((fetch) (decode) (execute) (writeback)))
+ (unit u-exec "Execution Unit" ()
+ 1 1 ; issue done
+ () () () ())
+)
+
+; Each mach must have at least one model.
+
+(define-model
+ (name m32rx) (comment "m32rx") (attrs)
+ (mach m32rx)
+
+ ; ??? It's 6 stages but I forget the details right now.
+ (pipeline p-o "" () ((fetch) (decode) (execute) (writeback)))
+ (pipeline p-s "" () ((fetch) (decode) (execute) (writeback)))
+ (pipeline p-o-mem "" () ((fetch) (decode) (execute) (memory) (writeback)))
+
+ (unit u-exec "Execution Unit" ()
+ 1 1 ; issue done
+ () ; state
+ ((sr INT -1) (dr INT -1)) ; inputs
+ ((dr INT -1)) ; outputs
+ () ; profile action (default)
+ )
+ (unit u-cmp "Compare Unit" ()
+ 1 1 ; issue done
+ () ; state
+ ((src1 INT -1) (src2 INT -1)) ; inputs
+ () ; outputs
+ () ; profile action (default)
+ )
+ (unit u-mac "Multiply/Accumulate Unit" ()
+ 1 1 ; issue done
+ () ; state
+ ((src1 INT -1) (src2 INT -1)) ; inputs
+ () ; outputs
+ () ; profile action (default)
+ )
+ (unit u-cti "Branch Unit" ()
+ 1 1 ; issue done
+ () ; state
+ ((sr INT -1)) ; inputs
+ ((pc)) ; outputs
+ () ; profile action (default)
+ )
+ (unit u-load "Memory Load Unit" ()
+ 1 1 ; issue done
+ () ; state
+ ((sr INT)) ; inputs
+ ((dr INT)) ; outputs
+ () ; profile action (default)
+ )
+ (unit u-store "Memory Store Unit" ()
+ 1 1 ; issue done
+ () ; state
+ ((src1 INT) (src2 INT)) ; inputs
+ () ; outputs
+ () ; profile action (default)
+ )
+)
+
+; The instruction fetch/execute cycle.
+; This is split into two parts as sometimes more than one instruction is
+; decoded at once.
+; The `const SI' argument to decode/execute is used to distinguish
+; multiple instructions processed at the same time (e.g. m32r).
+;
+; ??? This is wip, and not currently used.
+; ??? Needs to be moved to define-isa.
+
+; This is how to fetch and decode an instruction.
+
+;(define-extract
+; (sequence VOID
+; (if VOID (ne AI (and AI pc (const AI 3)) (const AI 0))
+; (sequence VOID
+; (set-quiet USI (scratch UHI insn1) (ifetch UHI pc))
+; (decode VOID pc (and UHI insn1 (const UHI #x7fff))
+; (const SI 0)))
+; (sequence VOID
+; (set-quiet USI (scratch USI insn) (ifetch USI pc))
+; (if VOID (ne USI (and USI insn (const USI #x80000000))
+; (const USI 0))
+; (decode VOID pc (srl USI insn (const WI 16)) (const SI 0))
+; (sequence VOID
+; ; ??? parallel support
+; (decode VOID pc (srl USI insn (const WI 16))
+; (const SI 0))
+; (decode VOID (add AI pc (const AI 2))
+; (and USI insn (const WI #x7fff))
+; (const SI 1))))))
+; )
+;)
+
+; This is how to execute a decoded instruction.
+
+;(define-execute
+; (sequence VOID () ; () is empty option list
+; ((AI new_pc))
+; (set AI new_pc (execute: AI (const 0)) #:quiet)
+; (set AI pc new_pc #:direct)
+; )
+;)
+
+; FIXME: It might simplify things to separate the execute process from the
+; one that updates the PC.
+
+; Instruction fields.
+;
+; Attributes:
+; PCREL-ADDR: pc relative value (for reloc and disassembly purposes)
+; ABS-ADDR: absolute address (for reloc and disassembly purposes?)
+; RESERVED: bits are not used to decode insn, must be all 0
+; RELOC: there is a relocation associated with this field (experiment)
+
+(define-attr
+ (for ifield operand)
+ (type boolean)
+ (name RELOC)
+ (comment "there is a reloc associated with this field (experiment)")
+)
+
+(dnf f-op1 "op1" () 0 4)
+(dnf f-op2 "op2" () 8 4)
+(dnf f-cond "cond" () 4 4)
+(dnf f-r1 "r1" () 4 4)
+(dnf f-r2 "r2" () 12 4)
+(df f-simm8 "simm8" () 8 8 INT #f #f)
+(df f-simm16 "simm16" () 16 16 INT #f #f)
+(dnf f-shift-op2 "shift op2" () 8 3)
+(dnf f-uimm4 "uimm4" () 12 4)
+(dnf f-uimm5 "uimm5" () 11 5)
+(dnf f-uimm16 "uimm16" () 16 16)
+(dnf f-uimm24 "uimm24" (ABS-ADDR RELOC) 8 24)
+(dnf f-hi16 "high 16 bits" (SIGN-OPT) 16 16)
+(df f-disp8 "disp8, slot unknown" (PCREL-ADDR RELOC) 8 8 INT
+ ((value pc) (sra WI (sub WI value (and WI pc (const -4))) (const 2)))
+ ((value pc) (add WI (sll WI value (const 2)) (and WI pc (const -4)))))
+(df f-disp16 "disp16" (PCREL-ADDR RELOC) 16 16 INT
+ ((value pc) (sra WI (sub WI value pc) (const 2)))
+ ((value pc) (add WI (sll WI value (const 2)) pc)))
+(df f-disp24 "disp24" (PCREL-ADDR RELOC) 8 24 INT
+ ((value pc) (sra WI (sub WI value pc) (const 2)))
+ ((value pc) (add WI (sll WI value (const 2)) pc)))
+
+(dnf f-op23 "op2.3" () 9 3)
+(dnf f-op3 "op3" () 14 2)
+(dnf f-acc "acc" () 8 1)
+(dnf f-accs "accs" () 12 2)
+(dnf f-accd "accd" () 4 2)
+(dnf f-bits67 "bits67" () 6 2)
+(dnf f-bit14 "bit14" () 14 1)
+
+(define-ifield (name f-imm1) (comment "1 bit immediate, 0->1 1->2")
+ (attrs)
+ (start 15) (length 1)
+ (encode (value pc) (sub WI value (const WI 1)))
+ (decode (value pc) (add WI value (const WI 1)))
+)
+
+; Enums.
+
+; insn-op1: bits 0-3
+; FIXME: should use die macro or some such
+(define-normal-insn-enum insn-op1 "insn format enums" () OP1_ f-op1
+ ("0" "1" "2" "3" "4" "5" "6" "7"
+ "8" "9" "10" "11" "12" "13" "14" "15")
+)
+
+; insn-op2: bits 8-11
+; FIXME: should use die macro or some such
+(define-normal-insn-enum insn-op2 "op2 enums" () OP2_ f-op2
+ ("0" "1" "2" "3" "4" "5" "6" "7"
+ "8" "9" "10" "11" "12" "13" "14" "15")
+)
+
+; Hardware pieces.
+; These entries list the elements of the raw hardware.
+; They're also used to provide tables and other elements of the assembly
+; language.
+
+(dnh h-pc "program counter" (PC PROFILE) (pc) () () ())
+
+(dnh h-hi16 "high 16 bits" ()
+ (immediate (UINT 16))
+ () () ()
+)
+
+; These two aren't technically needed.
+; They're here for illustration sake mostly.
+; Plus they cause the value to be stored in the extraction buffers to only
+; be 16 bits wide (vs 32 or 64). Whoopie ding. But it's fun.
+(dnh h-slo16 "signed low 16 bits" ()
+ (immediate (INT 16))
+ () () ()
+)
+(dnh h-ulo16 "unsigned low 16 bits" ()
+ (immediate (UINT 16))
+ () () ()
+)
+
+(define-keyword
+ (name gr-names)
+ (print-name h-gr)
+ (prefix "")
+ (values (fp 13) (lr 14) (sp 15)
+ (r0 0) (r1 1) (r2 2) (r3 3) (r4 4) (r5 5) (r6 6) (r7 7)
+ (r8 8) (r9 9) (r10 10) (r11 11) (r12 12) (r13 13) (r14 14) (r15 15))
+)
+
+(define-hardware
+ (name h-gr)
+ (comment "general registers")
+ (attrs PROFILE CACHE-ADDR)
+ (type register WI (16))
+ (indices extern-keyword gr-names)
+)
+
+(define-keyword
+ (name cr-names)
+ (print-name h-cr)
+ (prefix "")
+ (values (psw 0) (cbr 1) (spi 2) (spu 3)
+ (bpc 6) (bbpsw 8) (bbpc 14)
+ (cr0 0) (cr1 1) (cr2 2) (cr3 3)
+ (cr4 4) (cr5 5) (cr6 6) (cr7 7)
+ (cr8 8) (cr9 9) (cr10 10) (cr11 11)
+ (cr12 12) (cr13 13) (cr14 14) (cr15 15))
+)
+
+(define-hardware
+ (name h-cr)
+ (comment "control registers")
+ (type register UWI (16))
+ (indices extern-keyword cr-names)
+ (get (index) (c-call UWI "@cpu@_h_cr_get_handler" index))
+ (set (index newval) (c-call VOID "@cpu@_h_cr_set_handler" index newval))
+)
+
+; The actual accumulator is only 56 bits.
+; The top 8 bits are sign extended from bit 8 (when counting msb = bit 0).
+; To simplify the accumulator instructions, no attempt is made to keep the
+; top 8 bits properly sign extended (currently there's no point since they
+; all ignore them). When the value is read it is properly sign extended
+; [in the `get' handler].
+(define-hardware
+ (name h-accum)
+ (comment "accumulator")
+ (type register DI)
+ (get () (c-call DI "@cpu@_h_accum_get_handler"))
+ (set (newval) (c-call VOID "@cpu@_h_accum_set_handler" newval))
+)
+
+; FIXME: Revisit after sanitization can be removed. Remove h-accum.
+(define-hardware
+ (name h-accums)
+ (comment "accumulators")
+ (attrs (MACH m32rx))
+ (type register DI (2))
+ (indices keyword "" ((a0 0) (a1 1)))
+ ; get/set so a0 accesses are redirected to h-accum.
+ ; They're also so reads can properly sign extend the value.
+ ; FIXME: Needn't be a function call.
+ (get (index) (c-call DI "@cpu@_h_accums_get_handler" index))
+ (set (index newval) (c-call VOID "@cpu@_h_accums_set_handler" index newval))
+)
+
+; For condbit operand. FIXME: Need to allow spec of get/set of operands.
+; Having this separate from h-psw keeps the parts that use it simpler
+; [since they greatly outnumber those that use h-psw].
+(dsh h-cond "condition bit" () (register BI))
+
+; The actual values of psw,bpsw,bbpsw are recorded here to allow access
+; to them as a unit.
+(define-hardware
+ (name h-psw)
+ (comment "psw part of psw")
+ (type register UQI)
+ ; get/set to handle cond bit.
+ ; FIXME: missing: use's and clobber's
+ ; FIXME: remove c-call?
+ (get () (c-call UQI "@cpu@_h_psw_get_handler"))
+ (set (newval) (c-call VOID "@cpu@_h_psw_set_handler" newval))
+)
+(dsh h-bpsw "backup psw" () (register UQI))
+(dsh h-bbpsw "backup bpsw" () (register UQI))
+
+; FIXME: Later make add get/set specs and support SMP.
+(dsh h-lock "lock" () (register BI))
+
+; Instruction Operands.
+; These entries provide a layer between the assembler and the raw hardware
+; description, and are used to refer to hardware elements in the semantic
+; code. Usually there's a bit of over-specification, but in more complicated
+; instruction sets there isn't.
+
+; M32R specific operand attributes:
+
+(define-attr
+ (for operand)
+ (type boolean)
+ (name HASH-PREFIX)
+ (comment "immediates have an optional '#' prefix")
+)
+
+; ??? Convention says this should be o-sr, but then the insn definitions
+; should refer to o-sr which is clumsy. The "o-" could be implicit, but
+; then it should be implicit for all the symbols here, but then there would
+; be confusion between (f-)simm8 and (h-)simm8.
+; So for now the rule is exactly as it appears here.
+
+(dnop sr "source register" () h-gr f-r2)
+(dnop dr "destination register" () h-gr f-r1)
+;; The assembler relies upon the fact that dr and src1 are the same field.
+;; FIXME: Revisit.
+(dnop src1 "source register 1" () h-gr f-r1)
+(dnop src2 "source register 2" () h-gr f-r2)
+(dnop scr "source control register" () h-cr f-r2)
+(dnop dcr "destination control register" () h-cr f-r1)
+
+(dnop simm8 "8 bit signed immediate" (HASH-PREFIX) h-sint f-simm8)
+(dnop simm16 "16 bit signed immediate" (HASH-PREFIX) h-sint f-simm16)
+(dnop uimm4 "4 bit trap number" (HASH-PREFIX) h-uint f-uimm4)
+(dnop uimm5 "5 bit shift count" (HASH-PREFIX) h-uint f-uimm5)
+(dnop uimm16 "16 bit unsigned immediate" (HASH-PREFIX) h-uint f-uimm16)
+
+(dnop imm1 "1 bit immediate" ((MACH m32rx) HASH-PREFIX) h-uint f-imm1)
+(dnop accd "accumulator destination register" ((MACH m32rx)) h-accums f-accd)
+(dnop accs "accumulator source register" ((MACH m32rx)) h-accums f-accs)
+(dnop acc "accumulator reg (d)" ((MACH m32rx)) h-accums f-acc)
+
+; slo16,ulo16 are used in both with-hash-prefix/no-hash-prefix cases.
+; e.g. add3 r3,r3,#1 and ld r3,@(4,r4). We could use HASH-PREFIX.
+; Instead we create a fake operand `hash'. The m32r is an illustration port,
+; so we often try out various ways of doing things.
+
+(define-operand (name hash) (comment "# prefix") (attrs)
+ (type h-sint) ; doesn't really matter
+ (index f-nil)
+ (handlers (parse "hash") (print "hash"))
+)
+
+; For high(foo),shigh(foo).
+(define-operand
+ (name hi16)
+ (comment "high 16 bit immediate, sign optional")
+ (attrs)
+ (type h-hi16)
+ (index f-hi16)
+ (handlers (parse "hi16"))
+)
+
+; For low(foo),sda(foo).
+(define-operand
+ (name slo16)
+ (comment "16 bit signed immediate, for low()")
+ (attrs)
+ (type h-slo16)
+ (index f-simm16)
+ (handlers (parse "slo16"))
+)
+
+; For low(foo).
+(define-operand
+ (name ulo16)
+ (comment "16 bit unsigned immediate, for low()")
+ (attrs)
+ (type h-ulo16)
+ (index f-uimm16)
+ (handlers (parse "ulo16"))
+)
+
+(dnop uimm24 "24 bit address" (HASH-PREFIX) h-addr f-uimm24)
+
+(define-operand
+ (name disp8)
+ (comment "8 bit displacement")
+ (attrs RELAX)
+ (type h-iaddr)
+ (index f-disp8)
+ ; ??? Early experiments had insert/extract fields here.
+ ; Moving these to f-disp8 made things cleaner, but may wish to re-introduce
+ ; fields here to handle more complicated cases.
+)
+
+(dnop disp16 "16 bit displacement" () h-iaddr f-disp16)
+(dnop disp24 "24 bit displacement" (RELAX) h-iaddr f-disp24)
+
+; These hardware elements are refered to frequently.
+
+(dnop condbit "condition bit" (SEM-ONLY) h-cond f-nil)
+(dnop accum "accumulator" (SEM-ONLY) h-accum f-nil)
+
+; Instruction definitions.
+;
+; Notes while wip:
+; - dni is a cover macro to the real "this is an instruction" keyword.
+; The syntax of the real one is yet to be determined.
+; At the lowest level (i.e. the "real" one) it will probably take a variable
+; list of arguments where each argument [perhaps after the standard three of
+; name, comment, attrs] is "(keyword arg-to-keyword)". This syntax is simple
+; and yet completely upward extensible. And given the macro facility, one
+; needn't code at that low a level so even though it'll be more verbose than
+; necessary it won't matter. This same reasoning can be applied to most
+; types of entries in this file.
+
+; M32R specific instruction attributes:
+
+; FILL-SLOT: Need next insn to begin on 32 bit boundary.
+; (A "slot" as used here is a 32 bit quantity that can either be filled with
+; one 32 bit insn or two 16 bit insns which go in the "left bin" and "right
+; bin" where the left bin is the one with a lower address).
+
+(define-attr
+ (for insn)
+ (type boolean)
+ (name FILL-SLOT)
+ (comment "fill right bin with `nop' if insn is in left bin")
+)
+
+(define-attr
+ (for insn)
+ (type boolean)
+ (name SPECIAL)
+ (comment "non-public m32rx insn")
+)
+
+; IDOC attribute for instruction documentation.
+
+(define-attr
+ (for insn)
+ (type enum)
+ (name IDOC)
+ (comment "insn kind for documentation")
+ (attrs META)
+ (values
+ (MEM - () "Memory")
+ (ALU - () "ALU")
+ (BR - () "Branch")
+ (ACCUM - () "Accumulator")
+ (MAC - () "Multiply/Accumulate")
+ (MISC - () "Miscellaneous")
+ )
+)
+
+(define-pmacro (bin-op mnemonic op2-op sem-op imm-prefix imm)
+ (begin
+ (dni mnemonic
+ (.str mnemonic " reg/reg")
+ ((PIPE OS) (IDOC ALU))
+ (.str mnemonic " $dr,$sr")
+ (+ OP1_0 op2-op dr sr)
+ (set dr (sem-op dr sr))
+ ()
+ )
+ (dni (.sym mnemonic "3")
+ (.str mnemonic " reg/" imm)
+ ((IDOC ALU))
+ (.str mnemonic "3 $dr,$sr," imm-prefix "$" imm)
+ (+ OP1_8 op2-op dr sr imm)
+ (set dr (sem-op sr imm))
+ ()
+ )
+ )
+)
+(bin-op add OP2_10 add "$hash" slo16)
+; sub isn't present because sub3 doesn't exist.
+(bin-op and OP2_12 and "" uimm16)
+(bin-op or OP2_14 or "$hash" ulo16)
+(bin-op xor OP2_13 xor "" uimm16)
+
+(dni addi "addi"
+ ((PIPE OS) (IDOC ALU))
+ ;#.(string-append "addi " "$dr,$simm8") ; #. experiment
+ "addi $dr,$simm8"
+ (+ OP1_4 dr simm8)
+ (set dr (add dr simm8))
+ ((m32r/d (unit u-exec))
+ (m32rx (unit u-exec)))
+)
+
+(dni addv "addv"
+ ((PIPE OS) (IDOC ALU))
+ "addv $dr,$sr"
+ (+ OP1_0 OP2_8 dr sr)
+ (parallel ()
+ (set dr (add dr sr))
+ (set condbit (add-oflag dr sr (const 0))))
+ ()
+)
+
+(dni addv3 "addv3"
+ ((IDOC ALU))
+ "addv3 $dr,$sr,$simm16"
+ (+ OP1_8 OP2_8 dr sr simm16)
+ (parallel ()
+ (set dr (add sr simm16))
+ (set condbit (add-oflag sr simm16 (const 0))))
+ ()
+)
+
+(dni addx "addx"
+ ((PIPE OS) (IDOC ALU))
+ "addx $dr,$sr"
+ (+ OP1_0 OP2_9 dr sr)
+ (parallel ()
+ (set dr (addc dr sr condbit))
+ (set condbit (add-cflag dr sr condbit)))
+ ()
+)
+
+(dni bc8 "bc with 8 bit displacement"
+ (COND-CTI (PIPE O) (IDOC BR))
+ "bc.s $disp8"
+ (+ OP1_7 (f-r1 12) disp8)
+ (if condbit (set pc disp8))
+ ((m32r/d (unit u-cti))
+ (m32rx (unit u-cti)))
+)
+
+(dnmi bc8r "relaxable bc8"
+ (COND-CTI RELAXABLE (PIPE O) (IDOC BR))
+ "bc $disp8"
+ (emit bc8 disp8)
+)
+
+(dni bc24 "bc with 24 bit displacement"
+ (COND-CTI (IDOC BR))
+ "bc.l $disp24"
+ (+ OP1_15 (f-r1 12) disp24)
+ (if condbit (set pc disp24))
+ ((m32r/d (unit u-cti))
+ (m32rx (unit u-cti)))
+)
+
+(dnmi bc24r "relaxable bc24"
+ (COND-CTI RELAXED (IDOC BR))
+ "bc $disp24"
+ (emit bc24 disp24)
+)
+
+(dni beq "beq"
+ (COND-CTI (IDOC BR))
+ "beq $src1,$src2,$disp16"
+ (+ OP1_11 OP2_0 src1 src2 disp16)
+ (if (eq src1 src2) (set pc disp16))
+ ((m32r/d (unit u-cti) (unit u-cmp (cycles 0)))
+ (m32rx (unit u-cti) (unit u-cmp (cycles 0))))
+)
+
+(define-pmacro (cbranch sym comment op2-op comp-op)
+ (dni sym comment (COND-CTI (IDOC BR))
+ (.str sym " $src2,$disp16")
+ (+ OP1_11 op2-op (f-r1 0) src2 disp16)
+ (if (comp-op src2 (const WI 0)) (set pc disp16))
+ ((m32r/d (unit u-cti) (unit u-cmp (cycles 0)))
+ (m32rx (unit u-cti) (unit u-cmp (cycles 0))))
+ )
+)
+(cbranch beqz "beqz" OP2_8 eq)
+(cbranch bgez "bgez" OP2_11 ge)
+(cbranch bgtz "bgtz" OP2_13 gt)
+(cbranch blez "blez" OP2_12 le)
+(cbranch bltz "bltz" OP2_10 lt)
+(cbranch bnez "bnez" OP2_9 ne)
+
+(dni bl8 "bl with 8 bit displacement"
+ (UNCOND-CTI FILL-SLOT (PIPE O) (IDOC BR))
+ "bl.s $disp8"
+ (+ OP1_7 (f-r1 14) disp8)
+ (sequence ()
+ (set (reg h-gr 14)
+ (add (and pc (const -4)) (const 4)))
+ (set pc disp8))
+ ((m32r/d (unit u-cti))
+ (m32rx (unit u-cti)))
+)
+
+(dnmi bl8r "relaxable bl8"
+ (UNCOND-CTI FILL-SLOT RELAXABLE (PIPE O) (IDOC BR))
+ "bl $disp8"
+ (emit bl8 disp8)
+)
+
+(dni bl24 "bl with 24 bit displacement"
+ (UNCOND-CTI (IDOC BR))
+ "bl.l $disp24"
+ (+ OP1_15 (f-r1 14) disp24)
+ (sequence ()
+ (set (reg h-gr 14) (add pc (const 4)))
+ (set pc disp24))
+ ((m32r/d (unit u-cti))
+ (m32rx (unit u-cti)))
+)
+
+(dnmi bl24r "relaxable bl24"
+ (UNCOND-CTI RELAXED (IDOC BR))
+ "bl $disp24"
+ (emit bl24 disp24)
+)
+
+(dni bcl8 "bcl with 8 bit displacement"
+ (COND-CTI FILL-SLOT (MACH m32rx) (PIPE O) (IDOC BR))
+ "bcl.s $disp8"
+ (+ OP1_7 (f-r1 8) disp8)
+ (if condbit
+ (sequence ()
+ (set (reg h-gr 14)
+ (add (and pc (const -4))
+ (const 4)))
+ (set pc disp8)))
+ ((m32rx (unit u-cti)))
+)
+
+(dnmi bcl8r "relaxable bcl8"
+ (COND-CTI FILL-SLOT (MACH m32rx) (PIPE O) RELAXABLE (IDOC BR))
+ "bcl $disp8"
+ (emit bcl8 disp8)
+)
+
+(dni bcl24 "bcl with 24 bit displacement"
+ (COND-CTI (MACH m32rx) (IDOC BR))
+ "bcl.l $disp24"
+ (+ OP1_15 (f-r1 8) disp24)
+ (if condbit
+ (sequence ()
+ (set (reg h-gr 14) (add pc (const 4)))
+ (set pc disp24)))
+ ((m32rx (unit u-cti)))
+)
+
+(dnmi bcl24r "relaxable bcl24"
+ (COND-CTI (MACH m32rx) RELAXED (IDOC BR))
+ "bcl $disp24"
+ (emit bcl24 disp24)
+)
+
+(dni bnc8 "bnc with 8 bit displacement"
+ (COND-CTI (PIPE O) (IDOC BR))
+ "bnc.s $disp8"
+ (+ OP1_7 (f-r1 13) disp8)
+ (if (not condbit) (set pc disp8))
+ ((m32r/d (unit u-cti))
+ (m32rx (unit u-cti)))
+)
+
+(dnmi bnc8r "relaxable bnc8"
+ (COND-CTI RELAXABLE (PIPE O) (IDOC BR))
+ "bnc $disp8"
+ (emit bnc8 disp8)
+)
+
+(dni bnc24 "bnc with 24 bit displacement"
+ (COND-CTI (IDOC BR))
+ "bnc.l $disp24"
+ (+ OP1_15 (f-r1 13) disp24)
+ (if (not condbit) (set pc disp24))
+ ((m32r/d (unit u-cti))
+ (m32rx (unit u-cti)))
+)
+
+(dnmi bnc24r "relaxable bnc24"
+ (COND-CTI RELAXED (IDOC BR))
+ "bnc $disp24"
+ (emit bnc24 disp24)
+)
+
+(dni bne "bne"
+ (COND-CTI (IDOC BR))
+ "bne $src1,$src2,$disp16"
+ (+ OP1_11 OP2_1 src1 src2 disp16)
+ (if (ne src1 src2) (set pc disp16))
+ ((m32r/d (unit u-cti) (unit u-cmp (cycles 0)))
+ (m32rx (unit u-cti) (unit u-cmp (cycles 0))))
+)
+
+(dni bra8 "bra with 8 bit displacement"
+ (UNCOND-CTI FILL-SLOT (PIPE O) (IDOC BR))
+ "bra.s $disp8"
+ (+ OP1_7 (f-r1 15) disp8)
+ (set pc disp8)
+ ((m32r/d (unit u-cti))
+ (m32rx (unit u-cti)))
+)
+
+(dnmi bra8r "relaxable bra8"
+ (UNCOND-CTI FILL-SLOT RELAXABLE (PIPE O) (IDOC BR))
+ "bra $disp8"
+ (emit bra8 disp8)
+)
+
+(dni bra24 "bra with 24 displacement"
+ (UNCOND-CTI (IDOC BR))
+ "bra.l $disp24"
+ (+ OP1_15 (f-r1 15) disp24)
+ (set pc disp24)
+ ((m32r/d (unit u-cti))
+ (m32rx (unit u-cti)))
+)
+
+(dnmi bra24r "relaxable bra24"
+ (UNCOND-CTI RELAXED (IDOC BR))
+ "bra $disp24"
+ (emit bra24 disp24)
+)
+
+(dni bncl8 "bncl with 8 bit displacement"
+ (COND-CTI FILL-SLOT (MACH m32rx) (PIPE O) (IDOC BR))
+ "bncl.s $disp8"
+ (+ OP1_7 (f-r1 9) disp8)
+ (if (not condbit)
+ (sequence ()
+ (set (reg h-gr 14)
+ (add (and pc (const -4))
+ (const 4)))
+ (set pc disp8)))
+ ((m32rx (unit u-cti)))
+)
+
+(dnmi bncl8r "relaxable bncl8"
+ (COND-CTI FILL-SLOT (MACH m32rx) (PIPE O) RELAXABLE (IDOC BR))
+ "bncl $disp8"
+ (emit bncl8 disp8)
+)
+
+(dni bncl24 "bncl with 24 bit displacement"
+ (COND-CTI (MACH m32rx) (IDOC BR))
+ "bncl.l $disp24"
+ (+ OP1_15 (f-r1 9) disp24)
+ (if (not condbit)
+ (sequence ()
+ (set (reg h-gr 14) (add pc (const 4)))
+ (set pc disp24)))
+ ((m32rx (unit u-cti)))
+)
+
+(dnmi bncl24r "relaxable bncl24"
+ (COND-CTI (MACH m32rx) RELAXED (IDOC BR))
+ "bncl $disp24"
+ (emit bncl24 disp24)
+)
+
+(dni cmp "cmp"
+ ((PIPE OS) (IDOC ALU))
+ "cmp $src1,$src2"
+ (+ OP1_0 OP2_4 src1 src2)
+ (set condbit (lt src1 src2))
+ ((m32r/d (unit u-cmp))
+ (m32rx (unit u-cmp)))
+)
+
+(dni cmpi "cmpi"
+ ((IDOC ALU))
+ "cmpi $src2,$simm16"
+ (+ OP1_8 (f-r1 0) OP2_4 src2 simm16)
+ (set condbit (lt src2 simm16))
+ ((m32r/d (unit u-cmp))
+ (m32rx (unit u-cmp)))
+)
+
+(dni cmpu "cmpu"
+ ((PIPE OS) (IDOC ALU))
+ "cmpu $src1,$src2"
+ (+ OP1_0 OP2_5 src1 src2)
+ (set condbit (ltu src1 src2))
+ ((m32r/d (unit u-cmp))
+ (m32rx (unit u-cmp)))
+)
+
+(dni cmpui "cmpui"
+ ((IDOC ALU))
+ "cmpui $src2,$simm16"
+ (+ OP1_8 (f-r1 0) OP2_5 src2 simm16)
+ (set condbit (ltu src2 simm16))
+ ((m32r/d (unit u-cmp))
+ (m32rx (unit u-cmp)))
+)
+
+(dni cmpeq "cmpeq"
+ ((MACH m32rx) (PIPE OS) (IDOC ALU))
+ "cmpeq $src1,$src2"
+ (+ OP1_0 OP2_6 src1 src2)
+ (set condbit (eq src1 src2))
+ ((m32rx (unit u-cmp)))
+)
+
+(dni cmpz "cmpz"
+ ((MACH m32rx) (PIPE OS) (IDOC ALU))
+ "cmpz $src2"
+ (+ OP1_0 OP2_7 (f-r1 0) src2)
+ (set condbit (eq src2 (const 0)))
+ ((m32rx (unit u-cmp)))
+)
+
+(dni div "div"
+ ((IDOC ALU))
+ "div $dr,$sr"
+ (+ OP1_9 OP2_0 dr sr (f-simm16 0))
+ (if (ne sr (const 0)) (set dr (div dr sr)))
+ ((m32r/d (unit u-exec (cycles 37)))
+ (m32rx (unit u-exec (cycles 37))))
+)
+
+(dni divu "divu"
+ ((IDOC ALU))
+ "divu $dr,$sr"
+ (+ OP1_9 OP2_1 dr sr (f-simm16 0))
+ (if (ne sr (const 0)) (set dr (udiv dr sr)))
+ ((m32r/d (unit u-exec (cycles 37)))
+ (m32rx (unit u-exec (cycles 37))))
+)
+
+(dni rem "rem"
+ ((IDOC ALU))
+ "rem $dr,$sr"
+ (+ OP1_9 OP2_2 dr sr (f-simm16 0))
+ ; FIXME: Check rounding direction.
+ (if (ne sr (const 0)) (set dr (mod dr sr)))
+ ((m32r/d (unit u-exec (cycles 37)))
+ (m32rx (unit u-exec (cycles 37))))
+)
+
+(dni remu "remu"
+ ((IDOC ALU))
+ "remu $dr,$sr"
+ (+ OP1_9 OP2_3 dr sr (f-simm16 0))
+ ; FIXME: Check rounding direction.
+ (if (ne sr (const 0)) (set dr (umod dr sr)))
+ ((m32r/d (unit u-exec (cycles 37)))
+ (m32rx (unit u-exec (cycles 37))))
+)
+
+(dni divh "divh"
+ ((MACH m32rx) (IDOC ALU))
+ "divh $dr,$sr"
+ (+ OP1_9 OP2_0 dr sr (f-simm16 #x10))
+ (if (ne sr (const 0)) (set dr (div (ext WI (trunc HI dr)) sr)))
+ ((m32rx (unit u-exec (cycles 21))))
+)
+
+(dni jc "jc"
+ (COND-CTI (MACH m32rx) (PIPE O) SPECIAL (IDOC BR))
+ "jc $sr"
+ (+ OP1_1 (f-r1 12) OP2_12 sr)
+ (if condbit (set pc (and sr (const -4))))
+ ((m32rx (unit u-cti)))
+)
+
+(dni jnc "jnc"
+ (COND-CTI (MACH m32rx) (PIPE O) SPECIAL (IDOC BR))
+ "jnc $sr"
+ (+ OP1_1 (f-r1 13) OP2_12 sr)
+ (if (not condbit) (set pc (and sr (const -4))))
+ ((m32rx (unit u-cti)))
+)
+
+(dni jl "jl"
+ (UNCOND-CTI FILL-SLOT (PIPE O) (IDOC BR))
+ "jl $sr"
+ (+ OP1_1 (f-r1 14) OP2_12 sr)
+ (parallel ()
+ (set (reg h-gr 14)
+ (add (and pc (const -4)) (const 4)))
+ (set pc (and sr (const -4))))
+ ((m32r/d (unit u-cti))
+ (m32rx (unit u-cti)))
+)
+
+(dni jmp "jmp"
+ (UNCOND-CTI (PIPE O) (IDOC BR))
+ "jmp $sr"
+ (+ OP1_1 (f-r1 15) OP2_12 sr)
+ (set pc (and sr (const -4)))
+ ; The above works now so this kludge has been commented out.
+ ; It's kept around because the f-r1 reference in the semantic part
+ ; should work.
+ ; FIXME: kludge, instruction decoding not finished.
+ ; But this should work, so that's another FIXME.
+ ;(sequence VOID (if VOID (eq SI f-r1 (const SI 14))
+ ; FIXME: abuf->insn should be a macro of some sort.
+ ;(sequence VOID
+ ; (if VOID (eq SI (c-code SI "((abuf->insn >> 8) & 15)")
+ ; (const SI 14))
+ ; (set WI (reg WI h-gr 14)
+ ; (add WI (and WI pc (const WI -4)) (const WI 4))))
+ ; (set WI pc sr))
+ ((m32r/d (unit u-cti))
+ (m32rx (unit u-cti)))
+)
+
+(define-pmacro (no-ext-expr mode expr) expr)
+(define-pmacro (ext-expr mode expr) (ext mode expr))
+(define-pmacro (zext-expr mode expr) (zext mode expr))
+
+(define-pmacro (load-op suffix op2-op mode ext-op)
+ (begin
+ (dni (.sym ld suffix) (.str "ld" suffix)
+ ((PIPE O) (IDOC MEM))
+ (.str "ld" suffix " $dr,@$sr")
+ (+ OP1_2 op2-op dr sr)
+ (set dr (ext-op WI (mem mode sr)))
+ ((m32r/d (unit u-load))
+ (m32rx (unit u-load)))
+ )
+ (dnmi (.sym ld suffix "-2") (.str "ld" suffix "-2")
+ (NO-DIS (PIPE O) (IDOC MEM))
+ (.str "ld" suffix " $dr,@($sr)")
+ (emit (.sym ld suffix) dr sr))
+ (dni (.sym ld suffix -d) (.str "ld" suffix "-d")
+ ((IDOC MEM))
+ (.str "ld" suffix " $dr,@($slo16,$sr)")
+ (+ OP1_10 op2-op dr sr slo16)
+ (set dr (ext-op WI (mem mode (add sr slo16))))
+ ((m32r/d (unit u-load (cycles 2)))
+ (m32rx (unit u-load (cycles 2))))
+ )
+ (dnmi (.sym ld suffix -d2) (.str "ld" suffix "-d2")
+ (NO-DIS (IDOC MEM))
+ (.str "ld" suffix " $dr,@($sr,$slo16)")
+ (emit (.sym ld suffix -d) dr sr slo16))
+ )
+)
+(load-op "" OP2_12 WI no-ext-expr)
+(load-op b OP2_8 QI ext-expr)
+(load-op h OP2_10 HI ext-expr)
+(load-op ub OP2_9 QI zext-expr)
+(load-op uh OP2_11 HI zext-expr)
+
+(dni ld-plus "ld+"
+ ((PIPE O) (IDOC MEM))
+ "ld $dr,@$sr+"
+ (+ OP1_2 dr OP2_14 sr)
+ (parallel ()
+ ; wip: memory addresses in profiling support
+ ;(set dr (name ld-mem (mem WI sr)))
+ (set dr (mem WI sr))
+ (set sr (add sr (const 4))))
+ ; Note: `pred' is the constraint. Also useful here is (ref name)
+ ; and returns true if operand <name> was referenced
+ ; (where "referenced" means _read_ if input operand and _written_ if
+ ; output operand).
+ ; args to unit are "unit-name (name1 value1) ..."
+ ; - cycles(done),issue,pred are also specified this way
+ ; - if unspecified, default is used
+ ; - for ins/outs, extra arg is passed that says what was specified
+ ; - this is AND'd with `written' for outs
+ ((m32r/d (unit u-load (pred (const 1)))
+ (unit u-exec (in sr #f) (in dr sr) (out dr sr) (cycles 0) (pred (const 1))))
+ (m32rx (unit u-load)
+ (unit u-exec (in sr #f) (in dr sr) (out dr sr) (cycles 0) (pred (const 1))))
+ )
+)
+
+(dnmi pop "pop"
+ ((IDOC MEM))
+ "pop $dr"
+ (emit ld-plus dr (sr 15)) ; "ld %0,@sp+"
+)
+
+(dni ld24 "ld24"
+ ((IDOC MEM))
+ "ld24 $dr,$uimm24"
+ (+ OP1_14 dr uimm24)
+ (set dr uimm24)
+ ()
+)
+
+; ldi8 appears before ldi16 so we try the shorter version first
+
+(dni ldi8 "ldi8"
+ ((PIPE OS) (IDOC ALU))
+ "ldi8 $dr,$simm8"
+ (+ OP1_6 dr simm8)
+ (set dr simm8)
+ ()
+)
+
+(dnmi ldi8a "ldi8 alias"
+ ((PIPE OS) (IDOC ALU))
+ "ldi $dr,$simm8"
+ (emit ldi8 dr simm8)
+)
+
+(dni ldi16 "ldi16"
+ ((IDOC ALU))
+ "ldi16 $dr,$hash$slo16"
+ (+ OP1_9 OP2_15 (f-r2 0) dr slo16)
+ (set dr slo16)
+ ()
+)
+
+(dnmi ldi16a "ldi16 alias"
+ ((IDOC ALU))
+ "ldi $dr,$hash$slo16"
+ (emit ldi16 dr slo16)
+)
+
+(dni lock "lock"
+ ((PIPE O) (IDOC MISC))
+ "lock $dr,@$sr"
+ (+ OP1_2 OP2_13 dr sr)
+ (sequence ()
+ (set (reg h-lock) (const BI 1))
+ (set dr (mem WI sr)))
+ ((m32r/d (unit u-load))
+ (m32rx (unit u-load)))
+)
+
+(dni machi "machi"
+ (
+ ; (MACH m32r) is a temporary hack. This insn collides with machi-a
+ ; in the simulator so disable it for m32rx.
+ (MACH m32r) (PIPE S) (IDOC MAC)
+ )
+ "machi $src1,$src2"
+ (+ OP1_3 OP2_4 src1 src2)
+ ; FIXME: TRACE_RESULT will print the wrong thing since we
+ ; alter one of the arguments.
+ (set accum
+ (sra DI
+ (sll DI
+ (add DI
+ accum
+ (mul DI
+ (ext DI (and WI src1 (const #xffff0000)))
+ (ext DI (trunc HI (sra WI src2 (const 16))))))
+ (const 8))
+ (const 8)))
+ ((m32r/d (unit u-mac)))
+)
+
+(dni machi-a "machi-a"
+ ((MACH m32rx) (PIPE S) (IDOC MAC))
+ "machi $src1,$src2,$acc"
+ (+ OP1_3 src1 acc (f-op23 4) src2)
+ (set acc
+ (sra DI
+ (sll DI
+ (add DI
+ acc
+ (mul DI
+ (ext DI (and WI src1 (const #xffff0000)))
+ (ext DI (trunc HI (sra WI src2 (const 16))))))
+ (const 8))
+ (const 8)))
+ ((m32rx (unit u-mac)))
+)
+
+(dni maclo "maclo"
+ ((MACH m32r) (PIPE S) (IDOC MAC))
+ "maclo $src1,$src2"
+ (+ OP1_3 OP2_5 src1 src2)
+ (set accum
+ (sra DI
+ (sll DI
+ (add DI
+ accum
+ (mul DI
+ (ext DI (sll WI src1 (const 16)))
+ (ext DI (trunc HI src2))))
+ (const 8))
+ (const 8)))
+ ((m32r/d (unit u-mac)))
+)
+
+(dni maclo-a "maclo-a"
+ ((MACH m32rx) (PIPE S) (IDOC MAC))
+ "maclo $src1,$src2,$acc"
+ (+ OP1_3 src1 acc (f-op23 5) src2)
+ (set acc
+ (sra DI
+ (sll DI
+ (add DI
+ acc
+ (mul DI
+ (ext DI (sll WI src1 (const 16)))
+ (ext DI (trunc HI src2))))
+ (const 8))
+ (const 8)))
+ ((m32rx (unit u-mac)))
+)
+
+(dni macwhi "macwhi"
+ ((MACH m32r) (PIPE S) (IDOC MAC))
+ "macwhi $src1,$src2"
+ (+ OP1_3 OP2_6 src1 src2)
+ (set accum
+ (sra DI
+ (sll DI
+ (add DI
+ accum
+ (mul DI
+ (ext DI src1)
+ (ext DI (trunc HI (sra WI src2 (const 16))))))
+ (const 8))
+ (const 8)))
+ ((m32r/d (unit u-mac)))
+)
+
+(dni macwhi-a "macwhi-a"
+ ((MACH m32rx) (PIPE S) SPECIAL (IDOC MAC))
+ "macwhi $src1,$src2,$acc"
+ (+ OP1_3 src1 acc (f-op23 6) src2)
+ ; Note that this doesn't do the sign extension, which is correct.
+ (set acc
+ (add acc
+ (mul (ext DI src1)
+ (ext DI (trunc HI (sra src2 (const 16)))))))
+ ((m32rx (unit u-mac)))
+)
+
+(dni macwlo "macwlo"
+ ((MACH m32r) (PIPE S) (IDOC MAC))
+ "macwlo $src1,$src2"
+ (+ OP1_3 OP2_7 src1 src2)
+ (set accum
+ (sra DI
+ (sll DI
+ (add DI
+ accum
+ (mul DI
+ (ext DI src1)
+ (ext DI (trunc HI src2))))
+ (const 8))
+ (const 8)))
+ ((m32r/d (unit u-mac)))
+)
+
+(dni macwlo-a "macwlo-a"
+ ((MACH m32rx) (PIPE S) SPECIAL (IDOC MAC))
+ "macwlo $src1,$src2,$acc"
+ (+ OP1_3 src1 acc (f-op23 7) src2)
+ ; Note that this doesn't do the sign extension, which is correct.
+ (set acc
+ (add acc
+ (mul (ext DI src1)
+ (ext DI (trunc HI src2)))))
+ ((m32rx (unit u-mac)))
+)
+
+(dni mul "mul"
+ ((PIPE S) (IDOC ALU))
+ "mul $dr,$sr"
+ (+ OP1_1 OP2_6 dr sr)
+ (set dr (mul dr sr))
+ ((m32r/d (unit u-exec (cycles 4)))
+ (m32rx (unit u-exec (cycles 4))))
+)
+
+(dni mulhi "mulhi"
+ ((MACH m32r) (PIPE S) (IDOC ACCUM))
+ "mulhi $src1,$src2"
+ (+ OP1_3 OP2_0 src1 src2)
+ (set accum
+ (sra DI
+ (sll DI
+ (mul DI
+ (ext DI (and WI src1 (const #xffff0000)))
+ (ext DI (trunc HI (sra WI src2 (const 16)))))
+ (const 16))
+ (const 16)))
+ ((m32r/d (unit u-mac)))
+)
+
+(dni mulhi-a "mulhi-a"
+ ((MACH m32rx) (PIPE S) (IDOC ACCUM))
+ "mulhi $src1,$src2,$acc"
+ (+ OP1_3 (f-op23 0) src1 acc src2)
+ (set acc
+ (sra DI
+ (sll DI
+ (mul DI
+ (ext DI (and WI src1 (const #xffff0000)))
+ (ext DI (trunc HI (sra WI src2 (const 16)))))
+ (const 16))
+ (const 16)))
+ ((m32rx (unit u-mac)))
+)
+
+(dni mullo "mullo"
+ ((MACH m32r) (PIPE S) (IDOC ACCUM))
+ "mullo $src1,$src2"
+ (+ OP1_3 OP2_1 src1 src2)
+ (set accum
+ (sra DI
+ (sll DI
+ (mul DI
+ (ext DI (sll WI src1 (const 16)))
+ (ext DI (trunc HI src2)))
+ (const 16))
+ (const 16)))
+ ((m32r/d (unit u-mac)))
+)
+
+(dni mullo-a "mullo-a"
+ ((MACH m32rx) (PIPE S) (IDOC ACCUM))
+ "mullo $src1,$src2,$acc"
+ (+ OP1_3 src1 acc (f-op23 1) src2)
+ (set acc
+ (sra DI
+ (sll DI
+ (mul DI
+ (ext DI (sll WI src1 (const 16)))
+ (ext DI (trunc HI src2)))
+ (const 16))
+ (const 16)))
+ ((m32rx (unit u-mac)))
+)
+
+(dni mulwhi "mulwhi"
+ ((MACH m32r) (PIPE S) (IDOC ACCUM))
+ "mulwhi $src1,$src2"
+ (+ OP1_3 OP2_2 src1 src2)
+ (set accum
+ (sra DI
+ (sll DI
+ (mul DI
+ (ext DI src1)
+ (ext DI (trunc HI (sra WI src2 (const 16)))))
+ (const 8))
+ (const 8)))
+ ((m32r/d (unit u-mac)))
+)
+
+(dni mulwhi-a "mulwhi-a"
+ ((MACH m32rx) (PIPE S) SPECIAL (IDOC ACCUM))
+ "mulwhi $src1,$src2,$acc"
+ (+ OP1_3 src1 acc (f-op23 2) src2)
+ ; Note that this doesn't do the sign extension, which is correct.
+ (set acc
+ (mul (ext DI src1)
+ (ext DI (trunc HI (sra src2 (const 16))))))
+ ((m32rx (unit u-mac)))
+)
+
+(dni mulwlo "mulwlo"
+ ((MACH m32r) (PIPE S) (IDOC ACCUM))
+ "mulwlo $src1,$src2"
+ (+ OP1_3 OP2_3 src1 src2)
+ (set accum
+ (sra DI
+ (sll DI
+ (mul DI
+ (ext DI src1)
+ (ext DI (trunc HI src2)))
+ (const 8))
+ (const 8)))
+ ((m32r/d (unit u-mac)))
+)
+
+(dni mulwlo-a "mulwlo-a"
+ ((MACH m32rx) (PIPE S) SPECIAL (IDOC ACCUM))
+ "mulwlo $src1,$src2,$acc"
+ (+ OP1_3 src1 acc (f-op23 3) src2)
+ ; Note that this doesn't do the sign extension, which is correct.
+ (set acc
+ (mul (ext DI src1)
+ (ext DI (trunc HI src2))))
+ ((m32rx (unit u-mac)))
+)
+
+(dni mv "mv"
+ ((PIPE OS) (IDOC ALU))
+ "mv $dr,$sr"
+ (+ OP1_1 OP2_8 dr sr)
+ (set dr sr)
+ ()
+)
+
+(dni mvfachi "mvfachi"
+ ((MACH m32r) (PIPE S) (IDOC ACCUM))
+ "mvfachi $dr"
+ (+ OP1_5 OP2_15 (f-r2 0) dr)
+ (set dr (trunc WI (sra DI accum (const 32))))
+ ((m32r/d (unit u-exec (cycles 2))))
+)
+
+(dni mvfachi-a "mvfachi-a"
+ ((MACH m32rx) (PIPE S) (IDOC ACCUM))
+ "mvfachi $dr,$accs"
+ (+ OP1_5 dr OP2_15 accs (f-op3 0))
+ (set dr (trunc WI (sra DI accs (const 32))))
+ ((m32rx (unit u-exec (cycles 2))))
+)
+
+(dni mvfaclo "mvfaclo"
+ ((MACH m32r) (PIPE S) (IDOC ACCUM))
+ "mvfaclo $dr"
+ (+ OP1_5 OP2_15 (f-r2 1) dr)
+ (set dr (trunc WI accum))
+ ((m32r/d (unit u-exec (cycles 2))))
+)
+
+(dni mvfaclo-a "mvfaclo-a"
+ ((MACH m32rx) (PIPE S) (IDOC ACCUM))
+ "mvfaclo $dr,$accs"
+ (+ OP1_5 dr OP2_15 accs (f-op3 1))
+ (set dr (trunc WI accs))
+ ((m32rx (unit u-exec (cycles 2))))
+)
+
+(dni mvfacmi "mvfacmi"
+ ((MACH m32r) (PIPE S) (IDOC ACCUM))
+ "mvfacmi $dr"
+ (+ OP1_5 OP2_15 (f-r2 2) dr)
+ (set dr (trunc WI (sra DI accum (const 16))))
+ ((m32r/d (unit u-exec (cycles 2))))
+)
+
+(dni mvfacmi-a "mvfacmi-a"
+ ((MACH m32rx) (PIPE S) (IDOC ACCUM))
+ "mvfacmi $dr,$accs"
+ (+ OP1_5 dr OP2_15 accs (f-op3 2))
+ (set dr (trunc WI (sra DI accs (const 16))))
+ ((m32rx (unit u-exec (cycles 2))))
+)
+
+(dni mvfc "mvfc"
+ ((PIPE O) (IDOC MISC))
+ "mvfc $dr,$scr"
+ (+ OP1_1 OP2_9 dr scr)
+ (set dr scr)
+ ()
+)
+
+(dni mvtachi "mvtachi"
+ ((MACH m32r) (PIPE S) (IDOC ACCUM))
+ "mvtachi $src1"
+ (+ OP1_5 OP2_7 (f-r2 0) src1)
+ (set accum
+ (or DI
+ (and DI accum (const DI #xffffffff))
+ (sll DI (ext DI src1) (const 32))))
+ ((m32r/d (unit u-exec (in sr src1))))
+)
+
+(dni mvtachi-a "mvtachi-a"
+ ((MACH m32rx) (PIPE S) (IDOC ACCUM))
+ "mvtachi $src1,$accs"
+ (+ OP1_5 src1 OP2_7 accs (f-op3 0))
+ (set accs
+ (or DI
+ (and DI accs (const DI #xffffffff))
+ (sll DI (ext DI src1) (const 32))))
+ ((m32rx (unit u-exec (in sr src1))))
+)
+
+(dni mvtaclo "mvtaclo"
+ ((MACH m32r) (PIPE S) (IDOC ACCUM))
+ "mvtaclo $src1"
+ (+ OP1_5 OP2_7 (f-r2 1) src1)
+ (set accum
+ (or DI
+ (and DI accum (const DI #xffffffff00000000))
+ (zext DI src1)))
+ ((m32r/d (unit u-exec (in sr src1))))
+)
+
+(dni mvtaclo-a "mvtaclo-a"
+ ((MACH m32rx) (PIPE S) (IDOC ACCUM))
+ "mvtaclo $src1,$accs"
+ (+ OP1_5 src1 OP2_7 accs (f-op3 1))
+ (set accs
+ (or DI
+ (and DI accs (const DI #xffffffff00000000))
+ (zext DI src1)))
+ ((m32rx (unit u-exec (in sr src1))))
+)
+
+(dni mvtc "mvtc"
+ ((PIPE O) (IDOC MISC))
+ "mvtc $sr,$dcr"
+ (+ OP1_1 OP2_10 dcr sr)
+ (set dcr sr)
+ ()
+)
+
+(dni neg "neg"
+ ((PIPE OS) (IDOC ALU))
+ "neg $dr,$sr"
+ (+ OP1_0 OP2_3 dr sr)
+ (set dr (neg sr))
+ ()
+)
+
+(dni nop "nop"
+ ((PIPE OS) (IDOC MISC))
+ "nop"
+ (+ OP1_7 OP2_0 (f-r1 0) (f-r2 0))
+ (c-code VOID "PROFILE_COUNT_FILLNOPS (current_cpu, abuf->addr);\n")
+ ; FIXME: quick hack: parallel nops don't contribute to cycle count.
+ ; Other kinds of nops do however (which we currently ignore).
+ ((m32r/d (unit u-exec (cycles 0)))
+ (m32rx (unit u-exec (cycles 0))))
+)
+
+(dni not "not"
+ ((PIPE OS) (IDOC ALU))
+ "not $dr,$sr"
+ (+ OP1_0 OP2_11 dr sr)
+ (set dr (inv sr))
+ ()
+)
+
+(dni rac "rac"
+ ((MACH m32r) (PIPE S) (IDOC MAC))
+ "rac"
+ (+ OP1_5 OP2_9 (f-r1 0) (f-r2 0))
+ (sequence ((DI tmp1))
+ (set tmp1 (sll DI accum (const 1)))
+ (set tmp1 (add DI tmp1 (const DI #x8000)))
+ (set accum
+ (cond DI
+ ((gt tmp1 (const DI #x00007fffffff0000))
+ (const DI #x00007fffffff0000))
+ ((lt tmp1 (const DI #xffff800000000000))
+ (const DI #xffff800000000000))
+ (else (and tmp1 (const DI #xffffffffffff0000)))))
+ )
+ ((m32r/d (unit u-mac)))
+)
+
+(dni rac-dsi "rac-dsi"
+ ((MACH m32rx) (PIPE S) (IDOC MAC))
+ "rac $accd,$accs,$imm1"
+ (+ OP1_5 accd (f-bits67 0) OP2_9 accs (f-bit14 0) imm1)
+ (sequence ((DI tmp1))
+ (set tmp1 (sll accs imm1))
+ (set tmp1 (add tmp1 (const DI #x8000)))
+ (set accd
+ (cond DI
+ ((gt tmp1 (const DI #x00007fffffff0000))
+ (const DI #x00007fffffff0000))
+ ((lt tmp1 (const DI #xffff800000000000))
+ (const DI #xffff800000000000))
+ (else (and tmp1 (const DI #xffffffffffff0000)))))
+ )
+ ((m32rx (unit u-mac)))
+)
+
+(dnmi rac-d "rac-d"
+ ((MACH m32rx) (PIPE S) (IDOC MAC))
+ "rac $accd"
+ (emit rac-dsi accd (f-accs 0) (f-imm1 0))
+)
+
+(dnmi rac-ds "rac-ds"
+ ((MACH m32rx) (PIPE S) (IDOC MAC))
+ "rac $accd,$accs"
+ (emit rac-dsi accd accs (f-imm1 0))
+)
+
+
+(dni rach "rach"
+ ((MACH m32r) (PIPE S) (IDOC MAC))
+ "rach"
+ (+ OP1_5 OP2_8 (f-r1 0) (f-r2 0))
+ (sequence ((DI tmp1))
+ ; Lop off top 8 bits.
+ ; The sign bit we want to use is bit 55 so the 64 bit value
+ ; isn't properly signed which we deal with in the if's below.
+ (set tmp1 (and accum (const DI #xffffffffffffff)))
+ (if (andif (ge tmp1 (const DI #x003fff80000000))
+ (le tmp1 (const DI #x7fffffffffffff)))
+ (set tmp1 (const DI #x003fff80000000))
+ ; else part
+ (if (andif (ge tmp1 (const DI #x80000000000000))
+ (le tmp1 (const DI #xffc00000000000)))
+ (set tmp1 (const DI #xffc00000000000))
+ (set tmp1 (and (add accum (const DI #x40000000))
+ (const DI #xffffffff80000000)))))
+ (set tmp1 (sll tmp1 (const 1)))
+ ; Sign extend top 8 bits.
+ (set accum
+ ; FIXME: 7?
+ (sra DI (sll DI tmp1 (const 7)) (const 7)))
+ )
+ ((m32r/d (unit u-mac)))
+)
+
+(dni rach-dsi "rach-dsi"
+ ((MACH m32rx) (PIPE S) (IDOC MAC))
+ "rach $accd,$accs,$imm1"
+ (+ OP1_5 accd (f-bits67 0) OP2_8 accs (f-bit14 0) imm1)
+ (sequence ((DI tmp1))
+ (set tmp1 (sll accs imm1))
+ (set tmp1 (add tmp1 (const DI #x80000000)))
+ (set accd
+ (cond DI
+ ((gt tmp1 (const DI #x00007fff00000000))
+ (const DI #x00007fff00000000))
+ ((lt tmp1 (const DI #xffff800000000000))
+ (const DI #xffff800000000000))
+ (else (and tmp1 (const DI #xffffffff00000000)))))
+ )
+ ((m32rx (unit u-mac)))
+)
+
+(dnmi rach-d "rach-d"
+ ((MACH m32rx) (PIPE S) (IDOC MAC))
+ "rach $accd"
+ (emit rach-dsi accd (f-accs 0) (f-imm1 0))
+)
+
+(dnmi rach-ds "rach-ds"
+ ((MACH m32rx) (PIPE S) (IDOC MAC))
+ "rach $accd,$accs"
+ (emit rach-dsi accd accs (f-imm1 0))
+)
+
+(dni rte "rte"
+ (UNCOND-CTI (PIPE O) (IDOC BR))
+ "rte"
+ (+ OP1_1 OP2_13 (f-r1 0) (f-r2 6))
+ (sequence ()
+ ; pc = bpc & -4
+ (set pc (and (reg h-cr 6) (const -4)))
+ ; bpc = bbpc
+ (set (reg h-cr 6) (reg h-cr 14))
+ ; psw = bpsw
+ (set (reg h-psw) (reg h-bpsw))
+ ; bpsw = bbpsw
+ (set (reg h-bpsw) (reg h-bbpsw))
+ )
+ ()
+)
+
+(dni seth "seth"
+ ((IDOC ALU))
+ "seth $dr,$hash$hi16"
+ (+ OP1_13 OP2_12 dr (f-r2 0) hi16)
+ (set dr (sll WI hi16 (const 16)))
+ ()
+)
+
+(define-pmacro (shift-op sym op2-r-op op2-3-op op2-i-op sem-op)
+ (begin
+ (dni sym sym ((PIPE O) (IDOC ALU))
+ (.str sym " $dr,$sr")
+ (+ OP1_1 op2-r-op dr sr)
+ (set dr (sem-op dr (and sr (const 31))))
+ ()
+ )
+ (dni (.sym sym "3") sym ((IDOC ALU))
+ (.str sym "3 $dr,$sr,$simm16")
+ (+ OP1_9 op2-3-op dr sr simm16)
+ (set dr (sem-op sr (and WI simm16 (const 31))))
+ ()
+ )
+ (dni (.sym sym "i") sym ((PIPE O) (IDOC ALU))
+ (.str sym "i $dr,$uimm5")
+ (+ OP1_5 (f-shift-op2 op2-i-op) dr uimm5)
+ (set dr (sem-op dr uimm5))
+ ()
+ )
+ )
+)
+(shift-op sll OP2_4 OP2_12 2 sll)
+(shift-op sra OP2_2 OP2_10 1 sra)
+(shift-op srl OP2_0 OP2_8 0 srl)
+
+(define-pmacro (store-op suffix op2-op mode)
+ (begin
+ (dni (.sym st suffix) (.str "st" suffix)
+ ((PIPE O) (IDOC MEM))
+ (.str "st" suffix " $src1,@$src2")
+ (+ OP1_2 op2-op src1 src2)
+ (set mode (mem mode src2) src1)
+ ((m32r/d (unit u-store (cycles 1)))
+ (m32rx (unit u-store (cycles 1))))
+ )
+ (dnmi (.sym st suffix "-2") (.str "st" suffix "-2")
+ (NO-DIS (PIPE O) (IDOC MEM))
+ (.str "st" suffix " $src1,@($src2)")
+ (emit (.sym st suffix) src1 src2))
+ (dni (.sym st suffix -d) (.str "st" suffix "-d")
+ ((IDOC MEM))
+ (.str "st" suffix " $src1,@($slo16,$src2)")
+ (+ OP1_10 op2-op src1 src2 slo16)
+ (set mode (mem mode (add src2 slo16)) src1)
+ ((m32r/d (unit u-store (cycles 2)))
+ (m32rx (unit u-store (cycles 2))))
+ )
+ (dnmi (.sym st suffix -d2) (.str "st" suffix "-d2")
+ (NO-DIS (IDOC MEM))
+ (.str "st" suffix " $src1,@($src2,$slo16)")
+ (emit (.sym st suffix -d) src1 src2 slo16))
+ )
+)
+(store-op "" OP2_4 WI)
+(store-op b OP2_0 QI)
+(store-op h OP2_2 HI)
+
+(dni st-plus "st+"
+ ((PIPE O) (IDOC MEM))
+ "st $src1,@+$src2"
+ (+ OP1_2 OP2_6 src1 src2)
+ ; This has to be coded carefully to avoid an "earlyclobber" of src2.
+ (sequence ((WI new-src2))
+ (set new-src2 (add WI src2 (const WI 4)))
+ (set (mem WI new-src2) src1)
+ (set src2 new-src2))
+ ((m32r/d (unit u-store)
+ (unit u-exec (in dr src2) (out dr src2) (cycles 0)))
+ (m32rx (unit u-store)
+ (unit u-exec (in dr src2) (out dr src2) (cycles 0)))
+ )
+)
+
+(dni st-minus "st-"
+ ((PIPE O) (IDOC MEM))
+ "st $src1,@-$src2"
+ (+ OP1_2 OP2_7 src1 src2)
+ ; This is the original way. It doesn't work for parallel execution
+ ; because of the earlyclobber of src2.
+ ;(sequence ()
+ ; (set src2 (sub src2 (const 4)))
+ ; (set (mem WI src2) src1))
+ (sequence ((WI new-src2))
+ (set new-src2 (sub src2 (const 4)))
+ (set (mem WI new-src2) src1)
+ (set src2 new-src2))
+ ((m32r/d (unit u-store)
+ (unit u-exec (in dr src2) (out dr src2) (cycles 0)))
+ (m32rx (unit u-store)
+ (unit u-exec (in dr src2) (out dr src2) (cycles 0)))
+ )
+)
+
+(dnmi push "push" ((IDOC MEM))
+ "push $src1"
+ (emit st-minus src1 (src2 15)) ; "st %0,@-sp"
+)
+
+(dni sub "sub"
+ ((PIPE OS) (IDOC ALU))
+ "sub $dr,$sr"
+ (+ OP1_0 OP2_2 dr sr)
+ (set dr (sub dr sr))
+ ()
+)
+
+(dni subv "sub:rv"
+ ((PIPE OS) (IDOC ALU))
+ "subv $dr,$sr"
+ (+ OP1_0 OP2_0 dr sr)
+ (parallel ()
+ (set dr (sub dr sr))
+ (set condbit (sub-oflag dr sr (const 0))))
+ ()
+)
+
+(dni subx "sub:rx"
+ ((PIPE OS) (IDOC ALU))
+ "subx $dr,$sr"
+ (+ OP1_0 OP2_1 dr sr)
+ (parallel ()
+ (set dr (subc dr sr condbit))
+ (set condbit (sub-cflag dr sr condbit)))
+ ()
+)
+
+(dni trap "trap"
+ (UNCOND-CTI FILL-SLOT (PIPE O) (IDOC MISC))
+ "trap $uimm4"
+ (+ OP1_1 OP2_15 (f-r1 0) uimm4)
+ (sequence ()
+ ; bbpc = bpc
+ (set (reg h-cr 14) (reg h-cr 6))
+ ; Set bpc to the return address. Actually it's not quite the
+ ; return address as RTE rounds the address down to a word
+ ; boundary.
+ (set (reg h-cr 6) (add pc (const 4)))
+ ; bbpsw = bpsw
+ (set (reg h-bbpsw) (reg h-bpsw))
+ ; bpsw = psw
+ (set (reg h-bpsw) (reg h-psw))
+ ; sm is unchanged, ie,c are set to zero.
+ (set (reg h-psw) (and (reg h-psw) (const #x80)))
+ ; m32r_trap handles operating vs user mode
+ (set WI pc (c-call WI "m32r_trap" pc uimm4))
+ )
+ ()
+)
+
+(dni unlock "unlock"
+ ((PIPE O) (IDOC MISC))
+ "unlock $src1,@$src2"
+ (+ OP1_2 OP2_5 src1 src2)
+ (sequence ()
+ (if (reg h-lock)
+ (set (mem WI src2) src1))
+ (set (reg h-lock) (const BI 0)))
+ ((m32r/d (unit u-load))
+ (m32rx (unit u-load)))
+)
+
+; Saturate into byte.
+(dni satb "satb"
+ ((MACH m32rx) (IDOC ALU))
+ "satb $dr,$sr"
+ (+ OP1_8 dr OP2_6 sr (f-uimm16 #x0300))
+ (set dr
+ ; FIXME: min/max would simplify this nicely of course.
+ (cond WI
+ ((ge sr (const 127)) (const 127))
+ ((le sr (const -128)) (const -128))
+ (else sr)))
+ ()
+)
+
+; Saturate into half word.
+(dni sath "sath"
+ ((MACH m32rx) (IDOC ALU))
+ "sath $dr,$sr"
+ (+ OP1_8 dr OP2_6 sr (f-uimm16 #x0200))
+ (set dr
+ (cond WI
+ ((ge sr (const 32767)) (const 32767))
+ ((le sr (const -32768)) (const -32768))
+ (else sr)))
+ ()
+)
+
+; Saturate word.
+(dni sat "sat"
+ ((MACH m32rx) SPECIAL (IDOC ALU))
+ "sat $dr,$sr"
+ (+ OP1_8 dr OP2_6 sr (f-uimm16 0))
+ (set dr
+ (if WI condbit
+ (if WI (lt sr (const 0))
+ (const #x7fffffff)
+ (const #x80000000))
+ sr))
+ ()
+)
+
+; Parallel compare byte zeros.
+; Set C bit in condition register if any byte in source register is zero.
+(dni pcmpbz "pcmpbz"
+ ((MACH m32rx) (PIPE OS) SPECIAL (IDOC ALU))
+ "pcmpbz $src2"
+ (+ OP1_0 (f-r1 3) OP2_7 src2)
+ (set condbit
+ (cond BI
+ ((eq (and src2 (const #xff)) (const 0)) (const BI 1))
+ ((eq (and src2 (const #xff00)) (const 0)) (const BI 1))
+ ((eq (and src2 (const #xff0000)) (const 0)) (const BI 1))
+ ((eq (and src2 (const #xff000000)) (const 0)) (const BI 1))
+ (else (const BI 0))))
+ ((m32rx (unit u-cmp)))
+)
+
+; Add accumulators
+(dni sadd "sadd"
+ ((MACH m32rx) (PIPE S) (IDOC ACCUM))
+ "sadd"
+ (+ OP1_5 (f-r1 0) OP2_14 (f-r2 4))
+ (set (reg h-accums 0)
+ (add (sra (reg h-accums 1) (const 16))
+ (reg h-accums 0)))
+ ((m32rx (unit u-mac)))
+)
+
+; Multiply and add into accumulator 1
+(dni macwu1 "macwu1"
+ ((MACH m32rx) (PIPE S) (IDOC MAC))
+ "macwu1 $src1,$src2"
+ (+ OP1_5 src1 OP2_11 src2)
+ (set (reg h-accums 1)
+ (sra DI
+ (sll DI
+ (add DI
+ (reg h-accums 1)
+ (mul DI
+ (ext DI src1)
+ (ext DI (and src2 (const #xffff)))))
+ (const 8))
+ (const 8)))
+ ((m32rx (unit u-mac)))
+)
+
+; Multiply and subtract from accumulator 0
+(dni msblo "msblo"
+ ((MACH m32rx) (PIPE S) (IDOC MAC))
+ "msblo $src1,$src2"
+ (+ OP1_5 src1 OP2_13 src2)
+ (set accum
+ (sra DI
+ (sll DI
+ (sub accum
+ (sra DI
+ (sll DI
+ (mul DI
+ (ext DI (trunc HI src1))
+ (ext DI (trunc HI src2)))
+ (const 32))
+ (const 16)))
+ (const 8))
+ (const 8)))
+ ((m32rx (unit u-mac)))
+)
+
+; Multiply into accumulator 1
+(dni mulwu1 "mulwu1"
+ ((MACH m32rx) (PIPE S) (IDOC MAC))
+ "mulwu1 $src1,$src2"
+ (+ OP1_5 src1 OP2_10 src2)
+ (set (reg h-accums 1)
+ (sra DI
+ (sll DI
+ (mul DI
+ (ext DI src1)
+ (ext DI (and src2 (const #xffff))))
+ (const 16))
+ (const 16)))
+ ((m32rx (unit u-mac)))
+)
+
+; Multiply and add into accumulator 1
+(dni maclh1 "maclh1"
+ ((MACH m32rx) (PIPE S) (IDOC MAC))
+ "maclh1 $src1,$src2"
+ (+ OP1_5 src1 OP2_12 src2)
+ (set (reg h-accums 1)
+ (sra DI
+ (sll DI
+ (add DI
+ (reg h-accums 1)
+ (sll DI
+ (ext DI
+ (mul SI
+ (ext SI (trunc HI src1))
+ (sra SI src2 (const SI 16))))
+ (const 16)))
+ (const 8))
+ (const 8)))
+ ((m32rx (unit u-mac)))
+)
+
+; skip instruction if C
+(dni sc "sc"
+ ((MACH m32rx) (PIPE O) SPECIAL (IDOC BR))
+ "sc"
+ (+ OP1_7 (f-r1 4) OP2_0 (f-r2 1))
+ (skip (zext INT condbit))
+ ()
+)
+
+; skip instruction if not C
+(dni snc "snc"
+ ((MACH m32rx) (PIPE O) SPECIAL (IDOC BR))
+ "snc"
+ (+ OP1_7 (f-r1 5) OP2_0 (f-r2 1))
+ (skip (zext INT (not condbit)))
+ ()
+)
diff --git a/cpu/m32r.opc b/cpu/m32r.opc
new file mode 100644
index 0000000..dbb6f1d
--- /dev/null
+++ b/cpu/m32r.opc
@@ -0,0 +1,302 @@
+/* M32R opcode support. -*- C -*-
+
+ Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+
+ Contributed by Red Hat Inc; developed under contract from
+ Mitsubishi Electric Corporation.
+
+ This file is part of the GNU Binutils.
+
+ Contributed by Red Hat Inc; developed under contract from Fujitsu.
+
+ This file is part of the GNU Binutils.
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+
+/* This file is an addendum to m32r.cpu. Heavy use of C code isn't
+ appropriate in .cpu files, so it resides here. This especially applies
+ to assembly/disassembly where parsing/printing can be quite involved.
+ Such things aren't really part of the specification of the cpu, per se,
+ so .cpu files provide the general framework and .opc files handle the
+ nitty-gritty details as necessary.
+
+ Each section is delimited with start and end markers.
+
+ <arch>-opc.h additions use: "-- opc.h"
+ <arch>-opc.c additions use: "-- opc.c"
+ <arch>-asm.c additions use: "-- asm.c"
+ <arch>-dis.c additions use: "-- dis.c"
+ <arch>-ibd.h additions use: "-- ibd.h"
+*/
+
+/* -- opc.h */
+
+#undef CGEN_DIS_HASH_SIZE
+#define CGEN_DIS_HASH_SIZE 256
+#undef CGEN_DIS_HASH
+#define X(b) (((unsigned char *) (b))[0] & 0xf0)
+#define CGEN_DIS_HASH(buffer, value) \
+(X (buffer) | \
+ (X (buffer) == 0x40 || X (buffer) == 0xe0 || X (buffer) == 0x60 || X (buffer) == 0x50 ? 0 \
+ : X (buffer) == 0x70 || X (buffer) == 0xf0 ? (((unsigned char *) (buffer))[0] & 0xf) \
+ : X (buffer) == 0x30 ? ((((unsigned char *) (buffer))[1] & 0x70) >> 4) \
+ : ((((unsigned char *) (buffer))[1] & 0xf0) >> 4)))
+
+/* -- */
+
+/* -- asm.c */
+static const char * parse_hash
+ PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
+static const char * parse_hi16
+ PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
+static const char * parse_slo16
+ PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
+static const char * parse_ulo16
+ PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
+
+/* Handle '#' prefixes (i.e. skip over them). */
+
+static const char *
+parse_hash (cd, strp, opindex, valuep)
+ CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
+ const char **strp;
+ int opindex ATTRIBUTE_UNUSED;
+ unsigned long *valuep ATTRIBUTE_UNUSED;
+{
+ if (**strp == '#')
+ ++*strp;
+ return NULL;
+}
+
+/* Handle shigh(), high(). */
+
+static const char *
+parse_hi16 (cd, strp, opindex, valuep)
+ CGEN_CPU_DESC cd;
+ const char **strp;
+ int opindex;
+ unsigned long *valuep;
+{
+ const char *errmsg;
+ enum cgen_parse_operand_result result_type;
+ bfd_vma value;
+
+ if (**strp == '#')
+ ++*strp;
+
+ if (strncasecmp (*strp, "high(", 5) == 0)
+ {
+ *strp += 5;
+ errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_ULO,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing `)'";
+ ++*strp;
+ if (errmsg == NULL
+ && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
+ value >>= 16;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp, "shigh(", 6) == 0)
+ {
+ *strp += 6;
+ errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_SLO,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing `)'";
+ ++*strp;
+ if (errmsg == NULL
+ && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
+ value = (value >> 16) + (value & 0x8000 ? 1 : 0);
+ *valuep = value;
+ return errmsg;
+ }
+
+ return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
+}
+
+/* Handle low() in a signed context. Also handle sda().
+ The signedness of the value doesn't matter to low(), but this also
+ handles the case where low() isn't present. */
+
+static const char *
+parse_slo16 (cd, strp, opindex, valuep)
+ CGEN_CPU_DESC cd;
+ const char **strp;
+ int opindex;
+ long *valuep;
+{
+ const char *errmsg;
+ enum cgen_parse_operand_result result_type;
+ bfd_vma value;
+
+ if (**strp == '#')
+ ++*strp;
+
+ if (strncasecmp (*strp, "low(", 4) == 0)
+ {
+ *strp += 4;
+ errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing `)'";
+ ++*strp;
+ if (errmsg == NULL
+ && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
+ value &= 0xffff;
+ *valuep = value;
+ return errmsg;
+ }
+
+ if (strncasecmp (*strp, "sda(", 4) == 0)
+ {
+ *strp += 4;
+ errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_SDA16,
+ NULL, &value);
+ if (**strp != ')')
+ return "missing `)'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+
+ return cgen_parse_signed_integer (cd, strp, opindex, valuep);
+}
+
+/* Handle low() in an unsigned context.
+ The signedness of the value doesn't matter to low(), but this also
+ handles the case where low() isn't present. */
+
+static const char *
+parse_ulo16 (cd, strp, opindex, valuep)
+ CGEN_CPU_DESC cd;
+ const char **strp;
+ int opindex;
+ unsigned long *valuep;
+{
+ const char *errmsg;
+ enum cgen_parse_operand_result result_type;
+ bfd_vma value;
+
+ if (**strp == '#')
+ ++*strp;
+
+ if (strncasecmp (*strp, "low(", 4) == 0)
+ {
+ *strp += 4;
+ errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing `)'";
+ ++*strp;
+ if (errmsg == NULL
+ && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
+ value &= 0xffff;
+ *valuep = value;
+ return errmsg;
+ }
+
+ return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
+}
+
+/* -- */
+
+/* -- dis.c */
+static void print_hash PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
+static int my_print_insn PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *));
+
+/* Immediate values are prefixed with '#'. */
+
+#define CGEN_PRINT_NORMAL(cd, info, value, attrs, pc, length) \
+ do \
+ { \
+ if (CGEN_BOOL_ATTR ((attrs), CGEN_OPERAND_HASH_PREFIX)) \
+ (*info->fprintf_func) (info->stream, "#"); \
+ } \
+ while (0)
+
+/* Handle '#' prefixes as operands. */
+
+static void
+print_hash (cd, dis_info, value, attrs, pc, length)
+ CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
+ PTR dis_info;
+ long value ATTRIBUTE_UNUSED;
+ unsigned int attrs ATTRIBUTE_UNUSED;
+ bfd_vma pc ATTRIBUTE_UNUSED;
+ int length ATTRIBUTE_UNUSED;
+{
+ disassemble_info *info = (disassemble_info *) dis_info;
+ (*info->fprintf_func) (info->stream, "#");
+}
+
+#undef CGEN_PRINT_INSN
+#define CGEN_PRINT_INSN my_print_insn
+
+static int
+my_print_insn (cd, pc, info)
+ CGEN_CPU_DESC cd;
+ bfd_vma pc;
+ disassemble_info *info;
+{
+ char buffer[CGEN_MAX_INSN_SIZE];
+ char *buf = buffer;
+ int status;
+ int buflen = (pc & 3) == 0 ? 4 : 2;
+
+ /* Read the base part of the insn. */
+
+ status = (*info->read_memory_func) (pc, buf, buflen, info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, pc, info);
+ return -1;
+ }
+
+ /* 32 bit insn? */
+ if ((pc & 3) == 0 && (buf[0] & 0x80) != 0)
+ return print_insn (cd, pc, info, buf, buflen);
+
+ /* Print the first insn. */
+ if ((pc & 3) == 0)
+ {
+ if (print_insn (cd, pc, info, buf, 2) == 0)
+ (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
+ buf += 2;
+ }
+
+ if (buf[0] & 0x80)
+ {
+ /* Parallel. */
+ (*info->fprintf_func) (info->stream, " || ");
+ buf[0] &= 0x7f;
+ }
+ else
+ (*info->fprintf_func) (info->stream, " -> ");
+
+ /* The "& 3" is to pass a consistent address.
+ Parallel insns arguably both begin on the word boundary.
+ Also, branch insns are calculated relative to the word boundary. */
+ if (print_insn (cd, pc & ~ (bfd_vma) 3, info, buf, 2) == 0)
+ (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
+
+ return (pc & 3) ? 2 : 4;
+}
+
+/* -- */