node/lib/metasm/metasm/cpu/z80/decode.rb
# populate the @backtrace_binding hash with default values
populate the @backtrace_binding hash with default values
populate the @backtrace_binding hash with default values
def init_backtrace_binding
		@backtrace_binding ||= {}
		mask = 0xffff
		opcode_list.map { |ol| ol.basename }.uniq.sort.each { |op|
			binding = case op
			when 'ld'; lambda { |di, a0, a1, *aa| a2 = aa[0] ; a2 ? { a0 => Expression[a1, :+, a2] } : { a0 => Expression[a1] } }
			when 'ldi'; lambda { |di, a0, a1| hl = (a0 == :a ? a1 : a0) ; { a0 => Expression[a1], hl => Expression[hl, :+, 1] } }
			when 'ldd'; lambda { |di, a0, a1| hl = (a0 == :a ? a1 : a0) ; { a0 => Expression[a1], hl => Expression[hl, :-, 1] } }
			when 'add', 'adc', 'sub', 'sbc', 'and', 'xor', 'or'
				lambda { |di, a0, a1|
					e_op = { 'add' => :+, 'adc' => :+, 'sub' => :-, 'sbc' => :-, 'and' => :&, 'xor' => :^, 'or' => :| }[op]
					ret = Expression[a0, e_op, a1]
					ret = Expression[ret, e_op, :flag_c] if op == 'adc' or op == 'sbc'
					ret = Expression[ret.reduce] if not a0.kind_of? Indirection
					{ a0 => ret }
				}
			when 'cp', 'cmp'; lambda { |di, *a| {} }
			when 'inc'; lambda { |di, a0| { a0 => Expression[a0, :+, 1] } }
			when 'dec'; lambda { |di, a0| { a0 => Expression[a0, :-, 1] } }
			when 'not'; lambda { |di, a0| { a0 => Expression[a0, :^, mask] } }
			when 'push'
				lambda { |di, a0| { :sp => Expression[:sp, :-, 2],
					Indirection[:sp, 2, di.address] => Expression[a0] } }
			when 'pop'
				lambda { |di, a0| { :sp => Expression[:sp, :+, 2],
					a0 => Indirection[:sp, 2, di.address] } }
			when 'call'
				lambda { |di, a0| { :sp => Expression[:sp, :-, 2],
					  Indirection[:sp, 2, di.address] => Expression[di.next_addr] }
				}
			when 'ret', 'reti'; lambda { |di, *a| { :sp => Expression[:sp, :+, 2] } }
			when 'bswap'
				lambda { |di, a0| { a0 => Expression[
						[[a0, :&, 0xff00], :>>,  8], :|,
						[[a0, :&, 0x00ff], :<<,  8]] } }
			when 'nop', /^j/; lambda { |di, *a| {} }
			end
			@backtrace_binding[op] ||= binding if binding
		}
		@backtrace_binding
	end
def init_backtrace_binding @backtrace_binding ||= { } mask = 0xffff opcode_list . map { | ol | ol . basename } . uniq . sort . each { | op | binding = case op when 'ld' ; lambda { | di , a0 , a1 , * aa | a2 = aa [ 0 ] ; a2 ? { a0 => Expression [ a1 , :+ , a2 ] } : { a0 => Expression [ a1 ] } } when 'ldi' ; lambda { | di , a0 , a1 | hl = ( a0 == :a ? a1 : a0 ) ; { a0 => Expression [ a1 ] , hl => Expression [ hl , :+ , 1 ] } } when 'ldd' ; lambda { | di , a0 , a1 | hl = ( a0 == :a ? a1 : a0 ) ; { a0 => Expression [ a1 ] , hl => Expression [ hl , :- , 1 ] } } when 'add' , 'adc' , 'sub' , 'sbc' , 'and' , 'xor' , 'or' lambda { | di , a0 , a1 | e_op = { 'add' => :+ , 'adc' => :+ , 'sub' => :- , 'sbc' => :- , 'and' => :& , 'xor' => :^ , 'or' => :| } [ op ] ret = Expression [ a0 , e_op , a1 ] ret = Expression [ ret , e_op , :flag_c ] if op == 'adc' or op == 'sbc' ret = Expression [ ret . reduce ] if not a0 . kind_of? Indirection { a0 => ret } } when 'cp' , 'cmp' ; lambda { | di , * a | { } } when 'inc' ; lambda { | di , a0 | { a0 => Expression [ a0 , :+ , 1 ] } } when 'dec' ; lambda { | di , a0 | { a0 => Expression [ a0 , :- , 1 ] } } when 'not' ; lambda { | di , a0 | { a0 => Expression [ a0 , :^ , mask ] } } when 'push' lambda { | di , a0 | { :sp => Expression [ :sp , :- , 2 ] , Indirection [ :sp , 2 , di . address ] => Expression [ a0 ] } } when 'pop' lambda { | di , a0 | { :sp => Expression [ :sp , :+ , 2 ] , a0 => Indirection [ :sp , 2 , di . address ] } } when 'call' lambda { | di , a0 | { :sp => Expression [ :sp , :- , 2 ] , Indirection [ :sp , 2 , di . address ] => Expression [ di . next_addr ] } } when 'ret' , 'reti' ; lambda { | di , * a | { :sp => Expression [ :sp , :+ , 2 ] } } when 'bswap' lambda { | di , a0 | { a0 => Expression [ [ [ a0 , :& , 0xff00 ] , :>> , 8 ] , :| , [ [ a0 , :& , 0x00ff ] , :<< , 8 ] ] } } when 'nop' , / ^j / ; lambda { | di , * a | { } } end @backtrace_binding [ op ] ||= binding if binding } @backtrace_binding end
populate the @backtrace_binding hash with default values
populate the @backtrace_binding hash with default values
# TODO callCC, retCC ... # TODO flags ?