Class: AVR::Opcode
- Inherits:
-
Object
show all
- Extended by:
- T::Sig
- Defined in:
- lib/avr/opcode.rb,
lib/avr/opcode/nop.rb,
lib/avr/opcode/wdr.rb,
lib/avr/opcode/sreg.rb,
lib/avr/opcode/break.rb,
lib/avr/opcode/sleep.rb,
lib/avr/opcode/io/bit.rb,
lib/avr/opcode/compare.rb,
lib/avr/opcode/register.rb,
lib/avr/opcode/data/sram.rb,
lib/avr/opcode/io/in_out.rb,
lib/avr/opcode/data/stack.rb,
lib/avr/opcode/data/program.rb,
lib/avr/opcode/math/bitwise.rb,
lib/avr/opcode/branch/return.rb,
lib/avr/opcode/math/addition.rb,
lib/avr/opcode/data/immediate.rb,
lib/avr/opcode/operand_parsers.rb,
lib/avr/opcode/math/subtraction.rb,
lib/avr/opcode/branch/conditional.rb,
lib/avr/opcode/math/multiplication.rb,
lib/avr/opcode/branch/unconditional.rb
Defined Under Namespace
Classes: AbsolutePcExpected, BitNumberExpected, ByteConstantExpected, ConstantOutOfRange, FarRelativePcExpected, IncorrectArgumentCount, IoAddressExpected, LowerIoAddressExpected, NearRelativePcExpected, OpcodeException, RegisterExpected, StatusRegisterBitExpected, UpperRegisterExpected, WordConstantExpected, WordRegisterExpected
Constant Summary
collapse
- OPCODE_ARGUMENT_TYPES =
rubocop:disable Layout/HashAlignment
T.let(
{
sreg_flag: '%s',
near_relative_pc: proc { |arg| '.%+d' % [2 * arg] },
far_relative_pc: proc { |arg| '.%+d' % [2 * arg] },
absolute_pc: proc { |arg| '0x%04x' % [2 * arg] },
byte: '0x%02x',
word: '0x%04x',
register: '%s',
register_pair: proc { |arg| '%s:%s' % [arg[0], arg[1]] },
word_register: '%s',
modifying_word_register: proc { |arg|
if arg.is_a?(RegisterPair)
'%s' % arg
else
'%s%s%s' % [
arg[1] == :pre_decrement ? '-' : '',
arg[0].to_s,
arg[1] == :post_increment ? '+' : '',
]
end
},
displaced_word_register: proc { |arg|
'%s%+d' % [arg.register.name, arg.displacement]
},
register_with_bit_number: '%s',
io_address: '0x%02x',
lower_io_address: '0x%02x',
bit_number: '%d',
}.freeze,
T::Hash[Symbol, T.any(String, T.proc.params(arg: T::Array[Integer]).returns(String))]
)
- ProcType =
T.type_alias do
T.proc.params(
cpu: CPU,
memory: T.nilable(Memory),
args: Argument::ArrayType
).void
end
- ExtractedOperandHashType =
T.type_alias { T::Hash[Symbol, Integer] }
- OperandValueHashType =
T.type_alias { T::Hash[Symbol, Argument::ValueType] }
Class Attribute Summary collapse
Instance Attribute Summary collapse
Class Method Summary
collapse
-
.bit_jumble_for_lds_sts(k_in) ⇒ Object
-
.decode(pattern, mnemonic, &block) ⇒ Object
-
.exchange_memory_byte_with_register(memory_byte, register, mnemonic) ⇒ Object
-
.opcode(mnemonic, arg_types = [], sreg_flags = [], &block) ⇒ Object
-
.parse_operands(pattern, &block) ⇒ Object
-
.set_sreg_for_add_adc(cpu, r, rd, rr) ⇒ Object
-
.set_sreg_for_adiw(cpu, r, rd) ⇒ Object
-
.set_sreg_for_and_or(cpu, value) ⇒ Object
-
.set_sreg_for_cp_cpi_cpc(cpu, r, rd, rr_k, mnemonic) ⇒ Object
-
.set_sreg_for_dec(cpu, r, rd) ⇒ Object
-
.set_sreg_for_inc(cpu, r, rd) ⇒ Object
-
.set_sreg_for_sbiw(cpu, r, rd) ⇒ Object
-
.set_sreg_for_sub_sbc(cpu, r, rd, rr) ⇒ Object
-
.stack_pop(cpu) ⇒ Object
-
.stack_pop_word(cpu) ⇒ Object
-
.stack_push(cpu, byte) ⇒ Object
-
.stack_push_word(cpu, word) ⇒ Object
-
.twos_complement(value, bits) ⇒ Object
Instance Method Summary
collapse
Constructor Details
#initialize(mnemonic, arg_types, sreg_flags, opcode_proc) ⇒ Opcode
Returns a new instance of Opcode.
92
93
94
95
96
97
98
99
100
|
# File 'lib/avr/opcode.rb', line 92
def initialize(mnemonic, arg_types, sreg_flags, opcode_proc)
@mnemonic = mnemonic
@arg_types = arg_types
@sreg_flags = sreg_flags
@opcode_proc = opcode_proc
arg_types.each do |arg_type|
raise "Unknown Opcode argument type: #{arg_type}" unless OPCODE_ARGUMENT_TYPES[arg_type]
end
end
|
Class Attribute Details
.opcodes ⇒ Object
Returns the value of attribute opcodes.
185
186
187
|
# File 'lib/avr/opcode.rb', line 185
def opcodes
@opcodes
end
|
Instance Attribute Details
#arg_types ⇒ Object
Returns the value of attribute arg_types.
65
66
67
|
# File 'lib/avr/opcode.rb', line 65
def arg_types
@arg_types
end
|
#mnemonic ⇒ Object
Returns the value of attribute mnemonic.
62
63
64
|
# File 'lib/avr/opcode.rb', line 62
def mnemonic
@mnemonic
end
|
#opcode_proc ⇒ Object
Returns the value of attribute opcode_proc.
79
80
81
|
# File 'lib/avr/opcode.rb', line 79
def opcode_proc
@opcode_proc
end
|
#sreg_flags ⇒ Object
Returns the value of attribute sreg_flags.
68
69
70
|
# File 'lib/avr/opcode.rb', line 68
def sreg_flags
@sreg_flags
end
|
Class Method Details
.bit_jumble_for_lds_sts(k_in) ⇒ Object
13
14
15
16
17
18
19
|
# File 'lib/avr/opcode/operand_parsers.rb', line 13
def self.bit_jumble_for_lds_sts(k_in)
k_out = k_in & 0b00001111
k_out |= k_in & 0b01100000 >> 1
k_out |= k_in & 0b00010000 << 2
k_out |= ~(k_in & 0b00010000 << 3) & 0b10000000
k_out
end
|
.decode(pattern, mnemonic, &block) ⇒ Object
226
227
228
229
230
|
# File 'lib/avr/opcode.rb', line 226
def self.decode(pattern, mnemonic, &block)
OpcodeDecoder.add_opcode_definition(
OpcodeDecoder::OpcodeDefinition.new(pattern, mnemonic, block.to_proc)
)
end
|
.exchange_memory_byte_with_register(memory_byte, register, mnemonic) ⇒ Object
175
176
177
178
179
180
181
182
183
184
185
186
187
188
|
# File 'lib/avr/opcode/data/sram.rb', line 175
def self.exchange_memory_byte_with_register(memory_byte, register, mnemonic)
old_value = memory_byte.value
case mnemonic
when :xch
memory_byte.value = register.value
when :las
memory_byte.value = register.value | old_value
when :lac
memory_byte.value = (~register.value & old_value) & 0xff
when :lat
memory_byte.value = register.value ^ old_value
end
register.value = old_value
end
|
.opcode(mnemonic, arg_types = [], sreg_flags = [], &block) ⇒ Object
219
220
221
222
223
|
# File 'lib/avr/opcode.rb', line 219
def self.opcode(mnemonic, arg_types = [], sreg_flags = [], &block)
raise 'No block given' unless block_given?
opcodes[mnemonic] = Opcode.new(mnemonic, arg_types, sreg_flags, block.to_proc)
end
|
.parse_operands(pattern, &block) ⇒ Object
233
234
235
|
# File 'lib/avr/opcode.rb', line 233
def self.parse_operands(pattern, &block)
OpcodeDecoder.add_operand_parser(OpcodeDecoder::OperandParser.new(pattern, block.to_proc))
end
|
.set_sreg_for_add_adc(cpu, r, rd, rr) ⇒ Object
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
# File 'lib/avr/opcode/math/addition.rb', line 35
def self.set_sreg_for_add_adc(cpu, r, rd, rr)
b7 = (1 << 7)
r7 = (r & b7) != 0
rd7 = (rd & b7) != 0
rr7 = (rr & b7) != 0
r3 = (r & b7) != 0
rd3 = (rd & b7) != 0
rr3 = (rr & b7) != 0
n = r7
v = rd7 & rr7 & !r7 | !rd7 & !rr7 & r7
c = rd7 & rr7 | rr7 & !r7 | !r7 & rd7
h = rd3 & rr3 | rr3 & !r3 | !r3 & rd3
cpu.sreg.from_h(
{
H: h,
S: n ^ v,
V: v,
N: n,
Z: r.zero?,
C: c,
}
)
end
|
.set_sreg_for_adiw(cpu, r, rd) ⇒ Object
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
# File 'lib/avr/opcode/math/addition.rb', line 88
def self.set_sreg_for_adiw(cpu, r, rd)
b15 = (1 << 15)
b7 = (1 << 7)
rdh7 = (rd & b7) != 0
r15 = (r & b15) != 0
v = !rdh7 & r15
n = r15
c = !r15 & rdh7
cpu.sreg.from_h(
{
S: n ^ v,
V: v,
N: n,
Z: r.zero?,
C: c,
}
)
end
|
.set_sreg_for_and_or(cpu, value) ⇒ Object
7
8
9
10
11
12
13
14
15
16
17
18
|
# File 'lib/avr/opcode/math/bitwise.rb', line 7
def self.set_sreg_for_and_or(cpu, value)
r7 = (value & (1 << 7)) != 0
cpu.sreg.from_h(
{
S: r7 ^ false,
V: false,
N: r7,
Z: value.zero?,
}
)
end
|
.set_sreg_for_cp_cpi_cpc(cpu, r, rd, rr_k, mnemonic) ⇒ Object
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
|
# File 'lib/avr/opcode/compare.rb', line 9
def self.set_sreg_for_cp_cpi_cpc(cpu, r, rd, rr_k, mnemonic)
b7 = (1<<7)
r7 = (r & b7) != 0
rd7 = (rd & b7) != 0
rr_k7 = (rr_k & b7) != 0
r3 = (r & b7) != 0
rd3 = (rd & b7) != 0
rr_k3 = (rr_k & b7) != 0
n = r7
v = rd7 & rr_k7 & r7 | !rd7 & rr_k7 & r7
c = !rd7 & rr_k7 | rr_k7 & r7 | r7 & !rd7
h = !rd3 & rr_k3 | rr_k3 & r3 | r3 & !rd3
z = r.zero?
z = r.zero? ? cpu.sreg.Z : false if mnemonic == :cpc
cpu.sreg.from_h(
{
H: h,
S: n ^ v,
V: v,
N: n,
Z: z,
C: c,
}
)
end
|
.set_sreg_for_dec(cpu, r, rd) ⇒ Object
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# File 'lib/avr/opcode/math/subtraction.rb', line 8
def self.set_sreg_for_dec(cpu, r, rd)
n = (r & (1 << 7)) != 0
v = (rd == 0x80)
cpu.sreg.from_h(
{
S: n ^ v,
V: v,
N: n,
Z: r.zero?,
}
)
end
|
.set_sreg_for_inc(cpu, r, rd) ⇒ Object
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# File 'lib/avr/opcode/math/addition.rb', line 8
def self.set_sreg_for_inc(cpu, r, rd)
n = (r & (1 << 7)) != 0
v = (rd == 0x7f)
cpu.sreg.from_h(
{
S: n ^ v,
V: v,
N: n,
Z: r.zero?,
}
)
end
|
.set_sreg_for_sbiw(cpu, r, rd) ⇒ Object
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
# File 'lib/avr/opcode/math/subtraction.rb', line 105
def self.set_sreg_for_sbiw(cpu, r, rd)
b15 = (1 << 15)
b7 = (1 << 7)
rdh7 = (rd & b7) != 0
r15 = (r & b15) != 0
v = r15 & !rdh7
n = r15
c = r15 & !rdh7
cpu.sreg.from_h(
{
S: n ^ v,
V: v,
N: n,
Z: r.zero?,
C: c,
}
)
end
|
.set_sreg_for_sub_sbc(cpu, r, rd, rr) ⇒ Object
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
|
# File 'lib/avr/opcode/math/subtraction.rb', line 35
def self.set_sreg_for_sub_sbc(cpu, r, rd, rr)
b7 = (1 << 7)
r7 = (r & b7) != 0
rd7 = (rd & b7) != 0
rr7 = (rr & b7) != 0
r3 = (r & b7) != 0
rd3 = (rd & b7) != 0
rr3 = (rr & b7) != 0
n = r7
v = rd7 & rr7 & !r7 | !rd7 & rr7 & r7
c = !rd7 & rr7 | rr7 & r7 | r7 & !rd7
h = !rd3 & rr3 | rr3 & r3 | r3 & !rd3
cpu.sreg.from_h(
{
H: h,
S: n ^ v,
V: v,
N: n,
Z: r.zero?,
C: c,
}
)
end
|
.stack_pop(cpu) ⇒ Object
201
202
203
204
|
# File 'lib/avr/opcode.rb', line 201
def self.stack_pop(cpu)
cpu.sp.increment
cpu.sram.memory.fetch(cpu.sp.value).value
end
|
.stack_pop_word(cpu) ⇒ Object
207
208
209
|
# File 'lib/avr/opcode.rb', line 207
def self.stack_pop_word(cpu)
stack_pop(cpu) | (stack_pop(cpu) << 8)
end
|
.stack_push(cpu, byte) ⇒ Object
189
190
191
192
|
# File 'lib/avr/opcode.rb', line 189
def self.stack_push(cpu, byte)
cpu.sram.memory.fetch(cpu.sp.value).value = byte
cpu.sp.decrement
end
|
.stack_push_word(cpu, word) ⇒ Object
195
196
197
198
|
# File 'lib/avr/opcode.rb', line 195
def self.stack_push_word(cpu, word)
stack_push(cpu, (word & 0xff00) >> 8)
stack_push(cpu, (word & 0x00ff))
end
|
.twos_complement(value, bits) ⇒ Object
7
8
9
10
|
# File 'lib/avr/opcode/operand_parsers.rb', line 7
def self.twos_complement(value, bits)
mask = (2**(bits - 1)).to_i
-(value & mask) + (value & ~mask)
end
|
Instance Method Details
#execute(cpu, memory, args) ⇒ Object
176
177
178
|
# File 'lib/avr/opcode.rb', line 176
def execute(cpu, memory, args)
opcode_proc.call(cpu, memory, args)
end
|
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
# File 'lib/avr/opcode.rb', line 154
def format_args(args)
formatted_args = []
args.each_with_index do |arg, i|
arg_formatter = OPCODE_ARGUMENT_TYPES[T.must(arg_types[i])]
case arg_formatter
when String
formatted_args << (arg_formatter % arg)
when Proc
formatted_args << arg_formatter.call(arg)
else
raise "Unknown argument formatter (#{arg_formatter.class}) for #{arg}"
end
end
formatted_args
end
|
#inspect ⇒ Object
171
172
173
|
# File 'lib/avr/opcode.rb', line 171
def inspect
"#<#{self.class.name} #{mnemonic} #{arg_types}>"
end
|
#validate(args) ⇒ Object
141
142
143
144
145
146
147
148
149
150
151
|
# File 'lib/avr/opcode.rb', line 141
def validate(args)
raise IncorrectArgumentCount unless args.size == arg_types.size
args.each_with_index do |arg, i|
arg_exception = validate_arg(arg, i)
raise arg_exception, "Argument #{i} (#{arg}) invalid for #{arg_types[i]}" if arg_exception
end
true
end
|
#validate_arg(arg, arg_number) ⇒ Object
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
# File 'lib/avr/opcode.rb', line 103
def validate_arg(arg, arg_number)
case arg_types[arg_number]
when :register
return RegisterExpected unless arg.is_a?(Register)
when :word_register
return WordRegisterExpected unless arg.is_a?(RegisterPair)
when :byte
return ByteConstantExpected unless arg.is_a?(Value)
return ConstantOutOfRange unless arg.value >= 0x00 && arg.value <= 0xff
when :word
return WordConstantExpected unless arg.is_a?(Value)
return ConstantOutOfRange unless arg.value >= 0x0000 && arg.value <= 0xffff
when :absolute_pc
return AbsolutePcExpected unless arg.is_a?(Value)
return ConstantOutOfRange unless arg.value >= 0 && arg.value <= (2**22).to_i - 1
when :near_relative_pc
return NearRelativePcExpected unless arg.is_a?(Value)
return ConstantOutOfRange unless arg.value >= -64 && arg.value <= 63
when :far_relative_pc
return FarRelativePcExpected unless arg.is_a?(Value)
return ConstantOutOfRange unless arg.value >= -2048 && arg.value <= 2047
when :io_address
return IoAddressExpected unless arg.is_a?(Value)
return ConstantOutOfRange unless arg.value >= 0 && arg.value <= 63
when :lower_io_address
return IoAddressExpected unless arg.is_a?(Value)
return ConstantOutOfRange unless arg.value >= 0 && arg.value <= 31
when :register_with_bit_number
return RegisterExpected unless arg.register.is_a?(Register)
return BitNumberExpected unless arg.bit_number.is_a?(Integer)
return ConstantOutOfRange unless arg.bit_number >= 0 && arg.bit_number <= 7
when :sreg_flag
return StatusRegisterBitExpected unless arg.is_a?(Value)
return StatusRegisterBitExpected unless arg.value == 0 || arg.value == 1
end
end
|