class AVR::Opcode
Constants
- ExtractedOperandHashType
- I
- OPCODE_ARGUMENT_TYPES
rubocop:disable Layout/HashAlignment
- OperandValueHashType
- ProcType
- T
Attributes
opcodes[R]
arg_types[R]
mnemonic[R]
opcode_proc[R]
sreg_flags[R]
Public Class Methods
bit_jumble_for_lds_sts(k_in)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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
new(mnemonic, arg_types, sreg_flags, opcode_proc)
click to toggle source
# 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
opcode(mnemonic, arg_types = [], sreg_flags = [], &block)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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
Public Instance Methods
execute(cpu, memory, args)
click to toggle source
# File lib/avr/opcode.rb, line 176 def execute(cpu, memory, args) opcode_proc.call(cpu, memory, args) end
format_args(args)
click to toggle source
# 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()
click to toggle source
# File lib/avr/opcode.rb, line 171 def inspect "#<#{self.class.name} #{mnemonic} #{arg_types}>" end
validate(args)
click to toggle source
# 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)
click to toggle source
# 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