#!/usr/bin/ruby require 'xml' xml = Xml.parse_file(ARGV.shift || 'openrisc-insn.html') # [name, bin, args] addop = [] # arg => [flds] valid_args = {} # field => [bitoff, bitmask] fields = {} xml.each('ul') { |ul| syntax = nil bits = [] vals = [] trno = 0 ul.each('li') { |li| if li.children[0] == 'syntax:' #
  • syntax:l.add $rd, $ra, $rb
  • syntax = li.children[1].children[0].children[0] end } next if not syntax ul.each('tr') { |tr| case trno when 0; tr.each('td') { |td| bits << td.children[0].split.map { |b| b.to_i } } when 2; tr.each('td') { |td| vals << td.children.map { |v| v =~ /^0x/ ? v.to_i(16) : v.gsub('-', '') }.first } end trno += 1 } iname = syntax.split[0].sub(/^l\./, '') iargs = syntax.split[1].to_s.split(',').map { |a| a.gsub(/[${}-]/, '').gsub(/(\w+)\((\w+)\)/, '\2_\1') } bin = bits.zip(vals).inject(0) { |b, (bt, bv)| bv.kind_of?(Integer) ? b | (bv << bt.last) : b } addop << [iname, bin] flds = bits.zip(vals).inject({}) { |h, (bt, bv)| next h if bv.kind_of?(Integer) blen = bt.first + 1 - bt.last h.update bv => [bt.last, (1 << blen) - 1] } flds.each { |n, (o, m)| if not fields[n] fields[n] = [o, m] elsif fields[n] != [o, m] puts "# fields mismatch in #{iname} #{n}" end } addop.last << iargs iargs.each { |a| a.split('_').each { |f| if not flds.delete(f) puts "# no field #{f} for arg #{a} in #{iname}" end } valid_args[a] ||= a.split('_') } flds.each_key { |f| puts "# no arg using #{f} in #{iname}" a_i = "#{f}_ign" valid_args[a_i] ||= [f] addop.last.last << a_i } } puts "\tdef init_cpu" puts "\t\t@opcode_list = []" puts "\t\t@valid_args = { #{valid_args.map { |a, f| ":#{a} => [#{f.map { |ff| ':' + ff }.join(', ')}]" }.join(', ')} }" puts "\t\t@fields_off = { #{fields.map { |k, v| ":#{k} => #{v[0]}" }.join(', ')} }" puts "\t\t@fields_mask = { #{fields.map { |k, v| ":#{k} => #{'0x%02X' % v[1]}" }.join(', ')} }" puts addop.each { |op| puts "\t\taddop '#{op[0]}', #{'0x%08X' % op[1]}#{op[2].map { |a| ", :#{a}" }.join('')}" } puts "\tend"