# This file is part of Metasm, the Ruby assembly manipulation suite # Copyright (C) 2006-2009 Yoann GUILLOT # # Licence is LGPL, see LICENCE in the top-level directory require 'metasm/cpu/mips/main' # TODO coprocessors, floating point, 64bits, thumb mode module Metasm class MIPS 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] } @opcode_list << o end def init_mips32_obsolete addop 'beql', 0b010100 << 26, :rt, :rs, :i16, :setip # == , exec delay slot only if jump taken addop 'bnel', 0b010101 << 26, :rt, :rs, :i16, :setip # != addop 'blezl',0b010110 << 26, :rt_z, :rs, :i16, :setip # <= 0 addop 'bgtzl',0b010111 << 26, :rt_z, :rs, :i16, :setip # > 0 addop 'bltzl',1 << 26 | 0b00010 << 16, :rs, :i16, :setip addop 'bgezl',1 << 26 | 0b00011 << 16, :rs, :i16, :setip addop 'bltzall', 1 << 26 | 0b10010 << 16, :rs, :i16, :setip addop 'bgezall', 1 << 26 | 0b10011 << 16, :rs, :i16, :setip end def init_mips32_reserved addop 'future111011', 0b111011 << 26, :i26 %w[011000 011001 011010 011011 100111 101100 101101 110100 110111 111100 111111].each { |b| addop "reserved#{b}", b.to_i(2) << 26, :i26 } addop 'ase_jalx', 0b011101 << 26, :i26 addop 'ase011110', 0b011110 << 26, :i26 # TODO add all special/regimm/... end def init_mips32 @opcode_list = [] @fields_mask.update :rs => 0x1f, :rt => 0x1f, :rd => 0x1f, :sa => 0x1f, :i16 => 0xffff, :i26 => 0x3ffffff, :rs_i16 => 0x3e0ffff, :it => 0x1f, :ft => 0x1f, :idm1 => 0x1f, :idb => 0x1f, :sel => 7, :i20 => 0xfffff @fields_shift.update :rs => 21, :rt => 16, :rd => 11, :sa => 6, :i16 => 0, :i26 => 0, :rs_i16 => 0, :it => 16, :ft => 16, :idm1 => 11, :idb => 11, :sel => 0, :i20 => 6 @valid_props.update :mi8 => true, :mu8 => true, :mi16 => true, :mu16 => true init_mips32_obsolete init_mips32_reserved addop 'j', 0b000010 << 26, :i26, :setip, :stopexec # sets the program counter to (i26 << 2) | ((pc+4) & 0xfc000000) ie i26*4 in the 256M-aligned section containing the instruction in the delay slot addop 'jal', 0b000011 << 26, :i26, :setip, :stopexec, :saveip # same thing, saves return addr in r31 addop 'mov', 0b001000 << 26, :rt, :rs # rt <- rs+0 addop 'addi', 0b001000 << 26, :rt, :rs, :i16 # add rt <- rs+i addop 'li', 0b001001 << 26, :rt, :i16 # addiu rt <- zero+i addop 'addiu',0b001001 << 26, :rt, :rs, :i16 # add unsigned addop 'slti', 0b001010 << 26, :rt, :rs, :i16 # set on less than addop 'sltiu',0b001011 << 26, :rt, :rs, :i16 # set on less than unsigned addop 'andi', 0b001100 << 26, :rt, :rs, :i16 # and addop 'ori', 0b001101 << 26, :rt, :rs, :i16 # or addop 'xori', 0b001110 << 26, :rt, :rs, :i16 # xor addop 'lui', 0b001111 << 26, :rt, :i16 # load upper # addop 'li', (0b001111 << 26) << 32 | (0b001101 << 26), :rt_64, :i32 # lui + ori addop 'b', 0b000100 << 26, :i16, :setip, :stopexec # bz $zero addop 'bz', 0b000100 << 26, :rs, :i16, :setip # == 0 (beq $0) addop 'bz', 0b000100 << 26, :rt, :i16, :setip # == 0 addop 'bnz', 0b000101 << 26, :rs, :i16, :setip # != 0 addop 'bnz', 0b000101 << 26, :rt, :i16, :setip # != 0 addop 'beq', 0b000100 << 26, :rt, :rs, :i16, :setip # == addop 'bne', 0b000101 << 26, :rt, :rs, :i16, :setip # != addop 'blez', 0b000110 << 26, :rs, :i16, :setip # <= 0 addop 'bgtz', 0b000111 << 26, :rs, :i16, :setip # > 0 addop 'lb', 0b100000 << 26, :rt, :rs_i16, :mi8 # load byte rs <- [rt+i] addop 'lh', 0b100001 << 26, :rt, :rs_i16, :mi16 # load halfword addop 'lwl', 0b100010 << 26, :rt, :rs_i16 # load word left addop 'lw', 0b100011 << 26, :rt, :rs_i16 # load word addop 'lbu', 0b100100 << 26, :rt, :rs_i16, :mu8 # load byte unsigned addop 'lhu', 0b100101 << 26, :rt, :rs_i16, :mu16 # load halfword unsigned addop 'lwr', 0b100110 << 26, :rt, :rs_i16 # load word right addop 'sb', 0b101000 << 26, :rt, :rs_i16, :mi8 # store byte addop 'sh', 0b101001 << 26, :rt, :rs_i16, :mi16 # store halfword addop 'swl', 0b101010 << 26, :rt, :rs_i16 # store word left addop 'sw', 0b101011 << 26, :rt, :rs_i16 # store word addop 'swr', 0b101110 << 26, :rt, :rs_i16 # store word right addop 'll', 0b110000 << 26, :rt, :rs_i16 # load linked word (read for atomic r/modify/w, sc does the w) addop 'sc', 0b111000 << 26, :rt, :rs_i16 # store conditional word addop 'lwc1', 0b110001 << 26, :ft, :rs_i16 # load word in fpreg low addop 'swc1', 0b111001 << 26, :ft, :rs_i16 # store low fpreg word addop 'lwc2', 0b110010 << 26, :rt, :rs_i16 # load word to copro2 register low addop 'swc2', 0b111010 << 26, :rt, :rs_i16 # store low coproc2 register addop 'ldc1', 0b110101 << 26, :ft, :rs_i16 # load dword in fpreg low addop 'sdc1', 0b111101 << 26, :ft, :rs_i16 # store fpreg addop 'ldc2', 0b110110 << 26, :rt, :rs_i16 # load dword to copro2 register addop 'sdc2', 0b111110 << 26, :rt, :rs_i16 # store coproc2 register addop 'pref', 0b110011 << 26, :it, :rs_i16 # prefetch (it = %w[load store r2 r3 load_streamed store_streamed load_retained store_retained # r8 r9 r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 r20 r21 r22 r23 r24 writeback_invalidate # id26 id27 id28 id29 prepare_for_store id31] addop 'cache',0b101111 << 26, :it, :rs_i16 # do things with the proc cache # special addop 'nop', 0 addop 'ssnop',1<<6 addop 'ehb', 3<<6 addop 'sll', 0b000000, :rd, :rt, :sa addop 'movf', 0b000001, :rd, :rs, :cc addop 'movt', 0b000001 | (1<<16), :rd, :rs, :cc addop 'srl', 0b000010, :rd, :rt, :sa addop 'sra', 0b000011, :rd, :rt, :sa addop 'sllv', 0b000100, :rd, :rt, :rs addop 'srlv', 0b000110, :rd, :rt, :rs addop 'srav', 0b000111, :rd, :rt, :rs addop 'jr', 0b001000, :rs, :setip, :stopexec # hint field ? addop 'jr.hb',0b001000 | (1<<10), :rs, :setip, :stopexec addop 'jalr', 0b001001 | (31<<11), :rs, :setip, :stopexec, :saveip # rd = r31 implicit addop 'jalr', 0b001001, :rd, :rs, :setip, :stopexec, :saveip addop 'jalr.hb', 0b001001 | (1<<10) | (31<<11), :rs, :setip, :stopexec, :saveip addop 'jalr.hb', 0b001001 | (1<<10), :rd, :rs, :setip, :stopexec, :saveip addop 'movz', 0b001010, :rd, :rs, :rt # rt == 0 ? rd <- rs addop 'movn', 0b001011, :rd, :rs, :rt addop 'syscall', 0b001100, :i20 addop 'break',0b001101, :i20, :stopexec addop 'sync', 0b001111 # type 0 implicit addop 'sync', 0b001111, :sa addop 'mfhi', 0b010000, :rd # copies special reg HI to reg addop 'mthi', 0b010001, :rs # copies reg to special reg HI addop 'mflo', 0b010010, :rd # copies special reg LO to reg addop 'mtlo', 0b010011, :rs # copies reg to special reg LO addop 'mult', 0b011000, :rs, :rt # multiplies the registers and store the result in HI:LO addop 'multu',0b011001, :rs, :rt addop 'div', 0b011010, :rs, :rt addop 'divu', 0b011011, :rs, :rt addop 'add', 0b100000, :rd, :rs, :rt addop 'addu', 0b100001, :rd, :rs, :rt addop 'sub', 0b100010, :rd, :rs, :rt addop 'subu', 0b100011, :rd, :rs, :rt addop 'and', 0b100100, :rd, :rs, :rt addop 'or', 0b100101, :rd, :rs, :rt addop 'xor', 0b100110, :rd, :rs, :rt addop 'not', 0b100111, :rd, :rt # nor $0 addop 'not', 0b100111, :rd, :rs addop 'nor', 0b100111, :rd, :rs, :rt addop 'slt', 0b101010, :rd, :rs, :rt # rs= rt ? trap addop 'tgeu', 0b110001, :rs, :rt addop 'tlt', 0b110010, :rs, :rt addop 'tltu', 0b110011, :rs, :rt addop 'teq', 0b110100, :rs, :rt addop 'tne', 0b110110, :rs, :rt # regimm addop 'bltz', (1<<26) | (0b00000<<16), :rs, :i16, :setip addop 'bgez', (1<<26) | (0b00001<<16), :rs, :i16, :setip addop 'tgei', (1<<26) | (0b01000<<16), :rs, :i16, :setip addop 'tgfiu',(1<<26) | (0b01001<<16), :rs, :i16, :setip addop 'tlti', (1<<26) | (0b01010<<16), :rs, :i16, :setip addop 'tltiu',(1<<26) | (0b01011<<16), :rs, :i16, :setip addop 'teqi', (1<<26) | (0b01100<<16), :rs, :i16, :setip addop 'tnei', (1<<26) | (0b01110<<16), :rs, :i16, :setip addop 'bltzal', (1<<26) | (0b10000<<16), :rs, :i16, :setip, :saveip addop 'bgezal', (1<<26) | (0b10001<<16), :i16, :setip, :stopexec, :saveip # bgezal $zero => unconditionnal addop 'bgezal', (1<<26) | (0b10001<<16), :rs, :i16, :setip, :saveip # special2 addop 'madd', (0b011100<<26) | 0b000000, :rs, :rt addop 'maddu',(0b011100<<26) | 0b000001, :rs, :rt addop 'mul', (0b011100<<26) | 0b000010, :rd, :rs, :rt addop 'msub', (0b011100<<26) | 0b000100, :rs, :rt addop 'msubu',(0b011100<<26) | 0b000101, :rs, :rt addop 'clz', (0b011100<<26) | 0b100000, :rd, :rs, :rt # must have rs == rt addop 'clo', (0b011100<<26) | 0b100001, :rd, :rs, :rt # must have rs == rt addop 'sdbbp',(0b011100<<26) | 0b111111, :i20 # cp0 addop 'mfc0', (0b010000<<26) | (0b00000<<21), :rt, :idb addop 'mfc0', (0b010000<<26) | (0b00000<<21), :rt, :idb, :sel addop 'mtc0', (0b010000<<26) | (0b00100<<21), :rt, :idb addop 'mtc0', (0b010000<<26) | (0b00100<<21), :rt, :idb, :sel addop 'tlbr', (0b010000<<26) | (1<<25) | 0b000001 addop 'tlbwi',(0b010000<<26) | (1<<25) | 0b000010 addop 'tlbwr',(0b010000<<26) | (1<<25) | 0b000110 addop 'tlbp', (0b010000<<26) | (1<<25) | 0b001000 addop 'eret', (0b010000<<26) | (1<<25) | 0b011000 addop 'deret',(0b010000<<26) | (1<<25) | 0b011111 addop 'wait', (0b010000<<26) | (1<<25) | 0b100000 # mode field ? end def init_mips32r2 init_mips32 addop 'rotr', 0b000010 | (1<<21), :rd, :rt, :sa addop 'rotrv',0b000110 | (1<<6), :rd, :rt, :rs addop 'synci',(1<<26) | (0b11111<<16), :rs_i16 # special3 addop 'ext', (0b011111<<26) | 0b000000, :rt, :rs, :sa, :idm1 addop 'ins', (0b011111<<26) | 0b000100, :rt, :rs, :sa, :idb addop 'rdhwr',(0b011111<<26)| 0b111011, :rt, :rd addop 'wsbh',(0b011111<<26) | (0b00010<<6) | 0b100000, :rd, :rt addop 'seb', (0b011111<<26) | (0b10000<<6) | 0b100000, :rd, :rt addop 'seh', (0b011111<<26) | (0b11000<<6) | 0b100000, :rd, :rt # cp0 addop 'rdpgpr', (0b010000<<26) | (0b01010<<21), :rd, :rt addop 'wrpgpr', (0b010000<<26) | (0b01110<<21), :rd, :rt addop 'di', (0b010000<<26) | (0b01011<<21) | (0b01100<<11) | (0<<5) addop 'di', (0b010000<<26) | (0b01011<<21) | (0b01100<<11) | (0<<5), :rt addop 'ei', (0b010000<<26) | (0b01011<<21) | (0b01100<<11) | (1<<5) addop 'ei', (0b010000<<26) | (0b01011<<21) | (0b01100<<11) | (1<<5), :rt end alias init_latest init_mips32r2 end class MIPS64 def init_mips64 init_mips32r2 @valid_props.update :mi64 => true addop 'ld', 0b110111 << 26, :rt, :rs_i16, :m64 addop 'lwu', 0b100111 << 26, :rt, :rs_i16 addop 'sd', 0b111111 << 26, :rt, :rs_i16, :m64 addop 'scd', 0b111100 << 26, :rt, :rs_i16, :m64 addop 'ldl', 0b011010 << 26, :rt, :rs_i16 addop 'ldr', 0b011011 << 26, :rt, :rs_i16 addop 'sdl', 0b101100 << 26, :rt, :rs_i16 addop 'sdr', 0b101101 << 26, :rt, :rs_i16 addop 'lld', 0b110100 << 26, :rt, :rs_i16 addop 'daddi', 0b011000 << 26, :rt, :rs, :i16 addop 'daddiu', 0b011001 << 26, :rt, :rs, :i16 addop 'dclo', (0b011100 << 26) | (0b100101), :rd, :rt, :rs addop 'dclz', (0b011100 << 26) | (0b100100), :rd, :rt, :rs addop 'dadd', 0b101100, :rd, :rs, :rt addop 'daddu', 0b101101, :rd, :rs, :rt addop 'dsub', 0b101110, :rd, :rs, :rt addop 'dsubu', 0b101111, :rd, :rs, :rt addop 'dsll', 0b111000, :rd, :rt, :sa addop 'dsll32', 0b111100, :rd, :rt, :sa addop 'dsllv', 0b010100, :rd, :rt, :rs addop 'dsra', 0b111011, :rd, :rt, :sa addop 'dsra32', 0b111111, :rd, :rt, :sa addop 'dsrav', 0b010111, :rd, :rt, :rs addop 'dsrl', 0b111010, :rd, :rt, :sa addop 'dsrl32', 0b111110, :rd, :rt, :sa addop 'dsrlv', 0b010110, :rd, :rt, :rs addop 'ddiv', 0b011110, :rs, :rt addop 'ddivu', 0b011111, :rs, :rt addop 'dmult', 0b011100, :rs, :rt addop 'dmultu', 0b011101, :rs, :rt addop 'dmfc0', (0b010000<<26) | (0b00001<<21), :rt, :idb addop 'dmfc0', (0b010000<<26) | (0b00001<<21), :rt, :idb, :sel addop 'dmtc0', (0b010000<<26) | (0b00101<<21), :rt, :idb addop 'dmtc0', (0b010000<<26) | (0b00101<<21), :rt, :idb, :sel end def init_mips64r2 init_mips64 @fields_mask.update :msbd => 0x1f @fields_shift.update :msbd => 11 addop 'dext', (0b011111 << 26) | 0b000011, :rt, :rs, :sa, :msbd # sa => lsb addop 'dextm', (0b011111 << 26) | 0b000001, :rt, :rs, :sa, :msbd addop 'dextu', (0b011111 << 26) | 0b000010, :rt, :rs, :sa, :msbd addop 'dins', (0b011111 << 26) | 0b000111, :rt, :rs, :sa, :msbd addop 'dinsm', (0b011111 << 26) | 0b000101, :rt, :rs, :sa, :msbd addop 'dinsu', (0b011111 << 26) | 0b000110, :rt, :rs, :sa, :msbd addop 'drotr', (1 << 21) | 0b111010, :rd, :rt, :sa addop 'drotr32', (1 << 21) | 0b111110, :rd, :rt, :sa addop 'drotrv', (1 << 6) | 0b010110, :rd, :rt, :rs addop 'dsbh', (0b011111 << 26) | (0b00010 << 6) | 0b100100, :rd, :rt addop 'dshd', (0b011111 << 26) | (0b00101 << 6) | 0b100100, :rd, :rt end alias init_latest init_mips64r2 end end __END__ def macro_addop_cop1(name, bin, *aprops) flds = [ :rt, :fs ] addop name, :cop1, bin, 'rt, fs', flds, *aprops end def macro_addop_cop1_precision(name, type, bin, fmt, *aprops) flds = [ :ft, :fs, :fd ] addop name+'.'+(type.to_s[5,7]), type, bin, fmt, flds, *aprops end public # Initialize the instruction set with the MIPS32 Instruction Set def init_mips32 :cc => [7, 18, :fpcc], :op => [0x1F, 16, :op ], :cp2_rt => [0x1F, 16, :cp2_reg ], :stype => [0x1F, 6, :imm ], :code => [0xFFFFF, 6, :code ], :sel => [3, 0, :sel ]}) # --------------------------------------------------------------- # COP0, field rs # --------------------------------------------------------------- addop 'mfc0', :cop0, 0b00000, 'rt, rd, sel', [ :rt, :rd, :sel ] addop 'mtc0', :cop0, 0b00100, 'rt, rd, sel', [ :rt, :rd, :sel ] # --------------------------------------------------------------- # COP0 when rs=C0 # --------------------------------------------------------------- macro_addop_cop0_c0 'tlbr', 0b000001 macro_addop_cop0_c0 'tlbwi', 0b000010 macro_addop_cop0_c0 'tlwr', 0b000110 macro_addop_cop0_c0 'tlbp', 0b001000 macro_addop_cop0_c0 'eret', 0b011000 macro_addop_cop0_c0 'deret', 0b011111 macro_addop_cop0_c0 'wait', 0b100000 # --------------------------------------------------------------- # COP1, field rs # --------------------------------------------------------------- macro_addop_cop1 'mfc1', 0b00000 macro_addop_cop1 'cfc1', 0b00010 macro_addop_cop1 'mtc1', 0b00100 macro_addop_cop1 'ctc1', 0b00110 addop "bc1f", :cop1, 0b01000, 'cc, off', [ :cc, :off ], :diff_bits, [ 16, 3, 0 ] addop "bc1fl", :cop1, 0b01000, 'cc, off', [ :cc, :off ], :diff_bits, [ 16, 3, 2 ] addop "bc1t", :cop1, 0b01000, 'cc, off', [ :cc, :off ], :diff_bits, [ 16, 3, 1 ] addop "bc1tl", :cop1, 0b01000, 'cc, off', [ :cc, :off ], :diff_bits, [ 16, 3, 3 ] # --------------------------------------------------------------- # COP1, field rs=S/D # --------------------------------------------------------------- [ :cop1_s, :cop1_d ].each do |type| type_str = type.to_s[5,7] macro_addop_cop1_precision 'add', type, 0b000000, 'fd, fs, ft' macro_addop_cop1_precision 'sub', type, 0b000001, 'fd, fs, ft' macro_addop_cop1_precision 'mul', type, 0b000010, 'fd, fs, ft' macro_addop_cop1_precision 'abs', type, 0b000101, 'fd, fs', :ft_zero macro_addop_cop1_precision 'mov', type, 0b000110, 'fd, fs', :ft_zero macro_addop_cop1_precision 'neg', type, 0b000111, 'fd, fs', :ft_zero macro_addop_cop1_precision 'movz', type, 0b010010, 'fd, fs, ft' macro_addop_cop1_precision 'movn', type, 0b010011, 'fd, fs, ft' addop "movf.#{type_str}", type, 0b010001, 'fd, fs, cc', [ :cc, :fs, :fd ], :diff_bits, [ 16, 1, 0 ] addop "movt.#{type_str}", type, 0b010001, 'fd, fs, cc', [ :cc, :fs, :fd ], :diff_bits, [ 16, 1, 1 ] %w(f un eq ueq olt ult ole ule sf ngle seq ngl lt nge le ngt).each_with_index do |cond, index| addop "c.#{cond}.#{type_str}", type, 0b110000+index, 'cc, fs, ft', [ :ft, :fs, :cc ] end end # S and D Without PS [:cop1_s, :cop1_d].each do |type| macro_addop_cop1_precision 'div', type, 0b000011, 'fd, fs, ft' macro_addop_cop1_precision 'sqrt', type, 0b000100, 'fd, fs', :ft_zero macro_addop_cop1_precision 'round.w', type, 0b001100, 'fd, fs', :ft_zero macro_addop_cop1_precision 'trunc.w', type, 0b001101, 'fd, fs', :ft_zero macro_addop_cop1_precision 'ceil.w', type, 0b001110, 'fd, fs', :ft_zero macro_addop_cop1_precision 'floor.w', type, 0b001111, 'fd, fs', :ft_zero end # COP2 is not decoded (pretty useless) [:cop1_d,:cop1_w].each { |type| macro_addop_cop1_precision 'cvt.s', type, 0b100000, 'fd, fs', :ft_zero } [:cop1_s,:cop1_w].each { |type| macro_addop_cop1_precision 'cvt.d', type, 0b100001, 'fd, fs', :ft_zero } [:cop1_s,:cop1_d].each { |type| macro_addop_cop1_precision 'cvt.w', type, 0b100100, 'fd, fs', :ft_zero } [ :normal, :special, :regimm, :special2, :cop0, :cop0_c0, :cop1, :cop1_s, :cop1_d, :cop1_w ].each \ { |t| @@opcodes_by_class[t] = opcode_list.find_all { |o| o.type == t } } end # Initialize the instruction set with the MIPS32 Instruction Set Release 2 def init_mips64 init_mips32 #SPECIAL macro_addop_special "rotr", 0b000010, 'rd, rt, sa', :diff_bits, [ 26, 1, 1 ] macro_addop_special "rotrv", 0b000110, 'rd, rt, rs', :diff_bits, [ 6, 1, 1 ] # REGIMM addop "synci", :regimm, 0b11111, '', {:base => [5,21], :off => [16, 0] } # --------------------------------------------------------------- # SPECIAL3 opcode encoding of function field # --------------------------------------------------------------- addop "ext", :special3, 0b00000, 'rt, rs, pos, size', { :rs => [5, 21], :rt => [5, 16], :msbd => [5, 11], :lsb => [5, 6] } addop "ins", :special3, 0b00100, 'rt, rs, pos, size', { :rs => [5, 21], :rt => [5, 16], :msb => [5, 11], :lsb => [5, 6] } addop "rdhwr", :special3, 0b111011, 'rt, rd', { :rt => [5, 16], :rd => [5, 11] } addop "wsbh", :bshfl, 0b00010, 'rd, rt', { :rt => [5, 16], :rd => [5, 11] } addop "seb", :bshfl, 0b10000, 'rd, rt', { :rt => [5, 16], :rd => [5, 11] } addop "seh", :bshfl, 0b11000, 'rd, rt', { :rt => [5, 16], :rd => [5, 11] } # --------------------------------------------------------------- # COP0 # --------------------------------------------------------------- addop "rdpgpr", :cop0, 0b01010, 'rt, rd', {:rt => [5, 16], :rd => [5, 11] } addop "wdpgpr", :cop0, 0b01110, 'rt, rd', {:rt => [5, 16], :rd => [5, 11] } addop "di", :cop0, 0b01011, '', {}, :diff_bits, [ 5, 1 , 0] addop "ei", :cop0, 0b01011, '', {}, :diff_bits, [ 5, 1 , 1] # --------------------------------------------------------------- # COP1, field rs # --------------------------------------------------------------- macro_addop_cop1 "mfhc1", 0b00011 macro_addop_cop1 "mthc1", 0b00111 # Floating point [:cop1_s, :cop1_d].each do |type| macro_addop_cop1_precision 'round.l', type, 0b001000, 'fd, fs', :ft_zero macro_addop_cop1_precision 'trunc.l', type, 0b001001, 'fd, fs', :ft_zero macro_addop_cop1_precision 'ceil.l', type, 0b001010, 'fd, fs', :ft_zero macro_addop_cop1_precision 'floor.l', type, 0b001011, 'fd, fs', :ft_zero macro_addop_cop1_precision 'recip', type, 0b010101, 'fd, fs', :ft_zero macro_addop_cop1_precision 'rsqrt', type, 0b010110, 'fd, fs', :ft_zero macro_addop_cop1_precision 'cvt.l', type, 0b100101, 'fd, fs', :ft_zero end macro_addop_cop1_precision 'cvt.ps', :cop1_s, 0b100110, 'fd, fs', :ft_zero macro_addop_cop1_precision 'cvt.s', :cop1_l, 0b100000, 'fd, fs', :ft_zero macro_addop_cop1_precision 'cvt.d', :cop1_l, 0b100000, 'fd, fs', :ft_zero macro_addop_cop1_precision 'add', :cop1_ps, 0b000000, 'fd, fs, ft' macro_addop_cop1_precision 'sub', :cop1_ps, 0b000001, 'fd, fs, ft' macro_addop_cop1_precision 'mul', :cop1_ps, 0b000010, 'fd, fs, ft' macro_addop_cop1_precision 'abs', :cop1_ps, 0b000101, 'fd, fs', :ft_zero macro_addop_cop1_precision 'mov', :cop1_ps, 0b000110, 'fd, fs', :ft_zero macro_addop_cop1_precision 'neg', :cop1_ps, 0b000111, 'fd, fs', :ft_zero macro_addop_cop1_precision 'movz', :cop1_ps, 0b010010, 'fd, fs, ft' macro_addop_cop1_precision 'movn', :cop1_ps, 0b010011, 'fd, fs, ft' addop "movf.#{:cop1_ps_str}", :cop1_ps, 0b010001, 'fd, fs, cc', [ :cc, :fs, :fd ] addop "movt.#{:cop1_ps_str}", :cop1_ps, 0b010001, 'fd, fs, cc', [ :cc, :fs, :fd ] %w(f un eq ueq olt ult ole ule sf ngle seq ngl lt nge le ngt).each_with_index do |cond, index| addop "c.#{cond}.ps", :cop1_cond, 0b110000+index, 'cc, fs, ft', [ :ft, :fs, :cc ] # TODO: COP1X [ :special3, :bshfl, :cop1_l, :cop1_ps ].each \ { |t| @@opcodes_by_class[t] = opcode_list.find_all { |o| o.type == t } } end end # Reset all instructions def reset metaprops_allowed.clear args_allowed.clear props_allowed.clear fields_spec.clear opcode_list.clear end end # Array containing all the supported opcodes attr_accessor :opcode_list init_mips32 end end