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
.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
.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