node/lib/metasm/metasm/cpu/x86_64/compile_c.rb
def c_cexpr_inner_arith_int(l, op, r, type)
		op = case op
		when :+; 'add'
		when :-; 'sub'
		when :&; 'and'
		when :|; 'or'
		when :^; 'xor'
		when :>>; type.specifier == :unsigned ? 'shr' : 'sar'
		when :<<; 'shl'
		when :*; 'mul'
		when :/; 'div'
		when :%; 'mod'
		end

		case op
		when 'add', 'sub', 'and', 'or', 'xor'
			r = make_volatile(r, type) if l.kind_of?(ModRM) and r.kind_of?(ModRM)
			r = make_volatile(r, type) if r.kind_of?(ModRM) and r.sz != l.sz	# add rax, word [moo]
			unuse r
			r = Reg.new(r.val, l.sz) if r.kind_of?(Reg) and l.kind_of?(ModRM) and l.sz and l.sz != r.sz     # add byte ptr [rax], bl
			instr op, l, i_to_i32(r)
		when 'shr', 'sar', 'shl'
			if r.kind_of? Expression
				instr op, l, r
			else
				# XXX bouh
				r = make_volatile(r, C::BaseType.new(:__int8, :unsigned))
				unuse r
				if r.val != 1
					rcx = Reg.new(1, 64)
					instr 'xchg', rcx, Reg.new(r.val, 64)
					l = Reg.new(r.val, l.sz) if l.kind_of? Reg and l.val == 1
				end
				instr op, l, Reg.new(1, 8)
				instr 'xchg', rcx, Reg.new(r.val, 64) if r.val != 1
			end
		when 'mul'
			if l.kind_of? ModRM
				if r.kind_of? Expression
					ll = findreg
					instr 'imul', ll, l, r
				else
					ll = make_volatile(l, type)
					unuse ll
					instr 'imul', ll, r
				end
				instr 'mov', l, ll
			else
				instr 'imul', l, r
			end
			unuse r
		when 'div', 'mod'
			lv = l.val if l.kind_of? Reg
			rax = Reg.from_str 'rax'
			rdx = Reg.from_str 'rdx'
			if @state.used.include? rax.val and lv != rax.val
				instr 'push', rax
				saved_rax = true
			end
			if @state.used.include? rdx.val and lv != rdx.val
				instr 'push', rdx
				saved_rdx = true
			end

			instr 'mov', rax, l if lv != rax.val

			if r.kind_of? Expression
				instr 'push', r
				rsp = Reg.from_str 'rsp'
				r = ModRM.new(@cpusz, 64, nil, nil, rsp, nil)
				need_pop = true
			end

			if type.specifier == :unsigned
				instr 'mov', rdx, Expression[0]
				instr 'div', r
			else
				instr 'cdq'
				instr 'idiv', r
			end
			unuse r

			instr 'add', rsp, 8 if need_pop

			if op == 'div'
				instr 'mov', l, rax if lv != rax.val
			else
				instr 'mov', l, rdx if lv != rdx.val
			end

			instr 'pop', rdx if saved_rdx
			instr 'pop', rax if saved_rax
		end
	end
