fuzz update/node/lib/metasm/metasm/cpu/sh4/opcodes.rb
#    This file is part of Metasm, the Ruby assembly manipulation suite
#    Copyright (C) 2006-2010 Yoann GUILLOT
#
#    Licence is LGPL, see LICENCE in the top-level directory

require 'metasm/cpu/sh4/main'

module Metasm
class Sh4
	def addop(name, bin, *args)
		o = Opcode.new name, bin

		args.each { |a|
			o.args << a if @fields_mask[a]
			o.props[a] = true if @valid_props[a]
			o.fields[a] = [@fields_mask[a], @fields_shift[a]] if @fields_mask[a]
		}

		@opcode_list << o
	end

	def init
		@opcode_list = []

		# :@rm_ is used for @Rm+
		# :@_rn is used for @-Rn
		# :@r0rm is used for @(R0, Rm) (same for r0rn)
		# :@r0gbr is used for @(R0, GBR)
		@fields_mask = {
			:rm => 0xf, :rn => 0xf,
			:@rm => 0xf, :@rn => 0xf,
			:@rm_ => 0xf, :@rn_ => 0xf,
			:@_rn => 0xf,

			:frm => 0xf, :frn => 0xf,
			:xdm => 0x7, :xdn => 0x7,
			:drm => 0x7, :drn => 0x7,
			:fvm => 0x3, :fvn => 0x3,

			:@r0rm => 0xf, :@r0rn => 0xf,
			:rm_bank => 0x7, :rn_bank => 0x7,

			:@disprm => 0xff, :@dispr0rn => 0xff, :@disprmrn => 0xf0f,
			:@dispgbr => 0xff, :@disppc => 0xff,
			:disp8 => 0xff, :disp12 => 0xfff, :disppc => 0xff,

			:i8 => 0xff, # zero-extendded 8-bit immediate
			:s8 => 0xff, # 8-bit displacement s is sign-extended, doubled and added to PC+4
		}

		@fields_shift = {
			:rm => 4, :rn => 8,
			:@rm => 4, :@rn => 8,
			:@rm_ => 4, :@rn_ => 8,
			:@_rn => 8,

			:frm => 4, :frn => 8,
			:xdm => 5, :xdn => 9,
			:drm => 5, :drn => 9,
			:fvm => 8, :fvn => 10,

			:@r0rm => 4, :@r0rn => 8,
			:rm_bank => 7, :rn_bank => 4,

			:@disprm => 0, :@dispr0rn => 0, :@disprmrn => 0,
			:@dispgbr => 0, :@disppc => 0,
			:disp8 => 0, :disp12 => 0, :disppc => 0,

			:i8 => 0,
			:s8 => 0,
		}

		# implicit operands
		[:vbr, :gbr, :sr, :ssr, :spc, :sgr, :dbr, :mach, :macl, :pr, :fpul, :fpscr, :dbr, :pc, :r0].each { |a| @fields_mask[a] = @fields_shift[a] = 0 }

		@valid_props[:delay_slot] = true

		addop 'add', 0b0011 << 12 | 0b1100, :rm, :rn
		addop 'add', 0b0111 << 12, :s8, :rn
		addop 'addc', 0b0011 << 12 | 0b1110, :rm, :rn
		addop 'addv', 0b0011 << 12 | 0b1111, :rm, :rn

		addop 'and', 0b0010 << 12 | 0b1001, :rm, :rn
		addop 'and', 0b11001001 << 8, :i8, :r0
		addop 'and.b', 0b11001101 << 8, :i8, :@r0gbr

		addop 'bf', 0b10001011 << 8, :disp8, :setip
		addop 'bf/s', 0b10001111 << 8, :disp8, :setip, :delay_slot
		addop 'bra', 0b1010 << 12, :disp12, :setip, :stopexec, :delay_slot
		addop 'braf', 0b0000 << 12 | 0b00100011, :rn, :setip, :stopexec, :delay_slot
		addop 'brk', 0b0000000000111011, :stopexec  # causes a pre-execution BREAK exception
		addop 'bsr', 0b1011 << 12, :disp12, :setip, :saveip, :stopexec, :delay_slot
		addop 'bsrf', 0b0000 << 12 | 0b00000011, :rn, :setip, :saveip, :stopexec, :delay_slot
		addop 'bt', 0b10001001 << 8, :disp8, :setip
		addop 'bt/s', 0b10001101 << 8, :disp8, :setip, :delay_slot

		addop 'clrmac', 0b0000000000101000
		addop 'clrs', 0b0000000001001000
		addop 'clrt', 0b0000000000001000

		addop 'cmp/eq', 0b0011 << 12 | 0b0000, :rm, :rn
		addop 'cmp/eq', 0b10001000 << 8, :s8, :r0
		addop 'cmp/ge', 0b0011 << 12 | 0b0011, :rm, :rn
		addop 'cmp/gt', 0b0011 << 12 | 0b0111, :rm, :rn
		addop 'cmp/hi', 0b0011 << 12 | 0b0110, :rm, :rn
		addop 'cmp/hs', 0b0011 << 12 | 0b0010, :rm, :rn
		addop 'cmp/pl', 0b0100 << 12 | 0b00010101, :rn
		addop 'cmp/pz', 0b0100 << 12 | 0b00010001, :rn
		addop 'cmp/str', 0b0010 << 12 | 0b1100, :rm, :rn

		addop 'div0s', 0b0010 << 12 | 0b0111, :rm, :rn
		addop 'div0u', 0b0000000000011001
		addop 'div1', 0b0011 << 12 | 0b0100, :rm, :rn

		addop 'dmuls.l', 0b0011 << 12 | 0b1101, :rm, :rn
		addop 'dmulu.l', 0b0011 << 12 | 0b0101, :rm, :rn

		addop 'dt', 0b0100 << 12 | 0b00010000, :rn

		addop 'exts.b', 0b0110 << 12 | 0b1110, :rm, :rn
		addop 'exts.w', 0b0110 << 12 | 0b1111, :rm, :rn
		addop 'extu.b', 0b0110 << 12 | 0b1100, :rm, :rn
		addop 'extu.w', 0b0110 << 12 | 0b1101, :rm, :rn

		# fpu instructions
		addop 'fabs', 0b1111 << 12 | 0b001011101, :drn
		addop 'fabs', 0b1111 << 12 |  0b01011101, :frn

		addop 'fadd', 0b1111 << 12 | 0b0 << 8 | 0b00000, :drm, :drn
		addop 'fadd', 0b1111 << 12 | 0b0000, :frm, :frn

		addop 'fcmp/eq', 0b1111 << 12 | 0b0 << 8 | 0b00100, :drm, :drn
		addop 'fcmp/eq', 0b1111 << 12 | 0b0100, :frm, :frn

		addop 'fcmp/gt', 0b1111 << 12 | 0b0 << 8 | 0b00101, :drm, :drn
		addop 'fcmp/gt', 0b1111 << 12 | 0b0101, :frm, :frn

		addop 'fcnvds', 0b1111 << 12 | 0b010111101, :drn, :fpul
		addop 'fcnvsd', 0b1111 << 12 | 0b010101101, :fpul, :drn

		addop 'fdiv', 0b1111 << 12 | 0b0 << 8 | 0b00011, :drm, :drn
		addop 'fdiv', 0b1111 << 12 | 0b0011, :frm, :frn
		addop 'fipr', 0b1111 << 12 | 0b11101101, :fvm, :fvn

		addop 'flds', 0b1111 << 12 | 0b00011101, :frn, :fpul
		addop 'fldi0', 0b1111 << 12 | 0b10001101, :frn
		addop 'fldi1', 0b1111 << 12 | 0b10011101, :frn

		addop 'float', 0b1111 << 12 | 0b000101101, :fpul, :drn
		addop 'float', 0b1111 << 12 | 0b00101101, :fpul, :frn

		addop 'fmac', 0b1111 << 12 | 0b1110, :fr0, :frm, :frn

		addop 'fmov', 0b1111 << 12 | 0b0 << 8 | 0b01100, :drm, :drn
		addop 'fmov', 0b1111 << 12 | 0b1 << 8 | 0b01100, :drm, :xdn
		addop 'fmov', 0b1111 << 12 | 0b01010, :drm, :@rn
		addop 'fmov', 0b1111 << 12 | 0b01011, :drm, :@_rn
		addop 'fmov', 0b1111 << 12 | 0b00111, :drm, :@r0rn

		addop 'fmov.s', 0b1111 << 12 | 0b1100, :frm, :frn
		addop 'fmov.s', 0b1111 << 12 | 0b1010, :frm, :@rn
		addop 'fmov.s', 0b1111 << 12 | 0b1011, :frm, :@_rn
		addop 'fmov.s', 0b1111 << 12 | 0b0111, :frm, :@r0rn

		addop 'fmov', 0b1111 << 12 | 0b0 << 8 | 0b11100, :xdm, :drn
		addop 'fmov', 0b1111 << 12 | 0b1 << 8 | 0b11100, :xdm, :xdn
		addop 'fmov', 0b1111 << 12 | 0b11010, :xdm, :@rn
		addop 'fmov', 0b1111 << 12 | 0b11011, :xdm, :@_rn
		addop 'fmov', 0b1111 << 12 | 0b10111, :xdm, :@r0rn

		addop 'fmov', 0b1111 << 12 | 0b0 << 8 | 0b1000, :@rm, :drn
		addop 'fmov', 0b1111 << 12 | 0b0 << 8 | 0b1001, :@rm_, :drn
		addop 'fmov', 0b1111 << 12 | 0b0 << 8 | 0b0110, :@r0rm, :drn

		addop 'fmov.s', 0b1111 << 12 | 0b1000, :@rm, :frn
		addop 'fmov.s', 0b1111 << 12 | 0b1001, :@rm_, :frn
		addop 'fmov.s', 0b1111 << 12 | 0b0110, :@r0rm, :frn

		addop 'fmov', 0b1111 << 12 | 0b1 << 8 | 0b1000, :@rm, :xdn
		addop 'fmov', 0b1111 << 12 | 0b1 << 8 | 0b1001, :@rm_, :xdn
		addop 'fmov', 0b1111 << 12 | 0b1 << 8 | 0b0110, :@r0rm, :xdn

		addop 'fmul', 0b1111 << 12 | 0b0 << 8 | 0b00010, :drm, :drn
		addop 'fmul', 0b1111 << 12 | 0b0010, :frm, :frn

		addop 'fneg', 0b1111 << 12 | 0b001001101, :drn
		addop 'fneg', 0b1111 << 12 | 0b01001101, :frn

		addop 'frchg', 0b1111101111111101
		addop 'fschg', 0b1111001111111101

		addop 'fsqrt', 0b1111 << 12 | 0b001101101, :drn
		addop 'fsqrt', 0b1111 << 12 | 0b01101101, :frn
		addop 'fsts', 0b1111 << 12 | 0b00001101, :fpul, :frn

		addop 'fsub', 0b1111 << 12 | 0b0 << 8 | 0b00001, :@drm, :drn
		addop 'fsub', 0b1111 << 12 | 0b0001, :frm, :frn

		addop 'ftrc', 0b1111 << 12 | 0b000111101, :drn, :fpul
		addop 'ftrc', 0b1111 << 12 | 0b00111101, :frn, :fpul
		addop 'ftrv', 0b1111 << 12 | 0b0111111101, :xmtrx, :fvn

		addop 'jmp', 0b0100 << 12 | 0b00101011, :rn, :setip, :stopexec, :delay_slot
		addop 'jsr', 0b0100 << 12 | 0b00001011, :rn, :setip, :saveip, :stopexec, :delay_slot

		addop 'ldc', 0b0100 << 12 | 0b00011110, :rn, :gbr
		addop 'ldc', 0b0100 << 12 | 0b00001110, :rn, :sr  # privileged instruction
		addop 'ldc', 0b0100 << 12 | 0b00101110, :rn, :vbr # privileged instruction
		addop 'ldc', 0b0100 << 12 | 0b00111110, :rn, :ssr # privileged instruction
		addop 'ldc', 0b0100 << 12 | 0b01001110, :rn, :spc # privileged instruction
		addop 'ldc', 0b0100 << 12 | 0b11111010, :rn, :dbr # privileged instruction
		addop 'ldc', 0b0100 << 12 | 0b1 << 7 | 0b1110, :rn, :rn_bank # privileged instruction

		addop 'ldc.l', 0b0100 << 12 | 0b00010111, :@rn_, :gbr
		addop 'ldc.l', 0b0100 << 12 | 0b00000111, :@rn_, :sr  # privileged instruction
		addop 'ldc.l', 0b0100 << 12 | 0b00100111, :@rn_, :vbr # privileged instruction
		addop 'ldc.l', 0b0100 << 12 | 0b00110111, :@rn_, :ssr # privileged instruction
		addop 'ldc.l', 0b0100 << 12 | 0b01000111, :@rn_, :spc # privileged instruction
		addop 'ldc.l', 0b0100 << 12 | 0b11110110, :@rn_, :dbr # privileged instruction
		addop 'ldc.l', 0b0100 << 12 | 0b1 << 7 | 0b0111, :@rn_, :rn_bank # privileged instruction

		addop 'lds', 0b0100 << 12 | 0b01101010, :rn, :fpscr
		addop 'lds.l', 0b0100 << 12 | 0b01100110, :@rn_, :fpscr
		addop 'lds', 0b0100 << 12 | 0b01011010, :rn, :fpul
		addop 'lds.l', 0b0100 << 12 | 0b01010110, :@rn_, :fpul
		addop 'lds', 0b0100 << 12 | 0b00001010, :rn, :mach
		addop 'lds.l', 0b0100 << 12 | 0b00000110, :@rn_, :mach
		addop 'lds', 0b0100 << 12 | 0b00011010, :rn, :macl
		addop 'lds.l', 0b0100 << 12 | 0b00010110, :@rn_, :macl
		addop 'lds', 0b0100 << 12 | 0b00101010, :rn, :pr
		addop 'lds.l', 0b0100 << 12 | 0b00100110, :@rn_, :pr

		addop 'ldtlb', 0b0000000000111000

		addop 'mac.l', 0b0000 << 12 | 0b1111, :@rm_, :@rn_
		addop 'mac.w', 0b0100 << 12 | 0b1111, :@rm_, :@rn_

		addop 'mov', 0b0110 << 12 | 0b0011, :rm, :rn
		addop 'mov', 0b1110 << 12, :s8, :rn

		addop 'mov.b', 0b0010 << 12 | 0b0000, :rm, :@rn
		addop 'mov.b', 0b0010 << 12 | 0b0100, :rm, :@_rn
		addop 'mov.b', 0b0000 << 12 | 0b0100, :rm, :@r0rn
		addop 'mov.b', 0b11000000 << 8, :r0, :@dispgbr
		addop 'mov.b', 0b10000000 << 8, :r0, :@dispr0rn
		addop 'mov.b', 0b0110 << 12 | 0b0000, :@rm, :rn
		addop 'mov.b', 0b0110 << 12 | 0b0100, :@rm_, :rn
		addop 'mov.b', 0b0000 << 12 | 0b1100, :@r0rm, :rn
		addop 'mov.b', 0b11000100 << 8, :@dispgbr, :r0
		addop 'mov.b', 0b10000100 << 8, :@dispr0rn, :r0

		addop 'mov.l', 0b0010 << 12 | 0b0010, :rm, :@rn
		addop 'mov.l', 0b0010 << 12 | 0b0110, :rm, :@_rn
		addop 'mov.l', 0b0000 << 12 | 0b0110, :rm, :@r0rn
		addop 'mov.l', 0b11000010 << 8, :r0, :@dispgbr
		addop 'mov.l', 0b0001 << 12, :rm, :@disprmrn
		addop 'mov.l', 0b0110 << 12 | 0b0010, :@rm, :rn
		addop 'mov.l', 0b0110 << 12 | 0b0110, :@rm_, :rn
		addop 'mov.l', 0b0000 << 12 | 0b1110, :@r0rm, :rn
		addop 'mov.l', 0b11000110 << 8, :@dispgbr, :r0
		addop 'mov.l', 0b1101 << 12, :@disppc, :rn
		addop 'mov.l', 0b0101 << 12, :@disprm, :rn

		addop 'mov.w', 0b0010 << 12 | 0b0001, :rm, :@rn
		addop 'mov.w', 0b0010 << 12 | 0b0101, :rm, :@_rn
		addop 'mov.w', 0b0000 << 12 | 0b0101, :rm, :@r0rn
		addop 'mov.w', 0b11000001 << 8, :r0, :@dispgbr
		addop 'mov.w', 0b10000001 << 8, :r0, :@dispr0rn
		addop 'mov.w', 0b0110 << 12 | 0b0001, :@rm, :rn
		addop 'mov.w', 0b0110 << 12 | 0b0101, :@rm_, :rn
		addop 'mov.w', 0b0000 << 12 | 0b1101, :@r0rm, :rn
		addop 'mov.w', 0b11000101 << 8, :@dispgbr, :r0
		addop 'mov.w', 0b1001 << 12, :@disppc, :rn
		addop 'mov.w', 0b10000101 << 8, :@disprm, :r0

		addop 'mova', 0b11000111 << 8, :disppc, :r0 # calculates an effective address using PC-relative with displacement addressing
		addop 'movca.l', 0b0000 << 12 | 11000011, :r0, :@rn # stores the long-word in R0 to memory at the effective address specified in Rn.

		addop 'movt', 0b0000 << 12 | 0b00101001, :rn # copies the T-bit to Rn

		addop 'mul.l', 0b0000 << 12 | 0b0111, :rm, :rn
		addop 'muls.w', 0b0010 << 12 | 0b1111, :rm, :rn
		addop 'mulu.w', 0b0010 << 12 | 0b1110, :rm, :rn

		addop 'neg', 0b0110 << 12 | 0b1011, :rm, :rn
		addop 'negc', 0b0110 << 12 | 0b1010, :rm, :rn

		addop 'nop', 0b0000000000001001

		addop 'not', 0b0110 << 12 | 0b0111, :rm, :rn

		addop 'ocbi', 0b0000 << 12 | 0b10010011, :@rn # invalidates an operand cache block
		addop 'ocbp', 0b0000 << 12 | 0b10100011, :@rn # purges an operand cache block
		addop 'ocbwb', 0b0000 << 12 | 0b10110011, :@rn # write-backs an operand cache block

		addop 'or', 0b0010 << 12 | 0b1011, :rm, :rn
		addop 'or', 0b11001011 << 8, :i8, :r0
		addop 'or.b', 0b11001111 << 8, :i8, :@r0gbr

		addop 'pref', 0b0000 | 0b10000011, :@rn # indicates a software-directed data prefetch

		addop 'rotcl', 0b0100 | 0b00100100, :rn
		addop 'rotcr', 0b0100 | 0b00100101, :rn
		addop 'rotl',  0b0100 | 0b00000100, :rn
		addop 'rotr',  0b0100 | 0b00000101, :rn

		addop 'rte', 0b0000000000101011, :setip, :stopexec, :delay_slot # returns from an exception or interrupt handling routine,  privileged instruction
		addop 'rts', 0b0000000000001011, :setip, :stopexec, :delay_slot # returns from a subroutine

		addop 'sets', 0b0000000001011000
		addop 'sett', 0b0000000000011000

		addop 'shad',   0b0100 << 12 | 0b1100, :rm, :rn
		addop 'shal',   0b0100 << 12 | 0b00100000, :rn
		addop 'shar',   0b0100 << 12 | 0b00100001, :rn
		addop 'shld',   0b0100 << 12 | 0b1101, :rm, :rn
		addop 'shll',   0b0100 << 12 | 0b00000000, :rn
		addop 'shll2',  0b0100 << 12 | 0b00001000, :rn
		addop 'shll8',  0b0100 << 12 | 0b00011000, :rn
		addop 'shll16', 0b0100 << 12 | 0b00101000, :rn
		addop 'shlr',   0b0100 << 12 | 0b00000001, :rn
		addop 'shlr2',  0b0100 << 12 | 0b00001001, :rn
		addop 'shlr8',  0b0100 << 12 | 0b00011001, :rn
		addop 'shlr16', 0b0100 << 12 | 0b00101001, :rn

		addop 'sleep', 0b0000000000011011 # privileged instruction

		addop 'stc', 0b0000 << 12 | 0b00000010, :sr, :rn
		addop 'stc', 0b0000 << 12 | 0b00100010, :vbr, :rn
		addop 'stc', 0b0000 << 12 | 0b00110010, :ssr, :rn
		addop 'stc', 0b0000 << 12 | 0b01000010, :spc, :rn
		addop 'stc', 0b0000 << 12 | 0b00111010, :sgr, :rn
		addop 'stc', 0b0000 << 12 | 0b11111010, :dbr, :rn
		addop 'stc', 0b0000 << 12 | 0b1 << 7 | 0b0010, :rm_bank, :@_rn
		addop 'stc', 0b0000 << 12 | 0b00010010, :gbr, :rn

		addop 'stc.l', 0b0100 << 12 | 0b00000011, :sr, :@_rn
		addop 'stc.l', 0b0100 << 12 | 0b00100011, :vbr, :@_rn
		addop 'stc.l', 0b0100 << 12 | 0b00110011, :ssr, :@_rn
		addop 'stc.l', 0b0100 << 12 | 0b01000011, :spc, :@_rn
		addop 'stc.l', 0b0100 << 12 | 0b00110010, :sgr, :@_rn
		addop 'stc.l', 0b0100 << 12 | 0b11110010, :dbr, :@_rn
		addop 'stc.l', 0b0100 << 12 | 0b1 << 7 | 0b0011, :rm_bank, :@_rn
		addop 'stc.l', 0b0100 << 12 | 0b00010011, :gbr, :@_rn

		addop 'sts',   0b0000 << 12 | 0b01101010, :fpscr, :rn
		addop 'sts.l', 0b0100 << 12 | 0b01100010, :fpscr, :@_rn
		addop 'sts',   0b0000 << 12 | 0b01011010, :fpul, :rn
		addop 'sts.l', 0b0100 << 12 | 0b01010010, :fpul, :@_rn
		addop 'sts',   0b0000 << 12 | 0b00001010, :mach, :rn
		addop 'sts.l', 0b0100 << 12 | 0b00000010, :mach, :@_rn
		addop 'sts',   0b0000 << 12 | 0b00011010, :macl, :rn
		addop 'sts.l', 0b0100 << 12 | 0b00010010, :macl, :@_rn
		addop 'sts',   0b0000 << 12 | 0b00101010, :pr, :rn
		addop 'sts.l', 0b0100 << 12 | 0b00100010, :pr, :@_rn

		addop 'sub', 0b0011 << 12 | 0b1000, :rm, :rn
		addop 'subc', 0b0011 << 12 | 0b1010, :rm, :rn
		addop 'subv', 0b0011 << 12 | 0b1011, :rm, :rn

		addop 'swap.b', 0b0110 << 12 | 0b1000, :rm, :rn
		addop 'swap.w', 0b0110 << 12 | 0b1001, :rm, :rn

		addop 'tas.b', 0b0100 << 12 | 0b00011011, :@rn
		addop 'trapa', 0b11000011 << 8, :i8, :setip, :stopexec # This instruction causes a pre-execution trap.

		addop 'tst', 0b0010 << 12 | 0b1000, :rm, :rn
		addop 'tst', 0b11001000 << 8, :i8, :r0
		addop 'tst.b', 0b11001100 << 8, :i8, :@r0gbr

		addop 'xor', 0b0010 << 12 | 0b1010, :rm, :rn
		addop 'xor', 0b11001010 << 8, :i8, :r0
		addop 'xob.b', 0b11001110 << 8, :i8, :@r0gbr

		addop 'xtrct', 0b0010 << 12 | 0b1101, :rm, :rn
	end

end

end
