node/lib/metasm/metasm/cpu/ia32/compile_c.rb
# compile an integral arithmetic 64-bits expression on a non-64 cpu
compile an integral arithmetic 64-bits expression on a non-64 cpu
compile an integral arithmetic 64 - bits expression on a non - 64 cpu
def c_cexpr_inner_arith_int64compose(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
		ll, lh = get_composite_parts l
		r = make_volatile(r, C::BaseType.new("__int#{r.sz}".to_sym)) if l.kind_of? ModRM and r.kind_of? ModRM
		rl, rh = get_composite_parts(r) if not r.kind_of? Reg
		case op
		when 'add', 'sub', 'and', 'or', 'xor'
			unuse r
			instr op, ll, rl
			op = {'add' => 'adc', 'sub' => 'sbb'}[op] || op
			instr op, lh, rh unless (op == 'or' or op == 'xor') and rh.kind_of?(Expression) and rh.reduce == 0
		when 'shl', 'shr', 'sar'
			rlc = r.reduce if r.kind_of? Expression
			opd = { 'shl' => 'shld', 'shr' => 'shrd', 'sar' => 'shrd' }[op]
			ll, lh = lh, ll if op != 'shl'	
			llv = ll
			if llv.kind_of? ModRM
				llv = make_volatile(llv, C::BaseType.new(:__int32))
				inuse ll
			end
			if rlc.kind_of? Integer
				case rlc
				when 0
				when 1..31
					instr opd, llv, lh, Expression[rlc]
					instr op, ll, Expression[rlc]
				when 32..63
					instr 'mov', lh, llv
					if op == 'sar'
						instr 'sar', ll, Expression[31]
					else
						instr 'mov', ll, Expression[0]
					end
					instr op, lh, Expression[rlc-32] if rlc != 32
				else
					if op == 'sar'
						instr 'sar', ll, Expression[31]
						instr 'mov', lh, llv
					else
						instr 'mov', ll, Expression[0]
						instr 'mov', lh, Expression[0]
					end
				end
			else
				r = make_volatile(r, C::BaseType.new(:__int8, :unsigned))
				r = r.low if r.kind_of? Composite
				rl ||= r
				cl = Reg.new(1, 8)
				ecx = Reg.new(1, 32)
				if r.val != 1
					instr 'xchg', ecx, Reg.new(r.val, 32)
					lh  = Reg.new(r.val, lh.sz)  if lh.kind_of?(Reg)  and lh.val == 1
					ll  = Reg.new(r.val, ll.sz)  if ll.kind_of?(Reg)  and ll.val == 1
					llv = Reg.new(r.val, llv.sz) if llv.kind_of?(Reg) and llv.val == 1
					@state.used.delete r.val if not @state.used.include? 1
					inuse ecx
				end
				labelh = new_label('shldh')
				labeld = new_label('shldd')
				instr 'test', ecx, Expression[0x20]
				instr 'jnz', Expression[labelh]
				instr opd, llv, lh, cl
				instr op, ll, cl
				instr 'jmp', Expression[labeld]
				@source << Label.new(labelh)
				instr op, llv, cl
				instr 'mov', lh, llv
				if op == 'sar'
					instr 'sar', ll, Expression[31]
				else
					instr 'mov', ll, Expression[0]
				end
				@source << Label.new(labeld)
				instr 'xchg', ecx, Reg.new(r.val, 32) if r.val != 1
				unuse ecx
				unuse r
			end
		when 'mul'
			t1 = findreg(32)
			t2 = findreg(32)
			unuse t1, t2, r
			instr 'mov',  t1, ll
			instr 'mov',  t2, rl
			instr 'imul', t1, rh
			instr 'imul', t2, lh
			instr 'add',  t1, t2
			raise 
			instr 'mov',  eax, ll
			if rl.kind_of? Expression
				instr 'mov', t2, rl
				instr 'mul', t2
			else
				instr 'mul',  rl
			end
			instr 'add', t1, edx
			instr 'mov', lh, t1
			instr 'mov', ll, eax
		when 'div'
			raise 
		when 'mod'
			raise 
		end
	end
def c_cexpr_inner_arith_int64compose ( 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 ll , lh = get_composite_parts l r = make_volatile ( r , C :: BaseType . new ( "__int#{r.sz}" . to_sym ) ) if l . kind_of? ModRM and r . kind_of? ModRM rl , rh = get_composite_parts ( r ) if not r . kind_of? Reg case op when 'add' , 'sub' , 'and' , 'or' , 'xor' unuse r instr op , ll , rl op = { 'add' => 'adc' , 'sub' => 'sbb' } [ op ] || op instr op , lh , rh unless ( op == 'or' or op == 'xor' ) and rh . kind_of? ( Expression ) and rh . reduce == 0 when 'shl' , 'shr' , 'sar' rlc = r . reduce if r . kind_of? Expression opd = { 'shl' => 'shld' , 'shr' => 'shrd' , 'sar' => 'shrd' } [ op ] ll , lh = lh , ll if op != 'shl' llv = ll if llv . kind_of? ModRM llv = make_volatile ( llv , C :: BaseType . new ( :__int32 ) ) inuse ll end if rlc . kind_of? Integer case rlc when 0 when 1 .. 31 instr opd , llv , lh , Expression [ rlc ] instr op , ll , Expression [ rlc ] when 32 .. 63 instr 'mov' , lh , llv if op == 'sar' instr 'sar' , ll , Expression [ 31 ] else instr 'mov' , ll , Expression [ 0 ] end instr op , lh , Expression [ rlc - 32 ] if rlc != 32 else if op == 'sar' instr 'sar' , ll , Expression [ 31 ] instr 'mov' , lh , llv else instr 'mov' , ll , Expression [ 0 ] instr 'mov' , lh , Expression [ 0 ] end end else r = make_volatile ( r , C :: BaseType . new ( :__int8 , :unsigned ) ) r = r . low if r . kind_of? Composite rl ||= r cl = Reg . new ( 1 , 8 ) ecx = Reg . new ( 1 , 32 ) if r . val != 1 instr 'xchg' , ecx , Reg . new ( r . val , 32 ) lh = Reg . new ( r . val , lh . sz ) if lh . kind_of? ( Reg ) and lh . val == 1 ll = Reg . new ( r . val , ll . sz ) if ll . kind_of? ( Reg ) and ll . val == 1 llv = Reg . new ( r . val , llv . sz ) if llv . kind_of? ( Reg ) and llv . val == 1 @state . used . delete r . val if not @state . used . include? 1 inuse ecx end labelh = new_label ( 'shldh' ) labeld = new_label ( 'shldd' ) instr 'test' , ecx , Expression [ 0x20 ] instr 'jnz' , Expression [ labelh ] instr opd , llv , lh , cl instr op , ll , cl instr 'jmp' , Expression [ labeld ] @source << Label . new ( labelh ) instr op , llv , cl instr 'mov' , lh , llv if op == 'sar' instr 'sar' , ll , Expression [ 31 ] else instr 'mov' , ll , Expression [ 0 ] end @source << Label . new ( labeld ) instr 'xchg' , ecx , Reg . new ( r . val , 32 ) if r . val != 1 unuse ecx unuse r end when 'mul' t1 = findreg ( 32 ) t2 = findreg ( 32 ) unuse t1 , t2 , r instr 'mov' , t1 , ll instr 'mov' , t2 , rl instr 'imul' , t1 , rh instr 'imul' , t2 , lh instr 'add' , t1 , t2 raise instr 'mov' , eax , ll if rl . kind_of? Expression instr 'mov' , t2 , rl instr 'mul' , t2 else instr 'mul' , rl end instr 'add' , t1 , edx instr 'mov' , lh , t1 instr 'mov' , ll , eax when 'div' raise when 'mod' raise end end
compile an integral arithmetic 64-bits expression on a non-64 cpu
compile an integral arithmetic 64 - bits expression on a non - 64 cpu
# 1ULL << 2 -> 2 is not ULL # OMGHAX # high = (low1*high2) + (high1*low2) + (low1*low2).high # TODO push eax/edx, mul, pop # TODO # TODO
l
op
r
type