# compile an integral arithmetic expression, reg-sized
compile an integral arithmetic expression, reg-sized
compile an integral arithmetic expression reg - sized
def c_cexpr_inner_arith_int(l, op, r, type)
		op = case op
		when :+; 'add'
		when :-; 'sub'
		when :&; 'and'
		when :|; 'or'
		when :^; 'xor'
		when :>>; type.specifier == :unsigned ? 'shr' : 'sar'
		when :<<; 'shl'
		when :*; 'mul'
		when :/; 'div'
		when :%; 'mod'
		end
		case op
		when 'add', 'sub', 'and', 'or', 'xor'
			r = make_volatile(r, type) if l.kind_of?(ModRM) and r.kind_of?(ModRM)
			r = make_volatile(r, type) if r.kind_of?(ModRM) and r.sz != l.sz	
			unuse r
			r = Reg.new(r.val, l.sz) if r.kind_of?(Reg) and l.kind_of?(ModRM) and l.sz and l.sz != r.sz     
			instr op, l, i_to_i32(r)
		when 'shr', 'sar', 'shl'
			if r.kind_of? Expression
				instr op, l, r
			else
				r = make_volatile(r, C::BaseType.new(:__int8, :unsigned))
				unuse r
				if r.val != 1
					rcx = Reg.new(1, 64)
					instr 'xchg', rcx, Reg.new(r.val, 64)
					l = Reg.new(r.val, l.sz) if l.kind_of? Reg and l.val == 1
				end
				instr op, l, Reg.new(1, 8)
				instr 'xchg', rcx, Reg.new(r.val, 64) if r.val != 1
			end
		when 'mul'
			if l.kind_of? ModRM
				if r.kind_of? Expression
					ll = findreg
					instr 'imul', ll, l, r
				else
					ll = make_volatile(l, type)
					unuse ll
					instr 'imul', ll, r
				end
				instr 'mov', l, ll
			else
				instr 'imul', l, r
			end
			unuse r
		when 'div', 'mod'
			lv = l.val if l.kind_of? Reg
			rax = Reg.from_str 'rax'
			rdx = Reg.from_str 'rdx'
			if @state.used.include? rax.val and lv != rax.val
				instr 'push', rax
				saved_rax = true
			end
			if @state.used.include? rdx.val and lv != rdx.val
				instr 'push', rdx
				saved_rdx = true
			end
			instr 'mov', rax, l if lv != rax.val
			if r.kind_of? Expression
				instr 'push', r
				rsp = Reg.from_str 'rsp'
				r = ModRM.new(@cpusz, 64, nil, nil, rsp, nil)
				need_pop = true
			end
			if type.specifier == :unsigned
				instr 'mov', rdx, Expression[0]
				instr 'div', r
			else
				instr 'cdq'
				instr 'idiv', r
			end
			unuse r
			instr 'add', rsp, 8 if need_pop
			if op == 'div'
				instr 'mov', l, rax if lv != rax.val
			else
				instr 'mov', l, rdx if lv != rdx.val
			end
			instr 'pop', rdx if saved_rdx
			instr 'pop', rax if saved_rax
		end
	end
def c_cexpr_inner_arith_int ( l , op , r , type ) op = case op when :+ ; 'add' when :- ; 'sub' when :& ; 'and' when :| ; 'or' when :^ ; 'xor' when :>> ; type . specifier == :unsigned ? 'shr' : 'sar' when :<< ; 'shl' when :* ; 'mul' when :/ ; 'div' when :% ; 'mod' end case op when 'add' , 'sub' , 'and' , 'or' , 'xor' r = make_volatile ( r , type ) if l . kind_of? ( ModRM ) and r . kind_of? ( ModRM ) r = make_volatile ( r , type ) if r . kind_of? ( ModRM ) and r . sz != l . sz unuse r r = Reg . new ( r . val , l . sz ) if r . kind_of? ( Reg ) and l . kind_of? ( ModRM ) and l . sz and l . sz != r . sz instr op , l , i_to_i32 ( r ) when 'shr' , 'sar' , 'shl' if r . kind_of? Expression instr op , l , r else r = make_volatile ( r , C :: BaseType . new ( :__int8 , :unsigned ) ) unuse r if r . val != 1 rcx = Reg . new ( 1 , 64 ) instr 'xchg' , rcx , Reg . new ( r . val , 64 ) l = Reg . new ( r . val , l . sz ) if l . kind_of? Reg and l . val == 1 end instr op , l , Reg . new ( 1 , 8 ) instr 'xchg' , rcx , Reg . new ( r . val , 64 ) if r . val != 1 end when 'mul' if l . kind_of? ModRM if r . kind_of? Expression ll = findreg instr 'imul' , ll , l , r else ll = make_volatile ( l , type ) unuse ll instr 'imul' , ll , r end instr 'mov' , l , ll else instr 'imul' , l , r end unuse r when 'div' , 'mod' lv = l . val if l . kind_of? Reg rax = Reg . from_str 'rax' rdx = Reg . from_str 'rdx' if @state . used . include? rax . val and lv != rax . val instr 'push' , rax saved_rax = true end if @state . used . include? rdx . val and lv != rdx . val instr 'push' , rdx saved_rdx = true end instr 'mov' , rax , l if lv != rax . val if r . kind_of? Expression instr 'push' , r rsp = Reg . from_str 'rsp' r = ModRM . new ( @cpusz , 64 , nil , nil , rsp , nil ) need_pop = true end if type . specifier == :unsigned instr 'mov' , rdx , Expression [ 0 ] instr 'div' , r else instr 'cdq' instr 'idiv' , r end unuse r instr 'add' , rsp , 8 if need_pop if op == 'div' instr 'mov' , l , rax if lv != rax . val else instr 'mov' , l , rdx if lv != rdx . val end instr 'pop' , rdx if saved_rdx instr 'pop' , rax if saved_rax end end
compile an integral arithmetic expression, reg-sized
compile an integral arithmetic expression reg - sized
# add rax, word [moo] # add byte ptr [rax], bl # XXX bouh
l
op
r
type