node/lib/metasm/metasm/cpu/ia32/compile_c.rb
# 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
			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, 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
					ecx = Reg.new(1, 32)
					instr 'xchg', ecx, Reg.new(r.val, 32)
					l = Reg.new(r.val, l.sz) if l.kind_of? Reg and l.val == 1
					@state.used.delete r.val if not @state.used.include? 1
					inuse ecx
				end
				instr op, l, Reg.new(1, 8)
				instr 'xchg', ecx, Reg.new(r.val, 32) 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
			eax = Reg.from_str 'eax'
			edx = Reg.from_str 'edx'
			if @state.used.include? eax.val and lv != eax.val
				instr 'push', eax
				saved_eax = true
			end
			if @state.used.include? edx.val and lv != edx.val
				instr 'push', edx
				saved_edx = true
			end
			instr 'mov', eax, l if lv != eax.val
			if r.kind_of? Expression
				instr 'push', r
				esp = Reg.from_str 'esp'
				r = ModRM.new(@cpusz, 32, nil, nil, esp, nil)
				need_pop = true
			end
			if type.specifier == :unsigned
				instr 'mov', edx, Expression[0]
				instr 'div', r
			else
				instr 'cdq'
				instr 'idiv', r
			end
			unuse r
			instr 'add', esp, 4 if need_pop
			if op == 'div'
				instr 'mov', l, eax if lv != eax.val
			else
				instr 'mov', l, edx if lv != edx.val
			end
			instr 'pop', edx if saved_edx
			instr 'pop', eax if saved_eax
		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 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 , 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 ecx = Reg . new ( 1 , 32 ) instr 'xchg' , ecx , Reg . new ( r . val , 32 ) l = Reg . new ( r . val , l . sz ) if l . kind_of? Reg and l . val == 1 @state . used . delete r . val if not @state . used . include? 1 inuse ecx end instr op , l , Reg . new ( 1 , 8 ) instr 'xchg' , ecx , Reg . new ( r . val , 32 ) 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 eax = Reg . from_str 'eax' edx = Reg . from_str 'edx' if @state . used . include? eax . val and lv != eax . val instr 'push' , eax saved_eax = true end if @state . used . include? edx . val and lv != edx . val instr 'push' , edx saved_edx = true end instr 'mov' , eax , l if lv != eax . val if r . kind_of? Expression instr 'push' , r esp = Reg . from_str 'esp' r = ModRM . new ( @cpusz , 32 , nil , nil , esp , nil ) need_pop = true end if type . specifier == :unsigned instr 'mov' , edx , Expression [ 0 ] instr 'div' , r else instr 'cdq' instr 'idiv' , r end unuse r instr 'add' , esp , 4 if need_pop if op == 'div' instr 'mov' , l , eax if lv != eax . val else instr 'mov' , l , edx if lv != edx . val end instr 'pop' , edx if saved_edx instr 'pop' , eax if saved_eax end end
compile an integral arithmetic expression, reg-sized
compile an integral arithmetic expression reg - sized
# add byte ptr [eax], bl # XXX bouh
l
op
r
type