summaryrefslogtreecommitdiff
path: root/gen.rb
blob: c88b924732de0b5530fcd44d10f359807b7bfe52 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/bin/env ruby

require 'yaml'
require 'erb'

# load template data
DATA = YAML.load_file(File.join(__dir__, 'ops.yaml'))

switches = Hash.new { |h, k| h[k] = [] }
op_meta = []
DATA['ops'].each do |set_id, ops|
  op_meta += ops.map { |op|
    '{ "%s", %d }, /* 0x%02x + 0x%s */' % [
      op['id'],
      op['len'] || 0,
      (set_id == 'main') ? 0 : 255,
      op['hex'].to_s(16).upcase.rjust(2, '0'),
    ]
  }

  switches[set_id] = ops.select { |op|
    op['op'] != 'PREFIX'
  }.map { |op|
    # op hex string
    hex = op['hex'].to_s(16).upcase.rjust(2, '0')

    case op['op']
    when 'XX'
      [
        "case 0x%s: /* op: %s, cat: %s */",
        "  cpu_set_state(ctx, old_pc, GB_CPU_STATE_INVALID);",
        "  break;",
      ].join("\n") % [
        hex,
        op['id'],
        op['cat'],
      ]
    else
      # pc_expr
      pc_expr = if op['pc']
        'cpu_ww(ctx, RW_PC, old_pc + %d);' % [op['len']]
      else
        ''
      end

      # time expr
      time_expr = case op['time']
      when Numeric
        'clock = %d;' % [op['time']]
      when Hash
        'clock = %d; // t: %d, f: %d' % %w{f t f}.map { |k|
          op['time'][k]
        }
      else
        raise "unknown op time: #{hex}: #{op['time']}"
      end

      [
        "case 0x%s: /* op: \"%s\", cat: \"%s\" */",
        "  %s", # time_expr
        "  %s", # action_expr
        "  %s", # pc_expr
        "  break;"
      ].join("\n") % [
        hex,
        op['id'],
        op['cat'],
        time_expr,
        op['code'] || 'cpu_set_state(ctx, old_pc, GB_CPU_STATE_NOT_IMPLEMENTED);',
        pc_expr,
      ]
    end
  }.join("\n")
end

# build complete ops list
ops = op_meta.join("\n")

t = ERB.new(DATA['templates']['main'])
puts t.run(binding)