about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorserpilliere <devnull@localhost>2011-07-27 11:12:04 +0200
committerserpilliere <devnull@localhost>2011-07-27 11:12:04 +0200
commit066972d7f1e30792256c137ad2417a0adaee7753 (patch)
treec2d020ed21b556e8e5c926aa2dc97ce34dc4885a
downloadmiasm-066972d7f1e30792256c137ad2417a0adaee7753.tar.gz
miasm-066972d7f1e30792256c137ad2417a0adaee7753.zip
realease commit
-rw-r--r--README.org58
-rw-r--r--doc/Makefile126
-rw-r--r--doc/bigcenter.sty7
-rw-r--r--doc/figs/calc_mod.epsbin0 -> 13021 bytes
-rw-r--r--doc/figs/calc_mod.pngbin0 -> 12965 bytes
-rw-r--r--doc/figs/conficker_1.epsbin0 -> 16222 bytes
-rw-r--r--doc/figs/conficker_1.pngbin0 -> 19420 bytes
-rw-r--r--doc/figs/conficker_2.epsbin0 -> 17230 bytes
-rw-r--r--doc/figs/conficker_2.pngbin0 -> 10625 bytes
-rw-r--r--doc/figs/conficker_3.epsbin0 -> 18022 bytes
-rw-r--r--doc/figs/conficker_3.pngbin0 -> 11340 bytes
-rw-r--r--doc/figs/conficker_4.epsbin0 -> 42304 bytes
-rw-r--r--doc/figs/conficker_4.pngbin0 -> 30877 bytes
-rw-r--r--doc/figs/conficker_5.epsbin0 -> 5162 bytes
-rw-r--r--doc/figs/conficker_5.pngbin0 -> 699 bytes
-rw-r--r--doc/figs/gandalf_01.epsbin0 -> 49849 bytes
-rw-r--r--doc/figs/gandalf_01.pngbin0 -> 59766 bytes
-rw-r--r--doc/figs/gen_graph.epsbin0 -> 10768 bytes
-rw-r--r--doc/figs/gen_graph.pngbin0 -> 9348 bytes
-rw-r--r--doc/figs/ircbot_1.epsbin0 -> 103647 bytes
-rw-r--r--doc/figs/ircbot_1.pngbin0 -> 95747 bytes
-rw-r--r--doc/figs/ircbot_2.epsbin0 -> 43182 bytes
-rw-r--r--doc/figs/ircbot_2.pngbin0 -> 18120 bytes
-rw-r--r--doc/figs/ishield_unpacked.epsbin0 -> 40447 bytes
-rw-r--r--doc/figs/ishield_unpacked.pngbin0 -> 1395 bytes
-rw-r--r--doc/figs/mebroot_0.epsbin0 -> 21292 bytes
-rw-r--r--doc/figs/mebroot_0.pngbin0 -> 1357 bytes
-rw-r--r--doc/figs/mebroot_1.epsbin0 -> 9003 bytes
-rw-r--r--doc/figs/mebroot_1.pngbin0 -> 8289 bytes
-rw-r--r--doc/figs/mebroot_2.epsbin0 -> 11735 bytes
-rw-r--r--doc/figs/mebroot_2.pngbin0 -> 13332 bytes
-rw-r--r--doc/figs/mebroot_3.epsbin0 -> 46136 bytes
-rw-r--r--doc/figs/mebroot_3.pngbin0 -> 66841 bytes
-rw-r--r--doc/figs/mebroot_4.epsbin0 -> 4707 bytes
-rw-r--r--doc/figs/mebroot_4.pngbin0 -> 675 bytes
-rw-r--r--doc/figs/mebroot_5.epsbin0 -> 4643 bytes
-rw-r--r--doc/figs/mebroot_5.pngbin0 -> 588 bytes
-rw-r--r--doc/figs/mebroot_6.epsbin0 -> 23105 bytes
-rw-r--r--doc/figs/mebroot_6.pngbin0 -> 31420 bytes
-rw-r--r--doc/figs/mebroot_7.epsbin0 -> 4717 bytes
-rw-r--r--doc/figs/mebroot_7.pngbin0 -> 641 bytes
-rw-r--r--doc/figs/mebroot_obf_01.eps204
-rw-r--r--doc/figs/mebroot_obf_01.pngbin0 -> 65045 bytes
-rw-r--r--doc/figs/mebroot_obfdel_01.eps205
-rw-r--r--doc/figs/mebroot_obfdel_01.pngbin0 -> 46641 bytes
-rw-r--r--doc/figs/msgbox.epsbin0 -> 5351 bytes
-rw-r--r--doc/figs/msgbox.pngbin0 -> 1363 bytes
-rw-r--r--doc/figs/pe_format.epsbin0 -> 11936 bytes
-rw-r--r--doc/figs/pe_format.gifbin0 -> 7421 bytes
-rw-r--r--doc/figs/xxx_mnemo01.epsbin0 -> 19211 bytes
-rw-r--r--doc/figs/xxx_mnemo01.pngbin0 -> 18909 bytes
-rw-r--r--doc/figs/xxx_mnemo02.epsbin0 -> 20579 bytes
-rw-r--r--doc/figs/xxx_mnemo02.pngbin0 -> 23846 bytes
-rw-r--r--doc/figs/xxx_mnemo03.epsbin0 -> 14283 bytes
-rw-r--r--doc/figs/xxx_mnemo03.pngbin0 -> 12521 bytes
-rw-r--r--doc/figs/xxx_mnemo04.epsbin0 -> 47536 bytes
-rw-r--r--doc/figs/xxx_mnemo04.pngbin0 -> 55461 bytes
-rw-r--r--doc/figs/xxx_mnemo05.epsbin0 -> 40588 bytes
-rw-r--r--doc/figs/xxx_mnemo05.pngbin0 -> 46199 bytes
-rw-r--r--doc/figs/xxx_mnemo06.epsbin0 -> 34383 bytes
-rw-r--r--doc/figs/xxx_mnemo06.pngbin0 -> 40100 bytes
-rw-r--r--doc/figs/xxx_mnemo07.epsbin0 -> 91958 bytes
-rw-r--r--doc/figs/xxx_mnemo07.pngbin0 -> 101083 bytes
-rw-r--r--doc/figs/xxx_mnemo08.epsbin0 -> 20055 bytes
-rw-r--r--doc/figs/xxx_mnemo08.pngbin0 -> 19663 bytes
-rw-r--r--doc/figs/xxx_mnemo09.epsbin0 -> 14057 bytes
-rw-r--r--doc/figs/xxx_mnemo09.pngbin0 -> 13620 bytes
-rw-r--r--doc/figs/xxx_mnemo10.epsbin0 -> 26433 bytes
-rw-r--r--doc/figs/xxx_mnemo10.pngbin0 -> 26169 bytes
-rw-r--r--doc/figs/xxx_vm01.epsbin0 -> 16512 bytes
-rw-r--r--doc/figs/xxx_vm01.pngbin0 -> 20414 bytes
-rw-r--r--doc/slides.tex2243
-rwxr-xr-xexample/asm_arm.py68
-rwxr-xr-xexample/asm_x86.py76
-rwxr-xr-xexample/disas_and_graph.py79
-rw-r--r--example/sandbox_elf.py117
-rw-r--r--example/sandbox_pe.py125
-rw-r--r--miasm/__init__.py20
-rw-r--r--miasm/arch/__init__.py20
-rw-r--r--miasm/arch/arm_arch.py2054
-rw-r--r--miasm/arch/arm_sem.py621
-rw-r--r--miasm/arch/ia32_arch.py2223
-rw-r--r--miasm/arch/ia32_reg.py159
-rw-r--r--miasm/arch/ia32_sem.py2136
-rw-r--r--miasm/arch/ppc_arch.py2294
-rw-r--r--miasm/core/__init__.py20
-rw-r--r--miasm/core/asmbloc.py1364
-rw-r--r--miasm/core/bin_stream.py101
-rw-r--r--miasm/core/memory_pool.py283
-rw-r--r--miasm/core/parse_ad.py343
-rw-r--r--miasm/core/parse_asm.py232
-rw-r--r--miasm/expression/__init__.py18
-rw-r--r--miasm/expression/expression.py754
-rw-r--r--miasm/expression/expression_eval_abstract.py797
-rw-r--r--miasm/expression/expression_helper.py646
-rw-r--r--miasm/graph/__init__.py18
-rwxr-xr-xmiasm/graph/graph_qt.py806
-rw-r--r--miasm/tools/__init__.py18
-rw-r--r--miasm/tools/codenat.py160
-rwxr-xr-xmiasm/tools/emul_helper.py679
-rw-r--r--miasm/tools/emul_lib/Makefile20
-rw-r--r--miasm/tools/emul_lib/__init__.py18
-rw-r--r--miasm/tools/emul_lib/libcodenat.c1305
-rw-r--r--miasm/tools/emul_lib/libcodenat.h452
-rw-r--r--miasm/tools/emul_lib/libcodenat_interface.c1108
-rw-r--r--miasm/tools/emul_lib/libcodenat_tcc.c139
-rw-r--r--miasm/tools/emul_lib/main.c43
-rw-r--r--miasm/tools/emul_lib/queue.h553
-rwxr-xr-xmiasm/tools/func_analyser.py485
-rwxr-xr-xmiasm/tools/hook_helper.py237
-rw-r--r--miasm/tools/nux_api.py917
-rw-r--r--miasm/tools/pe_helper.py593
-rw-r--r--miasm/tools/seh_helper.py348
-rw-r--r--miasm/tools/to_c_helper.py1024
-rw-r--r--miasm/tools/win_api.py1509
-rwxr-xr-xsetup.py29
116 files changed, 27854 insertions, 0 deletions
diff --git a/README.org b/README.org
new file mode 100644
index 00000000..53100a0f
--- /dev/null
+++ b/README.org
@@ -0,0 +1,58 @@
+#+LANGUAGE: en
+#+OPTIONS: H:3 num:nil toc:nil \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t
+#+OPTIONS: TeX:t LaTeX:nil skip:nil d:nil todo:t pri:nil tags:not-in-toc
+#+EXPORT_EXCLUDE_TAGS: exclude
+#+STARTUP: showall
+
+* What is Miasm?
+Miasm is a a free and open source (GPLv2) reverse engineering framework.
+
+Miasm aims at analyzing/modifying/generating binary programs. Here is
+a non exhausting list of features:
+ - opening/modifying/generating PE/ELF 32/64 le/be using Elfesteem
+ - Assembling/Disassembling ia32/ppc/arm
+ - Representing assembly semantic using intermediate language
+ - Emulating using jit (dynamic code analysis, unpacking, ...)
+ - Expression simplification for automatic de-obfuscation
+ - Graphic disassembler using Grandalf
+ - ...
+
+* How does it work?
+Miasm embed its own disassembler, intermediate language and
+instruction semantic. It is written in Python.  
+
+To emulate code, it uses libtcc to jit C code generate from
+intermediate representation. It can emulate shellcodes, parts of
+binaries. Python callback can be executed to emulate library
+functions.
+
+* Documentation
+Documentation can be found under =doc/=.
+
+* Obtain Miasm
+
+* Software requirements
+Miasm uses:
+
+Grandalf (https://github.com/bdcht/grandalf.git) in order to render
+graphical disassembler.
+
+libtcc (http://bellard.org/tcc/) to Jit code for emulation mode. 
+
+python-ply for parsing
+
+numpy
+
+* Configuration
+Install libtcc
+clone grandalf repository
+set path:
+$ export PYTHONPATH=$PYTHONPATH:path_to_miasm:path_to_elfesteem
+
+Compile miasm emulation library:
+$ cd tools/emul_lib
+$ make
+
+* Misc
+Man, does miasm has a link with rr0d?
+Yes! crappy code and uggly documentation.
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 00000000..33d125a1
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,126 @@
+## Makefile for LaTeX presentations.
+## 
+## Will compile the LaTeX file as many times as necessary.
+## if FAST=1, always compile once
+##
+## The postscript :
+##    make mypres.ps
+## The PDF, compile only once, even if the TOC or references are outdated
+##    make mypres.pdf FAST=1
+## The PDF, 4 slides per page, A4
+##    make mypres.a4.4.pdf
+## The web page (create a directory, needs album: apt-get install album)
+##    make mypres.www
+##
+## <phil(at)secdev.org>
+
+PSNUPOPTS=-W128mm -H96mm -pa4 -m0.5cm -b0.2cm -d
+FORMAT ?= 1
+
+XFIG_FIGS=$(patsubst %.fig,%.eps,$(wildcard fig/*.fig))
+DIA_FIGS=$(patsubst %.dia,%.eps,$(wildcard fig/*.dia))
+ALL_FIGS=$(XFIG_FIGS) $(DIA_FIGS)
+
+all:
+	@echo 'USAGE: make <filename.ext> [FAST=1]'
+	@echo 'possible extentions :'
+	@echo ' .dvi, .ps or .pdf'
+	@echo ' .www to create a directory with web pages'
+	@echo ' .a4.n.pdf with n in 1-4,6,8,9,16,32 for n slides per page'
+
+
+.SUFFIXES: .pdf .tex .ps .dvi .www .eps .fig
+
+# cancel built-in implicit rule tex -> dvi
+%.dvi:%.tex
+
+%.eps: %.fig
+	fig2dev -L eps $< $@
+
+%.eps: %.dia
+	dia -e $@ $<
+
+%.pdf: %.ps
+	ps2pdf $*.ps
+
+%.ps: %.dvi
+	dvips -Ppdf $*
+
+%.dvi: %.tex $(ALL_FIGS)
+	[ -e $*.aux ] || touch $*.aux 
+	while true; do                           \
+		cp $*.aux $*.aux2               ;\
+		echo $(FORMAT) | latex $* || { rm $*.aux2 ; break; }; \
+		cmp $*.aux $*.aux2 && break     ;\
+		[ -z "$(FAST)" ] || break       ;\
+	done
+	@# if .aux2 does not exist, there was an error. Next line will be false.
+	@[ -e $*.aux2 ] && rm $*.aux2
+	@echo "#######[ warnings ]#######"
+	@grep -i warning $*.log
+	@echo "##########################"
+
+
+%.a4.0.ps: %.dvi
+	dvips -Ppdf -ta4 $* -o $@
+
+%.a4.1.ps: %.a4.0.ps
+	psnup $(PSNUPOPTS) -1  $< $@
+
+%.a4.2.ps: %.a4.0.ps
+	psnup $(PSNUPOPTS) -2  $< $@
+
+%.a4.3.ps: %.a4.0.ps
+	psnup $(PSNUPOPTS) -3  $< $@
+
+%.a4.4.ps: %.a4.0.ps
+	psnup $(PSNUPOPTS) -4  $< $@
+
+%.a4.6.ps: %.a4.0.ps
+	psnup $(PSNUPOPTS) -6  $< $@
+
+%.a4.8.ps: %.a4.0.ps
+	psnup $(PSNUPOPTS) -8  $< $@
+
+%.a4.9.ps: %.a4.0.ps
+	psnup $(PSNUPOPTS) -9  $< $@
+
+%.a4.16.ps: %.a4.0.ps
+	psnup $(PSNUPOPTS) -16  $< $@
+
+%.a4.24.ps: %.a4.0.ps
+	psnup $(PSNUPOPTS) -24  $< $@
+
+%.a4.32.ps: %.a4.0.ps
+	psnup $(PSNUPOPTS) -32  $< $@
+
+%.a4.ps: %.a4.0.ps
+	mv $< $@
+
+%.jpg: %.ppm
+	convert $< $@
+
+# gs or pdftoppm ? pdftoppm : better fonts, graphics not anti-aliased
+#gs -dBATCH -dNOPAUSE -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -sDEVICE=png16m -sOutputFile=$@/$@-%04d.png -r150  $<
+%.www: %.pdf
+	[ -e $@ ] && rm -rf $@ || true
+	mkdir $@
+	pdftoppm $< $@/$@
+	$(MAKE) alljpg PPMDIR=$@
+	rm $@/*.ppm
+	cd $@ ; album -geometry 200x150
+
+alljpg: 
+	@$(MAKE) $(patsubst %.ppm,%.jpg, $(wildcard $(PPMDIR)/*.ppm))
+
+
+.PRECIOUS: %.dvi %.ps %.pdf %.eps
+
+.PHONY: clean,test
+
+clean:
+	rm -f *.toc *.aux *.vrb *.snm *.log *.out *.nav *.ps *.dvi
+
+
+overclean: clean
+	rm -f *.pdf
diff --git a/doc/bigcenter.sty b/doc/bigcenter.sty
new file mode 100644
index 00000000..536c7bd2
--- /dev/null
+++ b/doc/bigcenter.sty
@@ -0,0 +1,7 @@
+\newskip\@bigflushglue \@bigflushglue = -100pt plus 1fil
+
+\def\bigcenter{\trivlist \bigcentering\item\relax}
+\def\bigcentering{\let\\\@centercr\rightskip\@bigflushglue%
+\leftskip\@bigflushglue
+\parindent\z@\parfillskip\z@skip}
+\def\endbigcenter{\endtrivlist}
diff --git a/doc/figs/calc_mod.eps b/doc/figs/calc_mod.eps
new file mode 100644
index 00000000..4f3ddfe1
--- /dev/null
+++ b/doc/figs/calc_mod.eps
Binary files differdiff --git a/doc/figs/calc_mod.png b/doc/figs/calc_mod.png
new file mode 100644
index 00000000..40a09804
--- /dev/null
+++ b/doc/figs/calc_mod.png
Binary files differdiff --git a/doc/figs/conficker_1.eps b/doc/figs/conficker_1.eps
new file mode 100644
index 00000000..e3370063
--- /dev/null
+++ b/doc/figs/conficker_1.eps
Binary files differdiff --git a/doc/figs/conficker_1.png b/doc/figs/conficker_1.png
new file mode 100644
index 00000000..73bb2711
--- /dev/null
+++ b/doc/figs/conficker_1.png
Binary files differdiff --git a/doc/figs/conficker_2.eps b/doc/figs/conficker_2.eps
new file mode 100644
index 00000000..115c00ba
--- /dev/null
+++ b/doc/figs/conficker_2.eps
Binary files differdiff --git a/doc/figs/conficker_2.png b/doc/figs/conficker_2.png
new file mode 100644
index 00000000..d5f990e5
--- /dev/null
+++ b/doc/figs/conficker_2.png
Binary files differdiff --git a/doc/figs/conficker_3.eps b/doc/figs/conficker_3.eps
new file mode 100644
index 00000000..a8008da6
--- /dev/null
+++ b/doc/figs/conficker_3.eps
Binary files differdiff --git a/doc/figs/conficker_3.png b/doc/figs/conficker_3.png
new file mode 100644
index 00000000..9d9aded2
--- /dev/null
+++ b/doc/figs/conficker_3.png
Binary files differdiff --git a/doc/figs/conficker_4.eps b/doc/figs/conficker_4.eps
new file mode 100644
index 00000000..d41d2cf5
--- /dev/null
+++ b/doc/figs/conficker_4.eps
Binary files differdiff --git a/doc/figs/conficker_4.png b/doc/figs/conficker_4.png
new file mode 100644
index 00000000..a1fce082
--- /dev/null
+++ b/doc/figs/conficker_4.png
Binary files differdiff --git a/doc/figs/conficker_5.eps b/doc/figs/conficker_5.eps
new file mode 100644
index 00000000..91e3ec0b
--- /dev/null
+++ b/doc/figs/conficker_5.eps
Binary files differdiff --git a/doc/figs/conficker_5.png b/doc/figs/conficker_5.png
new file mode 100644
index 00000000..5f572e25
--- /dev/null
+++ b/doc/figs/conficker_5.png
Binary files differdiff --git a/doc/figs/gandalf_01.eps b/doc/figs/gandalf_01.eps
new file mode 100644
index 00000000..a03c2ae1
--- /dev/null
+++ b/doc/figs/gandalf_01.eps
Binary files differdiff --git a/doc/figs/gandalf_01.png b/doc/figs/gandalf_01.png
new file mode 100644
index 00000000..ca7cc215
--- /dev/null
+++ b/doc/figs/gandalf_01.png
Binary files differdiff --git a/doc/figs/gen_graph.eps b/doc/figs/gen_graph.eps
new file mode 100644
index 00000000..fb1de3a7
--- /dev/null
+++ b/doc/figs/gen_graph.eps
Binary files differdiff --git a/doc/figs/gen_graph.png b/doc/figs/gen_graph.png
new file mode 100644
index 00000000..a6dc416b
--- /dev/null
+++ b/doc/figs/gen_graph.png
Binary files differdiff --git a/doc/figs/ircbot_1.eps b/doc/figs/ircbot_1.eps
new file mode 100644
index 00000000..9795355d
--- /dev/null
+++ b/doc/figs/ircbot_1.eps
Binary files differdiff --git a/doc/figs/ircbot_1.png b/doc/figs/ircbot_1.png
new file mode 100644
index 00000000..9da4d445
--- /dev/null
+++ b/doc/figs/ircbot_1.png
Binary files differdiff --git a/doc/figs/ircbot_2.eps b/doc/figs/ircbot_2.eps
new file mode 100644
index 00000000..a75180c0
--- /dev/null
+++ b/doc/figs/ircbot_2.eps
Binary files differdiff --git a/doc/figs/ircbot_2.png b/doc/figs/ircbot_2.png
new file mode 100644
index 00000000..83de6c06
--- /dev/null
+++ b/doc/figs/ircbot_2.png
Binary files differdiff --git a/doc/figs/ishield_unpacked.eps b/doc/figs/ishield_unpacked.eps
new file mode 100644
index 00000000..b866983b
--- /dev/null
+++ b/doc/figs/ishield_unpacked.eps
Binary files differdiff --git a/doc/figs/ishield_unpacked.png b/doc/figs/ishield_unpacked.png
new file mode 100644
index 00000000..0784ff27
--- /dev/null
+++ b/doc/figs/ishield_unpacked.png
Binary files differdiff --git a/doc/figs/mebroot_0.eps b/doc/figs/mebroot_0.eps
new file mode 100644
index 00000000..6ec74639
--- /dev/null
+++ b/doc/figs/mebroot_0.eps
Binary files differdiff --git a/doc/figs/mebroot_0.png b/doc/figs/mebroot_0.png
new file mode 100644
index 00000000..4f29c757
--- /dev/null
+++ b/doc/figs/mebroot_0.png
Binary files differdiff --git a/doc/figs/mebroot_1.eps b/doc/figs/mebroot_1.eps
new file mode 100644
index 00000000..a6980bc6
--- /dev/null
+++ b/doc/figs/mebroot_1.eps
Binary files differdiff --git a/doc/figs/mebroot_1.png b/doc/figs/mebroot_1.png
new file mode 100644
index 00000000..48a8f1b0
--- /dev/null
+++ b/doc/figs/mebroot_1.png
Binary files differdiff --git a/doc/figs/mebroot_2.eps b/doc/figs/mebroot_2.eps
new file mode 100644
index 00000000..181a0a5b
--- /dev/null
+++ b/doc/figs/mebroot_2.eps
Binary files differdiff --git a/doc/figs/mebroot_2.png b/doc/figs/mebroot_2.png
new file mode 100644
index 00000000..9fe802a8
--- /dev/null
+++ b/doc/figs/mebroot_2.png
Binary files differdiff --git a/doc/figs/mebroot_3.eps b/doc/figs/mebroot_3.eps
new file mode 100644
index 00000000..754c0af3
--- /dev/null
+++ b/doc/figs/mebroot_3.eps
Binary files differdiff --git a/doc/figs/mebroot_3.png b/doc/figs/mebroot_3.png
new file mode 100644
index 00000000..c663f0ed
--- /dev/null
+++ b/doc/figs/mebroot_3.png
Binary files differdiff --git a/doc/figs/mebroot_4.eps b/doc/figs/mebroot_4.eps
new file mode 100644
index 00000000..39d1ab70
--- /dev/null
+++ b/doc/figs/mebroot_4.eps
Binary files differdiff --git a/doc/figs/mebroot_4.png b/doc/figs/mebroot_4.png
new file mode 100644
index 00000000..6b152c06
--- /dev/null
+++ b/doc/figs/mebroot_4.png
Binary files differdiff --git a/doc/figs/mebroot_5.eps b/doc/figs/mebroot_5.eps
new file mode 100644
index 00000000..d268e4fe
--- /dev/null
+++ b/doc/figs/mebroot_5.eps
Binary files differdiff --git a/doc/figs/mebroot_5.png b/doc/figs/mebroot_5.png
new file mode 100644
index 00000000..e5f31422
--- /dev/null
+++ b/doc/figs/mebroot_5.png
Binary files differdiff --git a/doc/figs/mebroot_6.eps b/doc/figs/mebroot_6.eps
new file mode 100644
index 00000000..c1abf406
--- /dev/null
+++ b/doc/figs/mebroot_6.eps
Binary files differdiff --git a/doc/figs/mebroot_6.png b/doc/figs/mebroot_6.png
new file mode 100644
index 00000000..734b1df9
--- /dev/null
+++ b/doc/figs/mebroot_6.png
Binary files differdiff --git a/doc/figs/mebroot_7.eps b/doc/figs/mebroot_7.eps
new file mode 100644
index 00000000..49f0d8ac
--- /dev/null
+++ b/doc/figs/mebroot_7.eps
Binary files differdiff --git a/doc/figs/mebroot_7.png b/doc/figs/mebroot_7.png
new file mode 100644
index 00000000..80124211
--- /dev/null
+++ b/doc/figs/mebroot_7.png
Binary files differdiff --git a/doc/figs/mebroot_obf_01.eps b/doc/figs/mebroot_obf_01.eps
new file mode 100644
index 00000000..47260ddd
--- /dev/null
+++ b/doc/figs/mebroot_obf_01.eps
@@ -0,0 +1,204 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: (ImageMagick)
+%%Title: (mebroot_obf_01.eps)
+%%CreationDate: (2010-01-22T11:25:52+01:00)
+%%BoundingBox: 0 0 605 613
+%%HiResBoundingBox: 0 0 605 613
+%%LanguageLevel: 2
+%%Pages: 1
+%%EndComments
+
+%%BeginDefaults
+%%EndDefaults
+
+%%BeginProlog
+%
+% Display a color image.  The image is displayed in color on
+% Postscript viewers or printers that support color, otherwise
+% it is displayed as grayscale.
+%
+/DirectClassImage
+{
+  %
+  % Display a DirectClass image.
+  %
+  colorspace 0 eq
+  {
+    /DeviceRGB setcolorspace
+    <<
+      /ImageType 1
+      /Width columns
+      /Height rows
+      /BitsPerComponent 8
+      /Decode [0 1 0 1 0 1]
+      /ImageMatrix [columns 0 0 rows neg 0 rows]
+      compression 0 gt
+      { /DataSource pixel_stream /RunLengthDecode filter }
+      { /DataSource pixel_stream /RunLengthDecode filter } ifelse
+    >> image
+  }
+  {
+    /DeviceCMYK setcolorspace
+    <<
+      /ImageType 1
+      /Width columns
+      /Height rows
+      /BitsPerComponent 8
+      /Decode [1 0 1 0 1 0 1 0]
+      /ImageMatrix [columns 0 0 rows neg 0 rows]
+      compression 0 gt
+      { /DataSource pixel_stream /RunLengthDecode filter }
+      { /DataSource pixel_stream /RunLengthDecode filter } ifelse
+    >> image
+  } ifelse
+} bind def
+
+/PseudoClassImage
+{
+  %
+  % Display a PseudoClass image.
+  %
+  % Parameters:
+  %   colors: number of colors in the colormap.
+  %
+  currentfile buffer readline pop
+  token pop /colors exch def pop
+  colors 0 eq
+  {
+    %
+    % Image is grayscale.
+    %
+    currentfile buffer readline pop
+    token pop /bits exch def pop
+    /DeviceGray setcolorspace
+    <<
+      /ImageType 1
+      /Width columns
+      /Height rows
+      /BitsPerComponent bits
+      /Decode [0 1]
+      /ImageMatrix [columns 0 0 rows neg 0 rows]
+      compression 0 gt
+      { /DataSource pixel_stream /RunLengthDecode filter }
+      {
+        /DataSource pixel_stream /RunLengthDecode filter
+        <<
+           /K -1
+           /Columns columns
+           /Rows rows
+        >> /CCITTFaxDecode filter
+      } ifelse
+    >> image
+  }
+  {
+    %
+    % Parameters:
+    %   colormap: red, green, blue color packets.
+    %
+    /colormap colors 3 mul string def
+    currentfile colormap readhexstring pop pop
+    currentfile buffer readline pop
+    [ /Indexed /DeviceRGB colors 1 sub colormap ] setcolorspace
+    <<
+      /ImageType 1
+      /Width columns
+      /Height rows
+      /BitsPerComponent 8
+      /Decode [0 255]
+      /ImageMatrix [columns 0 0 rows neg 0 rows]
+      compression 0 gt
+      { /DataSource pixel_stream /RunLengthDecode filter }
+      { /DataSource pixel_stream /RunLengthDecode filter } ifelse
+    >> image
+  } ifelse
+} bind def
+
+/DisplayImage
+{
+  %
+  % Display a DirectClass or PseudoClass image.
+  %
+  % Parameters:
+  %   x & y translation.
+  %   x & y scale.
+  %   label pointsize.
+  %   image label.
+  %   image columns & rows.
+  %   class: 0-DirectClass or 1-PseudoClass.
+  %   colorspace: 0-RGB or 1-CMYK.
+  %   compression: 0-RLECompression or 1-NoCompression.
+  %   hex color packets.
+  %
+  gsave
+  /buffer 512 string def
+  /pixel_stream currentfile def
+
+  currentfile buffer readline pop
+  token pop /x exch def
+  token pop /y exch def pop
+  x y translate
+  currentfile buffer readline pop
+  token pop /x exch def
+  token pop /y exch def pop
+  currentfile buffer readline pop
+  token pop /pointsize exch def pop
+  /Helvetica findfont pointsize scalefont setfont
+  x y scale
+  currentfile buffer readline pop
+  token pop /columns exch def
+  token pop /rows exch def pop
+  currentfile buffer readline pop
+  token pop /class exch def pop
+  currentfile buffer readline pop
+  token pop /colorspace exch def pop
+  currentfile buffer readline pop
+  token pop /compression exch def pop
+  class 0 gt { PseudoClassImage } { DirectClassImage } ifelse
+} bind def
+%%EndProlog
+%%Page:  1 1
+%%PageBoundingBox: 0 0 605 613
+userdict begin
+%%BeginData:      1000988 Binary Bytes
+DisplayImage
+0 0
+605 613
+12.000000
+605 613
+0
+0
+0
+~ýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿý~þÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþ~ÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿ~ýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿý~þÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþ~ÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿ~ýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿý~þÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþ~ÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿ~ýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿý~þÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþ~ÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿ~ýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿý~þÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþ~ÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿ~ýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿý~þÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþ~ÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿ~ýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿý~þÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþ~ÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿ~ýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿý~þÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþ~ÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿ~ýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿý~þÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþ~ÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿ~ýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿý~þÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ~üþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿü~þÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþ~ÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿwüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿüþÿ‚
+00ÿ¬¬ÿ77ÿ¸¸²ÿþ
+;;ÿNNÿ½½ÿddýÿ
llÿIIÿÓÓÿ22ÿ‚‚÷ÿ
+44ÿEEÿÎÎÿOOýÿ
+BBÿ77ÿ¤¤ÿyy¯ÿþ
+¶¶Úyy¼ôôù!!þ	ÇÒÒè²²ÙŠŠÄòÿf³‹Å¨ÇãÕ9œj°ØÄjµl¶‘êôïËÿþ
+‡Ã˜Ì
Çâ
+¦¦Òrr¹OO§ŽŽþÇþãñââðøÿY¬Yþÿlµl¼Ý¼¾Þ¾E£EC¡C›ÿþ
+
+…»»ÝþÿGŽŽÇxx»LL¦nn¶ââð¥¥Òÿþÿ{¾z™Ë™¦Ò¦99r¹r•Ê•«Ô«H¤Fÿýÿ§¥Õùÿó@Ÿ@k¶kq·qVªV§Ó§.˜.òÿ$“$öúö…Â…‚þÿ;:žþÿþ
+ˆº°ç3ž/©Õ©¤Ñ¤×ë×/—/€¿€f³f¸Û¸ûÿúüútºt»Ý»…Â…;;×îÔÝÚñqq¸øÿþ
+
+…ôôúVV«ûÿŽªÿþ
+‰»±ç3.¬Ö¬£Ñ£¡Ð¡""¿ Ï õÿb°búüúŠÅŠd²dg¶däÜútt¹øÿþ
+ÿÿšÿÿ—ÿÿ‹üÿ-ÿÿ€ÿÿžÿÿ‰ÿÿ*üÿ
+õõÿññÿ¾¾ÿââýÿÃÃâÿææ‚ÿûÿþ
+‰»±ç3.¬Ö¬£Ñ£¼Þ¼  ÀŠÄŠíöíøÿ„„ãñã3™3ûÿ×Öëtt¹øÿþ
+<<``¯¹¹Ü__þ¯
+‚‚ÀÑÑèqq¸††þÃá[[­ÌÌåÚÿ¦¦ÓuuºÇ··Û··Ûpp¸||½ŸŸÏààðþÿ——ÊŽŽÆøÿÇ]]®ííöhh³§§Ó‹‹Åss¹õÿ ``¯óóù››Íxx»zz¼¿¿ß½½Þ??Ÿ¹¹Ûßßïkkµþþþ
+
+…ûûýþ
+ßßîdd²ÃÃáuuþº	ÜYY¬YY¬§§ÓÝÿýýþii´òòø¤¤Ñkkµååò……Âoo·þÿ
+‰»±ç3.¬Ö¬£Ñ£ÏçÏ‚À‚|½|àïàøÿÏçÏq¸qs¹sE¢EÎêËÞÛòtt¹øÿþ
+þÿ•Ê•‘È‘ÑèÑòÿ¨¨ÓŠŠÅþÿÂÂà×ÿþ
+ˆ»±ç3.©Ô©¤Ñ¤ÕêÕ0—0€¿€f³f¶Ú¶ûÿùüùr¹rÀßÀ[­[&“&ðûíÛÙïqq¸øÿþ
+
+…““Éööûpp¸ÊÊ䎎Ç¿ããñµµÚøÿ””ÊŸŸÏòòøpp¸ÊÊ䦦ÓkkµùùüûÿÐÐç
+%%EndData
+end
+%%PageTrailer
+%%Trailer
+%%BoundingBox: 0 0 605 613
+%%HiResBoundingBox: 0 0 605 613
+%%EOF
diff --git a/doc/figs/mebroot_obf_01.png b/doc/figs/mebroot_obf_01.png
new file mode 100644
index 00000000..ac379c9a
--- /dev/null
+++ b/doc/figs/mebroot_obf_01.png
Binary files differdiff --git a/doc/figs/mebroot_obfdel_01.eps b/doc/figs/mebroot_obfdel_01.eps
new file mode 100644
index 00000000..33f379b0
--- /dev/null
+++ b/doc/figs/mebroot_obfdel_01.eps
@@ -0,0 +1,205 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: (ImageMagick)
+%%Title: (mebroot_obfdel_01.eps)
+%%CreationDate: (2010-01-22T11:26:06+01:00)
+%%BoundingBox: 0 0 211 683
+%%HiResBoundingBox: 0 0 211 683
+%%LanguageLevel: 2
+%%Pages: 1
+%%EndComments
+
+%%BeginDefaults
+%%EndDefaults
+
+%%BeginProlog
+%
+% Display a color image.  The image is displayed in color on
+% Postscript viewers or printers that support color, otherwise
+% it is displayed as grayscale.
+%
+/DirectClassImage
+{
+  %
+  % Display a DirectClass image.
+  %
+  colorspace 0 eq
+  {
+    /DeviceRGB setcolorspace
+    <<
+      /ImageType 1
+      /Width columns
+      /Height rows
+      /BitsPerComponent 8
+      /Decode [0 1 0 1 0 1]
+      /ImageMatrix [columns 0 0 rows neg 0 rows]
+      compression 0 gt
+      { /DataSource pixel_stream /RunLengthDecode filter }
+      { /DataSource pixel_stream /RunLengthDecode filter } ifelse
+    >> image
+  }
+  {
+    /DeviceCMYK setcolorspace
+    <<
+      /ImageType 1
+      /Width columns
+      /Height rows
+      /BitsPerComponent 8
+      /Decode [1 0 1 0 1 0 1 0]
+      /ImageMatrix [columns 0 0 rows neg 0 rows]
+      compression 0 gt
+      { /DataSource pixel_stream /RunLengthDecode filter }
+      { /DataSource pixel_stream /RunLengthDecode filter } ifelse
+    >> image
+  } ifelse
+} bind def
+
+/PseudoClassImage
+{
+  %
+  % Display a PseudoClass image.
+  %
+  % Parameters:
+  %   colors: number of colors in the colormap.
+  %
+  currentfile buffer readline pop
+  token pop /colors exch def pop
+  colors 0 eq
+  {
+    %
+    % Image is grayscale.
+    %
+    currentfile buffer readline pop
+    token pop /bits exch def pop
+    /DeviceGray setcolorspace
+    <<
+      /ImageType 1
+      /Width columns
+      /Height rows
+      /BitsPerComponent bits
+      /Decode [0 1]
+      /ImageMatrix [columns 0 0 rows neg 0 rows]
+      compression 0 gt
+      { /DataSource pixel_stream /RunLengthDecode filter }
+      {
+        /DataSource pixel_stream /RunLengthDecode filter
+        <<
+           /K -1
+           /Columns columns
+           /Rows rows
+        >> /CCITTFaxDecode filter
+      } ifelse
+    >> image
+  }
+  {
+    %
+    % Parameters:
+    %   colormap: red, green, blue color packets.
+    %
+    /colormap colors 3 mul string def
+    currentfile colormap readhexstring pop pop
+    currentfile buffer readline pop
+    [ /Indexed /DeviceRGB colors 1 sub colormap ] setcolorspace
+    <<
+      /ImageType 1
+      /Width columns
+      /Height rows
+      /BitsPerComponent 8
+      /Decode [0 255]
+      /ImageMatrix [columns 0 0 rows neg 0 rows]
+      compression 0 gt
+      { /DataSource pixel_stream /RunLengthDecode filter }
+      { /DataSource pixel_stream /RunLengthDecode filter } ifelse
+    >> image
+  } ifelse
+} bind def
+
+/DisplayImage
+{
+  %
+  % Display a DirectClass or PseudoClass image.
+  %
+  % Parameters:
+  %   x & y translation.
+  %   x & y scale.
+  %   label pointsize.
+  %   image label.
+  %   image columns & rows.
+  %   class: 0-DirectClass or 1-PseudoClass.
+  %   colorspace: 0-RGB or 1-CMYK.
+  %   compression: 0-RLECompression or 1-NoCompression.
+  %   hex color packets.
+  %
+  gsave
+  /buffer 512 string def
+  /pixel_stream currentfile def
+
+  currentfile buffer readline pop
+  token pop /x exch def
+  token pop /y exch def pop
+  x y translate
+  currentfile buffer readline pop
+  token pop /x exch def
+  token pop /y exch def pop
+  currentfile buffer readline pop
+  token pop /pointsize exch def pop
+  /Helvetica findfont pointsize scalefont setfont
+  x y scale
+  currentfile buffer readline pop
+  token pop /columns exch def
+  token pop /rows exch def pop
+  currentfile buffer readline pop
+  token pop /class exch def pop
+  currentfile buffer readline pop
+  token pop /colorspace exch def pop
+  currentfile buffer readline pop
+  token pop /compression exch def pop
+  class 0 gt { PseudoClassImage } { DirectClassImage } ifelse
+} bind def
+%%EndProlog
+%%Page:  1 1
+%%PageBoundingBox: 0 0 211 683
+userdict begin
+%%BeginData:       346429 Binary Bytes
+DisplayImage
+0 0
+211 683
+12.000000
+211 683
+0
+0
+0
+~þþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþ~þÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþ~ÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿ~þþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþ~þÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþ~ÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿ~þþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþ~þÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþ~ÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿ~þþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþ~þÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþ~ÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿ~þþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþ~þÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþ~ÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿ~þþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþ~þÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþ~ÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿ~þþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþ~þÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþ~ÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿ~þþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþ~þÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþ~ÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿ~þþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþ~þÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþ~ÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿ~þþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþ~þÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþ~ÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿ~þþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþ~þÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþ~ÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿ~þþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþ~þÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþ~ÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿ~þþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþ~þÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþ~ÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿ~þþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþ~þÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþ~ÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿ~þþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþ~þÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþ~ÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿPþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿ‚
+ššÿWWÿ††ÿ//ýÿîîÿBBÿYYÿ„„ÿeeÿÜÜúÿˆˆÿ¥¥ÿWWÿTTÿ¿¿ÿòòÿAAÿ66ÿOO¬ÿþ
+
+…ÚÚ씔ʇ‡Ãääñòÿh´Ž1™eþÿ0—cÀßÏ%“\Æ©Èÿþ
+
+…þÿ
+…
+ÉãÉõÿ_°_õùõ!!M¦Mþÿ??ŸïÿJJ¤¥¥Ñ}}½ììõÍÍæ‚þÿþ
+<<``¯¹¹Ü__þ¯
+‰»±ç3.¬Ö¬£Ñ£ÏçÏ‚À‚|½|àïàøÿÏçÏq¸qs¹sE¢EÎêËÞÛòtt¹øÿþ
+þÿ•Ê•‘È‘ÑèÑòÿ¨¨ÓŠŠÅþÿÂÂà×ÿþ
+ˆ»±ç3.©Ô©¤Ñ¤ÕêÕ0—0€¿€f³f¶Ú¶ûÿùüùr¹rÀßÀ[­[&“&ðûíÛÙïqq¸øÿþ
+ˆ»±ç3.ªÕª¤Ñ¤ØëØ*”*Àj´jÁßÁøÿÁ»Ü»€À€A A×îÔÝÚñqq¸øÿþ
+÷÷ûýýþôôúüüþýþ××ë††ÂøÿUUª££Ñþÿòòøüüýññøööú÷÷ú==Ÿõÿýþýþþþÿíöíìÿþýþÿýþýûýûûÿóùó©Ô©ªÕªåòåòÿŽŽÇkkµøÿþ
+‰»±ç3.¬Ö¬£Ñ£¼Ý¼  À‹Å‹ï÷ïøÿ¡Ð¡ºÜºa°a<<ÅåÂÝÙòtt¹øÿþ
+þÿ”Ê”ÈÒèÒòÿ¨¨ÓŽŽÇþÿÇÇâ×ÿþ
+ˆ»±ç3.©Ô©¤Ñ¤ÕêÕ1˜1€¿€e²e´Ù´ûÿøûøp¸p»Ý»‡Ã‡9œ9×îÔÝÚñqq¸øÿþ
+‰»±ç3.¬Ö¬£Ñ£·Û·  ÀÇòøòøÿ}¾}ãñãŒÆŒg³gh·eæÝútt¹øÿþ
+‡»±ç3.¨Ô¨¤Ñ¤ÓéÓ8›8¿a°a¨Ó¨ûÿñøñÉäÉz¼z;;þÿûÿøØ×ìpp·øÿþ
+‰»±ç3.¬Ö¬¤Ñ¤ÛíÛŽƒÁƒr¸rØëØøÿ¢Ñ¢ºÜºs¹sK¥KÕíÒÞÛòss¹øÿþ
+‰»±ç3.¬Ö¬£Ñ£²Ø²!!€¿€“É“öúöøÿ¡Ð¡ºÜº\®\7›7Àã½ÝÙòtt¹øÿþ
+
+„©©Ôøÿ Ð ÇþÿÀ¾ß¾ÎÊåÊÙìÙøÿm¶mþÿœÍœw»wÒéÒÖêÖõÿ€À€¾ß¾ÏçÏuºuùýøþýþFF£þÿ
+‡»±ç3.¨Ô¨¤Ñ¤ÔéÔ5š5¿b±b¬Õ¬ûÿôùôÇãÇ¿;œ;þÿýÿúØ×ìpp·øÿþ
+‰»±ç3.¬Ö¬¤Ñ¤ÖëÖŽƒÁƒvºvÛíÛøÿ¢Ñ¢¿Þ¿6š6ûÿØØëtt¹øÿþ
+‰»±ç3.¬Ö¬£Ñ£Âà  À†Ã†êôêøÿÆâÆr¸rkµk?Ÿ?ÈçÅÞÚòtt¹øÿþ
+±±ÿÖÖÿÒÒÿŽŽýÿ
+ÆÆÿÿééÿŽŽèÿþ
+%%EndData
+end
+%%PageTrailer
+%%Trailer
+%%BoundingBox: 0 0 211 683
+%%HiResBoundingBox: 0 0 211 683
+%%EOF
diff --git a/doc/figs/mebroot_obfdel_01.png b/doc/figs/mebroot_obfdel_01.png
new file mode 100644
index 00000000..018ea0a4
--- /dev/null
+++ b/doc/figs/mebroot_obfdel_01.png
Binary files differdiff --git a/doc/figs/msgbox.eps b/doc/figs/msgbox.eps
new file mode 100644
index 00000000..c8e8e613
--- /dev/null
+++ b/doc/figs/msgbox.eps
Binary files differdiff --git a/doc/figs/msgbox.png b/doc/figs/msgbox.png
new file mode 100644
index 00000000..8987d6d8
--- /dev/null
+++ b/doc/figs/msgbox.png
Binary files differdiff --git a/doc/figs/pe_format.eps b/doc/figs/pe_format.eps
new file mode 100644
index 00000000..fe9b5ee0
--- /dev/null
+++ b/doc/figs/pe_format.eps
Binary files differdiff --git a/doc/figs/pe_format.gif b/doc/figs/pe_format.gif
new file mode 100644
index 00000000..4757f19e
--- /dev/null
+++ b/doc/figs/pe_format.gif
Binary files differdiff --git a/doc/figs/xxx_mnemo01.eps b/doc/figs/xxx_mnemo01.eps
new file mode 100644
index 00000000..da39ef98
--- /dev/null
+++ b/doc/figs/xxx_mnemo01.eps
Binary files differdiff --git a/doc/figs/xxx_mnemo01.png b/doc/figs/xxx_mnemo01.png
new file mode 100644
index 00000000..541112e4
--- /dev/null
+++ b/doc/figs/xxx_mnemo01.png
Binary files differdiff --git a/doc/figs/xxx_mnemo02.eps b/doc/figs/xxx_mnemo02.eps
new file mode 100644
index 00000000..2db59b92
--- /dev/null
+++ b/doc/figs/xxx_mnemo02.eps
Binary files differdiff --git a/doc/figs/xxx_mnemo02.png b/doc/figs/xxx_mnemo02.png
new file mode 100644
index 00000000..2bf7bdeb
--- /dev/null
+++ b/doc/figs/xxx_mnemo02.png
Binary files differdiff --git a/doc/figs/xxx_mnemo03.eps b/doc/figs/xxx_mnemo03.eps
new file mode 100644
index 00000000..9ab49443
--- /dev/null
+++ b/doc/figs/xxx_mnemo03.eps
Binary files differdiff --git a/doc/figs/xxx_mnemo03.png b/doc/figs/xxx_mnemo03.png
new file mode 100644
index 00000000..760970f7
--- /dev/null
+++ b/doc/figs/xxx_mnemo03.png
Binary files differdiff --git a/doc/figs/xxx_mnemo04.eps b/doc/figs/xxx_mnemo04.eps
new file mode 100644
index 00000000..ab74529d
--- /dev/null
+++ b/doc/figs/xxx_mnemo04.eps
Binary files differdiff --git a/doc/figs/xxx_mnemo04.png b/doc/figs/xxx_mnemo04.png
new file mode 100644
index 00000000..83610c7e
--- /dev/null
+++ b/doc/figs/xxx_mnemo04.png
Binary files differdiff --git a/doc/figs/xxx_mnemo05.eps b/doc/figs/xxx_mnemo05.eps
new file mode 100644
index 00000000..f636c3ed
--- /dev/null
+++ b/doc/figs/xxx_mnemo05.eps
Binary files differdiff --git a/doc/figs/xxx_mnemo05.png b/doc/figs/xxx_mnemo05.png
new file mode 100644
index 00000000..fe407617
--- /dev/null
+++ b/doc/figs/xxx_mnemo05.png
Binary files differdiff --git a/doc/figs/xxx_mnemo06.eps b/doc/figs/xxx_mnemo06.eps
new file mode 100644
index 00000000..dea835a8
--- /dev/null
+++ b/doc/figs/xxx_mnemo06.eps
Binary files differdiff --git a/doc/figs/xxx_mnemo06.png b/doc/figs/xxx_mnemo06.png
new file mode 100644
index 00000000..fe422111
--- /dev/null
+++ b/doc/figs/xxx_mnemo06.png
Binary files differdiff --git a/doc/figs/xxx_mnemo07.eps b/doc/figs/xxx_mnemo07.eps
new file mode 100644
index 00000000..6935c398
--- /dev/null
+++ b/doc/figs/xxx_mnemo07.eps
Binary files differdiff --git a/doc/figs/xxx_mnemo07.png b/doc/figs/xxx_mnemo07.png
new file mode 100644
index 00000000..d6f620e4
--- /dev/null
+++ b/doc/figs/xxx_mnemo07.png
Binary files differdiff --git a/doc/figs/xxx_mnemo08.eps b/doc/figs/xxx_mnemo08.eps
new file mode 100644
index 00000000..c1dbdc8e
--- /dev/null
+++ b/doc/figs/xxx_mnemo08.eps
Binary files differdiff --git a/doc/figs/xxx_mnemo08.png b/doc/figs/xxx_mnemo08.png
new file mode 100644
index 00000000..cfd200c6
--- /dev/null
+++ b/doc/figs/xxx_mnemo08.png
Binary files differdiff --git a/doc/figs/xxx_mnemo09.eps b/doc/figs/xxx_mnemo09.eps
new file mode 100644
index 00000000..9e947f9c
--- /dev/null
+++ b/doc/figs/xxx_mnemo09.eps
Binary files differdiff --git a/doc/figs/xxx_mnemo09.png b/doc/figs/xxx_mnemo09.png
new file mode 100644
index 00000000..990ad13f
--- /dev/null
+++ b/doc/figs/xxx_mnemo09.png
Binary files differdiff --git a/doc/figs/xxx_mnemo10.eps b/doc/figs/xxx_mnemo10.eps
new file mode 100644
index 00000000..4b838013
--- /dev/null
+++ b/doc/figs/xxx_mnemo10.eps
Binary files differdiff --git a/doc/figs/xxx_mnemo10.png b/doc/figs/xxx_mnemo10.png
new file mode 100644
index 00000000..3c985982
--- /dev/null
+++ b/doc/figs/xxx_mnemo10.png
Binary files differdiff --git a/doc/figs/xxx_vm01.eps b/doc/figs/xxx_vm01.eps
new file mode 100644
index 00000000..e56ac93b
--- /dev/null
+++ b/doc/figs/xxx_vm01.eps
Binary files differdiff --git a/doc/figs/xxx_vm01.png b/doc/figs/xxx_vm01.png
new file mode 100644
index 00000000..fc1e7e15
--- /dev/null
+++ b/doc/figs/xxx_vm01.png
Binary files differdiff --git a/doc/slides.tex b/doc/slides.tex
new file mode 100644
index 00000000..cf7057e7
--- /dev/null
+++ b/doc/slides.tex
@@ -0,0 +1,2243 @@
+\documentclass[
+               beamer,
+%               handout,
+%               notes=show,
+%               notes=onlyslideswithnotes,
+%               notes=only,
+%               xcolor=pst,
+                dvips,
+]{beamer}
+
+%\usepackage[francais]{babel}
+\usepackage[latin1]{inputenc}
+\usepackage{alltt}
+\usepackage{pstricks}
+\usepackage{pst-node}
+\usepackage{listings}
+\usepackage{xspace}
+\usepackage{xcolor}
+
+
+%Workarround some bugs in marvosym
+\let\RescueRightarrow=\Rightarrow
+\usepackage{marvosym}
+\renewcommand{\Rightarrow}{\RescueRightarrow}
+
+\usepackage{marvosym}
+
+\usepackage{tikz}
+\usetikzlibrary{matrix,calc,arrows,shapes,snakes,automata,backgrounds,petri,fit,positioning,chains}
+\usepackage{verbatim}
+\usepackage{bigcenter}
+%%\usetikzlibrary{calc}
+%%\usetikzlibrary[calc]
+%%\usetikzlibrary{shapes,arrows}
+
+%%\usetikzlibrary{calc,arrows,shapes,snakes,automata,backgrounds,petri,fit}
+%%
+%%\usetikzlibrary{%
+%%  arrows,%
+%%  shapes.misc,% wg. rounded rectangle
+%%  shapes.arrows,%
+%%  chains,%
+%%  matrix,%
+%%  positioning,% wg. " of "
+%%  scopes,%
+%%  decorations.pathmorphing,% /pgf/decoration/random steps | erste Graphik
+%%  shadows,%
+%%  fit
+%%}
+%%
+
+
+\usetikzlibrary{matrix}
+\usetikzlibrary{calc,arrows,shapes,snakes,automata,backgrounds,petri,fit}
+
+\usetikzlibrary{%
+  arrows,%
+  shapes.misc,% wg. rounded rectangle
+  shapes.arrows,%
+  chains,%
+  matrix,%
+  positioning,% wg. " of "
+  scopes,%
+  decorations.pathmorphing,% /pgf/decoration/random steps | erste Graphik
+  shadows%
+}
+
+
+\lstset{
+       basicstyle=\sffamily\color{darkgray},
+       keywordstyle=\bfseries\color{purple},
+       identifierstyle=\bfseries\color{black},
+       commentstyle=\ttfamily\itshape\color{purple},
+       stringstyle=\ttfamily\color{brown},
+       moredelim=[is][\color{red}]{==>}{<==},  % overwrited by language setting
+%       moredelim=**[is][\normalsize]{|}{|},  % overwrited by language setting
+       stringspaces=true,
+       showstringspaces=false,
+       frame=leftline,
+       numbersep=5pt,
+       defaultdialect=Python,
+       language=Python
+}
+
+
+
+\newcommand{\domain}{\textit}
+\newcommand{\tool}{\textsl}
+
+\newcommand{\scite}[1]{{\footnotesize\cite{#1}}}
+
+\mode<all>
+{
+%  \usetheme{Singapore}
+  \usetheme{Warsaw}
+  \usecolortheme{crane}
+  \setbeamercovered{transparent}
+  \setbeamercolor{background canvas}{bg=}
+}
+
+\setbeamertemplate{footline}
+{%
+  \begin{beamercolorbox}{section in head/foot}
+   \insertshortauthor\hfill\insertshorttitle{}\hfill\insertframenumber/\inserttotalframenumber
+%    \vskip2pt\insertnavigation{\paperwidth}\vskip2pt
+  \end{beamercolorbox}%
+}
+
+
+
+\mode<presentation> {
+%  \setbeamertemplate{background canvas}[vertical shading][bottom=blue!30,top=purple!10]
+}
+
+
+
+\mode<handout> {
+}
+
+\newenvironment{questionblock}{\begin{alertblock}}{\end{alertblock}}
+\newenvironment{hintblock}{\begin{block}}{\end{block}}
+\newenvironment{answerblock}{\begin{exampleblock}}{\end{exampleblock}}
+
+
+\pgfdeclareimage[height=8mm]{logo-eads}{logo/eads}
+\logo{\href{http://www.eads.net}{\pgfuseimage{logo-eads}}}
+
+
+\AtBeginSubsection[]
+{
+  \begin{frame}<beamer>[shrink]
+    \frametitle{Outline}
+    \tableofcontents[currentsection,currentsubsection]
+  \end{frame}
+}
+
+
+%\AtBeginPart{\frame{\partpage}}
+
+\subject{Binary manipulation with Miasm }
+\title{Miasm\\
+(incomprehensible documentation)}
+\date{}
+
+
+
+\institute[EADS/SE/CS]{
+  \texttt{serpilliere at droids-corp 0rg}\\
+  EADS Corporate Research Center --- IW/SE/CS\\
+  IT sec Lab\\
+  Suresnes, FRANCE
+}
+
+
+%\beamerdefaultoverlayspecification{<+->}
+
+\begin{document}
+
+
+\begin{frame} %-=-=-=-=-=-
+  \titlepage
+\end{frame}
+
+
+\begin{frame}[shrink] %-=-=-=-=-=-
+  \frametitle{Outline}
+  \tableofcontents
+\end{frame}
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%box style
+
+\tikzstyle{block} = [draw, fill=blue!20, rectangle, 
+  minimum height=1em, minimum width=2em,
+  top color=white, bottom color=blue!20]
+
+\tikzstyle{block2} = [draw, fill=blue!20, rectangle, 
+  minimum height=1em, minimum width=4em,
+  top color=white, bottom color=blue!20,
+  rounded corners=3mm]
+
+\tikzstyle{block3} = [draw, fill=blue!20, rectangle, 
+  minimum height=2em, minimum width=2em,
+  top color=white, bottom color=blue!20,
+  rounded corners=3mm]
+
+\tikzset{usblayer/.style={
+    rectangle,minimum size=6mm,% text width=10em,
+    very thick,draw=black!50,
+    top color=white,bottom color=black!20,
+    node distance = 2em, text centered,
+    font=\ttfamily}}
+
+
+\tikzstyle{sum} = [draw, fill=blue!20, circle, node distance=1cm]
+\tikzstyle{input} = [coordinate]
+\tikzstyle{output} = [coordinate]
+\tikzstyle{pinstyle} = [pin edge={to-,thin,black}]
+
+
+\tikzset{pfield/.style={
+    rectangle,minimum size=6mm, 
+    very thick,draw=black!50,
+    top color=white,bottom color=black!20,
+    font=\ttfamily}}
+
+
+\tikzset{conf/.style={
+    rectangle,minimum size=6mm, text width=7em,
+    very thick,draw=black!50,
+    top color=white,bottom color=black!20,
+    node distance = 2em, text centered,
+    font=\ttfamily}}
+
+\tikzset{confep/.style={
+    rectangle,minimum size=6mm, text width=3em,
+    very thick,draw=black!50,
+    top color=white,bottom color=black!20,
+    node distance = 2em, text centered,
+    font=\ttfamily}}
+
+\tikzset{usblayer/.style={
+    rectangle,minimum size=6mm,% text width=10em,
+    very thick,draw=black!50,
+    top color=white,bottom color=black!20,
+    node distance = 2em, text centered,
+    font=\ttfamily}}
+
+\tikzset{epbox/.style={
+    rectangle,minimum size=3mm, minimum width=6em,
+    very thick,draw=black!50,
+    top color=white,bottom color=black!20,
+    node distance = 0em,
+    text badly centered,
+    text width=8em,
+    font=\ttfamily}}
+
+\tikzset{bloc/.style={
+    rectangle,minimum size=6mm, minimum width=7em, minimum height=2em,
+    very thick,draw=black!50,
+    top color=white,bottom color=black!20,
+    rounded corners,
+    font=\scriptsize}}
+
+
+
+
+
+
+\section{Random manipulations}
+\subsection{PE}
+
+\begin{frame}[fragile]
+  \frametitle{Elfesteem use}
+
+  \begin{exampleblock}{EXE reading}
+    \begin{itemize}
+    \item EXE parsing
+    \item (MZ/PE/sections/Directories)
+    \end{itemize}
+  \end{exampleblock}
+
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+>>> from elfesteem import *
+>>> e = pe_init.PE(open('calc.exe', 'rb').read())
+#  section         offset   size   addr     flags   rawsize
+ 0 .text          00000400 0126b0 00001000 60000020 00012800  
+ 1 .data          00012c00 00101c 00014000 c0000040 00000a00  
+ 2 .rsrc          00013600 008a88 00016000 40000040 00008c00  
+	 \end{lstlisting}}
+\end{frame}
+
+
+\begin{frame}[fragile]
+  \frametitle{Accesses}
+
+  \begin{exampleblock}{File view}
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+>>> e.content[:4]
+'MZ\x90\x00'
+	 \end{lstlisting}}
+  \end{exampleblock}
+
+  \begin{exampleblock}{RVA view}
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+>>> e.drva[0x1000:0x1004]
+'\xea"\xdaw'
+	 \end{lstlisting}}
+  \end{exampleblock}
+
+  \begin{exampleblock}{Virtual addesses view}
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+>>> e.virt[0x1001000:0x1001004]
+'\xea"\xdaw'
+	 \end{lstlisting}}
+  \end{exampleblock}
+
+\end{frame}
+
+
+
+
+\begin{frame}[fragile]
+  \frametitle{EXE attributes}
+
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+>>> e.DirImport
+<Directory Import>
+ 0 <SHELL32.dll>             <W-ImpDesc=76968/4294967295L/4294967295L/77378/4252>
+     0 <148, ShellAboutW>
+ 1 <msvcrt.dll>              <W-ImpDesc=77256/4294967295L/4294967295L/77664/4540>
+     0 <82, __CxxFrameHandler>
+     1 <71, _CxxThrowException>
+     2 <824, wcstoul>
+     ...
+	 \end{lstlisting}}
+
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+>>> e.DirRes
+<ID RT_ICON subdir: 90192 None>
+    <ID RT_CURSOR subdir: 90528 None>
+        <ID 1036 data: 91152 <ResDataEntry=91576/744/1252/0>>
+    <ID RT_BITMAP subdir: 90552 None>
+        <ID 1036 data: 91168 <ResDataEntry=92320/296/1252/0>>
+    <ID RT_ICON subdir: 90576 None>
+    ...
+	 \end{lstlisting}}
+
+\end{frame}
+
+
+
+
+
+\begin{frame}[fragile]
+  \frametitle{Common manipulation}
+
+  \begin{exampleblock}{EXE generation}
+    \begin{itemize}
+    \item EXE creation
+    \item Default characteristics
+    \end{itemize}
+  \end{exampleblock}
+
+  \lstset{language=Python}
+	 {\scriptsize\begin{lstlisting}[]{}  
+e = PE()
+open('uu.bin', 'wb').write(str(e))
+	 \end{lstlisting}}
+\end{frame}
+
+
+
+\begin{frame}[fragile]
+  \begin{exampleblock}{Add a section to a binary}
+    \begin{itemize}
+    \item read the binary
+    \item add a section
+    \item generate binary
+    \end{itemize}
+  \end{exampleblock}
+
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+>>> e = PE(open('calc.exe', 'rb').read())
+#  section         offset   size   addr     flags   rawsize
+ 0 .text          00000400 0126b0 00001000 60000020 00012800  
+ 1 .data          00012c00 00101c 00014000 c0000040 00000a00  
+ 2 .rsrc          00013600 008a88 00016000 40000040 00008c00  
+>>> s_XXX = e.SHList.add_section(name='XXX', addr = 0x20000, rawsize = 0x1000)
+>>> open('out.bin', 'wb').write(str(e))
+
+>>> PE(open('out.bin', 'rb').read())
+#  section         offset   size   addr     flags   rawsize
+ 0 .text          00000400 0126b0 00001000 60000020 00012800
+ 1 .data          00012c00 00101c 00014000 c0000040 00000a00
+ 2 .rsrc          00013600 008a88 00016000 40000040 00008c00
+ 3 XXX            0001c200 001000 00020000 e0000020 00001000
+	 \end{lstlisting}}
+\end{frame}
+
+
+
+\begin{frame}[fragile]
+  \begin{exampleblock}{Menu edition}
+    \begin{itemize}
+    \item read DirRes
+    \item find menu
+    \item modify
+    \item generate the binary
+    \end{itemize}
+  \end{exampleblock}
+
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+>>> e = PE(open('calc.exe', 'rb').read())
+>>> e.DirRes.resdesc.resentries
+ 0 <ID RT_ICON subdir: 90192 None>ResEntry
+ 1 <ID RT_MENU subdir: 90272 None>ResEntry
+ ...
+>>> menu = e.DirRes.resdesc.resentries[1]
+>>> menu.subdir.resentries
+ 0 <ID 106 subdir: 90720 None>ResEntry
+ 1 <ID 107 subdir: 90744 None>ResEntry
+...
+
+>>> e.Opthdr.Optehdr[pe.DIRECTORY_ENTRY_BOUND_IMPORT].rva = 0
+>>> e.Opthdr.Optehdr[pe.DIRECTORY_ENTRY_BOUND_IMPORT].size = 0
+
+>>> e.DirRes.resdesc.resentries[1].subdir.resentries[1].\
+    subdir.resentries[0].data.s[8:22:2]
+'Edition'
+>>> e.DirRes.resdesc.resentries[1].subdir.resentries[1].\
+    subdir.resentries[0].data.s[8:22] = "\x00".join([x for x in 'Toto'])+'\x00'
+>>> open('out.bin.exe', 'wb').write(str(e))
+	 \end{lstlisting}}
+\end{frame}
+
+
+\begin{frame}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[width=1\textwidth]{figs/calc_mod.eps}
+    \end{center}
+  \end{figure}
+\end{frame}
+
+  
+\begin{frame}
+  \frametitle{Common case}
+
+  \begin{exampleblock}{EXE generation}
+    \begin{itemize}
+    \item create an EXE
+    \item default characteristics
+    \item new text section with ``xC3'' (ret)
+    \item place entry point
+    \item add some imports
+    \item $\rightarrow$ The binary is ready
+    \end{itemize}
+  \end{exampleblock}
+
+\end{frame}
+
+
+\begin{frame}[fragile]
+
+  \lstset{language=Python} 
+	 {\tiny\begin{lstlisting}[]{}  
+e = PE()
+mysh = "\xc3"
+s_text = e.SHList.add_section(name = "text", addr = 0x1000, rawsize = 0x1000, data = mysh)
+e.Opthdr.Opthdr.AddressOfEntryPoint = s_text.addr
+new_dll = [({"name":"kernel32.dll",
+             "firstthunk":s_text.addr+0x100},
+            ["CreateFileA", "SetFilePointer", "WriteFile", "CloseHandle"]
+            )
+           ,
+           ({"name":"USER32.dll",
+             "firstthunk":None},
+            ["SetDlgItemInt", "GetMenu", "HideCaret"]
+            )
+           ]
+e.DirImport.add_dlldesc(new_dll)
+s_myimp = e.SHList.add_section(name = "myimp", rawsize = 0x1000)    
+e.DirImport.set_rva(s_myimp.addr)
+open('uu.bin', 'wb').write(str(e))
+	 \end{lstlisting}}
+\end{frame}
+
+\begin{frame}[fragile]
+  \frametitle{Ida listing:}
+  \tiny\begin{verbatim}
+ ;******************************************************************x
+ ;  section 1 <text>                                                x
+ ;  virtual address  00001000  virtual size   00001000              x
+ ;  file offset      00001000  file size      00001000              x
+ ;******************************************************************x
+                                                                    x
+ ;****************************                                      x
+ ;  program entry point                                             x
+ ;****************************                                      x
+ entrypoint:                                                        x
+   ret                                                              x
+  \end{verbatim}
+\end{frame}
+
+
+
+
+
+
+\subsection{Assembleur/Désassembleur}
+
+
+
+
+
+\begin{frame}
+  \frametitle{Miasm}
+
+  \begin{block}{Goal}
+    \begin{itemize}
+    \item Asm/DisAsm x86/PPC/ARM
+    \item Work on multi sources
+    \item (str/shellcode txt/PE/ELF/.S)
+    \item assembly to intermediate language
+    \item emulate intermediate language (in an environment)
+    \item Snapshot/restore
+    \item library of emulation
+    \item ...
+    \end{itemize}
+  \end{block}
+
+\end{frame}
+
+
+\begin{frame}[fragile]
+  \frametitle{Common cases}
+
+  \begin{exampleblock}{Dis/Asm}
+    \begin{itemize}
+    \item work on bytes/asm text/container
+    \item mini integrated linker
+    \item graph generation
+    \item ...
+    \end{itemize}
+  \end{exampleblock}
+
+
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+>>> from x86_escape.x86_escape import *
+>>> l = x86_mn.dis('\x90')
+>>> str(l)
+'nop     '
+>>> x86_mn.asm('nop')
+['\x90']
+>>> x86_mn.asm('inc eax')
+['@', '\xff\xc0']
+>>> str(x86_mn.dis('@'))
+'inc       eax'
+>>> str(x86_mn.dis('\xff\xC0'))
+'inc       eax'
+	 \end{lstlisting}}
+\end{frame}
+
+
+
+\begin{frame}[fragile]
+  \frametitle{assembling x86 bloc}
+
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+all_bloc, symbol_pool = parse_asm.parse_txt(x86_escape.x86mnemo,r'''
+main:
+    push 0
+    push title
+    push msg
+    push 0
+    call test_call
+    ret
+test_call:
+    nop
+    ret
+title:
+.string "My box"
+msg:
+.string "My msg!"
+''')
+
+
+#fix shellcode addr
+symbol_pool.add(asmbloc.asm_label('base_address', 0))
+symbol_pool.getby_name("main").offset = 0
+
+####graph sc####
+g = asmbloc.bloc2graph(all_bloc[0])
+open("graph.txt" , "w").write(g)
+
+	 \end{lstlisting}}
+\end{frame}
+
+\begin{frame}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[width=1\textwidth]{figs/gen_graph.eps}
+    \end{center}
+  \end{figure}
+\end{frame}
+
+
+
+\begin{frame}[fragile]
+  \frametitle{shell code generation}
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+f = open('out.bin', 'wb')
+for p in patches:
+    f.seek(p)
+    f.write(patches[p])
+f.close()
+	 \end{lstlisting}}
+\end{frame}
+
+
+\begin{frame}[fragile]
+  \begin{block}{Dump hexa}    
+    \tiny\begin{verbatim}
+x00000000 6a 00 6a 18 6a 10 6a 00-e8 01 00 00 00 c3 90 c3 |j j?j?j ??   ???|
+x00000010 4d 79 20 6d 73 67 21 00-4d 79 20 62 6f 78 00    |My msg! My box  |
+    \end{verbatim}
+  \end{block}
+  \begin{block}{Disassemble}    
+    \tiny\begin{verbatim}
+x00000000 6a00                           push        0x0 
+x00000002 6a18                           push        0x18
+x00000004 6a10                           push        0x10
+x00000006 6a00                           push        0x0 
+x00000008 e801000000                     call        0xe 
+x0000000d c3                             ret             
+x0000000e 90                             nop             
+x0000000f c3                             ret              
+    \end{verbatim}
+  \end{block}
+
+\end{frame}
+
+
+\begin{frame}
+  \frametitle{In the next slide...}
+
+  \begin{block}{PE generation}
+    \begin{itemize}
+    \item generate a working PE
+    \item with imports
+    \item some code
+    \item which displays a dialog box
+    \item ...
+    \end{itemize}
+  \end{block}
+
+\end{frame}
+
+
+\begin{frame}[fragile]
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+#! /usr/bin/env python
+from x86_escape import *
+from elfesteem import *
+
+e = pe_init.PE()
+s_text = e.SHList.add_section(name = "text", addr = 0x1000, rawsize = 0x100)
+s_iat = e.SHList.add_section(name = "iat", rawsize = 0x100)
+new_dll = [({"name":"USER32.dll","firstthunk":s_iat.addr}, ["MessageBoxA"])]
+
+e.DirImport.add_dlldesc(new_dll)
+s_myimp = e.SHList.add_section(name = "myimp", rawsize = len(e.DirImport))
+e.DirImport.set_rva(s_myimp.addr)
+all_bloc, symbol_pool = parse_asm.parse_txt(x86_escape.x86mnemo,r'''
+main:
+    push 0
+    push title
+    push msg
+    push 0
+    call [MessageBoxA]
+    ret
+title:
+.string "My box"
+msg:
+.string "My msg!"
+''')
+symbol_pool.add(asmbloc.asm_label('base_address', 0))
+symbol_pool.getby_name("MessageBoxA").offset = e.DirImport.get_funcvirt('MessageBoxA')
+symbol_pool.getby_name("main").offset = e.rva2virt(s_text.addr)
+resolved_b, patches = asmbloc.asm_resolve_final(x86_escape.x86mnemo, all_bloc[0], symbol_pool, [])
+for p in patches:
+    e.virt[p] = patches[p]
+e.Opthdr.Opthdr.AddressOfEntryPoint = e.virt2rva(symbol_pool.getby_name("main").offset)
+open('uu.bin', 'wb').write(str(e))
+	 \end{lstlisting}}
+
+\end{frame}
+
+
+\begin{frame}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[width=0.3\textwidth]{figs/msgbox.eps}
+    \end{center}
+  \end{figure}
+\end{frame}
+
+\subsection{Graphe}
+\begin{frame}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[width=0.9\textwidth]{figs/gandalf_01.eps}
+    \end{center}
+  \end{figure}
+\end{frame}
+
+
+\subsection{Introduction to intermediate language}
+
+\begin{frame}[fragile]
+  \frametitle{Instruction semantic}
+
+  \begin{block}{Intermediate language}
+    \begin{itemize}
+    \item the instruction is composed of operations
+    \item each operation is executed in parallel
+    \item example: cmpsb
+    \end{itemize}
+  \end{block}
+
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+def cmpsb():
+    e= []
+    e+=l_cmp(ExprMem(esi, 8), ExprMem(edi, 8))
+    e.append(ExprAff(edi, ExprCond(df, ExprOp('+', edi, ExprInt(uint32(1))), ExprOp('-', edi, ExprInt(uint32(1))))))
+    e.append(ExprAff(esi, ExprCond(df, ExprOp('+', esi, ExprInt(uint32(1))), ExprOp('-', esi, ExprInt(uint32(1))))))
+    return e
+	 \end{lstlisting}}
+\end{frame}
+
+
+\begin{frame}[fragile]
+  \frametitle{cmpsb semantic}
+
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+>>> from x86_escape import ia32_sem
+>>> e = ia32_sem.cmpsb()
+>>> for x in e:
+...     print str(x)
+...
+zf = (== (- @8[esi] @8[edi]) 0x0)
+nf = (& (== 0x1 (>> (- @8[esi] @8[edi]) 0x7)) 0x1)
+pf = (parity (- @8[esi] @8[edi]))
+cf = (| (& (== (== 0x1 (>> @8[esi] 0x7)) 0x0) (== 0x1 (>> @8[edi] 0x7))) (& (== 0x1 (>> (- @8[esi] @8[edi]) 0x7)) (| (== (== 0x1 (>> @8[esi] 0x7)) 0x0) (== 0x1 (>> @8[edi] 0x7)))))
+of = (| (& (== (== 0x1 (>> (- @8[esi] @8[edi]) 0x7)) 0x1) (& (== (== 0x1 (>> @8[esi] 0x7)) 0x0) (== 0x1 (>> @8[edi] 0x7)))) (& (== (== 0x1 (>> (- @8[esi] @8[edi]) 0x7)) 0x0) (& (== 0x1 (>> @8[esi] 0x7)) (== (== 0x1 (>> @8[edi] 0x7)) 0x0))))
+af = (== (& (- @8[esi] @8[edi]) 0x10) 0x10)
+edi = df?((+ edi 0x1),(- edi 0x1))
+esi = df?((+ esi 0x1),(- esi 0x1))
+	 \end{lstlisting}}
+\end{frame}
+
+
+
+\begin{frame}[fragile]
+  \frametitle{Manipulation example}
+
+  \begin{block}{registers touched by an instruction}
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+>>> from analysis_helper import *
+>>> r, w = get_rw(ia32_sem.cmpsb())
+>>> r, w
+(set_expr[@8[edi], @8[esi], df, edi, esi], set_expr[zf, nf, pf, cf, of, af, edi, esi])
+	 \end{lstlisting}}
+  \end{block}
+\end{frame}
+
+\section{Langage intermédiaire}
+\subsection{Description du langage}
+
+
+\begin{frame}
+  \begin{block}{Expressions}
+    \begin{itemize}
+      \item ExprInt: interger
+      \item ExprId: identifier (variable)
+      \item ExprAff: a = b
+      \item ExprCond: a?b:c
+      \item ExprMem: dword ptr [a]
+      \item ExprOp: op(a, b, ...)
+      \item ExprSlice: a[0:8] (bits)
+      \item ExprCompose: slices composition
+      \item ExprSliceTo: position in a composition
+    \end{itemize}
+  \end{block}
+That's all.
+\end{frame}
+
+\begin{frame}[fragile]
+  \begin{exampleblock}{Some expressions}
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+>>> from expression import *
+>>> a = ExprId('A', 32)
+>>> b = ExprId('B', 32)
+>>> c = ExprId('C', 32)
+>>> o = a+b
+>>> print o
+(A + B)
+>>> print ExprAff(c, o)
+C = (A + B)
+	 \end{lstlisting}}
+  \end{exampleblock}
+  \begin{exampleblock}{Definition of some instructions}
+\begin{tabular}{ l l }
+    \lstset{language=Python}
+	   {\tiny\begin{lstlisting}[]{}  
+def mov(a, b):
+    return [ExprAff(a, b)]
+
+def xchg(a, b):
+    e = []
+    e.append(ExprAff(a, b))
+    e.append(ExprAff(b, a))
+    return e
+           \end{lstlisting}}& 
+    \lstset{language=Python}
+	   {\tiny\begin{lstlisting}[]{}  
+def update_flag_zf(a):
+    cast_int = tab_uintsize[a.get_size()]
+    return [ExprAff(zf, ExprOp('==', 
+                        a, 
+                        ExprInt(cast_int(0))))]
+def update_flag_nf(a):
+    return [ExprAff(nf, ExprOp('&', 
+            get_op_msb(a), 
+            ExprInt(tab_uintsize[a.get_size()](1))))]
+           \end{lstlisting}}
+\end{tabular}
+  \end{exampleblock}
+\end{frame}
+
+
+\subsection{Module de simplification d'expression}
+\begin{frame}[fragile]
+  \begin{block}{The language has simplification rules}
+    \begin{itemize}
+    \item X + Y - Y : X
+    \item - (-X) : X
+    \item X +int1 + int2 : X+int3 (=int1 + int2)
+    \item ...
+    \end{itemize}
+  \end{block}
+
+\begin{exampleblock}{Example}
+\begin{tabular}{ l l }
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+>>> print o
+(A + B)
+>>> p = o - b
+>>> print p
+((A + B) - B)
+>>> print expr_simp(p)
+A
+           \end{lstlisting}}&
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+>>> q = (a - ExprInt(uint32(1))) + ExprInt(uint32(3))
+>>> print q
+((A - 0x1) + 0x3)
+>>> print expr_simp(q)
+(A + 0x2)
+           \end{lstlisting}}
+\end{tabular}
+\end{exampleblock}
+\end{frame}
+
+\subsection{Symbolic execution}
+\begin{frame}[fragile]
+  \begin{block}{Assembly to intermediate language}
+    \begin{itemize}
+      \item expressions representing instructions are execution simultaneously
+      \item affectations are done into a memory representation
+      \item (a dictionary)
+      \item the key is the identifier (non reducible)
+    \end{itemize}
+  \end{block}
+
+  \begin{block}{interpretation machine}
+    \begin{itemize}
+      \item It defines usable registers
+    \end{itemize}
+	{\tiny\begin{lstlisting}[]{}  
+machine = eval_abs({esp:init_esp, ebp:init_ebp, eax:init_eax, ebx:init_ebx, 
+                    ecx:init_ecx, edx:init_edx, esi:init_esi, edi:init_edi,
+                cs:ExprInt(uint32(9)),
+                zf : ExprInt(uint32(0)), nf :  ExprInt(uint32(0)), 
+                pf : ExprInt(uint32(0)),  of :  ExprInt(uint32(0)), 
+                cf :  ExprInt(uint32(0)), tf : ExprInt(uint32(0)),...
+                tsc1: ExprInt(uint32(0)), dr7:ExprInt(uint32(0)),...},
+               mem_read_wrap,
+               mem_write_wrap, )
+
+        \end{lstlisting}}
+  \end{block}
+  
+\end{frame}
+
+
+\begin{frame}[fragile]
+  \begin{exampleblock}{Example}
+    \lstset{language=Python}
+           {\tiny\begin{lstlisting}[]{}  
+>>> l = x86_mn.dis("\x43")
+>>> print l
+inc       ebx
+>>> ex = get_instr_expr(l, eip)
+>>> for e in ex:
+...  print e
+... 
+zf = ((ebx + 0x1) == 0x0)
+nf = ((0x1 == ((ebx + 0x1) >> 0x1F)) & 0x1)
+...
+ebx = (ebx + 0x1)
+           \end{lstlisting}}
+  \end{exampleblock}
+
+  \begin{exampleblock}{Example}
+    \lstset{language=Python}
+	   {\tiny\begin{lstlisting}[]{}  
+>>> machine = eval_abs(dict(init_state))
+>>> print machine.pool[ebx]
+init_ebx
+>>> my_eip, mem_dst = emul_full_expr(ex, l, ExprInt(uint32(0)), None, machine)
+>>> print machine.pool[ebx]
+(init_ebx + 0x1)
+>>> print machine.pool[zf]
+((init_ebx + 0x1) == 0x0)
+           \end{lstlisting}}
+  \end{exampleblock}
+\end{frame}
+
+\section{Jit compilation}
+\subsection{Principle}
+\begin{frame}
+
+  \begin{block}{Memory}
+    \begin{itemize}
+    \item The memory is defined by zones
+    \item size, accesses and data
+    \item (for example a binary section)
+    \item it maps \emph{real addresses} to \emph{virtual addresses}
+    \end{itemize}
+  \end{block}
+  \begin{block}{translation}
+    \begin{itemize}
+    \item the code is disassembled
+    \item translated on the fly using semantic representation
+    \item and intermediate code is generated to C code and compiled
+    \end{itemize}
+  \end{block}
+\end{frame}
+
+
+\begin{frame}
+  \begin{block}{Emulation exception}
+    \begin{itemize}
+    \item if a translated bloc is modified, it is deleted from cache
+    \item and regenerated if pc reach it again (cache miss)
+    \item if errors, python is called back to deal it
+    \item for example, we can emulate windows SEH mechanism
+    \item Emulation des api
+    \end{itemize}
+  \end{block}
+\end{frame}
+
+
+
+
+\begin{frame}
+\begin{center}
+
+\begin{tikzpicture}[node distance = 1.2cm, auto]
+
+  \node [bloc] (runtime)   {RunTime};
+  \node [bloc, xshift=2cm,yshift=-1.5cm] (disasm) at (runtime)  {disassemble};
+  \node [bloc, below of=disasm] (inter)   {intermediate language};
+  \node [bloc, below of=inter] (ccode)   {C Code};
+  \node [bloc, below of=ccode] (python)   {Python module};
+
+  \node [bloc, xshift=-2cm,yshift=-1.5cm] (supprcode) at (runtime)  {Suppr code};
+
+  \draw[->] (runtime) -- (disasm) node[midway] {cache miss};
+  \draw[->] (disasm) -- (inter);
+  \draw[->] (inter) -- (ccode);
+  \draw[->] (ccode) -- (python);
+  \draw[->, looseness=1] (python) to [bend right=95] (runtime);
+
+  \draw[->, looseness=3] (runtime) to [out = 135, in=35] (runtime);
+
+
+  \draw[->] (runtime)  to [bend right=20] node[midway, left] {auto mod}  (supprcode) ;
+  \draw[->] (supprcode) to [bend right=40] (runtime);
+
+\end{tikzpicture}
+\end{center}
+\end{frame}
+
+
+\begin{frame}[fragile]
+  \frametitle{C translation}
+  \lstset{language=C}
+	 {\tiny\begin{lstlisting}[]{}  
+unsigned int bloc_0080400B(void)
+{
+ loc_0080400B:
+    //pop       eax
+    vmcpu.eax_new = MEM_LOOKUP_32(vmcpu.esp);
+    vmcpu.esp_new = (((vmcpu.esp&0xffffffff) + (0x4&0xffffffff))&0xffffffff);
+ 
+    if (vmcpu.vm_exception_flags > EXCEPT_NUM_UDPT_EIP) {
+        vmcpu.eip = 0x80400B;
+        return (unsigned int)vmcpu.eip;
+    }
+ 
+    vmcpu.eax = vmcpu.eax_new;
+    vmcpu.esp = vmcpu.esp_new;
+ 
+    if (vmcpu.vm_exception_flags) {
+        vmcpu.eip = (vmcpu.vm_exception_flags > EXCEPT_NUM_UDPT_EIP) ?  0x80400B : 0x80400C;
+        return (unsigned int)vmcpu.eip;
+    }
+ 
+ loc_0080400C:
+    //mov       ebx, eax
+    vmcpu.ebx_new = vmcpu.eax;
+ 
+    if (vmcpu.vm_exception_flags > EXCEPT_NUM_UDPT_EIP) {
+        vmcpu.eip = 0x80400C;
+        return (unsigned int)vmcpu.eip;
+    }
+	 \end{lstlisting}}
+\end{frame}
+
+
+\begin{frame}[fragile]
+  \frametitle{translation, memory accesses}
+
+  \begin{exampleblock}{Assembly code}
+  \lstset{language=[x86masm]Assembler}
+	 {\tiny\begin{lstlisting}[]{}  
+movzx   eax, ds:byte_410360[ecx]
+	 \end{lstlisting}}
+  \end{exampleblock}
+
+  \begin{exampleblock}{C code}
+  \lstset{language=C}
+	 {\tiny\begin{lstlisting}[]{}  
+//movzx     eax, byte ptr [ecx+{<asmlabel (unsigned int)&tab_00410340[0x20] >: 1}]
+eax_new = (((0x0 & (0xFFFFFFFF>>(32-24))) << 8) | ((MEM_LOOKUP(8, (((ecx&0xffffffff) + 
+          ((unsigned int)&tab_00410340[0x20]&0xffffffff))&0xffffffff)) & (0xFFFFFFFF>>(32-8))) << 0));
+eax = eax_new;
+	 \end{lstlisting}}
+  \end{exampleblock}
+
+
+\end{frame}
+
+
+\subsection{Exemples jit}
+\begin{frame}[fragile]
+  \frametitle{Demo: assembly code}
+{\tiny\begin{semiverbatim}
+objdump -D -b binary -m i386   -Maddr32,data32,intel sc_test.bin
+sc_test.bin:     file format binary
+Disassembly of section .data:
+00000000 <.data>:
+   0:   b8 ef be 37 13          mov    eax,0x1337beef
+   5:   b9 04 00 00 00          mov    ecx,0x4
+   a:   c1 c0 08                rol    eax,0x8
+   d:   e2 fb                   loop   0xa
+   f:   c3                      ret    
+  \end{semiverbatim}}
+\end{frame}
+
+
+\begin{frame}[fragile]
+  \begin{block}{Memory creation}
+    \lstset{language=Python}
+	   {\tiny\begin{lstlisting}[]{}  
+code_ad = 0x20000
+vm_add_memory_page(code_ad, PAGE_READ|PAGE_WRITE|PAGE_EXEC, open("sc_test.bin").read())
+stack_base_ad = 0x1230000
+stack_size = 0x10000
+vm_add_memory_page(stack_base_ad, PAGE_READ|PAGE_WRITE, "\x00"*stack_size)
+dump_memory_page_pool_py()
+
+regs = vm_get_gpreg()
+regs['eip'] = code_ad
+regs['esp'] = stack_base_ad+stack_size
+vm_set_gpreg(regs)
+dump_gpregs_py()
+
+             \end{lstlisting}}
+  \end{block}
+
+  \begin{exampleblock}{Result}
+    {\tiny\begin{semiverbatim}
+Memory
+ad 00020000 size 00000025 RWX hpad 0x8cd5000
+ad 01230000 size 00010000 RW_ hpad 0x8ce8000
+Registers
+eip 00020000 eax 00000000 ebx 00000000 ecx 00000000 edx 00000000
+esi 00000000 edi 00000000 esp 01240000 ebp 00000000
+    \end{semiverbatim}}
+  \end{exampleblock}
+  
+\end{frame}
+
+\begin{frame}[fragile]
+  \begin{block}{Memory creation}
+    \lstset{language=Python}
+	   {\tiny\begin{lstlisting}[]{}  
+vm_push_uint32_t(0)
+vm_push_uint32_t(0)
+vm_push_uint32_t(0x1337beef)
+
+symbol_pool = asmbloc.asm_symbol_pool()
+
+known_blocs = {}
+code_blocs_mem_range = []
+
+log_regs = True
+log_mn = True
+must_stop = False
+def run_bin(my_eip, known_blocs, code_blocs_mem_range):
+    while my_eip != 0x1337beef:        
+        if not my_eip in known_blocs:
+            updt_bloc_emul(known_blocs, in_str, my_eip, symbol_pool, code_blocs_mem_range, log_regs = log_regs, log_mn = log_mn)
+        try:
+            my_eip = vm_exec_blocs(my_eip, known_blocs)
+        except KeyboardInterrupt:
+            must_stop = True
+        py_exception = vm_get_exception()
+        if py_exception:
+            raise ValueEror("except at", hex(my_eip))
+
+print "start run"
+run_bin(code_ad, known_blocs, code_blocs_mem_range)
+             \end{lstlisting}}
+  \end{block}
+
+\end{frame}
+
+
+
+
+\begin{frame}[fragile]
+
+  \begin{exampleblock}{Result}
+    {\tiny\begin{semiverbatim}
+                                eax 00000000 ebx 0000...
+mov       eax, 0x1337BEEF                            ...
+                                eax 1337BEEF ebx 0000...
+mov       ecx, 0x00000004                            ...
+                                eax 1337BEEF ebx 0000...
+rol       eax, 0x00000008                            ...
+                                eax 37BEEF13 ebx 0000...
+loop      loc_0002000A                               ...
+loc_0002000A                                         ...
+                                eax 37BEEF13 ebx 0000...
+rol       eax, 0x00000008                            ...
+                                eax BEEF1337 ebx 0000...
+loop      loc_0002000A                               ...
+loc_0002000A                                         ...
+                                eax BEEF1337 ebx 0000...
+rol       eax, 0x00000008                            ...
+                                eax EF1337BE ebx 0000...
+loop      loc_0002000A                               ...
+loc_0002000A                                         ...
+                                eax EF1337BE ebx 0000...
+rol       eax, 0x00000008                            ...
+                                eax 1337BEEF ebx 0000...
+loop      loc_0002000A                               ...
+loc_0002000F                                         ...
+                                eax 1337BEEF ebx 0000...
+ret     
+    \end{semiverbatim}}
+  \end{exampleblock}
+  
+\end{frame}
+
+
+
+
+
+\begin{frame}[fragile]
+  \begin{block}{Interaction}
+    \lstset{language=Python}
+	   {\tiny\begin{lstlisting}[]{}  
+>>> vm_get_gpreg()
+{'eip': 322420463, 'esp': 19136504, 'edi': 0, 'eax': 322420463, 
+  'ebp': 0, 'edx': 0, 'ebx': 0, 'esi': 0, 'ecx': 0}
+>>> vm_get_str(code_ad, 0x10)
+'\xb8\xef\xbe7\x13\xb9\x04\x00\x00\x00\xc1\xc0\x08\xe2\xfb\xc3'
+             \end{lstlisting}}
+  \end{block}
+
+\end{frame}
+
+\section{Exemples}
+
+
+
+\subsection{Hooks, gadget finder, ...}
+
+\begin{frame}
+  \begin{block}{Goal: hook in calc.exe}
+    \begin{itemize}
+    \item spot interesting code
+    \item find characteristic code
+    \item generate a hook
+    \end{itemize}
+  \end{block}
+\end{frame}
+
+\begin{frame}[fragile]
+  \frametitle{Code search}
+             {
+               \tiny\begin{verbatim}
+#op code call[XXX]
+p = "\xFF\x15"+ struct.pack('L', ad_setwtext)
+p = re.escape(p)
+candidates = [x.start() for x in re.finditer(p, e.content)]
+candidates = [e.off2virt(x) for x in candidates]
+
+#search func setdisplaytext
+found = False
+for c in candidates:
+    #ad = guess_func_start(e, c)
+    job_done = set()
+    symbol_pool = asmbloc.asm_symbol_pool()    
+    try:
+        all_bloc = asmbloc.dis_bloc_all(x86_mn, in_str, c, job_done, symbol_pool)
+    except:
+        continue
+    #filter on setfocus caller
+    for b in all_bloc:
+        l = b.lines[-1]
+        if not l.m.name == "call" or not x86_afs.imm in l.arg[0]:
+            continue
+        if l.arg[0][x86_afs.imm] == ad_setfocus:
+            found = c
+if not found:
+    raise ValueError("caanot finc setdisplaytext")
+ad = guess_func_start(e, found)
+print "setdisplaytext:", hex(ad)
+              \end{verbatim}
+             }
+\end{frame}
+
+
+\begin{frame}[fragile]
+  \frametitle{Hook example}
+             {
+               \tiny\begin{verbatim}
+h.add_hook(aes_init_ad,
+           {
+               "1_aes_init_key":(0x20, "push ecx"),
+               })
+...
+h.add_hook(rsa_enc_priv_ad,
+           {
+            "1_seckey":(0x140, 'push [esp+0x34]'),
+            "2_txt":(0x80, 'push [esp+0x34]'),
+            "3_mod":(0x80, 'push [esp+0x34]')
+               })
+...
+h.add_hook(pwd_chk_ad,
+           {"1_pwd":('''
+             push [ebp+8]
+             call [lstrlenA]
+             push eax''', 'push ecx'),
+            "2_stack":(0x80, 'push [esp+0x30]')})
+
+              \end{verbatim}
+             }
+\end{frame}
+
+
+\begin{frame}[fragile]
+  \frametitle{Hook creation}
+             {
+               \tiny\begin{verbatim}
+h = hooks(in_str, symbol_pool, gen_data_log_code = False)
+
+hname = h.add_hook(ad,
+           {
+               "1_DONT_LOG":('''
+                mov eax, [ebp+8]
+                cmp byte ptr [eax], 0x31
+                jnz out
+                cmp byte ptr [eax+2], 0x33
+                jnz out
+                cmp byte ptr [eax+4], 0x33
+                jnz out
+                cmp byte ptr [eax+6], 0x37
+                jnz out
+                cmp byte ptr [eax+6], 0x2c
+                jnz out
+                push 0
+                push mtitle
+                push mtxt
+                push 0
+                call [MessageBoxA]
+                
+                
+            out:
+                ''', 'push [esp+0x30]')},
+           ['mtitle:\n.string "title"', 'mtxt:\n.string "txt"'])
+              \end{verbatim}
+             }
+\end{frame}
+
+\begin{frame}[fragile]
+  \frametitle{Binary modification}
+             {
+               \tiny\begin{semiverbatim}
+all_bloc = h.all_bloc
+
+symbol_pool.add(asmbloc.asm_label('base_address', 0))
+symbol_pool.getby_name("MessageBoxA").offset = e.DirImport.get_funcvirt('MessageBoxA')
+symbol_pool.getby_name(hname).offset = e.rva2virt(sh_ad)
+
+symb_reloc = {}
+\textcolor{blue}{#compilation du patch}
+resolved_b, patches = asmbloc.asm_resolve_final(x86mnemo, all_bloc[0], symbol_pool, [(0, sh_ad+e.Opthdr.Opthdr.ImageBase)], symb_reloc)
+add_rels = []
+\textcolor{blue}{#ajout des nouvelles relocations}
+for l, rels in symb_reloc.items():
+    for x in rels:
+        add_rels.append(e.virt2rva(x+l.offset))
+\textcolor{blue}{#ajout des nouveaux imports}
+s_myimp = e.SHList.add_section(name = "myimp", rawsize = len(e.DirImport))
+e.DirImport.set_rva(s_myimp.addr)
+\textcolor{blue}{#patch du binaire}
+for p in patches:
+    e.virt[p] = patches[p]
+\textcolor{blue}{#reconstruction du binaire}
+open('calc_mod.exe', 'wb').write(str(e))
+              \end{semiverbatim}
+             }
+\end{frame}
+
+\begin{frame}
+\frametitle{Go Go Gadget}
+  \begin{block}{Goal: find eip/esp control}
+    \begin{itemize}
+    \item binary mapping into memory
+    \item Memory creation
+    \item add context informations to a program
+    \item start interpretation:      \begin{itemize}
+    \item sweep on each code address range
+    \item execution maximum 10 instruction (for instance)
+    \item analyzes symbolic memory
+    \item filter interesting results
+    \end{itemize}
+    \end{itemize}
+  \end{block}
+\end{frame}
+
+
+\begin{frame}[fragile]
+  \begin{exampleblock}{Loading of a binary dump}
+    \lstset{language=Python}
+	   {\tiny\begin{lstlisting}[]{}  
+data = open(fname, 'rb').read()
+in_str = bin_stream_vm()
+init_memory_page_pool_py()
+init_code_bloc_pool_py()
+vm_add_memory_page(0x10000000, PAGE_READ|PAGE_WRITE, data)
+           \end{lstlisting}}
+  \end{exampleblock}
+  \begin{exampleblock}{variable creation}
+    \lstset{language=Python}
+	   {\tiny\begin{lstlisting}[]{}  
+arg1 = ExprId('ARG1', 32, True)
+arg2 = ExprId('ARG2', 32, True)
+ret1 = ExprId('RET1', 32, True)
+             \end{lstlisting}}
+  \end{exampleblock}
+  \begin{exampleblock}{machine creation}
+    \lstset{language=Python}
+	   {\tiny\begin{lstlisting}[]{}  
+machine = eval_abs({esp:init_esp, ebp:init_ebp, eax:init_eax, ebx:init_ebx, 
+                    ecx:init_ecx, edx:init_edx, esi:init_esi, edi:init_edi,
+                cs:ExprInt(uint32(9)),
+                zf :  ExprInt(uint32(0)), nf :  ExprInt(uint32(0)),
+                of :  ExprInt(uint32(0)), cf :  ExprInt(uint32(0)),
+                ...
+\end{lstlisting}}
+  \end{exampleblock}
+\end{frame}
+
+
+\begin{frame}[fragile]
+  \begin{exampleblock}{add context execution}
+    \lstset{language=Python}
+	   {\tiny\begin{lstlisting}[]{}  
+machine.eval_instr(push(arg2))
+machine.eval_instr(push(arg1))
+machine.eval_instr(push(ret1))
+machine.eval_instr(push(ebp))
+machine.eval_instr(mov(ebp, esp))
+machine.eval_instr(sub(esp, ExprInt(uint32(0x14))))
+machine.eval_instr(mov(eax, ExprMem(ebp + ExprInt(uint32(8)))))
+machine.eval_instr(mov(edx, ExprMem(eax + ExprInt(uint32(12)))))
+machine.eval_instr(mov(eax, ExprMem(ebp + ExprInt(uint32(12)))))
+machine.eval_instr(mov(ExprMem(esp), eax))
+machine.eval_instr(push(ExprInt(uint32(0x1337beef))))
+           \end{lstlisting}}
+(it could have been emulated as well)
+  \end{exampleblock}
+
+    \lstset{language=Python}
+	   {\tiny\begin{lstlisting}[]{}  
+print dump_reg(machine.pool)
+eax ARG2  ebx init_ebx  ecx init_ecx  edx @32[(+ ARG1 0xC)]  
+esi init_esi  edi init_edi  esp (init_esp - 0x28)  
+ebp (init_esp - 0x10)  zf ((init_esp - 0x24) == 0x0)
+           \end{lstlisting}}
+
+\end{frame}
+
+\begin{frame}[fragile]
+  \begin{exampleblock}{Filter results after symbolic execution}
+    \lstset{language=Python}
+	   {\tiny\begin{lstlisting}[]{}  
+myesp = machine.pool[esp]
+if not ('ARG' in str(myesp) or 'DATA' in str(myesp)):
+    continue
+print "eip", my_eip
+print "esp", myesp
+           \end{lstlisting}}
+  \end{exampleblock}
+  \begin{exampleblock}{Result}
+	   {\tiny
+\begin{verbatim}
+0x10002ccf
+eip @32[ARG2]
+esp (ARG2 + 0x4)
+Instructions:
+xchg        eax, esp
+ret                             
+\end{verbatim}
+           }
+  \end{exampleblock}
+\end{frame}
+
+
+\subsection{Conficker}
+\begin{frame}
+
+  \begin{block}{Binary protection}
+    \begin{itemize}
+    \item packed
+    \item the packer is split with indirect jmps
+    \end{itemize}
+  \end{block}
+
+  \begin{block}{Result}
+    \begin{itemize}
+    \item Ida knowns each basic bloc
+    \item but cannot graph
+    \end{itemize}
+  \end{block}
+
+
+  \begin{exampleblock}{Quick Counter measure}
+    \begin{itemize}
+    \item find each indirect jumps
+    \item find destination
+    \item patch the binary
+    \end{itemize}
+  \end{exampleblock}
+
+\end{frame}
+
+
+\begin{frame}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[width=1\textwidth]{figs/conficker_1.eps}
+    \end{center}
+  \end{figure}
+\end{frame}
+
+
+
+
+
+\begin{frame}[fragile]
+  \frametitle{indirect jump patching, binary regeneration}
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+e = pe_init.PE(open('conficker.ese', 'rb').read())
+s_text = e.getsectionbyname('.text')
+s_data = e.getsectionbyname('.data')
+
+for ad in xrange(ad_start, ad_end-15):
+    l1 = x86_mn.dis(e.virt[ad:ad+15])
+    if not l1: continue
+    if not l1.m.name == 'jmp': continue
+    if l1.prefix: continue
+
+    a = l1.arg[0]
+    if not x86_afs.ad in a or not x86_afs.imm in a:
+        continue
+    dst_ptr = a[x86_afs.imm]
+    if not (data_start <= dst_ptr < data_end): continue
+        continue
+    
+    dst_ad = struct.unpack('L', e.virt[dst_ptr:dst_ptr+4])[0]
+    if not( ad_start <= dst_ad < ad_end): continue
+
+    e.virt[ad] = '\x90'*l1.l
+    e.virt[ad] = "\xE9"+struct.pack('l', dst_ad-(ad-1+l1.l))
+
+open('out.bin', 'wb').write(str(e))
+
+	 \end{lstlisting}}
+\end{frame}
+
+\begin{frame}
+  \frametitle{Result: graph ok, but direct basic blocs are still splitted}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[height=0.9\textheight]{figs/conficker_2.eps}
+    \end{center}
+  \end{figure}
+\end{frame}
+
+
+
+\begin{frame}[fragile]
+  \frametitle{Disassembling: main function}
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+
+job_done = []
+symbol_pool = asmbloc.asm_symbol_pool()
+all_bloc = asmbloc.dis_bloc_all(x86_mn, in_str, 0x100041f4, job_done, symbol_pool, follow_call = False, patch_instr_symb = False)
+
+#find call address
+for b in all_bloc:
+    l = b.lines[-1]
+    if l.m.name != 'call': continue
+
+    a = l.arg[0]
+    if not x86_afs.symb in a: continue
+
+    dst,off = dict(a[x86_afs.symb]).popitem()
+    new_bloc = asmbloc.dis_bloc_all(x86_mn, in_str, off, job_done, symbol_pool, follow_call = False, patch_instr_symb = False)
+    all_bloc+=new_bloc
+
+lbl_start = symbol_pool.getby_offset(oep)
+bloc_merge(all_bloc, symbol_pool, [lbl_start])
+	 \end{lstlisting}}
+\end{frame}
+
+\begin{frame}[fragile]
+  \frametitle{clean binary regeneration}
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+#code to PIC
+for b in all_bloc:
+    del symbol_pool.s_offset[b.label.offset]
+    b.label.offset = None
+
+#patch entry point
+all_bloc2, symbol_pool2 = parse_asm.parse_txt(x86_mn,r'''
+dllentry:
+jmp main
+''')
+
+#fix shellcode addr
+#symbol_pool.add(asmbloc.asm_label('base_address', 0))
+symbol_pool2.getby_name("main").offset = 0x10001000
+symbol_pool2.getby_name("dllentry").offset = 0x1000434B
+
+#merge our sc and disassembled function
+all_bloc+=all_bloc2[0]
+for x in symbol_pool2.s.keys():
+    symbol_pool.add(symbol_pool2.s[x])
+...
+open('out.bin', 'wb').write(str(e))
+	 \end{lstlisting}}
+\end{frame}
+
+
+\begin{frame}
+  \frametitle{Result}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[height=0.9\textheight]{figs/conficker_3.eps}
+    \end{center}
+  \end{figure}
+\end{frame}
+
+\begin{frame}
+  \frametitle{We can analyze import functions loader}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[height=0.9\textheight]{figs/conficker_4.eps}
+    \end{center}
+  \end{figure}
+\end{frame}
+
+
+
+\begin{frame}[fragile]
+  \frametitle{Dump and binary reconstruction}
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+e = pe_init.PE()
+e.Opthdr.Opthdr.ImageBase = 0x3a0000
+
+data = open('_003A0000.mem', 'rb').read()
+s_text = e.SHList.add_section(name = "text", addr = 0x0, data = data)
+...
+e.DirImport.add_dlldesc(new_dll)
+s_myimp = e.SHList.add_section(name = "myimp", rawsize = len(e.DirImport))
+e.DirImport.set_rva(s_myimp.addr)
+
+open('out.bin', 'wb').write(str(e))
+	 \end{lstlisting}}
+\end{frame}
+
+\begin{frame}
+  \frametitle{binary reconstruction}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[width=0.9\textwidth]{figs/conficker_5.eps}
+    \end{center}
+  \end{figure}
+\end{frame}
+
+
+\subsection{mebroot}
+
+\begin{frame}
+  \frametitle{Obfuscated packer}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[width=1\textwidth]{figs/mebroot_4.eps}
+    \end{center}
+  \end{figure}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[width=1\textwidth]{figs/mebroot_1.eps}
+    \end{center}
+  \end{figure}
+\end{frame}
+
+\begin{frame}
+  \frametitle{Packer obscurci}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[width=1\textwidth]{figs/mebroot_2.eps}
+    \end{center}
+  \end{figure}
+\end{frame}
+
+
+\begin{frame}
+
+  \begin{block}{Reconstruction}
+    \begin{itemize}
+    \item goal: find non analyzed code
+    \item Disassemble a bloc
+    \item guess fake jcc destination
+    \item group and simplify blocs
+    \item regenerate binary
+    \end{itemize}
+  \end{block}
+\end{frame}
+
+
+\begin{frame}[fragile]
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+def get_mebbloc_instr(e, b):
+    if not b.lines:
+        return None
+    if b.lines[-1].m.name != "jnz":
+        return None
+    if b.lines[-2].m.name != "pop":
+        return None
+    if b.lines[-3].m.name != "test":
+        return None
+    ...
+        asmbloc.dis_bloc(x86mnemo, in_str, b, ad, job_done, symbol_pool, follow_call = False, patch_instr_symb = False)
+...
+asmbloc.bloc_merge(master_bloc, symbol_pool, call_ad)
+	 \end{lstlisting}}
+\end{frame}
+
+
+\begin{frame}
+  \frametitle{Code reconstruit}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[width=1\textwidth]{figs/mebroot_3.eps}
+    \end{center}
+  \end{figure}
+\end{frame}
+
+\begin{frame}
+  \frametitle{re generated binary mapping}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[width=1\textwidth]{figs/mebroot_4.eps}
+    \end{center}
+  \end{figure}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[width=1\textwidth]{figs/mebroot_5.eps}
+    \end{center}
+  \end{figure}
+
+
+\end{frame}
+
+\begin{frame}
+  \frametitle{Entry point}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[height=0.8\textheight]{figs/mebroot_6.eps}
+    \end{center}
+  \end{figure}
+\end{frame}
+
+
+
+\begin{frame}
+  \frametitle{Analysis}
+  \begin{block}{Reconstruction}
+    \begin{itemize}
+    \item The binary brute force its own key (hash)
+    \item Decipher itself
+    \item and decompress
+    \end{itemize}
+  \end{block}
+  
+  \begin{exampleblock}{We could borrow its own code}
+    \begin{itemize}
+    \item Disassemble deciphering code
+    \item Disassemble decompression code
+    \item Generate C code
+    \item and execute it on another ciphered code
+    \end{itemize}
+  \end{exampleblock}
+
+\end{frame}
+
+
+
+\begin{frame}[fragile]
+
+  \begin{exampleblock}{Deciphering function emulation}
+    {\tiny
+    \begin{verbatim}
+bsize: 33858
+bufs 0x976a000 0xb4bac008
+starting...
+dyn_call to B4E6B480
+dyn_call to B4E6B300
+nop func called
+...
+dyn_call to B4E6B480
+dyn_call to B4E6B300
+nop func called
+dyn_call to B4E6B480
+dyn_call to B4E6B300
+nop func called
+dyn_call to B4E6B480
+dyn_call to B4E6B300
+nop func called
+88B308C5 88B308C5
+C4FB632B C4FB632B
+AA94D763 AA94D763
+5C2BB68F 5C2BB68F
+end
+ret len 33858
+
+    \end{verbatim}
+}
+  \end{exampleblock}
+
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \begin{exampleblock}{Decompression function code}
+    {\tiny
+    \begin{verbatim}
+bsize: 33858
+bufs 0x947b000 0xb46b1008
+starting...
+dyn_call to B4AFC3F0
+func alloc 828B0 (ret B462E008)
+dyn_call to B4AFC5F0
+dyn_call to B4AFC3F0
+func alloc 3E6C (ret 94AF600)
+dyn_call to B4AFC9D0
+dyn_call to B4AFC350
+func free 94AF600 (from 401FB5)
+ret: 'MZ\x90\x00\x03\x00\x00\x00\x04\x00\x00\x00\xff\xff...'
+    \end{verbatim}
+}
+  \end{exampleblock}
+
+\end{frame}
+
+
+
+\begin{frame}
+  \frametitle{Final step}
+
+  \begin{exampleblock}{Second layer}
+    \begin{itemize}
+    \item The binary generate a new binary (driver)
+    \item It is packed as well
+    \item Redo previous steps
+    \item or use previous functions to decipher new binary
+    \end{itemize}
+  \end{exampleblock}
+
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[width=1\textwidth]{figs/mebroot_7.eps}
+    \end{center}
+  \end{figure}
+\end{frame}
+
+
+\begin{frame}
+  \frametitle{Obfuscated functions}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[height=0.8\textheight]{figs/mebroot_obf_01.eps}
+    \end{center}
+  \end{figure}
+\end{frame}
+
+
+
+\tikzset{bloc/.style={
+    rectangle,minimum size=6mm, minimum width=6em,
+    very thick,draw=black!50,
+    top color=white,bottom color=black!20,
+    rounded corners,
+    font=\scriptsize}}
+
+
+\tikzset{mywave/.style={
+    snake=expanding waves,segment length=2mm, segment angle=20}}
+
+\begin{frame}
+
+\begin{columns}
+
+\column{0.4\textwidth}
+
+\begin{bigcenter}
+\begin{figure}
+\scalebox{0.5}{
+\begin{tikzpicture}[node distance = 3cm,>=latex']
+  \node [bloc] (b1)   {b1};
+  \node [bloc, below right of=b1] (b2)   {b2};
+  \node [bloc, below left of=b1] (b3)   {b3};
+  \node [bloc, below left of=b2] (b4)   {b4};
+
+  \draw[->] (b1) -- (b2);
+  \draw[->] (b1) -- (b3);
+  \draw[->] (b2) -- (b4);
+  \draw[->] (b3) -- (b4);
+
+\end{tikzpicture}
+}
+\end{figure}
+\end{bigcenter}
+\column{0.4\textwidth}
+\begin{bigcenter}
+\scalebox{0.5}{
+\begin{tikzpicture}[node distance = 3cm,>=latex']
+  \node [bloc] (b0)   {\begin{minipage}{2cm}\begin{center}b0\\e = 0\end{center}\end{minipage}};
+
+
+  \node [bloc, below of=b0] (dispatch)   {dispatcher};
+
+
+  \node [bloc, below left of=dispatch] (b2)   {\begin{minipage}{2cm}\begin{center}b2\\e = 4\end{center}\end{minipage}};
+  \node [bloc, left of=b2] (b1)   {\begin{minipage}{2cm}\begin{center}b1\\e = [2,3]\end{center}\end{minipage}};
+  \node [bloc, below right of=dispatch] (b3)   {\begin{minipage}{2cm}\begin{center}b3\\e = 4\end{center}\end{minipage}};
+  \node [bloc, right of=b3] (b4)   {\begin{minipage}{2cm}\begin{center}b3\\e = ?\end{center}\end{minipage}};
+
+
+  \draw[->] (b0) -- (dispatch);
+  \draw[->] (dispatch) -- (b1);
+  \draw[->] (dispatch) -- (b2);
+  \draw[->] (dispatch) -- (b3);
+  \draw[->] (dispatch) -- (b4);
+
+  \draw[->] (b1) to [out = 135, in=180] (dispatch);
+  \draw[->] (b2) to [out = 135, in=180] (dispatch);
+  \draw[->] (b3) to [out = 45, in=0] (dispatch);
+  \draw[->] (b4) to [out = 45, in=0] (dispatch);
+
+
+
+\end{tikzpicture}
+}
+\end{bigcenter}
+\end{columns}
+\end{frame}
+
+\begin{frame}
+  \begin{block}{Reconstruction}
+    \begin{itemize}
+      \item disassemble a function
+      \item get semantic of each bloc
+      \item symbolic execution
+      \item get each bloc result of the automata
+      \item patch jcc
+      \item regenerate binary
+    \end{itemize}
+  \end{block}
+\end{frame}
+
+\begin{frame}
+  \frametitle{Résultat}
+  \begin{figure}[htp]
+    \begin{center}
+      \includegraphics[height=0.8\textheight]{figs/mebroot_obfdel_01.eps}
+    \end{center}
+  \end{figure}
+\end{frame}
+
+
+
+\subsection{VM Study}
+
+\begin{frame}
+  \frametitle{first layer}
+  \begin{block}{Packer}
+    \begin{itemize}
+      \item The binary is ciphered by layers.
+      \item Just create an environment and emulate it with miasm.
+    \end{itemize}
+  \end{block}
+  \begin{center}
+    \includegraphics[width=0.7\textwidth]{figs/xxx_vm01.eps}
+  \end{center}
+\end{frame}
+
+
+\begin{frame}
+  \frametitle{First disassembling of vm mnemonic parsing}
+  \begin{center}
+    \includegraphics[width=0.7\textwidth]{figs/xxx_mnemo02.eps}
+  \end{center}
+\end{frame}
+
+\begin{frame}
+  \frametitle{Obfuscation}
+  \begin{center}
+    \includegraphics[width=1.0\textwidth]{figs/xxx_mnemo03.eps}
+  \end{center}
+\end{frame}
+
+\begin{frame}
+  \begin{block}{Solution}
+    \begin{itemize}
+      \item Callback is the disassembler engine
+      \item symbolic execution of its parents
+      \item Test if jcc is always true/false
+      \item and delete fake edges
+    \end{itemize}
+  \end{block}
+  
+\end{frame}
+
+\begin{frame}
+  \frametitle{Result: simplified mnemonic parser}
+\begin{tabular}{p{5cm} p{5cm} }
+    \includegraphics[width=0.08\textwidth]{figs/xxx_mnemo08.eps}
+ &
+    \includegraphics[width=0.13\textwidth]{figs/xxx_mnemo09.eps}
+\end{tabular}
+
+\end{frame}
+
+\begin{frame}
+  \frametitle{End of parser: instruction dispatcher}
+  \begin{center}
+    \includegraphics[width=0.8\textwidth]{figs/xxx_mnemo10.eps}
+  \end{center}
+\end{frame}
+
+
+\begin{frame}[fragile]
+  \begin{exampleblock}{symbolic execution: touched variables}
+    {\tiny\begin{semiverbatim}
+eax = ((((@8[init_esi] ^ init_ebx[0:8]) - 0xA8) ^ 0x1)_to[0:8], 0x0_to[8:32])
+ebx = ((init_ebx[0:8] - (((@8[init_esi] ^ init_ebx[0:8]) - 0xA8) ^ 0x1))_to[0:8], init_ebx[8:32]_to[8:32])
+esi = (init_esi + 0x1)
+DST @32[((((((@8[init_esi] ^ init_ebx[0:8]) - 0xA8) ^ 0x1)_to[0:8], 0x0_to[8:32]) * 0x4) + init_edi)]
+    \end{semiverbatim}}
+  \end{exampleblock}
+  \begin{block}{Note}
+    \begin{itemize}
+    \item We need to follow modifications of ebx, esi, edi in each vm mnemonic
+    \item Those modifications are needed to known where disassembling next mnemonic
+    \end{itemize}
+  \end{block}
+\end{frame}
+
+\begin{frame}
+  \frametitle{Disassembling correction}
+  \begin{center}
+    \includegraphics[width=0.8\textwidth]{figs/xxx_mnemo04.eps}
+  \end{center}
+\end{frame}
+
+\begin{frame}
+  \frametitle{Bloc grouping}
+  \begin{center}
+    \includegraphics[width=1.0\textwidth]{figs/xxx_mnemo05.eps}
+  \end{center}
+\end{frame}
+
+\begin{frame}
+  \frametitle{More than 150 vm mnemonic}
+  \begin{center}
+    \includegraphics[width=1.0\textwidth]{figs/xxx_mnemo07.eps}
+  \end{center}
+\end{frame}
+
+\begin{frame}
+  \frametitle{Bloc analysis: erf}
+  \begin{center}
+    \includegraphics[width=0.6\textwidth]{figs/xxx_mnemo06.eps}
+  \end{center}
+\end{frame}
+
+
+\begin{frame}[fragile]
+  \frametitle{But symbolic execution (again :p)}
+{\tiny\begin{semiverbatim}
+Registers after a bloc execution
+ eax init_eax  
+ ebx init_ebx  
+ ecx (@16[init_esp]_to[0:16], init_ecx[16:32]_to[16:32])  
+ edx init_edx  
+ esi init_esi  
+ edi init_edi  
+ esp (init_esp-0x2)  
+ ebp init_ebp  
+
+stack modification:
+ @16[(init_esp+0x2)]    (@16[(init_esp+0x2)]<<(@8[init_esp]&0x1F))
+ @32[(init_esp-0x2)]    ((@8[init_esp]&0x1F)?(0x0,((@16[(init_esp+0x2)]>>(0x10-(@8[init_esp]&0x1F)))&0x1))_to[0:1], 0x1_to[1:2], (parity (@16[(init_esp+0x2)]<<(@8[init_esp]&0x1F)))_to[2:3], 0x0_to[3:4], (((init_esp+0x2)&0x10)==0x10)_to[4:5], 0x0_to[5:6], ((@16[(init_esp+0x2)]<<(@8[init_esp]&0x1F))==0x0)_to[6:7], ((0x1==((@16[(init_esp+0x2)]<<(@8[init_esp]&0x1F))>>0xF))&0x1)_to[7:8], 0x2_to[8:11], ((0x1==((@16[(init_esp+0x2)]<<(@8[init_esp]&0x1F))>>0xF))^((@16[(init_esp+0x2)]>>(0x10-(@8[init_esp]&0x1F)))&0x1))_to[11:12], 0x0_to[12:32])
+ 
+Result:
+\textcolor{blue}{a = pop16
+b = pop16
+push16(a<<b)
+push32(eflag)}      
+  \end{semiverbatim}}
+\end{frame}
+
+
+\begin{frame}[fragile]
+  \frametitle{Another example}
+{\tiny\begin{semiverbatim}
+---------- 12 0x6fab03 ----------
+eax = @32[init_esp]
+@32[(init_esp+0x4)]    (@32[(init_esp+0x4)]-@32[init_esp])
+@32[init_esp]    (flags(@32[(init_esp+0x4)]-@32[init_esp]))
+---------- 13 0x6fb100 ----------
+eax = @32[init_esp]
+esp = (init_esp+0x4)
+@32[(init_esp+0x4)]    (@32[(init_esp+0x4)]^@32[init_esp])
+---------- 15 0x6fb3b2 ----------
+@32[(init_edi+0x1C)]    (@32[(init_edi+0x1C)]&0xFFFFFBFF)
+---------- 19 0x6fb6b8 ----------
+ecx = @32[init_esp]
+esp = (init_esp+0x4)
+@32[(init_esp+0x4)]    (@32[(init_esp+0x4)]<<(@8[init_esp]&0x1F))
+---------- 21 0x6fb97e ----------
+eax = @32[init_esp]
+@32[init_esp]    @32[@32[init_esp]]
+---------- 24 0x6fc3d1 ----------
+eax = ((((@16[init_esi]_to[0:16], init_eax[16:32]_to[16:32])+init_ebx)^0x18EE5784)-0x12C0A81E)
+ebx = (init_ebx^((((@16[init_esi]_to[0:16], init_eax[16:32]_to[16:32])+init_ebx)^0x18EE5784)-0x12C0A81E))
+edx = (init_edx^((((@16[init_esi]_to[0:16], init_eax[16:32]_to[16:32])+init_ebx)^0x18EE5784)-0x12C0A81E))
+esi = (init_esi+0x2)
+---------- 28 0x6fc935 ----------
+...
+esp = (init_esp-0x4)
+@32[(init_esp+0x4)]    (@32[(init_esp+0x4)] umul32_hi @32[init_esp])
+@32[init_esp]    (@32[(init_esp+0x4)] umul32_lo @32[init_esp])
+@32[(init_esp-0x4)]    (0x2_to[0:2], (parity init_edi)_to[2:3], 0x0_to[3:4], (((init_esp+0x4)&0x10)==0x10)_to[4:5], 0x0_to[5:6], (init_edi==0x0)_to[6:7], ((0x1==(init_edi>>0x1F))&0x1)_to[7:8], 0x2_to[8:32])
+  \end{semiverbatim}}
+\end{frame}
+
+\begin{frame}[fragile]
+  \begin{block}{Instruct the interpreter}
+    \begin{itemize}
+    \item \verb?@32[(init_edi+0x1C)]? is the vm eflagest le eflag de la vm
+    \item we replace \verb?@8[(init_edi+0x28)]?, by  REG1, REG2, ...
+    \item we replace \verb?esp+X? by registers \verb?arg32_0?,  ...
+    \end{itemize}
+  \end{block}
+\end{frame}
+
+\begin{frame}[fragile]
+  \frametitle{Instruction}
+  \lstset{language=Python}
+	 {\tiny\begin{lstlisting}[]{}  
+known_vm_e = {
+    init_edi + ExprInt(uint32(0x1C)): regflag,
+    init_edi + ExprInt(uint32(0x20)): reg1,
+    init_edi + ExprInt(uint32(0x24)): reg2,
+    init_edi + ExprInt(uint32(0x28)): reg3,
+    init_edi + ExprInt(uint32(0x2C)): reg4,
+    init_edi + ExprInt(uint32(0x30)): reg5,
+    init_edi + ExprInt(uint32(0x34)): reg6,
+    init_edi + ExprInt(uint32(0x38)): reg7,
+    init_edi + ExprInt(uint32(0x3C)): reg8,
+    init_edi + ExprInt(uint32(0x40)): reg9,
+
+    ExprMem(init_esp-ExprInt(uint32(4))): argm1_32,
+    ExprMem(init_esp-ExprInt(uint32(2))): argm1_16,
+    ExprMem(init_esp): arg0_32,
+    ExprMem(init_esp+ExprInt(uint32(4))): arg1_32,
+    ExprMem(init_esp, size = 16): arg0_16,
+    ExprMem(init_esp+ExprInt(uint32(2)), size=16): arg1_16,
+    ExprMem(init_esp, size = 8): arg0_08,
+    ExprMem(init_esp+ExprInt(uint32(4)), size=8): arg1_08,
+}
+	 \end{lstlisting}}
+\end{frame}
+
+\begin{frame}[fragile]
+  \frametitle{Results}
+{\tiny\begin{semiverbatim}
+---------- 143 0x70a4f5 ----------    
+esp = (init_esp - 0x4)                
+arg-1_32 = @32[init_edx]              
+\textcolor{blue}{=> push 32@[edx]}
+---------- 151 0x70b1e1 ----------
+eax = arg1_32
+ecx = (arg1_32_to[0:8], ((0x1 == (arg1_08 >> 0x7)) == 0x1)?(0x0,0xFFFFFFFF)_to[8:32])
+esp = (init_esp + 0x4)
+arg1_32 = (arg1_32_to[0:8], ((0x1 == (arg1_08 >> 0x7)) == 0x1)?(0x0,0xFFFFFFFF)_to[8:32])
+\textcolor{blue}{=> pop   dum
+   pop   X
+   movsx X, X8
+   push  X}
+---------- 154 0x70b8b4 ----------
+ecx = (arg0_16_to[0:16], init_ecx[16:32]_to[16:32])
+esp = (init_esp - 0x2)
+arg1_16 = (arg1_16 a>> (arg0_08 & 0x1F))
+arg-1_16 = ... flags of op ...
+\textcolor{blue}{=> push arg1_16 >> arg0_08
+   push eflags}
+---------- 158 0x70bb56 ----------
+esp = (init_esp - 0x4)
+arg-1_32 = @32[reg4]
+\textcolor{blue}{=> push @32[reg4]}
+---------- 155 0x70ba09 ----------
+arg0_32 = (! arg0_32)
+DST 0x6F88F1
+\textcolor{blue}{=> not @32[esp]}
+  \end{semiverbatim}}
+\end{frame}
+
+\begin{frame}
+  \begin{block}{Multi bloc mnemonic}
+    \begin{itemize}
+    \item A mnemonic can have a complex graph
+    \item we can evaluate a bloc, and propagate its state to its sons
+    \item and so on
+    \item No loop for the moment
+    \end{itemize}
+  \end{block}
+\end{frame}
+
+\begin{frame}[fragile]
+  \frametitle{Result: multiple vm exit}
+\begin{tabular}{p{5cm} p{5cm}}
+\multicolumn{2}{c}{ teste si reg7 == 0x0}
+\\      
+{\tiny\begin{semiverbatim}
+
+\textcolor{blue}{---------- state 1 ----------}
+eax = @32[(init_esp + 0x1C)]
+ebx = @32[(init_esp + 0x10)]
+ecx = @32[(init_esp + 0x18)]
+edx = @32[(init_esp + 0x14)]
+esi = arg1_32
+edi = arg0_32
+\textcolor{blue}{the vm does not unstack args}
+esp = (init_esp + 0x28)
+ebp = @32[(init_esp + 0x8)]
+@32[reg5] = 0x0
+DST @32[(init_esp + 0x24)]
+  \end{semiverbatim}}
+&
+{\tiny\begin{semiverbatim}
+\textcolor{blue}{---------- state 2 ----------}
+eax = @32[(init_esp + 0x1C)]
+ebx = @32[(init_esp + 0x10)]
+ecx = @32[(init_esp + 0x18)]
+edx = @32[(init_esp + 0x14)]
+esi = arg1_32
+edi = arg0_32
+\textcolor{blue}{the vm unstack reg7 arguments}
+esp = ((init_esp + @32[reg7]) + 0x28)
+ebp = @32[(init_esp + 0x8)]
+@32[reg7] = 0x0
+@32[reg5] = 0x0
+arg-1_32 = ((init_esp + @32[reg7]) + 0x24)
+DST @32[(init_esp + 0x24)]
+  \end{semiverbatim}}
+\end{tabular}
+\end{frame}
+
+\end{document}
+
+
diff --git a/example/asm_arm.py b/example/asm_arm.py
new file mode 100755
index 00000000..b146a362
--- /dev/null
+++ b/example/asm_arm.py
@@ -0,0 +1,68 @@
+#! /usr/bin/env python
+
+from miasm.arch.arm_arch import arm_mn
+from miasm.core.bin_stream import  bin_stream
+from miasm.core import parse_asm
+from miasm.core import asmbloc
+import struct
+
+my_mn = arm_mn
+
+
+####filelogger sc####
+
+all_bloc, symbol_pool = parse_asm.parse_txt(my_mn,r'''
+toto:
+    STMFD  SP!, {R0-R12, LR}^
+    MOV    R11, LR
+    MOV    R11, R0, ROR 4
+    STC    P2,C3, [R5, 24]!
+    MOV    R1, R0
+    LDR    R2, [PC, R0 ROR 0x2]
+    CMP    R2, R3
+    BLE    tutu
+    ORR    R0, R1, R2
+    ORRLE  R0, R0, R0
+    ORR    R0, R0, R0
+    LDR    R3, [R11, 0x98]
+    LDR    R3, [R11, -0x98]
+    STMFD  SP!, {R4-R6,R11,R12,LR,PC}
+    STMFD  SP!, {R0-R12, SP, LR, PC}
+    LDMIA  R9, {R9, R12}
+    BLE    tutu
+    LDMFD  SP, {R4-R8,R11,SP,PC}
+     
+tutu:
+    LDMFD  SP!, {R0-R12, LR}
+    BX     LR
+''')
+
+g = asmbloc.bloc2graph(all_bloc[0])
+open("graph.txt" , "w").write(g)
+
+
+
+for b in all_bloc[0]:
+    print b
+symbol_pool.add(asmbloc.asm_label('base_address', 0x0))
+symbol_pool.getby_name("toto").offset = 0x0
+
+resolved_b, patches = asmbloc.asm_resolve_final(my_mn, all_bloc[0], symbol_pool)
+print patches
+
+f = open('uu.bin', 'w')
+for p, v in patches.items():
+    f.seek(p)
+    f.write(v)
+
+f.close()
+
+print 'DISASSEMBLE FILE'
+data = open('uu.bin', 'rb').read()
+in_str = bin_stream(data)
+job_done = set()
+symbol_pool = asmbloc.asm_symbol_pool()
+all_bloc = asmbloc.dis_bloc_all(my_mn, in_str, 0, job_done, symbol_pool, follow_call = False, lines_wd = 20)
+g = asmbloc.bloc2graph(all_bloc)
+open("graph2.txt" , "w").write(g)
+
diff --git a/example/asm_x86.py b/example/asm_x86.py
new file mode 100755
index 00000000..8e911676
--- /dev/null
+++ b/example/asm_x86.py
@@ -0,0 +1,76 @@
+#! /usr/bin/env python
+
+from miasm.arch.ia32_arch  import *
+from miasm.core.bin_stream import bin_stream
+from miasm.core import parse_asm
+from elfesteem import *
+
+from miasm.core import asmbloc
+import struct
+
+my_mn = x86_mn
+
+
+
+
+my_mn = x86_mn
+
+e = pe_init.PE()
+e.SHList.add_section(name = "text", addr = 0x1000, rawsize = 0x4000)
+
+####filelogger sc####
+all_bloc, symbol_pool = parse_asm.parse_txt(my_mn,r'''
+main:
+  jmp end
+getstr:
+  pop  ebp
+  push  0xb
+  pop	eax
+  cdq
+
+  push	edx
+  mov  cx, 0x632d
+  push	cx
+  mov	edi, esp
+
+  push	0xAA68732f
+  push	0x6e69622f
+  mov	ebx, esp
+  push	edx
+
+  push  ebp
+  mov   byte ptr [ebp+eend-mystr], dl
+  push	edi
+  push	ebx
+  mov   byte ptr [ebx+7], dl
+  mov	ecx, esp
+  int	0x80
+end:
+  call	getstr
+mystr:
+.string "cat /etc/passwd> /tmp/ooo; ls;"
+eend:
+  nop
+''')
+
+#fix shellcode addr
+symbol_pool.add(asmbloc.asm_label('base_address', 0x400000))
+symbol_pool.getby_name("main").offset = 0x401000
+
+for b in all_bloc[0]:
+    print b
+####graph sc####
+g = asmbloc.bloc2graph(all_bloc[0])
+open("graph.txt" , "w").write(g)
+
+print "symbols"
+print symbol_pool
+#dont erase from start to shell code padading
+resolved_b, patches = asmbloc.asm_resolve_final(my_mn, all_bloc[0], symbol_pool)
+print patches
+
+for offset, raw in patches.items():
+    e.virt[offset] = raw
+
+open('uu.bin', 'wb').write(str(e))
+
diff --git a/example/disas_and_graph.py b/example/disas_and_graph.py
new file mode 100755
index 00000000..0763f824
--- /dev/null
+++ b/example/disas_and_graph.py
@@ -0,0 +1,79 @@
+#! /usr/bin/env python
+import os
+from elfesteem import *
+from miasm.tools.pe_helper import *
+from miasm.tools import seh_helper
+from miasm.core import bin_stream
+import inspect
+from miasm.core import asmbloc
+from miasm.core import parse_asm
+from elfesteem import pe
+from miasm.arch import ia32_arch
+import pickle
+import sys
+fname = sys.argv[1]
+dis_oep = True
+print sys.argv
+if len(sys.argv) >2:
+    ad_to_dis = int(sys.argv[2], 16)
+    dis_oep = False
+
+
+
+dll_dyn_funcs = {}
+data = open(fname, 'rb').read()
+if data.startswith("MZ"):
+    e = pe_init.PE(open(fname, 'rb').read())
+    if dis_oep:
+        ad_to_dis = e.rva2virt(e.Opthdr.AddressOfEntryPoint)
+    in_str = bin_stream.bin_stream(e.virt)
+    try:
+        dll_dyn_funcs = get_import_address(e)
+    except:
+        print 'bug in import parsing'
+
+
+elif data.startswith("\x7fELF") :
+    e = elf_init.ELF(open(fname, 'rb').read())
+    if dis_oep:
+        ad_to_dis = e.Ehdr.entry
+    in_str = bin_stream.bin_stream(e.virt)
+    try:
+        dll_dyn_funcs = get_import_address_elf(e)
+    except:
+        print 'bug in import parsing'
+
+else:
+    in_str = bin_stream.bin_stream(data)
+
+print 'dis', fname, 'at', "0x%.8X"%ad_to_dis
+
+
+
+symbol_pool = asmbloc.asm_symbol_pool()
+# test qt
+from miasm.graph.graph_qt import graph_blocs
+
+
+
+#test symbols from ida
+for (n,f), ad in dll_dyn_funcs.items():
+    l = asmbloc.asm_label("%s_%s"%(n, f), ad)
+    print l
+    symbol_pool.add(l)
+
+
+def my_disasm_callback(ad):
+    all_bloc = asmbloc.dis_bloc_ia32(in_str, ad, symbol_pool = symbol_pool)
+    for b in all_bloc:
+        for l in b.lines:
+            for i, a in enumerate(l.arg):
+                if not ia32_arch.is_ad_lookup(a):
+                    continue
+                x = a[ia32_arch.x86_afs.imm]
+                if x in symbol_pool.s_offset:
+                    l.arg[i][x86_afs.symb] = symbol_pool.s_offset[x]
+                    del(l.arg[i][ia32_arch.x86_afs.imm])
+    return all_bloc
+
+graph_blocs(ad_to_dis, all_bloc = [], dis_callback = my_disasm_callback)
diff --git a/example/sandbox_elf.py b/example/sandbox_elf.py
new file mode 100644
index 00000000..7550cb20
--- /dev/null
+++ b/example/sandbox_elf.py
@@ -0,0 +1,117 @@
+import os
+from elfesteem import *
+from miasm.tools.pe_helper import *
+from miasm.tools import seh_helper
+import inspect
+from miasm.core import asmbloc
+from miasm.core import parse_asm
+from miasm.tools.to_c_helper import *
+from elfesteem import pe
+import cProfile
+import code
+import sys
+from miasm.tools import nux_api
+
+
+# test sandboxing pp100_05ad9efbc4b0c16f243
+
+fname = sys.argv[1]
+e = elf_init.ELF(open(fname, 'rb').read())
+in_str = bin_stream_vm()
+vm_init_regs()
+init_memory_page_pool_py()
+init_code_bloc_pool_py()
+
+codenat_tcc_init()
+
+filename = os.environ.get('PYTHONSTARTUP')
+if filename and os.path.isfile(filename):
+    execfile(filename)
+    
+vm_load_elf(e)
+
+runtime_lib, lib_dyn_funcs = preload_elf(e, patch_vm_imp = True, lib_base_ad = 0x77700000)
+lib_dyn_ad2name = dict([(x[1], x[0]) for x in lib_dyn_funcs.items()])
+dyn_func = {}
+
+
+stack_base_ad = 0x1230000
+stack_size = 0x10000
+vm_add_memory_page(stack_base_ad, PAGE_READ|PAGE_WRITE, "\x00"*stack_size)
+dump_memory_page_pool_py()
+
+
+
+ep =  e.sh.symtab.symbols['main'].value
+
+ptr_esp = stack_base_ad+stack_size-0x1000
+vm_set_mem(ptr_esp, "/home/toto\x00")
+ptr_arg0 = ptr_esp
+ptr_esp -=0x100
+ptr_args = ptr_esp
+vm_set_mem(ptr_args, struct.pack('LL', ptr_arg0, 0))
+           
+regs = vm_get_gpreg()
+regs['eip'] = ep
+regs['esp'] = ptr_esp
+vm_set_gpreg(regs)
+dump_gpregs_py()
+
+vm_push_uint32_t(ptr_args)
+vm_push_uint32_t(1)
+vm_push_uint32_t(0x1337beef)
+
+dump_memory_page_pool_py()
+
+symbol_pool = asmbloc.asm_symbol_pool()
+
+my_eip = ep
+
+
+known_blocs = {}
+code_blocs_mem_range = []
+
+
+log_regs = False
+log_mn = log_regs
+must_stop = False
+def run_bin(my_eip, known_blocs, code_blocs_mem_range):
+    global log_regs, log_mn
+    last_blocs = [None for x in xrange(10)]
+    cpt = 0
+    while True:
+        #dyn lib funcs
+        if my_eip in runtime_lib.fad2cname:
+            fname = runtime_lib.fad2cname[my_eip]
+            if not fname in nux_api.__dict__:
+                raise ValueError('unknown api', (hex(vm_pop_uint32_t()), hex(my_eip), fname, hex(cpt)))
+            nux_api.__dict__[fname]()
+            regs = vm_get_gpreg()
+            my_eip = regs['eip']
+
+            continue
+
+
+        if not my_eip in known_blocs:
+            last_blocs.pop(0)
+            last_blocs.append(my_eip)
+            updt_bloc_emul(known_blocs, in_str, my_eip, symbol_pool, code_blocs_mem_range, log_regs = log_regs, log_mn = log_mn)
+
+
+        try:
+            my_eip = vm_exec_blocs(my_eip, known_blocs)
+        except KeyboardInterrupt:
+            must_stop = True
+        py_exception = vm_get_exception()
+        if py_exception:
+            print hex(my_eip)
+            if py_exception & EXCEPT_CODE_AUTOMOD:
+                print 'automod code'
+                dump_gpregs_py()
+                known_blocs, code_blocs_mem_range = updt_automod_code(known_blocs)
+            else:
+                print "unknown exception", py_exception
+                break
+
+print "start run"
+run_bin(my_eip, known_blocs, code_blocs_mem_range)
diff --git a/example/sandbox_pe.py b/example/sandbox_pe.py
new file mode 100644
index 00000000..1b6457be
--- /dev/null
+++ b/example/sandbox_pe.py
@@ -0,0 +1,125 @@
+import os
+from elfesteem import *
+from miasm.tools.pe_helper import *
+import inspect
+from miasm.core import asmbloc
+from miasm.core import parse_asm
+from miasm.tools.to_c_helper import *
+from elfesteem import pe
+import cProfile
+import code
+from miasm.tools import emul_helper
+import sys
+from miasm.tools import win_api
+from miasm.arch.ia32_arch import *
+
+
+def whoami():
+    return inspect.stack()[1][3]
+
+
+fname = sys.argv[1]
+e = pe_init.PE(open(fname, 'rb').read())
+
+
+# /!\ no seh set for this demo
+
+vm_init_regs()
+init_memory_page_pool_py()
+init_code_bloc_pool_py()
+in_str = bin_stream_vm()
+
+codenat_tcc_init()
+
+vm_load_pe(e)
+
+filename = os.environ.get('PYTHONSTARTUP')
+if filename and os.path.isfile(filename):
+    execfile(filename)
+
+
+runtime_dll, dll_dyn_funcs = preload_lib(e, patch_vm_imp = True, lib_base_ad = 0x7c811111)
+# set winapi to ours
+win_api.runtime_dll = runtime_dll
+
+dll_dyn_ad2name = dict([(x[1], x[0]) for x in dll_dyn_funcs.items()])
+dyn_func = {}
+
+
+ep =  e.rva2virt(e.Opthdr.AddressOfEntryPoint)
+
+stack_base_ad = 0x1230000
+stack_size = 0x10000
+vm_add_memory_page(stack_base_ad, PAGE_READ|PAGE_WRITE, "\x00"*stack_size)
+dump_memory_page_pool_py()
+
+
+
+
+
+regs = vm_get_gpreg()
+regs['eip'] = ep
+regs['esp'] = stack_base_ad+stack_size
+vm_set_gpreg(regs)
+dump_gpregs_py()
+
+vm_push_uint32_t(0)
+vm_push_uint32_t(0)
+vm_push_uint32_t(0x1337beef)
+
+symbol_pool = asmbloc.asm_symbol_pool()
+
+known_blocs = {}
+code_blocs_mem_range = []
+
+
+def dump_raw_e(e):
+    e.Opthdr.AddressOfEntryPoint = e.virt2rva(vm_get_gpreg()['eip'])
+    str_e = StrPatchwork(str(e))
+    for s in e.SHList:
+        data = vm_get_str(e.rva2virt(s.addr), s.size)
+        svad = e.rva2virt(s.addr)
+        print hex(len(data))
+        str_e[s.offset] = data
+        e.virt[e.off2virt(s.offset)] = data
+    open('out.bin', 'w').write(str(str_e))
+
+
+log_regs = True
+log_mn = log_regs
+def run_bin(my_eip, known_blocs, code_blocs_mem_range):
+    global log_regs, log_mn
+    while my_eip != 0x1337beef:        
+
+        #dyn dll funcs
+        if my_eip in runtime_dll.fad2cname:
+            fname = runtime_dll.fad2cname[my_eip]
+            if not fname in win_api.__dict__:
+                print repr(fname)
+                raise ValueError('unknown api', hex(vm_pop_uint32_t()))
+            win_api.__dict__[fname]()
+            regs = vm_get_gpreg()
+            my_eip = regs['eip']
+            continue
+
+
+        if not my_eip in known_blocs:
+            updt_bloc_emul(known_blocs, in_str, my_eip, symbol_pool, code_blocs_mem_range, log_regs = log_regs, log_mn = log_mn)
+        try:
+            my_eip = vm_exec_blocs(my_eip, known_blocs)
+        except KeyboardInterrupt:
+            break
+        py_exception = vm_get_exception()
+        if py_exception:
+            if py_exception & EXCEPT_CODE_AUTOMOD:
+                print 'automod code'
+                dump_gpregs_py()
+                known_blocs, code_blocs_mem_range = updt_automod_code(known_blocs)
+            else:
+                raise ValueError("except at", hex(my_eip))
+            
+
+    
+print "start emulation"
+run_bin(ep, known_blocs, code_blocs_mem_range)
+dump_raw_e(e)
diff --git a/miasm/__init__.py b/miasm/__init__.py
new file mode 100644
index 00000000..6c254425
--- /dev/null
+++ b/miasm/__init__.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+__all__ = ['core/asmbloc', 'core/parse_asm', 'core/bin_stream', 'tools/pe_helper' ]
diff --git a/miasm/arch/__init__.py b/miasm/arch/__init__.py
new file mode 100644
index 00000000..acacfbeb
--- /dev/null
+++ b/miasm/arch/__init__.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+__all__ = ['ia32_reg']
diff --git a/miasm/arch/arm_arch.py b/miasm/arch/arm_arch.py
new file mode 100644
index 00000000..c5fb574f
--- /dev/null
+++ b/miasm/arch/arm_arch.py
@@ -0,0 +1,2054 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+from numpy import uint8, uint16, uint32, uint64, int8, int16, int32, int64
+import shlex
+import struct
+
+from miasm.arch.ia32_reg import x86_afs
+from miasm.core.bin_stream import bin_stream
+
+tab_int_size = {int8:8,
+                uint8:8,
+                int16:16,
+                uint16:16,
+                int32:32,
+                uint32:32,
+                int64:64,
+                uint64:64
+                }
+
+def hex2bin(op):
+    out = []
+    for i in xrange(31, -1, -1):
+        out.append(str((op>>i)&1))
+    for i in xrange(32, -1,  -4):
+        out[i:i] = ' '
+    return "".join(out)
+
+def myror(v, r):
+    return ((v&0xFFFFFFFFL)>>r)  | ((v << (32-r))&0xFFFFFFFFL)
+def myrol(v, r):
+    return ((v&0xFFFFFFFFL)>>(32-r))  | ((v << r)&0xFFFFFFFFL)
+
+
+def str2imm(i):
+    if type(i) is list and len(i) == 1:
+        i = i[0]
+    if i.startswith('0x') or i.startswith('-0x'):
+        d =16
+    else:
+        d = 10
+    try:
+        a = int(i, d)
+    except:
+        return False
+    return a
+    
+def imm2str(i):
+    if type(i) in [int, long]:
+        if i<0:
+            return "-0x%.x"%-i
+        else:
+            return "0x%.x"%i
+    return str(i)
+
+def is_imm(i):
+    if type(i) is list and len(i) == 1:
+        i = i[0]
+    if type(i) is list:
+        return False
+    
+    return type(str2imm(i)) is not bool
+
+
+
+def split_args(args):
+    t_enclosed = {'{':'}', '[':']', '(':')'}
+    t_v = ','
+    def get_until_t(args, lvl):
+        o = []
+        while args:
+            x = args.pop(0)
+            if x == lvl[-1]:
+                if len(lvl) == 1:
+                    break
+                else:
+                    lvl.pop()
+                    if x != t_v:
+                        o.append(x)
+                    continue
+            
+            if x != t_v:
+                o.append(x)
+            if x in t_enclosed:
+                lvl.append(t_enclosed[x])
+                continue
+            if x in t_enclosed.values():
+                raise ValueError('unbalanced expr')
+        if lvl and lvl != [',']:
+            raise ValueError('unbalanced expr')
+        return o
+            
+            
+    o = []
+    t = [x for x in shlex.shlex(args)]
+    while t:
+        a = get_until_t(t, [','])
+        o.append(a)
+    return o
+        
+            
+    
+    
+class bm(object):
+    class __metaclass__(type):
+        def __new__(cls, name, bases, odct):
+            if name is "bm":
+                return type.__new__(cls, name, bases, odct)
+            dct = {'fbits':None, 'l':None, "p_property":[], "checkinv" : False}
+            dct.update(odct)
+
+            pname = None
+            if name.startswith('bm_'):
+                pname = name[3:]
+                dct["p_property"] = [pname]+dct["p_property"]
+                
+
+            
+            b = bases[0]
+            
+            dct["check"] = b.check_no
+            l = dct["l"]
+            fbits = dct["fbits"]
+            if fbits:
+                l = len(fbits)
+                allbits = list(fbits)
+                allbits.reverse()
+                fbits = 0
+                fmask = 0
+                while allbits:
+                    a = allbits.pop()
+                    if a in '01':
+                        a = int(a)
+                    fbits<<=1
+                    fmask<<=1
+                    fbits|=[0, a][type(a) is int]
+                    fmask|=[0, 1][type(a) is int]
+                dct["l"] = l
+                dct["fbits"] = fbits
+                #for bm int
+                if pname:
+                    dct[pname] = fbits
+                dct['fmask'] = fmask
+                if dct['checkinv']:
+                    dct["check"] = b.check_fbits_inv
+                else:
+                    dct["check"] = b.check_fbits
+                    
+            p_property = dct["p_property"]
+                
+            for p in p_property:
+                dct["get_"+p] = lambda self, p=p:getattr(self, p)
+                dct["set_"+p] = lambda self, p=p:setattr(self, p)
+            return type.__new__(cls, name, bases, dct)
+
+    def __init__(self, parent, off, set_at = True):
+        self.parent = parent
+        self.off = off-self.l
+    def __repr__(self):
+        return "<W-"+str(self.__class__)+str(self.off+self.l-1)+" "+str(self.off)+">"
+    def check_no(self, v):
+        return True
+    def check_fbits(self, v):
+        return (v>>self.off) & self.fmask == self.fbits
+    def check_fbits_inv(self, v):
+        return (v>>self.off) & self.fmask != self.fbits
+
+    def get_val(self, v):
+        return (v>>self.off) & ((1<<self.l)-1)
+    def set_val(self, v = None):
+        
+        if v == None and len(self.p_property) >= 1:
+            p = self.p_property[0]
+            v = getattr(self, p)
+        return (v&((1<<self.l)-1))<<self.off 
+
+    def bin(self):
+        return self.set_val()
+        
+    def parse(self, v):
+        if len(self.p_property) >= 1:
+            p = self.p_property[0]
+            val = self.get_val(v)
+            setattr(self, p, val)
+        return True
+    def setprop(self, val = None):
+        if len(self.p_property) >= 1:
+            p = self.p_property[0]
+            if not hasattr(self, p):
+                setattr(self, p, None)
+
+
+COND_EQ = 0
+COND_NE = 1
+COND_CS = 2
+COND_CC = 3
+COND_MI = 4
+COND_PL = 5
+COND_VS = 6
+COND_VC = 7
+COND_HI = 8
+COND_LS = 9
+COND_GE = 10
+COND_LT = 11
+COND_GT = 12
+COND_LE = 13
+COND_AL = 14
+COND_NV = 15
+
+class bm_cond(bm):
+    l = 4
+    p_property = ["cond2str", 'str2cond']
+    n = ['EQ', 'NE', 'CS', 'CC', 'MI', 'PL', 'VS', 'VC', 'HI', 'LS', 'GE', 'LT', 'GT', 'LE', 'AL', 'NV']
+
+    def cond2str(self):
+        return self.n[self.cond]
+
+    def str2cond(self, cond):
+        if not cond in self.n:
+            raise ValueError('unknown cond')
+        self.cond = self.n.index(cond)    
+    
+
+class bm_int0(bm):
+    fbits = '0'
+
+class bm_int1(bm):
+    fbits = '1'
+
+class bm_int00(bm):
+    fbits = '00'
+
+class bm_int01(bm):
+    fbits = '01'
+
+class bm_int000(bm):
+    fbits = '000'
+
+class bm_int011(bm):
+    fbits = '011'
+class bm_int0111(bm):
+    fbits = '0111'
+
+
+class bm_int01101(bm):
+    fbits = '01101'
+class bm_int100(bm):
+    fbits = '100'
+
+class bm_int101(bm):
+    fbits = '101'
+
+class bm_int110(bm):
+    fbits = '110'
+
+class bm_int0000(bm):
+    fbits = '0000'
+
+class bm_int1001(bm):
+    fbits = '1001'
+
+class bm_int1110(bm):
+    fbits = '1110'
+
+class bm_int1111(bm):
+    fbits = '1111'
+
+class bm_int00001(bm):
+    fbits = '00001'
+
+class bm_int00010(bm):
+    fbits = '00010'
+
+class bm_int000000(bm):
+    fbits = '000000'
+
+class bm_accum(bm):
+    l = 1
+    n = ['MUL', 'MLA']
+    def name2str(self):
+        return self.n[self.accum]
+
+    def str2name(self, name):
+        if not name in self.n:
+            raise ValueError('unknown name')
+        self.accum = self.n.index(name)
+
+class bm_immop(bm):
+    l = 1
+
+class bm_opc(bm):
+    l = 4
+
+class bm_opsz(bm):
+    l = 1
+
+class bm_szext(bm):
+    l = 2
+
+class bm_rot(bm):
+    l = 2
+
+class bm_scc(bm):
+    l = 1
+    p_property = ["scc2str"]
+    def scc2str(self):
+        return ['', 'S'][self.scc==1]
+
+class bm_lnk(bm):
+    l = 1
+    p_property = ["lnk2str"]
+    def lnk2str(self):
+        return ['', 'L'][self.lnk==1]
+
+class bm_offs(bm):
+    l = 24
+
+    def parse(self, v):
+        val = self.get_val(v)
+        val<<=2
+        if val & (1<<25):
+            val |=0xFC000000
+        self.offs = val
+        return True
+    def bin(self):
+        if not type(self.offs) in [int, long]:
+            v = 0
+        else:
+            v = (self.offs>>2)&0xffffff
+        return self.set_val(v)
+
+class bm_cooff(bm):
+    l = 8
+
+    def parse(self, v):
+        val = self.get_val(v)
+        val<<=2
+        self.cooff = val
+        return True
+    def bin(self):
+        v = (self.cooff>>2)&0xff
+        return self.set_val(v)
+
+class bm_size(bm):
+    l = 1
+    p_property = ["size2str"]
+    def size2str(self):
+        return ['', 'B'][self.size==1]
+
+class bm_tlen(bm):
+    l = 1
+
+class bm_ppndx(bm):
+    l = 1
+
+class bm_updown(bm):
+    l = 1
+
+class bm_psr(bm):
+    l = 1
+
+class bm_wback(bm):
+    l = 1
+
+class bm_ldst(bm):
+    l = 1
+
+class bm_reglist(bm):
+    l = 16
+
+    def parse(self, v):
+        val = self.get_val(v)
+        self.reglist = []
+        for i in xrange(0x10):
+            if val & (1<<i):
+                self.reglist.append(i)
+        return True
+    def bin(self):
+        v = 0
+        for r in self.reglist:
+            v|=(1<<r)
+        return self.set_val(v)
+            
+class bm_rn(bm):
+    l = 4
+
+class bm_rd(bm):
+    l = 4
+
+class bm_rdh(bm):
+    l = 4
+
+class bm_rdl(bm):
+    l = 4
+
+class bm_rs(bm):
+    l = 4
+
+class bm_rm(bm):
+    l = 4
+
+class bm_crd(bm):
+    l = 4
+
+class bm_crn(bm):
+    l = 4
+
+class bm_crm(bm):
+    l = 4
+
+class bm_cpnum(bm):
+    l = 4
+
+class bm_cpopc(bm):
+    l = 4
+
+class bm_opmode(bm):
+    l = 3
+
+class bm_info(bm):
+    l = 3
+
+class bm_swint(bm):
+    l = 24
+
+class bm_op2(bm):
+    l = 12
+    p_property = ["rm", "rot", "imm", "rs", 'shiftt', 'sub_shift_type', 'amount']
+
+    def parse(self, v):
+        val = self.get_val(v)
+        self.op2 = val
+
+        if self.parent.immop:
+            self.rot = val>>8
+            self.imm = val&0xff
+        else:
+            self.rm = val&0xf
+            self.shift = val>>4
+            self.sub_shift_type = self.shift&1
+            self.shift>>=1
+            self.shiftt = self.shift&0x3
+            self.shift>>=2
+            
+            if self.sub_shift_type:
+                #sub shift type is reg
+                if self.shift&1:
+                    return False
+                self.rs = self.shift>>1
+                if self.rs==0:
+                    return False
+            else:
+                #sub shift type is imm
+                self.amount = self.shift
+                
+        return True
+
+    def bin(self):
+        if self.parent.immop:
+            val = self.rot<<8
+            val+=self.imm&0xff
+        else:
+            shift = self.sub_shift_type
+            shift |= self.shiftt<<1
+            if self.sub_shift_type:
+                shift|=self.rs<<4
+            else:
+                shift|=self.amount<<3
+            val = (shift<<4) | (self.rm&0xf)
+            
+        self.op2 = val
+        return self.set_val()
+
+class bm_opoff(bm):
+    l = 12
+    p_property = ["rm", "imm", 'shiftt', 'amount']
+
+    def parse(self, v):
+        val = self.get_val(v)
+        self.opoff = val
+        
+        if self.parent.immop:
+            self.shift = val>>4
+            self.rm = val&0xf
+            if self.shift&1:
+                #no reg shift
+                return False
+            
+            self.shift>>=1
+            self.shiftt = self.shift&0x3
+            self.amount = self.shift>>2
+        else:
+            self.imm = val&0xfff
+            
+        return True
+
+    def bin(self):
+        if self.parent.immop:
+            shift = 0
+            shift |= self.shiftt<<1
+            shift|=self.amount<<3
+            val = (shift<<4) | (self.rm&0xf)
+        else:
+            val = self.imm&0xfff
+            
+        self.opoff = val
+        return self.set_val()
+
+class bm_undef1(bm):
+    l = 20
+
+class bm_undef2(bm):
+    l = 4
+
+class bmi_int1XX1(bm):
+    fbits = '0XXXXXXXXXXXXXXXXX1XX1'
+    checkinv = True
+
+class bmi_int1111(bm):
+    fbits = '1111'
+    checkinv = True
+
+class bmi_intX00X(bm):
+    fbits = '1XXXXXXXXXXXXXXXX1001'
+    checkinv = True
+
+class bmi_int11110XX1(bm):
+    fbits = 'X0XXXXXXXXXXXXX11110XX1'
+    checkinv = True
+
+class bm_int000100101111111111110001(bm):
+    fbits = '000100101111111111110001'
+
+class bm_int0001001011111111111100(bm):
+    fbits = '0001001011111111111100'
+    
+class bmi_int1XXXX1(bm):
+    fbits = '1XXXXXXXXXXXXXXXXXXXX1'
+    checkinv = True
+
+class bm_sh(bm):
+    l = 2
+
+class bm_hdoff1(bm):
+    l = 4
+
+class bm_hdoff2(bm):
+    l = 4
+
+class bm_sign(bm):
+    l = 1
+
+
+class arm_mnemo_metaclass(type):
+    rebuilt_inst = False
+
+    def __call__(cls, op, offset = 0):
+        if type(op) in [int, long]:
+            cls = cls.class_from_op(op)
+            i = cls.__new__(cls)
+            i.__init__(op, offset)
+        elif type(op) is str:
+            cls = cls.asm(op)
+            i = cls.__new__(cls)
+            i.__init__(op, 0, False)
+        else:
+            raise ValueError('zarb arg')
+        return i
+        
+    def class_from_op(cls, op):
+        #print "dis", hex(op), hex2bin(op)
+        tab_mn = [arm_data, arm_mul, arm_mull, arm_swp, arm_brxchg, arm_hdtreg, arm_hdtimm, arm_sdt, arm_bdt, arm_br, arm_codt, arm_cort, arm_codo, arm_swi, arm_szext]#, arm_undef]
+        ret = filter(lambda x:x.check(op), tab_mn)
+        if len(ret)==1:
+            return ret[0]
+        raise ValueError('ambiquity %s'%str(ret))
+
+
+    def dis(cls, bin, amode = None, sex = None):
+        if type(bin) == str:
+            bin = bin_stream(bin)
+        elif not isinstance(bin, bin_stream):
+            raise ValueError('unknown input')
+
+        op = bin.readbs(4)
+        op = struct.unpack('<L', op)[0]
+        return cls(op, bin.offset-4)
+        
+    def asm_instr(cls, txt):
+        tab_mn = [arm_data, arm_mul, arm_mull, arm_swp, arm_brxchg, arm_hdtreg, arm_hdtimm, arm_sdt, arm_bdt, arm_br, arm_codt, arm_cort, arm_codo, arm_swi, arm_szext]#, arm_undef]
+        t = [x for x in shlex.shlex(txt)]
+        t.reverse()
+        name = t.pop()
+        ret = filter(lambda x:x.check_mnemo(name), tab_mn)
+        if len(ret)!=1:
+            raise ValueError('parse name err %s'%str(ret))
+        cls = ret[0]
+        i = cls.__new__(cls)
+        i.__init__(txt, 0, False)
+        return i
+
+    def asm(cls, txt, symbol_reloc_off = {}):
+        #print txt
+        i = cls.asm_instr(txt)
+        return [struct.pack('<L', i.bin())]
+        
+    def __new__(cls, name, bases, dct):
+        ret_c = type.__new__(cls, name, bases, dct)
+        if name is "arm_mn":
+            return ret_c
+
+        mask = []
+        if 'mask' in dct:
+            for off in dct['mask']:
+                mc = dct['mask'][off](None, off+1)
+                mask.append(mc)
+            
+        mask_orig = [bm_cond]+dct["mask_list"]
+        ret_c.mask_orig = mask_orig
+        off = 32
+        for m in mask_orig:
+            mc = m(None, off)
+            off-=mc.l
+            mask.append(mc)
+            for pname in m.p_property:
+                '''
+                p = property(lambda self=ret_c, pname=pname:getattr(getattr(self, "bm_"+pname), pname),
+                             lambda self=ret_c, val=None,pname=pname:setattr(getattr(self, "bm_"+pname), pname, val))
+                '''
+                p = property(lambda self, pname=pname:getattr(getattr(self, "bm_"+pname), pname),
+                             lambda self, val=None,pname=pname:setattr(getattr(self, "bm_"+pname), pname, val))
+                
+                setattr(ret_c, pname, p)
+                
+        if off!=0:
+            raise ValueError('invalid mnemonic %d'%off)
+        ret_c.mask_chk = mask
+        
+        return ret_c
+    
+    def check(self, op):
+        for m in self.mask_chk:
+            if m.off<20 and m.fbits==None:
+                continue
+            if not m.check(op):
+                return False
+        return True
+
+    def check_opts(self, rest):
+        if rest:
+            return False
+        return True
+
+    def check_mnemo(self, mnemo):
+        found = False
+        for n in self.namestr:
+            if mnemo.startswith(n):
+                found = True
+                break
+        if not found:
+            return False
+        
+        rest = mnemo[len(n):]
+        for c in bm_cond.n:
+            if rest.startswith(c):
+                rest = rest[len(c):]
+                break
+        return self.check_opts(rest)
+        
+    def pre_parse_mnemo(self, args):
+        mn = [x for x in shlex.shlex(args)][0]
+        t = split_args(args[args.index(mn)+len(mn):])
+        t = [mn]+t
+        t.reverse()
+        return t
+
+    def parse_mnemo(cls, args):
+        t = cls.pre_parse_mnemo(args)
+        mn = t.pop()
+        t.reverse()
+        
+
+        return [], mn, t
+
+
+    def parse_address(self, a):
+        o = {}
+        if len(a) != 1:
+            return a
+        if a[0] in regs_str+cop_str+copr_str:
+            return a
+        return {x86_afs.symb:{a[0]:1}}
+
+    def prefix2hex(self, prefix):
+        return ""
+
+    def has_symb(cls, a):
+        if type(a) in [int, long]+tab_int_size.keys():
+            return False
+        if x86_afs.symb in a:
+            return True
+        return False
+    def get_symbols(cls, a):
+        if x86_afs.symb in a:
+            return a[x86_afs.symb].items()
+        return []
+    def names2symbols(cls, a, s_dict):
+        all_s = a[x86_afs.symb]
+        for name, s in s_dict.items():
+            count = all_s[name]
+            del(all_s[name])
+            all_s[s] = count
+    def fix_symbol(cls, a, symbol_pool = None):
+        pass
+    def is_mem(cls, a):
+        pass
+
+    def get_label(cls, a):
+        if x86_afs.ad in a and a[x86_afs.ad]:
+            return None
+        if x86_afs.imm in a:
+            return None
+        if not x86_afs.symb in a:
+            return None
+        n = a[x86_afs.symb]
+        if len(n)!=1:
+            return None
+        k = n.keys()[0]
+        if n[k] != 1:
+            return None
+        return k
+    
+regs_str = ['R%d'%r for r in xrange(0x10)]
+regs_str[13] = 'SP'
+regs_str[14] = 'LR'
+regs_str[15] = 'PC'
+
+cop_str = ['P%d'%r for r in xrange(0x10)]
+copr_str = ['C%d'%r for r in xrange(0x10)]
+
+def reg2str(r):
+    return regs_str[r]
+def str2reg(r):
+    if type(r) is list and len(r) == 1:
+        r = r[0]
+    return regs_str.index(r)
+
+def cop2str(r):
+    return cop_str[r]
+def str2cop(r):
+    if type(r) is list and len(r) == 1:
+        r = r[0]    
+    return cop_str.index(r)
+
+def copr2str(r):
+    return copr_str[r]
+def str2copr(r):
+    if type(r) is list and len(r) == 1:
+        r = r[0]    
+    return copr_str.index(r)
+
+def reglist2str(rlist):
+        out = []
+        i = 0
+        while i < len(rlist):
+            j = i+1
+            while j < len(rlist) and rlist[j] <13 and rlist[j]  == rlist[j-1]+1:
+                j+=1
+            j-=1
+            if j < i+2:
+                out.append(reg2str(rlist[i]))
+                i+=1
+            else:
+                out.append(reg2str(rlist[i])+'-'+reg2str(rlist[j]))
+                i = j+1
+
+        return "{"+", ".join(out)+'}'
+
+
+def str2reglist(rlist):
+    r_start = None
+    out = []
+    rlist.pop()
+    while rlist:
+        tmp = rlist.pop()
+        if tmp =='-':
+            r_end = str2reg(rlist.pop())
+            for i in xrange(r_start, r_end+1):
+                out.append(i)
+            r_start = None
+        elif tmp == '}':
+            if r_start!=None:
+                out.append(r_start)
+            break
+        elif r_start==None:
+            r_start = str2reg(tmp)
+        else:
+            out.append(r_start)
+            r_start = str2reg(tmp)
+    return out
+            
+def args2reduce(args):
+    out = []
+    for a in args:
+        if type(a) is list:
+            out+=args2reduce(a)
+        else:
+            out.append(a)
+    return out
+
+def arglist2str(args):
+    out = ""
+    for a in args:
+        if a in ['[', ']', 'LSL', 'LSR', 'ASR', 'ROR']:
+            out+=a+' '
+        else:
+            out+=str(a)
+            out+=', '
+    if out.endswith(', '):
+        out = out[:-2]
+    return out
+
+
+def args2str(args):
+    return arglist2str(args2reduce(args))
+            
+       
+class arm_mn(object):
+    mask_list = []
+    __metaclass__ = arm_mnemo_metaclass
+    def __init__(self, op, offset = 0, dis = True):
+        
+        off=32
+        mask = []
+        self.offset = offset
+        self.l = 4
+        self.m = None
+        self.arg = []
+
+
+
+        for m in self.mask_orig:
+            mc = m(self, off)
+            off-=mc.l
+            for pname in m.p_property:
+                setattr(self, "bm_"+pname, mc)
+            mask.append(mc)
+        self.mask = mask
+        
+        if dis:
+            for m in self.mask:
+                ret = m.parse(op)
+                if not ret:
+                    raise ValueError('cannot parse %.8X'%op)
+        else:
+            for m in self.mask:
+                ret = m.setprop()
+            
+            full_mnemo = arm_mn.pre_parse_mnemo(op)
+            mnemo = full_mnemo.pop()
+            name, cond, rest = self.parse_name_cond(mnemo)
+            self.name = name
+            self.cond = cond
+            self.parse_opts(rest)
+            self.str2name(name)
+
+            self.parse_args(full_mnemo)
+
+    def parse_opts(self, rest):
+        pass
+    def str2name(self, n):
+        pass
+    
+    def getname(self):
+        name = self.name2str()
+        cond = self.cond2str()
+        scc = ""
+        if cond =="AL":cond = "" #XXX smart display
+        
+        return name+cond+scc
+
+    def bin(self):
+        v = 0
+        for m in self.mask:
+            if not m.checkinv:
+                v|=m.bin()
+        return v
+
+    def parse_name_cond(self, mnemo):
+        name, cond = None, None
+        for i, n in enumerate(self.namestr):
+            if mnemo.startswith(n):
+                name = n
+                break
+        if name == None:
+            raise ValueError('cannot parse name')
+
+        rest = mnemo[len(n):]
+        for i, c in enumerate(bm_cond.n):
+            if rest.startswith(c):
+                cond = i
+                break
+            
+        if cond == None:
+            cond = COND_AL         #default cond is AL
+        else:
+            rest = rest[len(c):]
+        return name, cond, rest
+    def breakflow(self):
+        return False
+    def splitflow(self):
+        return False
+    def dstflow(self):
+        return False
+
+    def getnextflow(self):
+        return self.offset+self.l
+
+
+MN_AND = 0
+MN_EOR = 1
+MN_SUB = 2
+MN_RSB = 3
+MN_ADD = 4
+MN_ADC = 5
+MN_SBC = 6
+MN_RSC = 7
+MN_TST = 8
+MN_TEQ = 9
+MN_CMP = 10
+MN_CMN = 11
+MN_ORR = 12
+MN_MOV = 13
+MN_BIC = 14
+MN_MVN = 15
+
+
+class arm_data(arm_mn):
+    mask_list = [bm_int00, bm_immop, bm_opc, bm_scc, bm_rn, bm_rd, bm_op2]
+    mask = {25:bmi_int1XX1, 26:bmi_int11110XX1}
+
+    namestr = ['AND', 'EOR', 'SUB', 'RSB', 'ADD', 'ADC', 'SBC', 'RSC', 'TST', 'TEQ', 'CMP', 'CMN', 'ORR', 'MOV', 'BIC', 'MVN']
+    allshifts = ['LSL', 'LSR', 'ASR', 'ROR']
+
+    def name2str(self):
+        return self.namestr[self.opc]
+    def str2name(self, n):
+        self.opc = self.namestr.index(n)
+
+    @classmethod
+    def check_opts(cls, rest):
+        if rest in ['', 'S']:
+            return True
+        return False
+
+    def args2str(self):
+        args = []
+        if self.opc in [MN_MOV, MN_MVN]:
+            args.append(reg2str(self.rd))
+        elif self.opc in [MN_CMP, MN_CMN, MN_TEQ, MN_TST]:
+            args.append(reg2str(self.rn))
+        else:
+            args.append(reg2str(self.rd))
+            args.append(reg2str(self.rn))
+            
+        if self.immop:
+            #arg is pure imm
+            imm = myror(self.imm, self.rot*2)
+            args.append(imm2str(imm))
+        else:
+            a = reg2str(self.rm)
+            if self.sub_shift_type:
+                #shift with another reg
+                a = [a, self.allshifts[self.shiftt], reg2str(self.rs)]
+            elif self.amount: #if no amount, no display needed
+                a = [a, self.allshifts[self.shiftt], imm2str(self.amount)]
+            args.append(a)
+        return args
+    
+    def __str__(self):
+        name = self.getname()
+        name+=self.scc2str()
+        args = self.args2str()
+        args = args2str(args)
+        return name+" "+args
+
+    def parse_opts(self, opts):
+        self.scc = 0
+        if not opts:
+            return
+        if opts[0] == "S":
+            self.scc = 1
+
+    def parse_args(self, args):
+        if self.opc in [MN_MOV, MN_MVN]:
+            self.rd = str2reg(args.pop())
+            self.rn = 0 #default reg value
+        elif self.opc in [MN_CMP, MN_CMN, MN_TEQ, MN_TST]:
+            self.rn = str2reg(args.pop())
+            self.rd = 0 #default reg value
+        else:
+            self.rd = str2reg(args.pop())
+            self.rn = str2reg(args.pop())
+        self.immop = [0,1][len(args) == 1 and is_imm(args[0])]
+        self.sub_shift_type = 0
+        if self.immop:
+            #pure imm
+
+            i = 0
+            im = str2imm(args.pop())
+            #find rol
+            while myrol(im, 2*i) > 0xFF:
+                i+=1
+                if i > 16:
+                    raise ValueError('cannot encod imm for shift!')
+            self.rot = i
+            self.imm = myrol(im, 2*i)
+            return
+
+        self.rm = str2reg(args.pop())
+
+        #reg shift
+        self.shiftt=0
+        self.amount = 0
+
+        if not args:
+            return
+
+        if len(args) != 1:
+            raise ValueError('zarb arg1', args)
+        args = args.pop()
+
+        #reg shift shift
+        if is_imm(args[-1]):
+            #shift reg shift num
+            self.sub_shift_type = 0
+            self.amount = str2imm(args.pop())
+        else:
+            #shift reg shift reg
+            self.sub_shift_type = 1
+            self.rs = str2reg(args.pop())
+
+        self.shiftt = self.allshifts.index(args.pop())
+        if args:
+            raise ValueError('zarb arg2', args)
+            
+
+            
+
+class arm_mul(arm_mn):
+    mask_list = [bm_int000000, bm_accum, bm_scc, bm_rd, bm_rn, bm_rs, bm_int1001, bm_rm]
+    #cannot have pc in reg
+    namestr = ['MUL', 'MLA']
+    def name2str(self):
+        return self.namestr[self.accum]
+    def str2name(self, n):
+        self.accum = self.namestr.index(n)
+
+    @classmethod
+    def check_opts(cls, rest):
+        if rest in ['', 'S']:
+            return True
+        return False
+
+    def args2str(self):
+        args = []
+        args.append(reg2str(self.rd))
+        args.append(reg2str(self.rm))
+        args.append(reg2str(self.rs))
+        if self.accum:
+            args.append(reg2str(self.rn))
+        return args
+    
+    def __str__(self):
+        name = self.getname()
+        name+=self.scc2str()
+        args = self.args2str()
+        args = args2str(args)
+        return name+" "+args
+
+    def parse_opts(self, opts):
+        self.scc = 0
+        if not opts:
+            return
+        if opts[0] == "S":
+            self.scc = 1
+
+    def parse_args(self, args):
+        self.rd = str2reg(args.pop())
+        self.rm = str2reg(args.pop())
+        self.rs = str2reg(args.pop())
+        if self.accum:
+            self.rn = str2reg(args.pop())
+        else:
+            self.rn = 0 #default reg value
+        
+
+class arm_mull(arm_mn):
+    mask_list = [bm_int00001, bm_sign, bm_accum, bm_scc, bm_rdh, bm_rdl, bm_rs, bm_int1001, bm_rm]
+    #cannot habe pc as reg
+    namestr = ['UMULL', 'UMLAL', 'SMULL', 'SMLAL']
+    def name2str(self):
+        return self.namestr[self.sign*2+self.accum]
+    def str2name(self, n):
+        tmp = self.namestr.index(n)
+        self.accum = tmp&1
+        self.sign = tmp>>1
+
+    @classmethod
+    def check_opts(cls, rest):
+        if rest in ['', 'S']:
+            return True
+        return False
+
+    def args2str(self):
+        args = []
+        args.append(reg2str(self.rdh))
+        args.append(reg2str(self.rdl))
+        args.append(reg2str(self.rm))
+        args.append(reg2str(self.rs))
+        return args
+    
+    def __str__(self):
+        name = self.getname()
+        name+= self.scc2str()
+        args = self.args2str()
+        args = args2str(args)
+        return name+" "+args
+
+    def parse_opts(self, opts):
+        self.scc = 0
+        if not opts:
+            return
+        if opts[0] == "S":
+            self.scc = 1
+
+    def parse_args(self, args):
+        self.rdh = str2reg(args.pop())
+        self.rdl = str2reg(args.pop())
+        self.rm = str2reg(args.pop())
+        self.rs = str2reg(args.pop())
+        
+
+class arm_swp(arm_mn):
+    mask_list = [bm_int00010, bm_size, bm_int00, bm_rn, bm_rd, bm_int0000, bm_int1001, bm_rm]
+    mask = {19:bmi_int1111, 15:bmi_int1111, 3:bmi_int1111}
+    #cannot have PC as reg
+    namestr = ["SWP"]
+    def name2str(self):
+        return self.namestr[0]
+    
+    @classmethod
+    def check_opts(cls, rest):
+        if not rest or rest == 'B':
+            return True
+        return False
+
+    def args2str(self):
+        args = []
+        args.append(reg2str(self.rd))
+        args.append(reg2str(self.rm))
+        args.append(['[', reg2str(self.rn), ']'])
+        return args
+    
+    def __str__(self):
+        name = self.getname()
+        name+=self.size2str()
+        args = self.args2str()
+        args = args2str(args)
+        return name+' '+args
+
+    def parse_opts(self, opts):
+        self.size = 0
+        if not opts:
+            return
+        if opts[0] == "B":
+            self.size = 1
+
+    def parse_args(self, args):
+        self.rd = str2reg(args.pop())
+        self.rm = str2reg(args.pop())
+        p1 = args.pop()
+        self.rn = str2reg(args.pop())
+        p2 = args.pop()
+        if p1== '[' and p2 ==']':
+            return
+        raise ValueError('cannot parse %s %s'%(str(p1), str(p2)))
+
+class arm_brxchg(arm_mn):
+    mask_list = [bm_int0001001011111111111100, bm_lnk, bm_int1, bm_rn]
+
+    namestr = ["BX", "BXL"]
+    def name2str(self):
+        return self.namestr[self.lnk]
+    def str2name(self, n):
+        self.lnk = self.namestr.index(n)
+
+    def parse_name_cond(self, mnemo):
+        name, cond = None, None
+        if not mnemo.startswith('BX'):
+            raise  ValueError('zarb mnemo %s'%str(mnemo))
+        l = len(mnemo)
+        if l in [2,4]:
+            n = mnemo[:2]
+        elif l in [3,4]:
+            n = mnemo[:3]
+        else:
+            raise ValueError('zarb mnemo %s'%str(mnemo))
+        name = n
+        rest = mnemo[len(n):]
+        for i, c in enumerate(bm_cond.n):
+            if rest.startswith(c):
+                cond = i
+                break
+        if cond == None:
+            cond = COND_AL         #default cond is AL
+        else:
+            rest = rest[len(c):]
+        return name, cond, rest
+
+    @classmethod
+    def check_mnemo(self, mnemo):
+        if mnemo in self.namestr:
+            return True
+        return False
+
+
+    def args2str(self):
+        args = []
+        args.append(reg2str(self.rn))
+        return args
+
+    def __str__(self):
+        name = self.getname()
+        args = self.args2str()
+        args = args2str(args)
+        return name+' '+args
+    
+    def parse_args(self, args):
+        self.rn = str2reg(args.pop())
+
+    def breakflow(self):
+        return True
+    def splitflow(self):
+        return self.cond != COND_AL
+    def dstflow(self):
+        return True
+    def getdstflow(self):
+        return []
+    def setdstflow(self, dst):
+        return []
+    def is_subcall(self):
+        return self.lnk
+
+class arm_hdtreg(arm_mn):
+    mask_list = [bm_int000, bm_ppndx, bm_updown, bm_int0, bm_wback, bm_ldst, bm_rn, bm_rd, bm_int00001, bm_sh, bm_int1, bm_rm]
+    #and XXX str cant be SB nor SH
+    mask = {24:bmi_intX00X}
+    
+    typestr = ["XXX", "H", "SB", "SH"]
+    namestr = ['STR', 'LDR']
+    def name2str(self):
+        return self.namestr[self.ldst]
+    def str2name(self, n):
+        self.ldst = self.namestr.index(n)
+
+    @classmethod
+    def check_opts(cls, rest):
+        found = False
+        for t in cls.typestr:
+            if rest.startswith(t):
+                found = True
+                rest = rest[len(t):]
+        if not found:
+            return False
+        #XXX check diff with hdreg TODO
+        return True
+
+    def args2str(self):
+        args = []
+        args.append(reg2str(self.rd))
+        o = []
+        o.append('[')
+        o.append(reg2str(self.rn))
+        if not self.ppndx:
+            o.append(']')
+        if not self.updown:
+            o.append("-")
+        o.append(reg2str(self.rm))
+        if self.ppndx:
+            o.append(']')
+        
+        args.append(o)
+        return args
+        
+    def __str__(self):
+        name = self.getname()
+        #XXX XXX swp?? 
+        name += self.typestr[self.sh]
+        args = self.args2str()
+        args = args2str(args)
+        wb = ['', '!'][self.wback==1]
+        return name+' '+args+wb
+
+    def breakflow(self):
+        if self.ldst == 0 or self.rd!=15:
+            return False
+        #XXX pc pp incremented
+        return True
+    def splitflow(self):
+        if self.ldst == 0 or self.rd!=15:
+            return False
+        #XXX pc pp incremented
+        return self.cond != COND_AL
+    def dstflow(self):
+        return True
+
+
+class arm_hdtimm(arm_mn):
+    mask_list = [bm_int000, bm_ppndx, bm_updown, bm_int1, bm_wback, bm_ldst, bm_rn, bm_rd, bm_hdoff1, bm_int1, bm_sh, bm_int1, bm_hdoff2]
+    #and XXX str cant be SB nor SH
+    mask = {24:bmi_intX00X}
+
+    typestr = ["XXX", "H", "SB", "SH"]
+    namestr = ['STR', 'LDR']
+    def name2str(self):
+        return self.namestr[self.ldst]
+    def str2name(self, n):
+        self.ldst = self.namestr.index(n)
+
+    @classmethod
+    def check_opts(cls, rest):
+        found = False        
+        for t in cls.typestr:
+            if rest.startswith(t):
+                found = True
+                rest = rest[len(t):]
+        if not found:
+            return False
+        #XXX check diff with hdreg TODO
+        return True
+
+    def args2str(self):
+        args = []
+        args.append(reg2str(self.rd))
+        o = []
+        o.append('[')
+        o.append(reg2str(self.rn))
+        if not self.ppndx:
+            o.append(']')
+        imm = [-1, 1][self.updown==1]*((self.hdoff1<<4)+self.hdoff2)
+        o.append(imm2str(imm))
+        if self.ppndx:
+            o.append(']')
+        
+        args.append(o)
+        return args
+
+        
+    def __str__(self):
+        name = self.getname()
+        #XXX XXX swp?? 
+        name += self.typestr[self.sh]
+        args = self.args2str()
+        args = args2str(args)
+        wb = ['', '!'][self.wback==1]
+
+        return name+' '+args+wb
+
+
+    def breakflow(self):
+        if self.ldst == 0 or self.rd!=15:
+            return False
+        #XXX pc pp incremented
+        return True
+    def splitflow(self):
+        if self.ldst == 0 or self.rd!=15:
+            return False
+        #XXX pc pp incremented
+        return self.cond != COND_AL
+    def dstflow(self):
+        return True
+
+
+class arm_sdt(arm_mn):
+    mask_list = [bm_int01, bm_immop, bm_ppndx, bm_updown, bm_size, bm_wback, bm_ldst, bm_rn, bm_rd, bm_opoff]
+    #cannot shift amount with immop
+    mask = {25:bmi_int1XXXX1}
+    
+    namestr = ['STR', 'LDR']
+    def name2str(self):
+        return self.namestr[self.ldst]
+    def str2name(self, n):
+        self.ldst = self.namestr.index(n)
+
+    allshifts = ['LSL', 'LSR', 'ASR', 'ROR']
+
+    @classmethod
+    def check_opts(cls, rest):
+        if not rest:
+            return True
+        if rest[0] == "B":
+            rest = rest[1:]
+        if not rest:
+            return True
+        if rest[0] == "T":
+            rest = rest[1:]
+        if rest:
+            return False
+        return True
+
+    def args2str(self):
+        args = []
+        args.append(reg2str(self.rd))
+        o = []
+        o.append('[')
+        o.append(reg2str(self.rn))
+        if not self.ppndx:
+            o.append(']')
+
+        if self.immop:
+            if not self.updown:
+                o.append("-")
+            o.append([reg2str(self.rm), self.allshifts[self.shiftt], imm2str(self.amount)])
+        else:
+            imm = [-1, 1][self.updown==1]*self.imm
+            o.append(imm2str(imm))
+        if self.ppndx:
+            o.append(']')
+        args.append(o)
+        return args
+        
+    
+    def __str__(self):
+        name = self.getname()
+        name+=self.size2str()
+        #XXX TODO T bit??? name+=['', 'T'][self.wback==1]
+        wb = ['', '!'][self.wback==1]
+        args = self.args2str()
+        args = args2str(args)
+        return name+' '+args+wb
+
+    def parse_opts(self, opts):
+        self.wback = 0
+        self.size = 0
+        if not opts:
+            return
+        if opts[0] == "B":
+            self.size = 1
+
+    def parse_args(self, args):
+        self.rd = str2reg(args.pop())
+
+        if len(args)!=1:
+            raise ValueError("zarb arg3", args)
+        args = args.pop()
+        args = args[::-1]
+        p1 = args.pop()
+        self.rn = str2reg(args.pop())
+
+        param = []
+        if args[-1] == ']':
+            self.ppndx = 0
+            param = args[:-1]
+            args = []
+        else:
+            self.ppndx = 1
+            param = args[args.index(']')+1:]
+            args = args[:args.index(']')]
+
+        self.updown = 1
+        tmp = param.pop()
+        if tmp =='-':
+            self.updown = 0
+            tmp = param.pop()
+
+        if is_imm(tmp):
+            self.immop = 0
+            self.imm = str2imm(tmp)
+        else:
+            self.immop = 1
+            self.rm = str2reg(tmp)
+            self.shiftt = self.allshifts.index(param.pop())
+            tmp = param.pop()
+            if not is_imm(tmp):
+                raise ValueError('amount must be int')
+            self.amount = str2imm(tmp)
+
+        if args:
+            tmp = args.pop()
+            if tmp!= '!':
+                raise "arg zarb %s"%str(tmp)
+            self.wback = 1
+        if args:
+            raise ValueError('rest args...'%str(param))
+
+
+    def breakflow(self):
+        if self.ldst == 0 or self.rd!=15:
+            return False
+        #XXX pc pp incremented
+        return True
+    def splitflow(self):
+        if self.ldst == 0 or self.rd!=15:
+            return False
+        #XXX pc pp incremented
+        return self.cond != COND_AL
+    def dstflow(self):
+        return False
+    def getdstflow(self):
+        return []
+    def setdstflow(self, dst):
+        if len(dst)==0:
+            return
+        if len(dst)!=1:
+            raise ValueError('should be 1 dst')
+    def is_subcall(self):
+        return False
+
+class arm_undef(arm_mn):
+    mask_list = [bm_int011, bm_undef1, bm_int1, bm_undef2]
+
+    namestr = ["UNDEF"]
+    def name2str(self):
+        return self.namestr[0]
+
+    def args2str(self):
+        args = []
+        args.append(imm2str(self.undef1))
+        args.append(imm2str(self.undef2))
+        return args
+    
+    def __str__(self):
+        name = self.getname()
+        args = self.args2str()
+        args = args2str(args)
+        
+        return name+' '+args
+    
+    def parse_args(self, args):
+        self.undef1 = str2imm(args.pop())
+        self.undef2 = str2imm(args.pop())
+
+class arm_bdt(arm_mn):
+    mask_list = [bm_int100, bm_ppndx, bm_updown, bm_psr, bm_wback, bm_ldst, bm_rn, bm_reglist]
+    
+    ad_mode_nostack = ['DA', 'DB', 'IA', 'IB']
+    ad_mode_stack = ['FA', 'EA', 'FD',  'ED']
+
+    namestr = ['STM', 'LDM']
+    def name2str(self):
+        return self.namestr[self.ldst]
+    def str2name(self, n):
+        self.ldst = self.namestr.index(n)
+
+    @classmethod
+    def check_opts(cls, rest):
+        for m in cls.ad_mode_stack+cls.ad_mode_nostack:
+            if rest.startswith(m):
+                rest = rest[len(m):]
+                break
+        if rest:
+            return False
+        return True
+
+    def args2str(self):
+        args = []
+        args.append(reg2str(self.rn))
+        if self.wback:
+            args.append('!')
+        args+=[reg2str(r) for r in self.reglist]
+        if self.psr:
+            args.append('^')
+        return args
+
+    def __str__(self):
+        name = self.getname()
+        tmp = (self.ppndx<<1)+self.updown
+        if self.ldst!=0:
+            tmp = 3-tmp
+        if self.rn == 13:
+            ad_mode = self.ad_mode_stack[tmp]
+        else:
+            ad_mode = self.ad_mode_nostack[tmp]
+
+        name+=ad_mode
+        args = []
+        wb = ['', '!'][self.wback]
+        psr = ['', '^'][self.psr]
+        args.append(reg2str(self.rn)+wb)
+        args.append(reglist2str(self.reglist))
+        return name+" "+", ".join(args)+psr
+
+    def parse_opts(self, opts):
+        if opts in self.ad_mode_stack:
+            self.stackattr = True
+            self.bits = self.ad_mode_stack.index(opts)
+        elif opts in self.ad_mode_nostack:
+            self.stackattr = False
+            self.bits = self.ad_mode_nostack.index(opts)
+        else:
+            raise ValueError('opt zarb %s'%str(opts))
+
+
+    def parse_args(self, args):
+        self.wback = 0
+        a = args.pop()
+        if len(a) >1:
+            w = a.pop()
+            if w == "!":
+                self.wback = 1
+            else:
+                raise ValueError('zarb arg 4', (args, a, w))
+        
+            
+        self.rn = str2reg(a.pop())
+        if self.stackattr != (self.rn==13):
+            raise ValueError('unmatch stack/nostack')
+
+        if self.ldst!=0:
+            self.bits = 3-self.bits
+
+        self.updown = self.bits & 1
+        self.ppndx = self.bits >> 1
+
+        if len(args) !=1:
+            raise ValueError('zarb arg 4', args)
+        args = args.pop()
+        args = args[::-1]
+        self.reglist = str2reglist(args)
+
+        self.psr = 0
+        if args:
+            tmp = args.pop()
+            if tmp == '^':
+                self.psr = 1
+            else:
+                raise ValueError('zarb last arg %s'%str(tmp))
+
+    def breakflow(self):
+        if self.ldst == 0 or not 15 in self.reglist:
+            return False
+        #XXX pc pp incremented
+        return True
+    def splitflow(self):
+        if self.ldst == 0 or not 15 in self.reglist:
+            return False
+        #XXX pc pp incremented
+        return self.cond != COND_AL
+    def dstflow(self):
+        return False
+        
+class arm_br(arm_mn):
+    mask_list = [bm_int101, bm_lnk, bm_offs]
+
+    namestr = ["B", "BL"]
+    def name2str(self):
+        return self.namestr[self.lnk]
+    def str2name(self, n):
+        self.lnk = self.namestr.index(n)
+
+    @classmethod
+    def check_mnemo(self, mnemo):
+        if not mnemo.startswith('B'):
+            return False
+        l = len(mnemo)        
+        if l==1 and mnemo in ['B']:
+            return True
+        elif l in [2,4] and mnemo.startswith('BL'):
+            return True
+        elif l == 3 and mnemo[1:] in bm_cond.n:
+            return True
+        return False
+
+    def parse_name_cond(self, mnemo):
+        name, cond = None, None
+        if not mnemo.startswith('B'):
+            raise  ValueError('zarb mnemo %s'%str(mnemo))
+        l = len(mnemo)
+        if l in [1,3]:
+            n = mnemo[:1]
+        elif l in [2,4]:
+            n = mnemo[:2]
+        else:
+            raise ValueError('zarb mnemo %s'%str(mnemo))
+        name = n
+        rest = mnemo[len(n):]
+        for i, c in enumerate(bm_cond.n):
+            if rest.startswith(c):
+                cond = i
+                break
+        if cond == None:
+            cond = COND_AL         #default cond is AL
+        else:
+            rest = rest[len(c):]
+        return name, cond, rest
+
+    def args2str(self):
+        if type(self.offs) in [int, long]:
+            args = [imm2str(self.offs)]
+        else:
+            args = [self.offs]
+        return args
+    
+    def __str__(self):
+        name = self.getname()
+        args = self.args2str()
+        args = args2str(args)
+        return name+' '+args
+
+    def parse_args(self, args):
+        ad = args.pop()
+        if is_imm(ad):
+            self.offs = str2imm(ad)
+        else:
+            self.offs = {x86_afs.symb:{ad[0]:1}}
+    def breakflow(self):
+        return True
+    def splitflow(self):
+        return self.cond != COND_AL or self.lnk
+    def dstflow(self):
+        return True
+
+    def getdstflow(self):
+        if type(self.offs) in [int, long]:
+            dst = (self.offset+8+self.offs)&0xFFFFFFFF
+        else:
+            dst = self.arg[0]
+        return [dst]
+
+    def setdstflow(self, dst):
+        if len(dst)==0:
+            return
+        if len(dst)!=1:
+            raise ValueError('should be 1 dst')
+        l = dst[0]
+        #patch only known symbols
+        if l.offset !=None:
+            self.offs = l
+    def is_subcall(self):
+        return self.lnk
+
+    def fixdst(self, lbls, my_offset, is_mem):
+        l = self.offs[x86_afs.symb].keys()[0]
+        offset = lbls[l]
+        if is_mem:
+            arg = {x86_afs.ad:is_mem, x86_afs.imm:offset}
+        else:
+            arg = {x86_afs.imm:offset-(my_offset)}
+
+        self.arg = [arg]
+        self.offs = lbls[l]-my_offset-4
+        
+class arm_codt(arm_mn):
+    mask_list = [bm_int110, bm_ppndx, bm_updown, bm_tlen, bm_wback, bm_ldst, bm_rn, bm_crd, bm_cpnum, bm_cooff]
+
+    namestr = ['STC', 'LDC']
+    def name2str(self):
+        return self.namestr[self.ldst]
+    def str2name(self, n):
+        self.ldst = self.namestr.index(n)
+
+    @classmethod
+    def check_opts(cls, rest):
+        if not rest or rest == 'L':
+            return True
+        return False
+
+    def args2str(self):
+        args = []
+        args.append(cop2str(self.cpnum))
+        args.append(copr2str(self.crd))
+        o = []
+        o.append('[')
+        o.append(reg2str(self.rn))
+        if not self.ppndx:
+            o.append(']')
+        o.append(imm2str(self.cooff))
+        if self.ppndx:
+            o.append(']')
+        args.append(o)
+        return args
+    
+    def __str__(self):
+        name = self.getname()
+        if self.tlen:
+            name+='L'
+        args = self.args2str()
+        args = args2str(args)
+        wb = ['', '!'][self.wback]
+        return name+' '+args+wb
+
+    def parse_opts(self, opts):
+        self.tlen = 0
+        if not opts:
+            return
+        if opts =='L':
+            self.tlen = 1
+            return
+        raise ValueError('opt zarb %s'%str(opts))
+
+    def parse_args(self, args):
+        self.wback = 0
+        self.updown = 0
+        self.cpnum = str2cop(args.pop())
+        self.crd = str2copr(args.pop())
+        if len(args) !=1:
+            raise ValueError('zarb arg 6', str(args))
+        args = args.pop()
+        args = args[::-1]
+        p1 = args.pop()
+        self.rn = str2reg(args.pop())
+
+        param = []
+        if args[-1] == ']':
+            self.ppndx = 0
+            param = args[:-1]
+            args = []
+        else:
+            self.ppndx = 1
+            param = args[args.index(']')+1:]
+            args = args[:args.index(']')]
+
+        self.updown = 1
+        tmp = param.pop()
+        if tmp =='-':
+            self.updown = 0
+            tmp = param.pop()
+
+        self.cooff = str2imm(tmp)
+        
+        if args:
+            tmp = args.pop()
+            if tmp!= '!':
+                raise "arg zarb %s"%str(tmp)
+            self.wback = 1
+        if args:
+            raise ValueError('rest args...'%str(param))
+            
+
+
+class arm_codo(arm_mn):
+    mask_list = [bm_int1110, bm_cpopc, bm_crn, bm_crd, bm_cpnum, bm_info, bm_int0, bm_crm]
+
+    namestr = ["CDP"]
+    def name2str(self):
+        return self.namestr[0]
+
+    def args2str(self):
+        args = []
+        args.append(cop2str(self.cpnum))
+        args.append(imm2str(self.cpopc))
+        args.append(copr2str(self.crd))
+        args.append(copr2str(self.crn))
+        args.append(copr2str(self.crm))
+        args.append(imm2str(self.info))
+        return args
+    
+    def __str__(self):
+        name = self.getname()
+        args = self.args2str()
+        args = args2str(args)
+        return name+' '+args
+
+    def parse_args(self, args):
+        self.cpnum = str2cop(args.pop())
+        self.cpopc = str2imm(args.pop())
+        self.crd = str2copr(args.pop())
+        self.crn = str2copr(args.pop())
+        self.crm = str2copr(args.pop())
+        self.info = str2imm(args.pop())
+        
+        
+
+
+class arm_cort(arm_mn):
+    mask_list = [bm_int1110, bm_opmode, bm_ldst, bm_crn, bm_rd, bm_cpnum, bm_info, bm_int1, bm_crm]
+
+    namestr = ['MCR', 'MRC']
+    def name2str(self):
+        return self.namestr[self.ldst]
+    def str2name(self, n):
+        self.ldst = self.namestr.index(n)
+
+    def args2str(self):
+        args = []
+        args.append(cop2str(self.cpnum))
+        args.append(imm2str(self.opmode))
+        args.append(reg2str(self.rd))
+        args.append(copr2str(self.crn))
+        args.append(copr2str(self.crm))
+        args.append(imm2str(self.info))
+        return args
+    
+    def __str__(self):
+        name = self.getname()
+        args = self.args2str()
+        args = args2str(args)
+        return name+' '+args
+
+
+    def parse_args(self, args):
+        self.cpnum = str2cop(args.pop())
+        self.opmode = str2imm(args.pop())
+        self.rd = str2reg(args.pop())
+        self.crn = str2copr(args.pop())
+        self.crm = str2copr(args.pop())
+        self.info = str2imm(args.pop())
+
+class arm_swi(arm_mn):
+    mask_list = [bm_int1111, bm_swint]
+
+    namestr = ["SWI"]
+    def name2str(self):
+        return self.namestr[0]
+
+    def args2str(self):
+        args = [imm2str(self.swint)]
+        return args
+
+    def __str__(self):
+        name = self.getname()
+        args = self.args2str()
+        args = args2str(args)
+        return name+' '+args
+
+    def parse_args(self, args):
+        self.swint = str2imm(args.pop())
+        
+    def breakflow(self):
+        return True
+    def splitflow(self):
+        return True
+    def dstflow(self):
+        return False
+
+
+class arm_szext(arm_mn):
+    mask_list = [bm_int01101, bm_opsz, bm_szext, bm_rn, bm_rd, bm_rot, bm_int00, bm_int0111, bm_rm]
+    #szext may not be 01
+    namestr = ['SXT', 'UXT']
+    szextname = ['B16', None, 'B', 'H']
+    def name2str(self):
+        return self.namestr[self.opsz]+['A', ''][self.rn==15]+self.szextname[self.szext]
+    def str2name(self, n):
+        self.opsz = self.namestr.index(n)
+
+    @classmethod
+    def check_mnemo(self, mnemo):
+        if len(mnemo)<3:
+            return False
+        if not mnemo[:3] in self.namestr:
+            return False
+        rest = mnemo[3:]
+        if rest[0] =='A':
+            rest = rest[1:]
+        found = False
+        for n in self.szextname:
+            if not n:
+                continue
+            if rest.startswith(n):
+                found = True
+        if not found:
+            return False
+        rest = rest[len(n):]
+        if not rest or rest in bm_cond.n:
+            return True
+        return False
+
+    def parse_name_cond(self, mnemo):
+        name, szextname, cond = None, None, None
+        for n in self.namestr:
+            if mnemo.startswith(n):
+                name = n
+                break
+        if not name:
+            raise ValueError('zarb mnemo1 %s'%str(mnemo))
+        rest = mnemo[len(n):]
+        out = []
+        if rest[0] =='A':
+            rest = rest[1:]
+            out.append('A')
+            self.rn = 0
+        else:
+            self.rn=15
+        for i, n in enumerate(self.szextname):
+            if n and rest.startswith(n):
+                szextname = n
+                self.szext = i
+                break
+        if not szextname:
+            raise ValueError('zarb mnemo2 %s'%str(mnemo))
+        rest = rest[len(n):]
+        
+        for i, c in enumerate(bm_cond.n):
+            if rest.startswith(c):
+                cond = i
+                break
+        if cond == None:
+            cond = COND_AL         #default cond is AL
+        else:
+            rest = rest[len(c):]
+        if rest:
+            raise ValueError("rest! %s"%str(rest))
+        return name, cond, rest
+
+    def parse_opts(self, opts):
+        if not opts:
+            return
+        raise ValueError('opt zarb %s'%str(opts))
+
+    def args2str(self):
+        args = []
+        args.append(reg2str(self.rd))
+        if self.rn!=15:
+            args.append(reg2str(self.rn))
+        args.append(reg2str(self.rm))
+        return args
+    
+    def __str__(self):
+        name = self.getname()
+        args = self.args2str()
+        args = args2str(args)
+        return name+' '+args
+
+
+    def parse_args(self, args):
+        
+        self.rd = str2reg(args.pop())
+        if self.rn!=15:
+            self.rn = str2reg(args.pop())
+        self.rm = str2reg(args.pop())
+        self.rot = 0
+    
+
+    
+
+if __name__ == "__main__":
+ 
+    import struct
diff --git a/miasm/arch/arm_sem.py b/miasm/arch/arm_sem.py
new file mode 100644
index 00000000..c60b9cd0
--- /dev/null
+++ b/miasm/arch/arm_sem.py
@@ -0,0 +1,621 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+from miasm.expression.expression import *
+from miasm.arch.arm_arch import *
+from miasm.core.asmbloc import *
+
+
+reg_r0 = 'R0'
+reg_r1 = 'R1'
+reg_r2 = 'R2'
+reg_r3 = 'R3'
+reg_r4 = 'R4'
+reg_r5 = 'R5'
+reg_r6 = 'R6'
+reg_r7 = 'R7'
+reg_r8 = 'R8'
+reg_r9 = 'R9'
+reg_r10 = 'R10'
+reg_r11 = 'R11'
+reg_r12 = 'R12'
+reg_sp = 'SP'
+reg_lr = 'LR'
+reg_pc = 'PC'
+
+reg_zf = 'zf'
+reg_nf = 'nf'
+reg_of = 'of'
+reg_cf = 'cf'
+
+zf = ExprId(reg_zf, size=1)
+nf = ExprId(reg_nf, size=1)
+of = ExprId(reg_of, size=1)
+cf = ExprId(reg_cf, size=1)
+
+R0  = ExprId(reg_r0)
+R1  = ExprId(reg_r1)
+R2  = ExprId(reg_r2)
+R3  = ExprId(reg_r3)
+R4  = ExprId(reg_r4)
+R5  = ExprId(reg_r5)
+R6  = ExprId(reg_r6)
+R7  = ExprId(reg_r7)
+R8  = ExprId(reg_r8)
+R9  = ExprId(reg_r9)
+R10 = ExprId(reg_r10)
+R11 = ExprId(reg_r11)
+R12 = ExprId(reg_r12)
+SP = ExprId(reg_sp)
+LR  = ExprId(reg_lr)
+PC  = ExprId(reg_pc)
+
+
+all_registers = [
+    R0,
+    R1,
+    R2,
+    R3,
+    R4,
+    R5,
+    R6,
+    R7,
+    R8,
+    R9,
+    R10,
+    R11,
+    R12,
+    SP,
+    LR,
+    PC,
+    ]
+
+tab_intsize = {8:int8,
+               16:int16,
+               32:int32,
+               64:int64
+               }
+tab_uintsize ={8:uint8,
+               16:uint16,
+               32:uint32,
+               64:uint64
+               }
+
+str2regid = dict([(x.name,x) for x in all_registers])
+
+
+
+
+def get_op_msb(a):
+    cast_int = tab_uintsize[a.get_size()]
+    return ExprOp('==', ExprInt(cast_int(1)), ExprOp('>>', a, ExprInt(cast_int(a.get_size()-1))))
+
+
+def update_flag_zf(a):
+    cast_int = tab_uintsize[a.get_size()]
+    return [ExprAff(zf, ExprOp('==', a, ExprInt(cast_int(0))))]
+
+def update_flag_nf(a):
+    return [ExprAff(nf, ExprOp('&', get_op_msb(a), ExprInt(tab_uintsize[a.get_size()](1))))]
+
+
+def update_flag_zn(a):
+    e = []
+    e+=update_flag_zf(a)
+    e+=update_flag_nf(a)
+    return e
+
+def update_flag_logic(a):
+    e = []
+    e+=update_flag_zn(a)
+    e.append(ExprAff(of, ExprInt(uint32(0))))
+    e.append(ExprAff(cf, ExprInt(uint32(0))))
+    return e
+
+def update_flag_arith(a):
+    e = []
+    e+=update_flag_zn(a)
+    return e
+
+def check_ops_msb(a, b, c):
+    if not a or not b or not c or a!=b or a!=c:
+        raise 'bad ops size %s %s %s'%(str(a), str(b), str(c))
+
+def arith_flag(a, b, c):
+    a_s, b_s, c_s = a.get_size(), b.get_size(), c.get_size()
+    check_ops_msb(a_s, b_s, c_s)
+    a_s, b_s, c_s = get_op_msb(a), get_op_msb(b), get_op_msb(c)
+    return a_s, b_s, c_s
+
+#z = x+y (+cf?)
+def update_flag_add(x, y, z):
+    a, b, c = arith_flag(x, y, z)
+    cast_int = tab_uintsize[z.get_size()]
+    e = []
+    e.append(update_flag_add_cf(cast_int, a, b, c))
+    e.append(update_flag_add_of(cast_int, a, b, c))    
+    return e
+
+#z = x-y (+cf?)
+def update_flag_sub(x, y, z):
+    a, b, c = arith_flag(x, y, z)
+    cast_int = tab_uintsize[z.get_size()]
+    e = []
+    e.append(update_flag_sub_cf(cast_int, a, b, c))
+    e.append(update_flag_sub_of(cast_int, a, b, c))
+    return e
+
+def update_flag_sub_cf(cast_int, a, b, c):
+    return ExprAff(cf, ExprOp('|',
+                              ExprOp('&', ExprOp('==', a, ExprInt(cast_int(0))), b),
+                              ExprOp('&', c, ExprOp('|', ExprOp('==', a, ExprInt(cast_int(0))), b)
+                                     )
+                              )
+                   )
+
+
+def update_flag_sub_of(cast_int, a, b, c):
+    return ExprAff(of, ExprOp('|',
+                              ExprOp('&',
+                                     ExprOp('==', c, ExprInt(cast_int(1))),
+                                     ExprOp('&', ExprOp('==', a, ExprInt(cast_int(0))), b)
+                                     ),
+                              ExprOp('&',
+                                     ExprOp('==', c, ExprInt(cast_int(0))),
+                                     ExprOp('&', a, ExprOp('==', b, ExprInt(cast_int(0))))
+                                     )
+                              )
+                   )
+
+
+
+
+def get_cf_shifter(a):
+    e = []
+    if not isinstance(a, ExprOp):
+        return e
+    if not a.op in ['<<', '>>', 'a>>', '>>>']:
+        return e
+    #int shift amount
+    shifter = a.args[1]
+    source = a.args[0]
+    if isinstance(shifter, ExprInt) and shifter.arg == 0:
+        if a.op == '<<':
+            #cf is old cf
+            return e
+        elif a.op in  ['>>', 'a>>']:
+            e.append(ExprAff(cf, get_op_msb(source)))                
+            return e
+        elif a.op == '>>>':
+            new_cf = ExprOp('&',
+                            ExprInt(cast_int(1)),
+                            source
+                            )
+            e.append(ExprAff(cf, new_cf))
+            return e
+        raise ValueError('bad op')
+        
+            
+    if a.op == '<<':            
+        new_cf = ExprOp('&',
+                        ExprInt(uint32(1)),
+                        ExprOp('>>',
+                               source,
+                               ExprOp('-',
+                                      ExprInt(uint32(source.get_size())),
+                                      shifter
+                                      )
+                               
+                               )
+                        )
+        
+    elif a.op in ['>>', 'a>>']:
+        new_cf = ExprOp('&',
+                        ExprInt(uint32(1)),
+                        ExprOp(a.op,
+                               source,
+                               ExprOp('-',
+                                      shifter,
+                                      ExprInt(uint32(1))
+                                      )
+                               
+                               )
+                        )
+    elif a.op == '>>>':
+        c = ExprOp('>>>', source, shifter)
+        new_cf = get_op_msb(c)
+
+    if isinstance(shifter, ExprInt):
+        e.append(ExprAff(cf, new_cf))
+    else:
+        e.append(ExprAff(cf, ExprCond(shifter,
+                                      new_cf,
+                                      cf))
+                 )
+    return e
+    
+        
+
+
+def add(x, a, b):
+    e = []
+    c = ExprOp('+', a, b)
+    e.append(ExprAff(x, c))    
+    return e
+
+def adds(x, a, b):
+    e = []
+    c = ExprOp('+', a, b)
+    e+=update_flag_arith(c)
+    e+=update_flag_add(a, b, c)
+    e.append(ExprAff(x, c))    
+    return e
+
+def sub(x, a, b):
+    e = []
+    c = ExprOp('-', a, b)
+    e.append(ExprAff(x, c))    
+    return e
+
+def subs(x, a, b):
+    e = []
+    c = ExprOp('-', a, b)
+    e+=update_flag_arith(c)
+    e+=update_flag_sub(a, b, c)
+    e.append(ExprAff(x, c))    
+    return e
+
+def eor(x, a, b):
+    e= []
+    c = ExprOp('^', a, b)
+    e.append(ExprAff(x, c))
+    return e
+
+def eors(x, a, b):
+    e= []
+    c = ExprOp('^', a, b)
+    e+=update_flag_logic(c)
+    e.append(ExprAff(x, c))
+    return e
+
+def l_and(x, a, b):
+    e= []
+    c = ExprOp('&', a, b)
+    e.append(ExprAff(x, c))
+    return e
+
+def l_ands(x, a, b):
+    e= []
+    c = ExprOp('&', a, b)
+    e+=update_flag_logic(c)
+    e.append(ExprAff(x, c))
+    return e
+
+def rsb(x, a, b):
+    return sub(x, b, a)
+
+def rsbs(x, a, b):
+    return subs(x, b, a)
+
+def adc(x, a, b):
+    e= []
+    c = ExprOp('+', a, ExprOp('+', b, ExprCompose([ExprSliceTo(ExprInt(uint32(0)), 1, a.get_size()), ExprSliceTo(cf, 0, 1)])))
+    e.append(ExprAff(x, c))
+    return e
+
+def adcs(x, a, b):
+    e= []
+    c = ExprOp('+', a, ExprOp('+', b, ExprCompose([ExprSliceTo(ExprInt(uint32(0)), 1, a.get_size()), ExprSliceTo(cf, 0, 1)])))
+    e+=update_flag_arith(c)
+    e+=update_flag_add(a, b, c)
+    e.append(ExprAff(x, c))
+    return e
+
+def sbc(x, a, b):
+    e= []
+    c = ExprOp('-',
+               ExprOp('+', a, ExprCompose([ExprSliceTo(ExprInt(uint32(0)), 1, a.get_size()), ExprSliceTo(cf, 0, 1)])),
+               ExprOp('+', b, ExprInt(uint32(1)))
+               )
+    e.append(ExprAff(x, c))
+    return e
+
+def sbcs(x, a, b):
+    e= []
+    c = ExprOp('-',
+               ExprOp('+', a, ExprCompose([ExprSliceTo(ExprInt(uint32(0)), 1, a.get_size()), ExprSliceTo(cf, 0, 1)])),
+               ExprOp('+', b, ExprInt(uint32(1)))
+               )
+    e+=update_flag_arith(c)
+    e+=update_flag_sub(a, b, c)
+    e.append(ExprAff(x, c))
+    return e
+
+def rsc(x, a, b):
+    return sbc(x, b, a)
+
+def rscs(x, a, b):
+    return sbcs(x, b, a)
+
+def tst(a, b):
+    e= []
+    c = ExprOp('&', a, b)
+    e+=update_flag_logic(c)
+    return e
+
+def teq(a, b):
+    e= []
+    c = ExprOp('^', a, b)
+    e+=update_flag_logic(c)
+    return e
+
+def l_cmp(a, b):
+    e= []
+    c = ExprOp('-', a, b)
+    e+=update_flag_arith(c)
+    e+=update_flag_sub(a, b, c)
+    return e
+
+def cmn(a, b):
+    e= []
+    c = ExprOp('+', a, b)
+    e+=update_flag_arith(c)
+    e+=update_flag_sub(a, b, c)
+    return e
+
+def orr(x, a, b):
+    e= []
+    c = ExprOp('|', a, b)
+    e.append(ExprAff(x, c))
+    return e
+
+def orrs(x, a, b):
+    e= []
+    c = ExprOp('|', a, b)
+    e+=update_flag_logic(c)
+    e.append(ExprAff(x, c))
+    return e
+
+def mov(x, a):
+    return [ExprAff(x, a)]
+
+def bic(x, a, b):
+    e= []
+    c = ExprOp('&', a, ExprOp('^', b, ExprInt(uint32(0xFFFFFFFF))))
+    e.append(ExprAff(x, c))
+    return e
+
+def bics(x, a, b):
+    e= []
+    c = ExprOp('&', a, ExprOp('^', b, ExprInt(uint32(0xFFFFFFFF))))
+    e+=update_flag_logic(c)
+    e.append(ExprAff(x, c))
+    return e
+
+
+def mla(x, a, b, c):
+    e = []
+    d = ExprOp('+',
+               ExprOp('*', a, b),
+               c)
+    e.append(ExprAff(x, d))
+
+
+def mlas(x, a, b, c):
+    e = []
+    d = ExprOp('+',
+               ExprOp('*', a, b),
+               c)
+    e+=update_flag_zn(d)
+    e.append(ExprAff(x, d))
+
+
+def mul(x, a, b):
+    e = []
+    c = ExprOp('*', a, b)
+    e.append(ExprAff(x, c))
+
+
+
+def muls(x, a, b):
+    e = []
+    c = ExprOp('*', a, b)
+    e+=update_flag_zn(c)
+    e.append(ExprAff(x, c))
+
+
+def branch(my_eip, a):
+    e = []
+    e.append(ExprAff(PC, a))
+    return e
+
+
+
+def branchl(my_eip, a):
+    e = []
+    l = ExprOp('+',
+               my_eip,
+               ExprInt(uint32(4)),
+               )
+    e.append(ExprAff(PC, a))
+    e.append(ExprAff(LR, l))
+    return e
+
+mnemo_func = {'add': add,
+              'adds': adds,
+              'sub':sub,
+              'subs':subs,
+              'eor':eor,
+              'eors':eors,
+              'and':l_and,
+              'ands':l_ands,
+              'rsb':rsb,
+              'rsbs':rsbs,
+              'adc':adc,
+              'adcs':adcs,
+              'sbc':sbc,
+              'sbcs':sbcs,
+              'rsc':rsc,
+              'rscs':rscs,
+              'tst':tst,
+              'tsts':tst,
+              'teq':teq,
+              'teqs':teq,
+              'cmp':l_cmp,
+              'cmps':l_cmp,
+              'cmn':cmn,
+              'cmns':cmn,
+              'orr':orr,
+              'orrs':orrs,
+              'mov':mov,
+              'movs':mov,
+              'bic':bic,
+              'bics':bics,
+              'b':branch,
+              'bl':branchl,
+              }
+              
+              
+              
+shifts2op = {'LSL':'<<', 'LSR':'>>', 'ASR':'a>>', 'ROR':'>>>', '-':'-'}
+
+def condition_expr(cond, exprs):
+    if cond  == COND_AL:
+        return exprs
+
+    tab_cond = {COND_EQ:zf,
+                COND_NE:ExprOp('==', zf, ExprInt(uint32(0))),
+                COND_CS:cf,
+                COND_CC:ExprOp('==', cf, ExprInt(uint32(0))),
+                COND_MI:nf,
+                COND_PL:ExprOp('==', nf, ExprInt(uint32(0))),
+                COND_VS:of,
+                COND_VC:ExprOp('==', of, ExprInt(uint32(0))),
+                COND_HI:ExprOp('&', cf, ExprOp('==', zf, ExprInt(uint32(0)))),
+                COND_LS:ExprOp('&', zf, ExprOp('==', cf, ExprInt(uint32(0)))),
+                COND_GE:ExprOp('==', nf, of),
+                COND_LT:ExprOp('^', nf, of),
+                COND_GT:ExprOp('|',
+                               ExprOp('&',
+                                      ExprOp('==', zf, ExprInt(uint32(0))),
+                                      ExprOp('|',nf, of)
+                                      ),
+                               ExprOp('&',
+                                      ExprOp('==', nf, ExprInt(uint32(0))),
+                                      ExprOp('==', of, ExprInt(uint32(0)))
+                                      )
+                               ),
+                COND_LE:ExprOp('|',
+                               zf,
+                               ExprOp('^', nf, of)
+                               ),
+                }
+    if not cond in tab_cond:
+        raise 'unknown cond'
+    cond = tab_cond[cond]
+    out = []
+    for e in exprs:
+        src, dst = e.src, e.dst
+        out.append(ExprAff(dst, ExprCond(cond, src, dst)))
+    return out
+
+
+def get_instr_expr_args(mn, args, my_eip):
+    print args
+    wback = False
+    outa = []
+    optmem = lambda x:x
+    for a in args:
+        l = len(a)
+        if type(a) is str and a in str2regid:
+            outa.append(str2regid[a])
+            continue
+        elif type(a) is str and is_imm(a):
+            outa.append(ExprInt(uint32(str2imm(a))))
+            continue
+        elif type(a) is str and a == '!':
+            wback = True
+            continue
+        elif not type(a) == list:
+            print 'spot symb', a
+            break
+        if a[0] == '[' and a[-1] == ']':
+            optmem = ExprMem
+            a = a[1:-1]
+            l-=2
+            
+
+        print a
+        t = None
+        a.reverse()
+        u = a.pop()
+        if not u in str2regid:
+            raise ValueError('unknown1 arg', str(a))
+        u1 = str2regid[u]
+        if len(a) >1:
+            u = a.pop()
+            if not u in shifts2op:
+                raise ValueError('unknown2 arg', str(a))
+            t = shifts2op[u]
+
+        if len(a)>0:
+            u = a.pop()
+            print u
+            if is_imm(u):
+                u2 = ExprInt(uint32(str2imm(u)))
+            elif u in str2regid:
+                u2 = str2regid[u]
+            else:
+                raise ValueError('unknown3 arg', str(a))
+        if l==1:
+            o = u1
+        elif l == 2:
+            o = ExprOp('+', u1, u2)
+        elif l == 3:
+            o = ExprOp(t, u1, u2)
+        else:
+            rezrezrezr
+        o = optmem(o)
+        outa.append(o)
+    print args
+    print [str(x) for x in outa]
+    n = mn.name2str()
+
+    exprs = []
+    if isinstance(mn, arm_data):
+        if n in ['mov', 'eor', 'and', 'tst', 'teq', 'cmp', 'orr', 'bic']:
+            exprs += get_cf_shifter(outa[-1])
+        n+=mn.scc2str()
+    elif isinstance(mn, arm_br):
+        d = mn.getdstflow()
+        if len(d) !=1:
+            raise ValueError("zarb dst", d)
+        
+        outa = [my_eip, ExprInt(uint32(d[0].offset))]
+    else:
+        print 'unimpl mnemo', str(n)
+        return None
+
+    
+    print 'ARGS', [str(x) for x in outa]
+    print n, args
+    exprs += mnemo_func[n.lower()](*outa)
+
+    exprs = condition_expr(mn.cond, exprs)
+    print 'EXPR', [str(x) for x in exprs]
+    return exprs
+    
diff --git a/miasm/arch/ia32_arch.py b/miasm/arch/ia32_arch.py
new file mode 100644
index 00000000..5cb2a3ec
--- /dev/null
+++ b/miasm/arch/ia32_arch.py
@@ -0,0 +1,2223 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+from numpy import uint8, uint16, uint32, uint64, int8, int16, int32, int64
+import struct
+import logging
+from miasm.core.parse_ad import parse_ad, ad_to_generic
+from miasm.arch.ia32_reg import x86_afs
+import shlex
+
+
+log = logging.getLogger("x86escape")
+console_handler = logging.StreamHandler()
+console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
+log.addHandler(console_handler)
+log.setLevel(logging.WARN)
+
+
+tab_int_size = {int8:8,
+                uint8:8,
+                int16:16,
+                uint16:16,
+                int32:32,
+                uint32:32,
+                int64:64,
+                uint64:64
+                }
+
+tab_size2int = {x86_afs.u08:uint8,
+                x86_afs.u16:uint16,
+                x86_afs.u32:uint32,
+                x86_afs.s08:int8,
+                x86_afs.s16:int16,
+                x86_afs.s32:int32}
+                
+                
+
+
+
+prefix_dic = {"lock":0xF0, "repnz":0xF2, "repne":0xF2, "repz":0xF3, "repe":0xF3, "rep":0xF3, }
+
+prefix_dic_inv = dict(map(lambda x:(x[1],x[0]), prefix_dic.items()))
+
+#'es'|'cs'|'ss'|'ds'|'fs'|'gs') ':' '''
+prefix_seg = {0:0x26, 1:0x2E, 2:0x36, 3:0x3E, 4:0x64, 5:0x65}
+
+prefix_seg_inv = dict(map(lambda x:(x[1],x[0]), prefix_seg.items()))
+
+class mnemonic:
+    def __init__(self, name, opc, afs, rm, modifs, modifs_orig, sem):
+        self.name = name
+        self.opc = opc
+
+        self.afs = afs
+        self.rm = rm
+
+        self.modifs = modifs
+        self.modifs_orig = modifs_orig
+
+    def __str__(self):
+        return self.name+' '+str(self.opc)+' '+str(self.afs)+' '+str(self.rm)+' '+str(self.modifs)+' '+str(self.modifs_orig)#+' '+str(self.sem)+' '
+
+
+def mask_opc_to_i(mask, opc):
+    log.debug("mask %x opc %x"%(mask, opc))
+    return [i for i in range(0x100) if (i & mask) == opc]
+        
+mask_d = 0x38
+mask_reg = 0xF8
+mask_cond = 0xF0
+
+d0 = 0<<3
+d1 = 1<<3
+d2 = 2<<3
+d3 = 3<<3
+d4 = 4<<3
+d5 = 5<<3
+d6 = 6<<3
+d7 = 7<<3
+reg = "reg"
+noafs = "noafs"
+cond = "cond"
+cond_list = ["o",
+             "no",
+             "b",
+             "ae",
+             "e",
+             "nz",
+             "be",
+             "a",
+             "s",
+             "ns",
+             "p",
+             "np",
+             "l",#             "nge",
+             "ge",
+             "le",
+             "g"
+             ]
+no_rm = []
+rmr = "rmr"
+
+imm = x86_afs.imm
+ims = x86_afs.ims
+mim = x86_afs.mim
+u08 = x86_afs.u08
+s08 = x86_afs.s08
+u16 = x86_afs.u16
+s16 = x86_afs.s16
+u32 = x86_afs.u32
+s32 = x86_afs.s32
+im1 = x86_afs.im1
+im3 = x86_afs.im3
+ 
+r_eax = {x86_afs.r_eax:1, x86_afs.ad:False}
+r_cl  = {x86_afs.reg_list8.index(x86_afs.r_cl):1, x86_afs.ad:False, x86_afs.size:x86_afs.u08}
+r_dx  = {x86_afs.reg_list16.index(x86_afs.r_dx):1, x86_afs.ad:False, x86_afs.size:x86_afs.u16}
+
+
+w8 = "w8"
+se = "se"
+sw = "sw"
+ww = "ww"
+sg = "sg"
+dr = "dr"
+cr = "cr"
+ft = "ft"
+w64= "w64"
+sd = "sd" #single/double
+wd = "wd" #word/dword
+
+
+bkf = "breakflow"
+spf = "splitflow"
+dtf = "dstflow"
+
+seip = "seip" #seteip
+stpeip = "stpeip" #stop eip
+
+unsanity_mnemo = ['nop', 'monitor', 'mwait', 'fadd', 'faddp', 'fiadd', 'fcmovb', 'fcom', 'fcomp', 'fcomip',
+                  'fdiv', 'fdivr', 'fidivr', 'fdivrp', 'ficom', 'ficomp', 'fild', 'fist', 'fistp', 'fisttp',
+                  'fld', 'fldcw', 'fld1', 'fldl2t', "fldl2e", "fldpi", "fldlg2", "fldln2", "fldz", 'fldenv', 'fmul', 'fimul', 'fmulp', 'fst', 'fstp', 'fnstcw', 'fnstenv',
+                  'fnstsw', 'fsub', 'fsubr', 'fisubr', 'fsubrp', 'ftst', 'fucom', 'fucompp', 'fxam', 'fxtract', 'fyl2x', 'fyl2xp1', 'fsqrt', 'fsincos', 'fsin', 'fscale',
+                  'fcos', 'fdecstp', 'fnop', 'fpatan', 'fprem', 'fprem1', 'fptan', 'frndint', "shl", 'sal', 'sar']
+
+
+mask_drcrsg = {cr:0x100, dr:0x200, sg:0x400}
+
+def hexdump(a):
+    return reduce(lambda x,y:x+"%.2X"%ord(y), a, "")
+
+def is_address(a):
+    if x86_afs.ad in a and a[x86_afs.ad]:
+        return True
+    return False
+
+def is_imm(a):
+    if x86_afs.ad in a and a[x86_afs.ad]:
+        return False
+    if not (x86_afs.imm in a or x86_afs.symb in a) :
+        return False
+    for k in a:
+        if not k in [x86_afs.imm, x86_afs.size, x86_afs.ad, x86_afs.symb]:
+            return False
+    return True
+
+def is_ad_lookup(a):
+    if not x86_afs.ad in a or not a[x86_afs.ad]:
+        return False
+    if not (x86_afs.imm in a or x86_afs.symb in a) :
+        return False
+    for k in a:
+        if not k in [x86_afs.imm, x86_afs.size, x86_afs.ad, x86_afs.symb]:
+            return False
+    return True
+
+def is_reg(a):
+    if x86_afs.ad in a and a[x86_afs.ad]:
+        return False
+    if x86_afs.imm in a:
+        return False
+    if x86_afs.symb in a:
+        return False
+    
+    return True
+
+def get_label(a):
+    if x86_afs.ad in a:
+        return None
+    if x86_afs.imm in a:
+        return None
+    if not x86_afs.symb in a:
+        return None
+    n = a[x86_afs.symb]
+    if len(n)!=1:
+        return None
+    k = n.keys()[0]
+    if n[k] != 1:
+        return None
+    return k
+
+
+
+def check_imm_size(imm, size):
+    i = int32(uint32(imm))
+    if not size in [u08, s08, u16, s16, u32, s32]:
+        raise ValueError("unknown size %s"%size)
+    if size == u08 and imm >= 0 and imm < 0x100:
+        return uint8(imm)
+    elif size == s08 and i >=-0x80 and i < 0x80:
+        return int8(i)
+    elif size == u16 and imm >= 0 and imm < 0x10000:
+        return uint16(imm)
+    elif size == s16 and i >=-0x8000 and i < 0x8000:
+        return int16(i)
+    elif size == u32 and imm >=-0x100000000L and imm < 0x100000000L:
+        return uint32(imm)
+    elif size == s32 and i >=-0x80000000 and i < 0x80000000:
+        return int32(i)
+    return None
+  
+
+def dict_to_ad(d, modifs = {}, mnemo_mode = u32):
+    size = [x86_afs.u32, x86_afs.u08][modifs[w8]==True]
+    #overwrite w8
+    if modifs[sd]!=None:
+        size = [x86_afs.f32, x86_afs.f64][modifs[sd]==True]
+    elif modifs[wd]:
+        size = x86_afs.u16
+
+    tab32 = {x86_afs.u08:x86_afs.reg_list8, x86_afs.u16:x86_afs.reg_list16, x86_afs.u32:x86_afs.reg_list32,x86_afs.f32:x86_afs.reg_flt}
+    tab16 = {x86_afs.u08:x86_afs.reg_list8, x86_afs.u16:x86_afs.reg_list32, x86_afs.u32:x86_afs.reg_list16}
+    ad_size = {x86_afs.u08:"byte ptr", x86_afs.u16:"word ptr", x86_afs.u32:"dword ptr", x86_afs.f32:"single ptr", x86_afs.f64:"double ptr"}
+
+    if is_reg(d):
+        n = [x for x in d if type(x) in [int, long]]
+        if len(n)!=1:
+            raise ValueError("bad reg! %s"%str(d))
+        n = n[0]        
+        if x86_afs.size in d and d[x86_afs.size] == x86_afs.size_seg :
+            t = x86_afs.reg_sg
+        elif x86_afs.size in d:
+            my_s = d[x86_afs.size]
+            if my_s == x86_afs.f64:
+                my_s = x86_afs.u32
+            t = tab32[my_s]
+        else:
+            if mnemo_mode == u32:
+                t = tab32[size]
+            else:
+                t = tab16[size]
+        if modifs[dr] and n>0x7:
+            t = x86_afs.reg_dr
+            n&=7
+        if modifs[cr] and n>0x7:
+            t = x86_afs.reg_cr
+            n&=7
+        if modifs[sg] and n>0x7:
+            t = x86_afs.reg_sg
+            n&=7
+        if modifs[sd] is not None:
+            t = tab32[size]
+            n&=7
+
+        try:
+            out = t[n]
+        except:
+            print 'WARNING!dict2ad', t, str(d)
+            out = ""
+    elif is_imm(d):
+        out = ""
+        if x86_afs.imm in d:
+            imm_tmp = int(d[x86_afs.imm]) &0xffffffffL
+            if imm_tmp<0:
+                out+='-0x%.8X'%-imm_tmp
+            else:
+                out+='0x%.8X'%imm_tmp
+                
+        if x86_afs.symb in d:
+            #XXX todo multiple ref
+            if out!="": out+='+'
+            for c in d[x86_afs.symb]:
+                
+                if d[x86_afs.symb][c]==1:
+                    out += '%s'%str(c.name)
+                else:
+                    out += '%d,%s'%(int(d[x86_afs.symb][c]), str(c))
+                
+    elif is_address(d):
+        if x86_afs.size in d:
+            size = d[x86_afs.size]
+            
+        out = [ad_size[size]]
+        segment = " "
+        if x86_afs.segm in d:
+            segment += x86_afs.reg_sg[d[x86_afs.segm]]+':'
+            
+        for k in d:
+            if k in [x86_afs.ad, x86_afs.size, x86_afs.segm]:
+                continue
+            elif k == x86_afs.imm:
+                if int(d[k])<0:
+                    out.append('-0x%.8X'%-int(d[k]))
+                else:
+                    out.append('0x%.8X'%int(d[k]))
+            elif type(k) in [int, long]:
+                if d[k] ==1:
+                    out.append(x86_afs.reg_list32[k])
+                else:
+                    out.append(str(int(d[k]))+'*'+x86_afs.reg_list32[k])
+            elif k == x86_afs.symb:
+                out.append(str(d[k]))
+            else:
+                raise ValueError('strange ad componoant: %s'%str(d))
+        out = out[0]+segment+'['+ reduce(lambda x,y: x+"+"+y, out[1:], "")[1:] + ']'
+    else:
+        raise ValueError('unknown arg %s'%str(d))
+    return out
+
+
+
+class x86allmncs:
+    def print_op(self, optab, decal):
+        cpt = -1
+        for i in optab:
+            cpt+=1
+            if type(i) == list:
+                self.print_op(i, decal+1)
+            elif i == None:
+                pass
+            else:
+                print "%.3d "%cpt+"\t"*decal + str(i)
+        
+
+    def print_tab(self):
+        for i in range(0x100):
+            if type(self.db_afs[i]) == list:
+                for j in range(0x100):
+                    print "%.2X %.2X\t"%(i,j),
+                    print self.db_afs[i][j]
+            else:
+                print "%.2X\t"%i+str(self.db_afs[i])
+
+        
+
+    def get_afs(self, bin, m, size_m):
+        my_uint = uint32
+        if size_m == u32:
+            db_afs = self.db_afs
+        else:
+            db_afs = self.db_afs_16
+        
+        mod, re, rm = self.modrm(m)
+        if type(db_afs[m])==list:
+            a = dict(db_afs[m][ord(bin.readbs())])
+        else:
+            a = dict(db_afs[m])
+        if x86_afs.imm in a:
+            if a[x86_afs.imm] == x86_afs.u08:
+                a[x86_afs.imm] = my_uint(struct.unpack('B', bin.readbs())[0])
+            elif a[x86_afs.imm] == x86_afs.s08:
+                a[x86_afs.imm] = my_uint(struct.unpack('b', bin.readbs())[0])
+            elif a[x86_afs.imm] == x86_afs.u32:
+                a[x86_afs.imm] = my_uint(struct.unpack('I', bin.readbs(4))[0])
+            elif a[x86_afs.imm] == x86_afs.u16:
+                a[x86_afs.imm] = my_uint(struct.unpack('H', bin.readbs(2))[0])
+            else:
+                raise ValueError('imple other afs ... ', str(a[x86_afs.imm]))
+        return re, a
+
+    def get_afs_re(self, re):
+        return {x86_afs.ad:False, re:1}
+        
+        
+
+    def get_im_fmt(self, modifs, mnemo_mode, im):
+        if modifs[se]:
+            fmt,t = ('b',s08)
+        elif modifs[w8]:
+            if im == x86_afs.imm:
+                fmt,t = ('B',u08)
+            elif im == x86_afs.ims:
+                fmt,t = ('b',s08)
+            else:
+                raise ValueError("error encode %s"%str(im))
+        else:
+            if im == x86_afs.imm:
+                if mnemo_mode == u32: fmt,t = ('I',u32)
+                else:                 fmt,t = ('H',u16)
+            elif im == x86_afs.ims:
+                if mnemo_mode == u32: fmt,t = ('i',s32)
+                else:                 fmt,t = ('h',s16)
+
+                
+        return struct.calcsize(fmt), fmt,t
+    
+    def modrm(self, c):
+        return (c>>6)&3, (c>>3)&7, c&7
+    def sib(self, c):
+        return self.modrm(c)
+
+    def init_pre_modrm(self):
+
+        self.sib_rez_u08_ebp = [{x86_afs.ad:True} for i in range(0x100)]
+        self.sib_rez_u32_ebp = [{x86_afs.ad:True} for i in range(0x100)]
+        self.sib_rez_u32 = [{x86_afs.ad:True} for i in range(0x100)]
+
+        for sib_rez in [self.sib_rez_u08_ebp,
+                        self.sib_rez_u32_ebp,
+                        self.sib_rez_u32
+                        ]:
+            for index in range(0x100):
+                ss, i, r = self.modrm(index)
+
+                if r == 5:
+                    if sib_rez == self.sib_rez_u08_ebp:
+                        sib_rez[index][x86_afs.imm] = x86_afs.s08
+                        sib_rez[index][x86_afs.reg_dict[x86_afs.r_ebp]] = 1
+                    elif sib_rez == self.sib_rez_u32_ebp:
+                        sib_rez[index][x86_afs.imm] = x86_afs.u32
+                        sib_rez[index][x86_afs.reg_dict[x86_afs.r_ebp]] = 1
+                    elif sib_rez == self.sib_rez_u32:
+                        sib_rez[index][x86_afs.imm] = x86_afs.u32
+                else:
+                    if sib_rez == self.sib_rez_u08_ebp:
+                        sib_rez[index][r]=1
+                        sib_rez[index][x86_afs.imm] = x86_afs.s08
+                    elif sib_rez == self.sib_rez_u32_ebp:
+                        sib_rez[index][r]=1
+                        sib_rez[index][x86_afs.imm] = x86_afs.u32
+                    elif sib_rez == self.sib_rez_u32:
+                        sib_rez[index][r]=1
+                    
+    
+                if i == 4:
+                    continue
+    
+                tmp = i
+                if tmp in sib_rez[index]:
+                    sib_rez[index][tmp]+=[1, 2, 4, 8][ss]
+                else:
+                    sib_rez[index][tmp] =[1, 2, 4, 8][ss]
+
+        #32bit
+        self.db_afs = [None for i in range(0x100)]
+        for i in range(0x100):
+            index = i
+            mod, re, rm = self.modrm(i)
+
+            if mod == 0:
+                if rm == 4:
+                    self.db_afs[index] = self.sib_rez_u32
+                elif rm == 5:
+                    self.db_afs[index] = {x86_afs.ad:True, x86_afs.imm:x86_afs.u32}
+                else:
+                    self.db_afs[index] = {x86_afs.ad:True, rm:1}
+            elif mod == 1:
+                if rm == 4:
+                    self.db_afs[index] = self.sib_rez_u08_ebp
+                    continue
+                tmp = {x86_afs.ad:True, rm:1}
+                if rm == 0:
+                    tmp[x86_afs.imm] = x86_afs.s08
+                else:
+                    tmp[x86_afs.imm] = x86_afs.s08
+                self.db_afs[index] = tmp
+
+            elif mod == 2:
+                if rm == 4:
+                    self.db_afs[index] = self.sib_rez_u32_ebp
+                else:
+                    self.db_afs[index] = {x86_afs.ad:True, rm:1,x86_afs.imm:x86_afs.u32}
+            elif mod == 3:
+                self.db_afs[index] = {x86_afs.ad:False, rm:1}
+
+        #16bit
+        self.db_afs_16 = [None for i in range(0x100)]
+        _si = x86_afs.reg_dict[x86_afs.r_si]
+        _di = x86_afs.reg_dict[x86_afs.r_di]
+        _bx = x86_afs.reg_dict[x86_afs.r_bx]
+        _bp = x86_afs.reg_dict[x86_afs.r_bp]
+        for i in range(0x100):
+            index = i
+            mod, re, rm = self.modrm(i)
+
+            if mod == 0:
+                if rm == 4:
+                    self.db_afs_16[index] = {x86_afs.ad:True,_si:1}
+                elif rm == 5:
+                    self.db_afs_16[index] = {x86_afs.ad:True,_di:1}
+                elif rm == 6:
+                    self.db_afs_16[index] = {x86_afs.ad:True,x86_afs.imm:x86_afs.u16}#{x86_afs.ad:True,_bp:1}
+                elif rm == 7:
+                    self.db_afs_16[index] = {x86_afs.ad:True,_bx:1}
+                else:                    
+                    self.db_afs_16[index] = {x86_afs.ad:True,
+                                             [_si, _di][rm%2]:1,
+                                             [_bx, _bp][(rm>>1)%2]:1}
+            elif mod in [1,2]:
+                if mod==1:
+                    if rm==0:
+                        my_imm=x86_afs.s08
+                    else:
+                        my_imm=x86_afs.u08
+                else:
+                    my_imm=x86_afs.u16
+                    
+                if rm==4:
+                    self.db_afs_16[index] = {x86_afs.ad:True,_si:1, x86_afs.imm:my_imm}
+                elif rm==5:
+                    self.db_afs_16[index] = {x86_afs.ad:True,_di:1, x86_afs.imm:my_imm}
+                elif rm==6:
+                    self.db_afs_16[index] = {x86_afs.ad:True,_bp:1, x86_afs.imm:my_imm}
+                elif rm==7:
+                    self.db_afs_16[index] = {x86_afs.ad:True,_bx:1, x86_afs.imm:my_imm}
+                else:
+                    self.db_afs_16[index] = {x86_afs.ad:True,
+                                             [_si, _di][rm%2]:1,
+                                             [_bx, _bp][(rm>>1)%2]:1,
+                                             x86_afs.imm:my_imm}
+
+            elif mod == 3:
+                self.db_afs_16[index] = {x86_afs.ad:False, rm:1}
+
+
+    def addop(self, name, opc, afs, rm, modif_desc, prop_dict, sem):
+        prop_dict.update(sem)
+        modifs = dict([[x, True] for x in modif_desc])
+        base_modif = dict([[x, None] for x in [w8, se, sw, ww, sg, dr, cr, ft, w64, sd, wd, bkf, spf, dtf]])
+        base_modif.update(modifs)
+        
+        #update with forced properties
+        base_modif.update(prop_dict)
+        base_mnemo = [(opc, base_modif)]
+
+        #XXX zarb: default se inverted?
+        if se in modif_desc:
+            tmp = base_mnemo[0][1]
+            tmp[se] = False
+            base_mnemo = [(base_mnemo[0][0], tmp)]
+
+        log.debug(modifs)
+        for modif in modifs:
+            base_mnemo_add = []
+            for opc, n_m in base_mnemo:
+                n_m = dict(n_m)
+                n_m[modif]= not n_m[modif]
+
+                opc = opc[:]
+                opc[modif_desc[modif][0]] |=(1<<modif_desc[modif][1])
+                
+                base_mnemo_add.append((opc, n_m))
+
+            base_mnemo+=base_mnemo_add
+
+        for opc, n_m in base_mnemo:
+            #unassociable modifs XXX here cause structure generation
+            if n_m[se] and n_m[w8]:
+                continue
+        
+            if afs in [d0, d1, d2, d3, d4, d5, d6, d7]:
+                opc+=[afs]
+                mask = mask_d
+            elif afs in [reg]:
+                mask = mask_reg
+            elif afs == noafs:
+                mask = 0xFF
+            elif afs == cond:
+                mask = mask_cond
+            else:
+                raise ValueError('bug in %s %d'%(name, afs))
+    
+            #find mnemonic table
+            insert_tab = self.db_mnemo
+            log.debug(name)
+            log.debug(opc )
+            log.debug(mask)
+            for i in opc[:-1]:
+                if insert_tab[i] == None:
+                    insert_tab[i] = [None for x in range(0x100)]
+                insert_tab = insert_tab[i]
+    
+            keys = mask_opc_to_i(mask, opc[-1])
+            if afs == cond:
+                for k in keys:
+                    opc_tmp = opc[:]
+                    i_k = k&(mask_cond^0xFF)
+                    opc_tmp[-1]|=i_k
+                    mnemo = mnemonic(name+cond_list[i_k], opc_tmp, afs, rm, n_m, modif_desc, sem)
+                    if insert_tab[k]!=None and not name in unsanity_mnemo:
+                        raise ValueError("sanity check fail in mnemo affect %s"%str(insert_tab[k]))
+                    insert_tab[k] = mnemo
+                    #fast mnemo_lookup
+                    if not mnemo.name in self.mnemo_lookup:
+                        self.mnemo_lookup[mnemo.name] = [mnemo]
+                    elif not mnemo in self.mnemo_lookup[mnemo.name]:
+                        self.mnemo_lookup[mnemo.name].append(mnemo)
+                        
+            else:
+                mnemo = mnemonic(name, opc, afs, rm, n_m, modif_desc, sem)
+                for k in keys:
+                    if insert_tab[k]!=None and not name in unsanity_mnemo:
+                        raise ValueError("sanity check fail in mnemo affect %s"%str(insert_tab[k]))
+                    insert_tab[k] = mnemo
+                    #fast mnemo_lookup
+                    if not mnemo.name in self.mnemo_lookup:
+                        self.mnemo_lookup[mnemo.name] = [mnemo]
+                    elif not mnemo in self.mnemo_lookup[mnemo.name]:
+                        self.mnemo_lookup[mnemo.name].append(mnemo)
+    
+    def find_mnemo(self, name, mnemo_list = None, candidate = None):
+        if name in self.mnemo_lookup.keys():
+            return self.mnemo_lookup[name]
+        else:
+            return []
+    
+        
+        
+
+        
+        
+
+    def get_address_afs(self, a):
+        l = parse_ad(a)
+        return ad_to_generic(l)
+        
+    def get_address_afs_hex(self, adprops):
+        out = []
+        for ad in adprops:
+            candidate = []
+            for i in range(0x100):
+                index = i&0xC7
+                if type(self.db_afs[index])==list:
+                    for j in range(0x100):
+                        if self.db_afs[index][j] == ad:
+                            if not (index, j)  in candidate:
+                                candidate.append((index, j) )
+                        
+                else:
+                    if self.db_afs[index] == ad:
+                        if not (index, None)  in candidate:
+                            candidate.append((index, None) )
+
+            out.append(candidate)
+        return out
+
+    def forge_opc(self, out_opc, a, a2 = None):
+        if a2!=None :
+            k = [x for x in a2.keys() if type(x) in [long, int]]
+            if a2[x86_afs.ad] or x86_afs.imm in a2 or len(k)!=1:
+                raise ValueError('bad a2 forge %s'%str(a2))
+            out_opc[0].append(k[0]<<3)
+            
+        #if not a[x86_afs.ad]:
+        del a[x86_afs.size]
+
+        log.debug(a)
+        b = ad_to_generic(a)
+        log.debug(b)
+        raw = self.get_address_afs_hex(b)
+
+        b_out = []
+        raw_out = []
+        for i in range(len(b)):
+            if not raw[i] :
+                continue
+            b_out.append(b[i])
+            raw_out.append(raw[i])
+
+        b = b_out
+        raw = raw_out
+        out_opc_o = []
+        p_val = []
+
+        for i in range(len(raw)):
+            for r in raw[i]:
+                out_opc_o.append(out_opc[0][:])
+                out_opc_o[-1][-1]|=r[0]
+                if r[1]!=None:
+                    out_opc_o[-1].append(r[1])
+                log.debug( b[i])
+                if x86_afs.imm in b[i]:
+                    if x86_afs.imm in a:
+                        v = a[x86_afs.imm]
+                    else:
+                        v = 0
+                    
+                    v = check_imm_size(v, b[i][x86_afs.imm])
+                    if v == None:
+                        log.debug("cannot encode this val in size forge!")
+                        return None, None
+
+                    p_val.append({x86_afs.size:b[i][x86_afs.imm], x86_afs.imm:v})
+                else:
+                    p_val.append({})
+
+        return out_opc_o, p_val
+
+    def check_size_modif(self, size, modifs):
+        if modifs[sd] is not None:
+            if size != [x86_afs.f32, x86_afs.f64][modifs[sd]==False]: #XXX 32 should be reg not stX???
+                log.debug('checksize: not good fXX (%s)'%str(size))
+                return False
+            else:
+                return True
+        if modifs[wd] is not None:
+            if size != [x86_afs.u32, x86_afs.u16][modifs[wd]]:
+                log.debug('checksize: not good w/dw')
+                return False
+            else:
+                return True
+            
+        if size != [x86_afs.u32, x86_afs.u08][modifs[w8]==True]:
+            log.debug('checksize: not good w8:%s'%str(size))
+            return False
+        return True
+
+
+    def __init__(self):
+
+        self.mnemo_lookup = {}
+        self.init_pre_modrm()
+        self.op_db = {}
+        
+        self.db_mnemo = [None for x in range(0x100)]
+        addop = self.addop
+
+
+        #x86
+        
+        addop("aaa",   [0x37],             noafs, no_rm         , {}                 ,{}                , {},                         )
+        #addop("aad",   [0xD5, 0x0A],       noafs, no_rm         , {}                 ,{}                , {},                         )
+        #addop("aam",   [0xD4, 0x0A],       noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("aad",   [0xD5],             noafs, [u08]         , {}                 ,{}                , {},                         )
+        addop("aam",   [0xD4],             noafs, [u08]         , {}                 ,{}                , {},                         )
+        
+        addop("aas",   [0x3F],             noafs, no_rm         , {}                 ,{}                , {},                         )
+                                                                                                            
+        addop("adc",   [0x14],             noafs, [r_eax,imm]   , {w8:(0,0)}         ,{}                , {},                         )
+        addop("adc",   [0x80],             d2,    [imm]         , {w8:(0,0),se:(0,1)},{}                , {},                         )
+        addop("adc",   [0x10],             noafs, [rmr]         , {w8:(0,0),sw:(0,1)},{}                , {},                         )
+                                                                                                            
+        addop("add",   [0x04],             noafs, [r_eax,imm]   , {w8:(0,0)}         ,{}                , {},                         )
+        addop("add",   [0x80],             d0,    [imm]         , {w8:(0,0),se:(0,1)},{}                , {},                         )
+        addop("add",   [0x00],             noafs, [rmr]         , {w8:(0,0),sw:(0,1)},{}                , {},                         )
+                                                                                                            
+        addop("and",   [0x24],             noafs, [r_eax,imm]   , {w8:(0,0)}         ,{}                , {},                         )
+        addop("and",   [0x80],             d4,    [imm]         , {w8:(0,0),se:(0,1)},{w8:True}         , {},                         )
+        addop("and",   [0x20],             noafs, [rmr]         , {w8:(0,0),sw:(0,1)},{}                , {},                         )
+                                                                                                            
+        addop("arpl",  [0x63],             noafs, [rmr]         , {}                 ,{sw:True,wd:True} , {},                         )
+                                                                                                            
+        addop("bsf",   [0x0F, 0xBC],       noafs, [rmr]         , {}                 ,{}                , {},                         )
+        addop("bsr",   [0x0F, 0xBD],       noafs, [rmr]         , {}                 ,{}                , {},                         )
+        addop("bswap", [0x0F, 0xC8],       reg  , no_rm         , {}                 ,{}                , {},                         )
+                                                                                                            
+        addop("bt",    [0x0F, 0xA3],       noafs, [rmr]         , {}                 ,{sw:True}         , {},                         )
+        addop("bt",    [0x0F, 0xBA],       d4   , [u08]         , {}                 ,{}                , {},                         )
+        addop("btc",   [0x0F, 0xBB],       noafs, [rmr]         , {}                 ,{sw:True}         , {},                         )
+        addop("btc",   [0x0F, 0xBA],       d7   , [u08]         , {}                 ,{}                , {},                         )
+        addop("btr",   [0x0F, 0xB3],       noafs, [rmr]         , {}                 ,{sw:True}         , {},                         )
+        addop("btr",   [0x0F, 0xBA],       d6   , [u08]         , {}                 ,{}                , {},                         )
+        addop("bts",   [0x0F, 0xAB],       noafs, [rmr]         , {}                 ,{sw:True}         , {},                         )
+        addop("bts",   [0x0F, 0xBA],       d5   , [u08]         , {}                 ,{}                , {},                         )
+                                                                                                            
+        addop("call",  [0xE8],             noafs, [s32]         , {}                 ,{}                , {bkf:True,spf:True,dtf:True})
+        addop("call",  [0xFF],             d2   , no_rm         , {}                 ,{}                , {bkf:True,spf:True,dtf:True})
+        addop("call",  [0x9A],             noafs, [imm,u16]     , {}                 ,{}                , {bkf:True,spf:True,dtf:True})
+        addop("callf", [0xFF],             d3,    no_rm         , {}                 ,{}                , {bkf:True,spf:True,dtf:True}) #XXX
+                                                                                                            
+        addop("cbw",   [0x98],             noafs, [r_eax]       , {}                 ,{}                , {},                         )
+        addop("clc",   [0xF8],             noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("cld",   [0xFC],             noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("cli",   [0xFA],             noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("clts",  [0x0F, 0x06],       noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("cmc",   [0xF5],             noafs, no_rm         , {}                 ,{}                , {},                         )
+                                                                                                            
+        addop("cmov",  [0x0F, 0x40],       cond , [rmr]         , {}                 ,{}                , {},                         )
+                                                                                                            
+        addop("cmp",   [0x3C],             noafs, [r_eax,imm]   , {w8:(0,0)}         ,{}                , {},                         )
+        addop("cmp",   [0x80],             d7,    [imm]         , {w8:(0,0),se:(0,1)},{}                , {},                         )
+        addop("cmp",   [0x38],             noafs, [rmr]         , {w8:(0,0),sw:(0,1)},{}                , {},                         )
+                                                                                                            
+        addop("cmpsb", [0xA6],             noafs, no_rm         , {}                 ,{w8:True}         , {},                         )
+        addop("cmpsd", [0xA7],             noafs, no_rm         , {}                 ,{w8:False}        , {},                         )
+
+                                                                                                            
+        addop("cmpxchg",[0x0F, 0xB0],      noafs, [r_eax,rmr]   , {w8:(1,0)}         ,{}                , {},                         )
+        addop("cmpxchg8b",[0x0F, 0xC7],    d1   , no_rm         , {}                 ,{}                , {},                         )
+        addop("cpuid", [0x0F, 0xA2],       noafs, no_rm         , {}                 ,{}                , {},                         )
+                                                                                                            
+        #ddop("cwd",   [0x99],             noafs, [r_eax]       , {}                 ,{}                , {},                         )
+        addop("cdq",   [0x99],             noafs, no_rm         , {}                 ,{}                , {},                         )
+                                                                                                            
+        addop("daa",   [0x27],             noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("das",   [0x2F],             noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("dec",   [0x48],             reg  , no_rm         , {}                 ,{}                , {},                         )
+        addop("dec",   [0xFE],             d1   , no_rm         , {w8:(0,0)}         ,{}                , {},                         )
+        addop("div",   [0xF6],             d6   , no_rm         , {w8:(0,0)}         ,{}                , {},                         )
+                                                                                                            
+        addop("enter", [0xC8],             noafs, [u08, u16]    , {}                 ,{}                , {},                         )
+                                                                                                            
+        addop("hlt",   [0xF4],             noafs, no_rm         , {}                 ,{}                , {bkf:True}                  )
+                                                                                                            
+        addop("idiv",  [0xF6],             d7   , no_rm         , {w8:(0,0)}         ,{}                , {},                         )
+                                                                                                            
+        addop("imul",  [0xF6],             d5   , no_rm         , {w8:(0,0)}         ,{}                , {},                         )
+        addop("imul",  [0x0F, 0xAF],       noafs, [rmr]         , {}                 ,{sw:False}        , {},                         )
+        addop("imul",  [0x69],             noafs, [rmr, imm]    , {se:(0,1)}         ,{sw:False}        , {},                         )
+                                                                                                            
+        addop("in",    [0xE4],             noafs, [r_eax, u08]  , {w8:(0,0)}         ,{}                , {},                         )
+        addop("in",    [0xEC],             noafs, [r_eax,r_dx]  , {w8:(0,0)}         ,{}                , {},                         )
+                                                                                                            
+        addop("inc",   [0x40],             reg  , no_rm         , {}                 ,{}                , {},                         )
+        addop("inc",   [0xFE],             d0   , no_rm         , {w8:(0,0)}         ,{}                , {},                         )
+                                                                                                            
+        addop("ins",   [0x6C],             noafs, no_rm         , {w8:(0,0)}         ,{}                , {},                         )
+                                                                                                            
+        addop("int",   [0xCC],             noafs, [im3]         , {}                 ,{}                , {},                         )
+        addop("int",   [0xCD],             noafs, [u08]         , {}                 ,{}                , {},                         )
+                                                                                                            
+        addop("into",  [0xCE],             noafs, no_rm         , {}                 ,{}                , {},                         )
+                                                                                                            
+        addop("invd",  [0x0F, 0x08],       noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("invlpg",[0x0F, 0x01],       d7   , no_rm         , {}                 ,{}                , {},                         )
+                                                                                                            
+        addop("iret",  [0xCF],             noafs, no_rm         , {}                 ,{}                , {bkf:True}                  )
+                                                                                                            
+        addop("j",     [0x70],             cond , [s08]         , {}                 ,{}                , {bkf:True,spf:True,dtf:True})
+        addop("j",     [0x0F, 0x80],       cond , [s32]         , {}                 ,{}                , {bkf:True,spf:True,dtf:True})
+        addop("jecxz", [0xE3],             noafs, [s08]         , {}                 ,{}                , {bkf:True,spf:True,dtf:True})
+                                                                                                            
+        addop("jmp",   [0xE9],             noafs, [ims]         , {w8:(0,1)}         ,{w8:False}        , {bkf:True,dtf:True}         )
+        addop("jmp",   [0xFF],             d4   , no_rm         , {}                 ,{}                , {bkf:True,dtf:True}         )
+        addop("jmpf",  [0xFF],             d5   , no_rm         , {}                 ,{}                , {bkf:True,dtf:True}         )
+                                                                                                            
+        addop("lahf",  [0x9F],             noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("lar",   [0x0F, 0x02],       noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("ldmxcsr",[0x0F, 0xAE],      d2   , no_rm         , {}                 ,{}                , {},                         )
+        addop("lds",   [0xC5],             noafs, [rmr]         , {}                 ,{}                , {},                         )
+        addop("lss",   [0x0F, 0xB2],       noafs, [rmr]         , {}                 ,{}                , {},                         )
+        addop("les",   [0xC4],             noafs, [rmr]         , {}                 ,{}                , {},                         )
+        addop("lfs",   [0x0F, 0xB4],       noafs, [rmr]         , {}                 ,{}                , {},                         )
+        addop("lgs",   [0x0F, 0xB5],       noafs, [rmr]         , {}                 ,{}                , {},                         )
+                                                                                                            
+        addop("lea",   [0x8D],             noafs, [rmr]         , {}                 ,{}                , {},                         )
+                                                                                                            
+        addop("leave", [0xC9],             noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("lfence",[0x0F, 0xAE],       d5   , no_rm         , {}                 ,{}                , {},                         )
+        addop("lgdt",  [0x0F, 0x01],       d2   , no_rm         , {}                 ,{}                , {},                         )
+        addop("lidt",  [0x0F, 0x01],       d3   , no_rm         , {}                 ,{}                , {},                         )
+        addop("lldt",  [0x0F, 0x00],       d2   , no_rm         , {}                 ,{}                , {},                         )
+        addop("lmsw",  [0x0F, 0x01],       d6   , no_rm         , {}                 ,{}                , {},                         )
+                                                                                                            
+        #ddop("lods",  [0xAC],             noafs, no_rm         , {w8:(0,0)}         ,{}                , {},                         )
+        addop("lodsb", [0xAC],             noafs, no_rm         , {}                 ,{w8:True}         , {},                         )
+        addop("lodsd", [0xAD],             noafs, no_rm         , {}                 ,{w8:False}        , {},                         )
+                                                                                                            
+        addop("loop",  [0xE2],             noafs, [s08]         , {}                 ,{}                , {bkf:True,spf:True,dtf:True})
+        addop("loope", [0xE1],             noafs, [s08]         , {}                 ,{}                , {bkf:True,spf:True,dtf:True})
+        addop("loopne",[0xE0],             noafs, [s08]         , {}                 ,{}                , {bkf:True,spf:True,dtf:True})
+
+        addop("lsl",   [0x0F, 0x03],       noafs, [rmr]         , {}                 ,{}                , {},                         )
+
+        addop("ltr",   [0x0F, 0x00],       d3   , no_rm         , {}                 ,{wd:True}         , {},                         )
+
+        addop("mfence",[0x0F, 0xAE],       d6   , no_rm         , {}                 ,{}                , {},                         )
+
+        addop("mov",   [0x88],             noafs, [rmr]         , {w8:(0,0),sw:(0,1)},{}                , {},                         )
+        addop("mov",   [0xA0],             noafs, [r_eax,mim]   , {w8:(0,0)}         ,{}                , {},                         )
+        addop("mov",   [0xA2],             noafs, [mim,r_eax]   , {w8:(0,0)}         ,{}                , {},                         )
+
+        addop("mov",   [0xB0],             reg  , [imm]         , {w8:(0,3)}         ,{}                , {},                         )
+        addop("mov",   [0x0F, 0x20],       noafs, [rmr]         , {sw:(1,1)}         ,{cr:True}         , {},                         )
+        addop("mov",   [0x0F, 0x21],       noafs, [rmr]         , {sw:(1,1)}         ,{dr:True}         , {},                         )
+        addop("mov",   [0x8C],             noafs, [rmr]         , {sw:(0,1)}         ,{sg:True,sw:True} , {},                         )
+        addop("mov",   [0xC6],             d0   , [imm]         , {w8:(0,0)}         ,{}                , {},                         )
+
+        addop("movnti",[0x0F, 0xC3],       noafs, [rmr]         , {}                 ,{}                , {},                         )
+
+        addop("movsb", [0xA4],             noafs, no_rm         , {}                 ,{w8:True}         , {},                         )
+        addop("movsd", [0xA5],             noafs, no_rm         , {}                 ,{w8:False}        , {},                         )
+        addop("movsx", [0x0F, 0xBE],       noafs, [rmr]         , {se:(1,0)}         ,{}                , {},                         )
+        addop("movzx", [0x0F, 0xB6],       noafs, [rmr]         , {se:(1,0)}         ,{}                , {},                         )
+
+        addop("mul",   [0xF6],             d4   , no_rm         , {w8:(0,0)}         ,{}                , {},                         )
+
+        addop("neg",   [0xF6],             d3   , no_rm         , {w8:(0,0)}         ,{}                , {},                         )
+        addop("nop",   [0x0F, 0x1F],       d0   , no_rm         , {}                 ,{}                , {},                         )
+        addop("not",   [0xF6],             d2   , no_rm         , {w8:(0,0)}         ,{}                , {},                         )
+
+        addop("or",    [0x0C],             noafs, [r_eax,imm]   , {w8:(0,0)}         ,{}                , {},                         )
+        addop("or",    [0x80],             d1,    [imm]         , {w8:(0,0),se:(0,1)},{}                , {},                         )
+        addop("or",    [0x08],             noafs, [rmr]         , {w8:(0,0),sw:(0,1)},{}                , {},                         )
+
+        addop("out",   [0xE6],             noafs, [u08,r_eax]   , {w8:(0,0)}         ,{}                , {},                         )
+        addop("out",   [0xEE],             noafs, [r_dx,r_eax]  , {w8:(0,0)}         ,{}                , {},                         )
+        addop("outs",  [0x6E],             noafs, no_rm         , {w8:(0,0)}         ,{}                , {},                         )
+
+        addop("pause", [0xF3, 0x90],       noafs, no_rm         , {}                 ,{}                , {},                         )
+
+        addop("pop",   [0x58],             reg  , no_rm         , {}                 ,{}                , {},                         )
+        addop("pop",   [0x8F],             d0   , no_rm         , {}                 ,{}                , {},                         )
+        addop("popad", [0x61],             noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("popfd", [0x9D],             noafs, no_rm         , {}                 ,{}                , {},                         )
+
+        addop("prefetch",[0x0F, 0x18],     d0   , no_rm         , {}                 ,{}                , {},                         )
+        addop("prefetch",[0x0F, 0x18],     d1   , no_rm         , {}                 ,{}                , {},                         )
+        addop("prefetch",[0x0F, 0x18],     d2   , no_rm         , {}                 ,{}                , {},                         )
+        addop("prefetch",[0x0F, 0x18],     d3   , no_rm         , {}                 ,{}                , {},                         )
+
+        addop("push",  [0x68],             noafs, [imm]         , {se:(0,1)}         ,{}                , {},                         )
+        addop("push",  [0x50],             reg  , no_rm         , {}                 ,{}                , {},                         )
+        addop("push",  [0xFF],             d6   , no_rm         , {}                 ,{}                , {},                         )
+        addop("pushad",[0x60],             noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("pushfd",[0x9C],             noafs, no_rm         , {}                 ,{}                , {},                         )
+
+        addop("rcl",   [0xD0],             d2   , [im1]         , {w8:(0,0)}         ,{}                , {},                         )
+        addop("rcl",   [0xD2],             d2   , [r_cl]        , {w8:(0,0)}         ,{}                , {},                         )
+        addop("rcl",   [0xC0],             d2   , [u08]         , {w8:(0,0)}         ,{}                , {},                         )
+
+        addop("rcr",   [0xD0],             d3   , [im1]         , {w8:(0,0)}         ,{}                , {},                         )
+        addop("rcr",   [0xD2],             d3   , [r_cl]        , {w8:(0,0)}         ,{}                , {},                         )
+        addop("rcr",   [0xC0],             d3   , [u08]         , {w8:(0,0)}         ,{}                , {},                         )
+
+        addop("rol",   [0xD0],             d0   , [im1]         , {w8:(0,0)}         ,{}                , {},                         )
+        addop("rol",   [0xD2],             d0   , [r_cl]        , {w8:(0,0)}         ,{}                , {},                         )
+        addop("rol",   [0xC0],             d0   , [u08]         , {w8:(0,0)}         ,{}                , {},                         )
+
+        addop("ror",   [0xD0],             d1   , [im1]         , {w8:(0,0)}         ,{}                , {},                         )
+        addop("ror",   [0xD2],             d1   , [r_cl]        , {w8:(0,0)}         ,{}                , {},                         )
+        addop("ror",   [0xC0],             d1   , [u08]         , {w8:(0,0)}         ,{}                , {},                         )
+
+        addop("rdmsr", [0x0F, 0x32],       noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("rdpmc", [0x0F, 0x33],       noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("rdtsc", [0x0F, 0x31],       noafs, no_rm         , {}                 ,{}                , {},                         )
+
+        addop("ret",   [0xC3],             noafs, no_rm         , {}                 ,{}                , {bkf:True}                  )
+        addop("retf",  [0xCB],             noafs, no_rm         , {}                 ,{}                , {bkf:True},                 )
+
+        addop("ret",   [0xC2],             noafs, [u16]         , {}                 ,{}                , {bkf:True},                 )
+        addop("retf",  [0xCA],             noafs, [u16]         , {}                 ,{}                , {bkf:True},                 )
+
+        addop("rms",   [0x0F, 0xAA],       noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("sahf",  [0x9E],             noafs, no_rm         , {}                 ,{}                , {},                         )
+
+
+        addop("sal",   [0xC0],             d4   , [u08]        , {w8:(0,0)}         ,{}                , {},                         )
+        addop("sal",   [0xC0],             d6   , [u08]        , {w8:(0,0)}         ,{}                , {},                         )
+
+        addop("sal",   [0xC1],             d4   , [u08]        , {w8:(0,0)}         ,{}                , {},                         )
+        addop("sal",   [0xC1],             d6   , [u08]        , {w8:(0,0)}         ,{}                , {},                         )
+        
+        addop("sal",   [0xD1],             d4   , [r_cl]        , {w8:(0,0)}         ,{}                , {},                         )
+        addop("sal",   [0xD1],             d6   , [r_cl]        , {w8:(0,0)}         ,{}                , {},                         )
+        
+        addop("sal",   [0xD3],             d4   , [r_cl]        , {w8:(0,0)}         ,{}                , {},                         )
+        addop("sal",   [0xD3],             d6   , [r_cl]        , {w8:(0,0)}         ,{}                , {},                         )
+        """
+        addop("sal",   [0xD2],             d4   , [r_cl]        , {w8:(0,0)}         ,{}                , {},                         )
+        addop("sal",   [0xC0],             d4   , [u08]         , {w8:(0,0)}         ,{}                , {},                         )
+        """                                                                                             , {}
+
+        addop("sal",   [0xD0],             d6   , [r_cl]        , {w8:(0,0)}         ,{}                , {},                         )
+        addop("sar",   [0xD0],             d7   , [im1]         , {w8:(0,0)}         ,{}                , {},                         )
+        
+        addop("sar",   [0xD2],             d6   , [r_cl]        , {w8:(0,0)}         ,{}                , {},                         )
+        addop("sar",   [0xD2],             d7   , [r_cl]        , {w8:(0,0)}         ,{}                , {},                         )
+        addop("sar",   [0xC0],             d7   , [u08]         , {w8:(0,0)}         ,{}                , {},                         )
+
+        addop("shl",   [0xD0],             d4   , [im1]         , {w8:(0,0)}         ,{}                , {},                         )
+        addop("shl",   [0xD2],             d4   , [r_cl]        , {w8:(0,0)}         ,{}                , {},                         )
+        addop("shl",   [0xC0],             d4   , [u08]         , {w8:(0,0)}         ,{}                , {},                         )
+
+        addop("shr",   [0xD0],             d5   , [im1]         , {w8:(0,0)}         ,{}                , {},                         )
+        addop("shr",   [0xD2],             d5   , [r_cl]        , {w8:(0,0)}         ,{}                , {},                         )
+        addop("shr",   [0xC0],             d5   , [u08]         , {w8:(0,0)}         ,{}                , {},                         )
+
+        addop("sbb",   [0x1C],             noafs, [r_eax,imm]   , {w8:(0,0)}         ,{}                , {},                         )
+        addop("sbb",   [0x80],             d3,    [imm]         , {w8:(0,0),se:(0,1)},{}                , {},                         )
+        addop("sbb",   [0x18],             noafs, [rmr]         , {w8:(0,0),sw:(0,1)},{}                , {},                         )
+
+        #addop("scas",  [0xAE],             noafs, no_rm         , {w8:(0,0)}         ,{}                , {},                         )
+        addop("scasb", [0xAE],             noafs, no_rm         , {}                 ,{w8:True}         , {},                         )
+        addop("scasd", [0xAF],             noafs, no_rm         , {}                 ,{w8:False}        , {},                         )
+
+
+        addop("set",   [0x0F, 0x90],       cond , [rmr]         , {}                 ,{w8:True}         , {},                         )
+
+        addop("qfence",[0x0F, 0xAE],       d7   , no_rm         , {}                 ,{}                , {},                         )
+        addop("sgdt",  [0x0F, 0x01],       d0   , no_rm         , {}                 ,{}                , {},                         )
+
+        addop("shld",  [0x0F, 0xA4],       noafs, [rmr, u08]    , {}                 ,{sw:True}         , {},                         )
+        addop("shld_cl",[0x0F, 0xA5],      noafs, [rmr]         , {}                 ,{sw:True}         , {},                         )
+        addop("shrd",  [0x0F, 0xAC],       noafs, [rmr, u08]    , {}                 ,{sw:True}         , {},                         )
+        addop("shrd_cl",[0x0F, 0xAD],      noafs, [rmr]         , {}                 ,{sw:True}         , {},                         )
+
+        addop("sidt",  [0x0F, 0x01],       d1   , no_rm         , {}                 ,{}                , {},                         )
+        addop("sldt",  [0x0F, 0x00],       d0   , no_rm         , {}                 ,{}                , {},                         )
+        addop("smsw",  [0x0F, 0x01],       d4   , no_rm         , {}                 ,{}                , {},                         )
+        addop("stc",   [0xF9],             noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("std",   [0xFD],             noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("sti",   [0xFB],             noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("stmxcsr",[0x0F, 0xAE],      d3   , no_rm         , {}                 ,{}                , {},                         )
+
+        #addop("stos",  [0xAA],             noafs, [r_eax]       , {w8:(0,0)}         ,{}                , {},                         )
+        addop("stosb", [0xAA],             noafs, no_rm         , {}                 ,{w8:True}         , {},                         )
+        addop("stosd", [0xAB],             noafs, no_rm         , {}                 ,{w8:False}        , {},                         )
+
+        addop("str",   [0x0F, 0x00],       d1   , no_rm         , {}                 ,{}                , {},                         )
+
+        addop("sub",   [0x2C],             noafs, [r_eax,imm]   , {w8:(0,0)}         ,{}                , {},                         )
+        addop("sub",   [0x80],             d5,    [imm]         , {w8:(0,0),se:(0,1)},{}                , {},                         )
+        addop("sub",   [0x28],             noafs, [rmr]         , {w8:(0,0),sw:(0,1)},{}                , {},                         )
+
+        """                                                                                             , {}
+        #XXX dup opcode => modrm encoding                                                               , {}
+        addop("swapgs",[0x0F, 0x01],       d7   , no_rm         , {}                 ,{}                , {},                         )
+        """                                                                                             , {}
+        addop("syscall",[0x0F, 0x05],      noafs, no_rm         , {}                 ,{}                , {bkf:True},                         )
+        addop("sysenter",[0x0F, 0x34],     noafs, no_rm         , {}                 ,{}                , {bkf:True},                         )
+        addop("sysexit",[0x0F, 0x35],      noafs, no_rm         , {}                 ,{}                , {bkf:True},                         )
+        addop("sysret",[0x0F, 0x07],       noafs, no_rm         , {}                 ,{}                , {bkf:True},                         )
+
+        addop("test",  [0xA8],             noafs, [r_eax,imm]   , {w8:(0,0)}         ,{}                , {},                         )
+        addop("test",  [0xF6],             d0,    [imm]         , {w8:(0,0)}         ,{}                , {},                         )
+        addop("test",  [0x84],             noafs, [rmr]         , {w8:(0,0)}         ,{sw:True}         , {},                         )
+
+        addop("ud2",   [0x0F, 0x0B],       noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("verr",  [0x0F, 0x00],       d4   , no_rm         , {}                 ,{}                , {},                         )
+        addop("verw",  [0x0F, 0x00],       d5   , no_rm         , {}                 ,{}                , {},                         )
+        #ddop("wait",  [0x9B],             noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("wbinvd",[0x0F, 0x09],       noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("wrmsr", [0x0F, 0x30],       noafs, no_rm         , {}                 ,{}                , {},                         )
+
+        addop("xadd",  [0x0F, 0xC0],       noafs, [rmr]         , {w8:(1,0)}         ,{}                , {},                         )
+
+        addop("xchg",  [0x90],             reg  , [r_eax]       , {}                 ,{}                , {},                         )
+
+        addop("nop",   [0x90],             noafs, no_rm         , {}                 ,{}                , {},                         )
+
+        addop("xchg",  [0x86],             noafs, [rmr]         , {w8:(0,0)}         ,{}                , {},                         )
+
+        addop("xlat",  [0xD7],             noafs, no_rm         , {}                 ,{}                , {},                         )
+
+        addop("xor",   [0x34],             noafs, [r_eax,imm]   , {w8:(0,0)}         ,{}                , {},                         )
+        addop("xor",   [0x80],             d6,    [imm]         , {w8:(0,0),se:(0,1)},{}                , {},                         )
+        addop("xor",   [0x30],             noafs, [rmr]         , {w8:(0,0),sw:(0,1)},{}                , {},                         )
+
+        addop("monitor",[0x0F, 0x01, 0xC8],noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("mwait", [0x0F, 0x01, 0xC9], noafs, no_rm         , {}                 ,{}                , {},                         )
+
+        #x87 fpu                                                                                        , {}
+        addop("f2xm1", [0xD9, 0xF0],       noafs, no_rm         , {}                 ,{}                , {},                         )
+        addop("fabs",  [0xD9, 0xE1],       noafs, no_rm         , {}                 ,{}                , {},                         )
+
+        addop("fadd",  [0xD8],             d0,    no_rm         , {sd:(0,2)}         ,{}         , {},                         )
+        addop("fadd",  [0xD8, 0xC0],       reg,   [r_eax]       , {sw:(0,2)}         ,{sd:False,sw:False},{},                         )
+        addop("fiadd", [0xDA],             d0,    no_rm         , {wd:(0,2)}         ,{}                , {},                         )
+        addop("faddp", [0xDE, 0xC0],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+
+        addop("fbld",  [0xDF],             d4,    no_rm         , {}                 ,{}                , {},                         )
+        addop("fbstp", [0xDF],             d6,    no_rm         , {}                 ,{}                , {},                         )
+
+        addop("fchs",  [0xD9, 0xE0],       noafs, no_rm         , {}                 ,{}                , {},                         )
+        #ddop("fclex", [0x9B, 0xDB, 0xE2], noafs, no_rm         , {}                 ,{}                , {},                         ) #XXX no mnemo
+        addop("fnclex",[0xDB, 0xE2],       noafs, no_rm         , {}                 ,{}                , {},                         )
+
+        addop("fcmovb",[0xDA, 0xC0],       reg,   [r_eax]       , {}                 ,{}                , {},                         )
+        addop("fcmove",[0xDA, 0xC8],       reg,   [r_eax]       , {}                 ,{}                , {},                         )
+        addop("fcmovbe",[0xDA, 0xD0],      reg,   [r_eax]       , {}                 ,{}                , {},                         )
+        addop("fcmovu",[0xDA, 0xD8],       reg,   [r_eax]       , {}                 ,{}                , {},                         )
+        addop("fcmovnb",[0xDB, 0xC0],      reg,   [r_eax]       , {}                 ,{}                , {},                         )
+        addop("fcmovne",[0xDB, 0xC8],      reg,   [r_eax]       , {}                 ,{}                , {},                         )
+        addop("fcmovnbe",[0xDB, 0xD0],     reg,   [r_eax]       , {}                 ,{}                , {},                         )
+        addop("fcmovnu",[0xDB, 0xD8],      reg,   [r_eax]       , {}                 ,{}                , {},                         )
+
+        addop("fcom",  [0xD8],             d2,    no_rm         , {sd:(0,2)}         ,{}                , {},                         )
+        addop("fcom",  [0xD8, 0xD0],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fcomp", [0xD8],             d3,    no_rm         , {sd:(0,2)}         ,{}                , {},                         )
+        addop("fcomp", [0xD8, 0xD8],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fcompp",[0xDE, 0xD9],       noafs, no_rm         , {}                 ,{}                , {},                         )
+
+        addop("fcomi", [0xDB, 0xF0],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fcomip",[0xDF, 0xF0],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fucomi",[0xDB, 0xE8],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fucomi",[0xDF, 0xE8],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+
+        addop("ficom", [0xDA],             d2,    no_rm         , {wd:(0,2)}         ,{}                , {},                         )
+        addop("ficomp",[0xDA],             d3,    no_rm         , {wd:(0,2)}         ,{}                , {},                         )
+
+
+        addop("fdiv",  [0xD8],             d6,    no_rm         , {sd:(0,2)}         ,{}                , {},                         )
+        addop("fdiv",  [0xD8, 0xF0],       reg,   [r_eax]       , {sw:(0,2)}         ,{sd:False,sw:False},{},                         )
+        addop("fidiv", [0xDA],             d6,    no_rm         , {wd:(0,2)}         ,{}                , {},                         )
+        addop("fdivp", [0xDE, 0xF8],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+
+        addop("fdivr", [0xD8],             d7,    no_rm         , {sd:(0,2)}         ,{}                , {},                         )
+        addop("fdivr", [0xD8, 0xF8],       reg,   [r_eax]       , {sw:(0,2)}         ,{sd:False,sw:False},{},                         )
+        addop("fidivr",[0xDA],             d7,    no_rm         , {wd:(0,2)}         ,{}                , {},                         )
+        addop("fdivrp",[0xDE, 0xF0],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+
+        addop("ffree", [0xDD, 0xC0],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+
+        addop("fwait", [0x9B],             noafs, no_rm         , {}                 ,{}                , {},                         )
+
+        addop("fild",  [0xDB],             d0,    no_rm         , {wd:(0,2)}         ,{wd:False}        , {},                         )
+        addop("fild",  [0xDF],             d5,    no_rm         , {}                 ,{sd:True,wd:False}, {},                         ) #XXX 64
+
+        addop("fincstp",[0xD9, 0xF7],      noafs, no_rm         , {}                 ,{}                , {},                         )
+
+        #ddop("finit", [0x9B, 0xDB, 0xE3], noafs, no_rm         , {}                 ,{}                , {},                         ) #XXX no mnemo
+        addop("fninit",[0xDB, 0xE3],       noafs, no_rm         , {}                 ,{}                , {},                         )
+
+        addop("fist",  [0xDB],             d2,    no_rm         , {wd:(0,2)}         ,{wd:False}        , {},                         )
+        addop("fistp", [0xDB],             d3,    no_rm         , {wd:(0,2)}         ,{wd:False}        , {},                         )
+        addop("fistp", [0xDF],             d7,    no_rm         , {}                 ,{sd:False}        , {},                         ) #XXX 64
+        addop("fisttp",[0xDB],             d1,    no_rm         , {wd:(0,2)}         ,{wd:False}        , {},                         )
+        addop("fisttp",[0xDD],             d1,    no_rm         , {}                 ,{sd:False}        , {},                         ) #XXX 64
+
+
+
+        addop("fmul",  [0xD8],             d1,    no_rm         , {sd:(0,2)}         ,{}                , {},                         )
+        addop("fmul",  [0xD8, 0xC8],       reg,   [r_eax]       , {sw:(0,2)}         ,{sd:False,sw:False},{},                         )
+        addop("fimul", [0xDA],             d1,    no_rm         , {wd:(0,2)}         ,{}                , {},                         )
+        addop("fmulp", [0xDE, 0xC8],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+
+
+        addop("frstor",[0xDD],             d4,    no_rm         , {}                 ,{wd:False}        , {},                         ) #XXX 94/108
+
+        #ddop("fsave", [0x9B, 0xDD],       d6,    no_rm         , {}                 ,{wd:False}        , {},                         ) #XXX no mnemo
+        addop("fnsave",[0xDD],             d6,    no_rm         , {}                 ,{wd:False}        , {},                         ) #XXX 94/108
+
+
+        addop("fst",   [0xD9],             d2,    no_rm         , {sd:(0,2)}         ,{}                , {},                         )
+        addop("fst",   [0xDD, 0xD0],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fstp",  [0xD9],             d3,    no_rm         , {sd:(0,2)}         ,{sd:True}                , {},                         )
+        addop("fstp",  [0xDB],             d7,    no_rm         , {}                 ,{sd:False}        , {},                         ) #XXX 80
+        addop("fstp",  [0xDD, 0xD8],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+
+        #ddop("fstcw", [0x9B, 0xD9],       d7,    no_rm         , {}                 ,{wd:False}        , {},                         ) #XXX no mnemo
+        addop("fnstcw",[0xD9],             d7,    no_rm         , {}                 ,{wd:True}         , {},                         ) 
+        #ddop("fstenv",[0x9B, 0xD9],       d6,    no_rm         , {}                 ,{wd:False}        , {},                         ) #XXX no mnemo
+        addop("fnstenv",[0xD9],            d6,    no_rm         , {}                 ,{wd:False}        , {},                         ) 
+
+        addop("fnop",  [0xD9, 0xD0],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+
+        addop("fpatan",[0xD9, 0xF3],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fprem", [0xD9, 0xF8],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fprem1",[0xD9, 0xF5],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fptan", [0xD9, 0xF2],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("frndint",[0xD9, 0xFC],      noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+
+        addop("fscale",[0xD9, 0xFD],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fsin",  [0xD9, 0xFE],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fsincos",[0xD9, 0xFB],      noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fsqrt", [0xD9, 0xFA],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+
+        addop("fcos",  [0xD9, 0xFF],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fdecstp",[0xD9, 0xF6],      noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+
+        addop("fld",   [0xD9],             d0,    no_rm         , {sd:(0,2)}         ,{}                , {},                         )
+        addop("fld",   [0xDB],             d5,    no_rm         , {}                 ,{sd:False}        , {},                         ) #XXX 80
+        addop("fld",   [0xD9, 0xC0],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+
+        addop("fldcw", [0xD9],             d5,    no_rm         , {}                 ,{wd:True}         , {},                         ) 
+        addop("fldenv",[0xD9],             d4,    no_rm         , {}                 ,{wd:False}        , {},                         ) 
+
+        addop("fld1",  [0xD9, 0xE8],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fldl2t",[0xD9, 0xE9],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fldl2e",[0xD9, 0xEA],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fldpi", [0xD9, 0xEB],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fldlg2",[0xD9, 0xEC],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fldln2",[0xD9, 0xED],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fldz",  [0xD9, 0xEE],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+
+
+        #ddop("fstsw", [0x9B, 0xDD],       d7,    no_rm         , {}                 ,{wd:False}        , {},                         ) #XXX no mnemo
+        addop("fnstsw",[0xDD],             d7,    no_rm         , {}                 ,{wd:True}         , {},                         ) 
+        #ddop("fstsw",[0x9B, 0xDF, 0xE0],  noafs, no_rm         , {}                 ,{wd:False}        , {},                         ) #XXX no mnemo
+        addop("fnstsw",[0xDF, 0xE0],       noafs, no_rm         , {}                 ,{wd:False}        , {},                         ) 
+
+        addop("fsub",  [0xD8],             d4,    no_rm         , {sd:(0,2)}         ,{}                , {},                         )
+        addop("fsub",  [0xD8, 0xE0],       reg,   [r_eax]       , {sw:(0,2)}         ,{sd:False,sw:False},{},                         )
+        addop("fisub", [0xDA],             d4,    no_rm         , {wd:(0,2)}         ,{}                , {},                         )
+        addop("fsubp", [0xDE, 0xE8],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+
+        addop("fsubr", [0xD8],             d5,    no_rm         , {sd:(0,2)}         ,{}                , {},                         )
+        addop("fsubr", [0xD8, 0xE8],       reg,   [r_eax]       , {sw:(0,2)}         ,{sd:False,sw:False},{},                         )
+        addop("fisubr",[0xDA],             d5,    no_rm         , {wd:(0,2)}         ,{}                , {},                         )
+        addop("fsubrp",[0xDE, 0xE0],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+
+        addop("ftst",  [0xD9, 0xE4],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         ) 
+
+        addop("fucom", [0xDD, 0xE0],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fucomp",[0xDD, 0xE8],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fucompp",[0xDA, 0xE9],      noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+
+        addop("fxam",  [0xD9, 0xE5],       noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fxch",  [0xD9, 0xC8],       reg,   no_rm         , {}                 ,{sd:False}        , {},                         )
+
+        addop("fxrstor",[0x0f, 0xAE],      d1,    no_rm         , {}                 ,{sd:False}        , {},                         ) #XXX 512
+        addop("fxrsave",[0x0f, 0xAE],      d0,    no_rm         , {}                 ,{sd:False}        , {},                         ) #XXX 512
+        addop("fxtract",[0xD9, 0xF4],      noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fyl2x",  [0xD9, 0xF1],      noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        addop("fyl2xp1",[0xD9, 0xF9],      noafs, no_rm         , {}                 ,{sd:False}        , {},                         )
+        pm = self.db_mnemo[0x9c]
+        self.pushfw_m = mnemonic(pm.name, pm.opc, pm.afs, pm.rm, pm.modifs, pm.modifs_orig, None)#, pm.sem)
+        self.pushfw_m.name = "pushfw"
+        
+    
+
+x86mndb = x86allmncs()
+
+class x86_mnemo_metaclass(type):
+    rebuilt_inst = True
+
+    def dis(cls, op, admode = u32, opmode = u32, sex = 0):
+        i = cls.__new__(cls)
+        i.__init__(admode, opmode, sex)
+        i.size_op = opmode
+        i.size_ad = admode
+        u = i._dis(op)
+        if not u:
+            return None
+        #XXX error in scasd mnemo 16 bit
+        if i.m.name == "scasd":
+            if i.size_op == u16:
+                i.m.name = "scasw"
+            
+        return i
+    def asm(cls, l, symbol_off = []):
+        i = cls.__new__(cls)
+        i.__init__(admode = u32, opmode = u32, sex = 0)
+        return i._asm(l, symbol_off)
+        
+
+    def has_symb(cls, a):
+        if type(a) in [int, long]+tab_int_size.keys():
+            return False
+        if x86_afs.symb in a:
+            return True
+        return False
+    
+    def fix_symbol(cls, a, symbol_pool = None):
+        if type(a) in [int, long]+tab_int_size.keys():
+            return a
+    
+        cp = dict(a)
+        if not x86_afs.symb in cp:
+            return cp
+    
+        if not symbol_pool:
+            del cp[x86_afs.symb]
+            if not x86_afs.imm in cp:
+                cp[x86_afs.imm] = 0
+            return cp
+    
+        imm_total = 0
+        if x86_afs.imm in cp:
+            imm_total+=cp[x86_afs.imm]
+        for s in cp[x86_afs.symb]:
+            base_ad = symbol_pool.s['base_address'].offset_g
+            imm_total+=cp[x86_afs.symb][s]*(symbol_pool.s[s.name].offset_g+base_ad)
+    
+        cp[x86_afs.imm] = imm_total
+        del cp[x86_afs.symb]
+        
+    
+        return cp
+
+    def is_mem(cls, a):
+        return x86_afs.ad in a and a[x86_afs.ad]
+
+    def get_label(cls, a):
+        if not x86_afs.symb in a:
+            return None
+        n = a[x86_afs.symb]
+        if len(n)!=1:
+            return None
+        k = n.keys()[0]
+        if n[k] != 1:
+            return None
+        return k
+        
+    def get_symbols(cls, a):
+        if not x86_afs.symb in a:
+            return None
+        return a[x86_afs.symb].items()
+    def set_symbols(cls, a, s):
+        print a, s
+    def names2symbols(cls, a, s_dict):
+        all_s = a[x86_afs.symb]
+        for name, s in s_dict.items():
+            count = all_s[name]
+            del(all_s[name])
+            all_s[s] = count
+            
+
+class x86_mn:
+    __metaclass__ = x86_mnemo_metaclass
+    def __init__(self, admode = u32, opmode = u32, sex = 0):
+        self.admode = admode
+        self.opmode = opmode
+        self.mnemo_mode = self.admode
+
+        self.size_op = u32
+        self.size_ad = u32
+
+    @classmethod
+    def prefix2hex(self, prefix):
+        return reduce(lambda x,y:x+chr(y), prefix, "")
+
+
+    def breakflow(self):
+        return self.m.modifs[bkf]
+    def splitflow(self):
+        return self.m.modifs[spf]
+    def dstflow(self):
+        return self.m.modifs[dtf]
+
+    def getnextflow(self):
+        return self.offset+self.l
+
+    def getdstflow(self):
+        if len(self.arg) !=1:
+            print ValueError('should be 1 arg %s'%str(self))
+            return []
+        a = self.arg[0]
+        if is_imm(a) and not x86_afs.symb in a:
+            dst = (self.offset+self.l+a[x86_afs.imm])&0xFFFFFFFF
+            out = [dst]
+        else:
+            out = [a]
+        return out
+    
+    def setdstflow(self, dst):
+        if len(self.arg) !=1:
+            print ValueError('should be 1 arg %s'%str(self))
+            return
+        if len(dst)==0:
+            return
+        if len(dst)!=1:
+            raise ValueError('should be 1 dst')
+        l = dst[0]
+        
+        #patch only known symbols
+        if l.offset !=None:
+            self.arg = [{x86_afs.symb:{l:1}}]
+        
+    def fixdst(self, lbls, my_offset, is_mem):
+        if len(self.arg) !=1:
+            raise ValueError('should be 1 arg %s'%str(self))
+        a = self.arg[0]
+        l = a[x86_afs.symb].keys()[0]
+        offset = lbls[l.name]
+        if is_mem:
+            arg = {x86_afs.ad:is_mem, x86_afs.imm:offset}
+        else:
+            arg = {x86_afs.imm:offset-(my_offset)}
+
+        self.arg = [arg]
+
+    def is_subcall(self):
+        return self.m.name == 'call'
+            
+    def __str__(self):
+        if type(self.instr_string) is str:
+            return self.instr_string
+
+        args_str = ""
+        for p in self.prefix:
+            if p in prefix_dic_inv:
+                args_str += prefix_dic_inv[p]+" "
+        args_str+="%-10s"%(self.m.name)
+        
+        for a in self.arg:
+            if type(a) in [int, long]:
+                raise ValueError("should be intsized %s"%str(a))
+            if type(a) in tab_int_size:
+                raise ValueError("should be dict.. %s"%str(a))
+            elif type(a) == dict:
+                args_str+="%s, "%dict_to_ad(a, self.m.modifs, self.mnemo_mode)
+            else:
+                raise ValueError("arg zarbi %s"%str(a))
+        return args_str[:-2]
+
+    def intsize(self, im, ext = False):
+        if ext:
+            return [uint16, uint32][self.mnemo_mode == u32](im)
+        if self.m.modifs[w8]:
+            return uint8(im)
+        if self.mnemo_mode == u32:
+            return uint32(im)
+        elif self.mnemo_mode == u16:
+            return uint16(im)
+        else:
+            raise ValueError('unknown mnemo mode %s'%str(im))
+            
+    def _dis(self, bin):
+        size_op = self.size_op
+        size_ad = self.size_ad
+
+        
+        
+        if type(bin) == str:
+            from miasm.core.bin_stream import bin_stream
+
+            bin = bin_stream(bin)
+        
+        init_offset = bin.offset
+
+        try:
+            #find mnemonic
+            l = x86mndb.db_mnemo
+            index = 0
+            m = None
+            read_prefix = []
+            prefix_done =False
+            while True:
+                c = ord(bin.readbs())
+                if not prefix_done and c in x86_afs.x86_prefix:
+                    read_prefix.append(c)
+                    continue
+                else:
+                    prefix_done = True
+                if l[c] == None:
+                    log.debug( "unknown mnemo")
+                    break
+                if isinstance(l[c] ,mnemonic):
+                    m = l[c]
+                    break
+                if type(l[c]) == list:
+                    l = l[c]
+                    
+            if m == None:
+                return None
+            self.m = m
+    
+            log.debug(m)
+            log.debug("prefix: %s"%str(read_prefix))
+
+            self.mnemo_mode = self.admode
+            if 0x66 in read_prefix:
+                self.mnemo_mode = [u16,u32][self.mnemo_mode==u16]
+                self.size_op = [u16,u32][size_op == u16]
+            if 0x67 in read_prefix:
+                self.size_ad = [u16,u32][size_ad == u16]
+                
+
+            
+            #parse mnemonic args
+            mnemo_args = []
+
+            afs, dibs = m.afs, m.rm
+            modrm = None
+            #digit 
+            if afs in [d0, d1, d2, d3, d4, d5, d6, d7]:
+                re, modr = x86mndb.get_afs(bin, c, self.size_ad)
+                mnemo_args.append(modr)
+                mnemo_args[-1][x86_afs.size] = self.mnemo_mode
+
+                if m.modifs[sd] is not None:
+                    if m.modifs[sd]:
+                        mnemo_args[-1][x86_afs.size] = x86_afs.f32
+                    else:
+                        mnemo_args[-1][x86_afs.size] = x86_afs.f64
+                    
+                if m.modifs[w8]:
+                    mnemo_args[-1][x86_afs.size] = x86_afs.u08
+                if m.modifs[wd]:
+                    #XXX check (for fnst??)=
+                    mnemo_args[-1][x86_afs.size] = x86_afs.u16
+            #+reg
+            elif afs == reg:
+                mafs = dict(x86mndb.get_afs_re(c&(0xFF^mask_reg)))
+                if m.modifs[w8]:
+                    mafs[x86_afs.size] = x86_afs.u08
+                else:
+                    mafs[x86_afs.size] = self.mnemo_mode
+                
+                mnemo_args.append(mafs)
+            #rm mod
+            elif afs in [noafs, cond]:
+                if rmr in m.rm:
+                    c = ord(bin.readbs())
+                    re, modr = x86mndb.get_afs(bin, c, self.size_ad)
+
+                    reg_cat = 0
+                    if m.modifs[dr]:
+                        reg_cat+=0x8
+                    if m.modifs[cr]:
+                        reg_cat+=0x10
+                    if m.modifs[sg]:
+                        reg_cat+=0x20
+                    mafs = dict(x86mndb.get_afs_re(re+reg_cat))
+                    if m.modifs[w8]:
+                        mafs[x86_afs.size] = x86_afs.u08
+                    else:
+                        mafs[x86_afs.size] = self.mnemo_mode
+                    
+                    mnemo_args.append(mafs)
+                    mnemo_args.append(modr)
+                    
+
+                    mnemo_args[-1][x86_afs.size] = self.mnemo_mode
+                    if m.modifs[w8] :
+                        mnemo_args[-1][x86_afs.size] = x86_afs.u08
+                    if m.modifs[se] !=None and not (imm in dibs or ims in dibs):
+                        mnemo_args[-1][x86_afs.size] = [x86_afs.u08, x86_afs.u16][m.modifs[se]]
+                        
+
+                    if m.modifs[wd]:
+                        mnemo_args[-1][x86_afs.size] = x86_afs.u16
+                        mnemo_args[-2][x86_afs.size] = x86_afs.u16
+                    if m.modifs[sg]:
+                        mnemo_args[-2][x86_afs.size] = x86_afs.size_seg
+                    if afs == cond and m.name.startswith('set'):
+                        mnemo_args.pop(0)
+                        
+                        
+            elif afs == cond:
+                pass
+            else:
+                raise ValueError('bug in %s %d'%(name, afs))
+
+            #swap args?
+            if m.modifs[sw]:
+                mnemo_args.reverse()
+                
+
+            dib_out = []
+            for dib in dibs:
+                #unsigned
+                log.debug(m.modifs)
+                if dib in [u08, s08, u16, s16, u32, s32]:
+                    if self.mnemo_mode !=u32:
+                        if dib == u32:
+                            dib = u16
+                        if dib == s32:
+                            dib = s16
+                    l = struct.calcsize(x86_afs.dict_size[dib])
+                    d = struct.unpack(x86_afs.dict_size[dib], bin.readbs(l))[0]
+                    d = self.intsize(d)
+                    
+                    dib_out.append({x86_afs.imm:d})
+                elif dib in [imm, ims]:
+                    taille, fmt, t = x86mndb.get_im_fmt(m.modifs, self.mnemo_mode, dib)
+                    dib_out.append({x86_afs.imm:self.intsize(struct.unpack(fmt, bin.readbs(taille))[0], dib==ims)})
+                    
+                elif dib in [im1, im3]:
+                    dib_out.append({im1:{x86_afs.imm:self.intsize(1)},im3:{x86_afs.imm:self.intsize(3)}}[dib])
+                elif dib == rmr:
+                    continue
+                elif dib == r_eax:
+                    mafs = dict(x86mndb.get_afs_re(x86_afs.reg_dict[x86_afs.r_eax]))
+                    if m.modifs[w8]:
+                        mafs[x86_afs.size] = x86_afs.u08
+                    else:
+                        mafs[x86_afs.size] = self.mnemo_mode
+
+                    r = mafs
+
+                    if len(mnemo_args):
+                        if m.modifs[sw]:
+                            mnemo_args = mnemo_args+[r]
+                        else:
+                            mnemo_args = [r]+mnemo_args
+                        
+                    else:
+                        dib_out.append(r)                    
+
+                elif dib == mim:
+                    l = struct.calcsize(x86_afs.dict_size[self.size_ad])
+                    d = struct.unpack(x86_afs.dict_size[self.size_ad], bin.readbs(l))[0]
+                    d = uint32(d)
+
+                    
+                    size = [self.mnemo_mode, x86_afs.u08][m.modifs[w8]]
+                    dib_out.append({x86_afs.ad:True, x86_afs.size:size, x86_afs.imm:d})
+                elif dib in [r_cl, r_dx]:
+                    dib_out.append(dib)                    
+                    pass
+
+                    
+                else:
+                    raise ValueError('bad dib!!%X'%dib)
+
+            mnemo_args+=dib_out
+
+            for a in mnemo_args:
+                for p in read_prefix:
+                    if is_address(a) and p in prefix_seg.values():
+                        a[x86_afs.segm]=prefix_seg_inv[p]
+                        continue
+                        
+                    
+
+            t_len = bin.offset-init_offset
+            bin.offset = init_offset
+            bytes_ret = bin.readbs(t_len)
+            self.offset = init_offset
+            self.instr_string = None
+            self.l = t_len
+            self.b = bytes_ret
+            self.m = m
+            self.arg = mnemo_args
+            self.prefix = read_prefix
+
+            #XXX hack
+            if 0x66 in read_prefix and self.m.name == "pushfd":
+                self.m = x86mndb.pushfw_m
+            if 0x66 in read_prefix and self.m.name == "lodsd":
+                self.m.name = "lodsw"
+            if 0x66 in read_prefix and self.m.name == "stosd":
+                self.m.name = "stosw"
+            if 0x66 in read_prefix and self.m.name == "movsd":
+                self.m.name = "movsw"
+                
+            return True
+
+    
+        except IOError:
+            log.warning( "cannot dis: not enougth bytes")
+            return None
+
+    @classmethod
+    def parse_mnemo(self, l):
+        tokens = [t for t in shlex.shlex(l)]
+        prefix = []
+        if not tokens:
+            raise ValueError('cannot parse mnemo?', l)
+        while True:
+            name = tokens[0]
+            tokens = tokens[1:]
+    
+            if name in prefix_dic:
+                prefix.append(name)
+                continue
+            break
+        
+        args = []
+        arg = []
+        s = ','
+        while s in tokens:
+            i = tokens.index(s)
+            args.append(tokens[:i])
+            tokens = tokens[i+1:]
+        args.append(tokens)
+        args = map(lambda x: reduce(lambda x,y: x+' '+y, x, ""), args)
+    
+        if args == ['']:
+            return prefix, name, []
+
+        for a in args:
+            if x86_afs.segm in a:
+                prefix.append(x86_afs.reg_sg.index(a[x86_afs.segm]))
+            
+        return prefix, name, args
+
+    @classmethod
+    def parse_address(self, a):
+        return parse_ad(a)
+        
+    def asm_parse(self, l):
+        log.debug("asm: %s"%l)
+
+        prefix, name, args = x86_mn.parse_mnemo(l)
+        prefix = [prefix_dic[x] for x in prefix]
+
+        log.debug("name: %s"%name)
+        log.debug("args: %s"%str(args))
+
+        args_eval = []
+        for a in args:
+            args_eval.append(x86_mn.parse_address(a))
+            if x86_afs.segm in args_eval[-1]:
+                prefix.append(prefix_seg[args_eval[-1][x86_afs.segm]])
+                del args_eval[-1][x86_afs.segm]
+
+            #XXX test if symbol in arg and replace with imm... for pre asm
+            if x86_afs.symb in args_eval[-1]:
+                log.debug('pre-assembling with symbol! %s'%str(args_eval[-1][x86_afs.symb]))
+                if not x86_afs.imm in args_eval[-1]:
+                    args_eval[-1][x86_afs.imm] = 0
+                    
+                del args_eval[-1][x86_afs.symb]
+            
+        log.info("prefix:%s"%str(prefix))        
+        log.info('eval: %s'%str(args_eval))
+
+        
+
+        #search all candidates
+        log.debug('Find mnemo')
+        candidate = x86mndb.find_mnemo(name)
+        if not candidate:
+            log.warning("no mnemonic found")
+
+        can_be_16_32 = True
+        log.debug("candi:")
+        for c in candidate:
+            if c.modifs[sd] or c.modifs[wd]:
+                can_be_16_32 = False
+            log.debug( c)
+
+
+
+
+        #test for 16/32 bit mode
+        if can_be_16_32:
+            self.mnemo_mode = None
+            for a in args_eval:
+                #32 priority
+                if (is_reg(a)) and a[x86_afs.size] == u32:
+                    self.mnemo_mode = u32
+                    break
+
+                #XXX if eax, cx .... 32 bit bug
+                if (is_reg(a) or is_address(a)) and a[x86_afs.size] == u16 and self.mnemo_mode == None:
+                    self.mnemo_mode = u16
+                    break
+
+    
+            if self.mnemo_mode == None:
+                self.mnemo_mode = u32
+    
+            if self.mnemo_mode == u16:
+                log.debug("16 bit mode detected for %s"%str(l))
+                prefix.append(0x66)
+                if  name in ["movzx", "movsx"]:
+                    if args_eval[0][x86_afs.size] == u16:
+                        args_eval[0][x86_afs.size] = u32
+                        if args_eval[0][x86_afs.ad]:
+                            args_eval[0][x86_afs.ad] = u32
+                else:
+                        
+                    for a in args_eval:
+                        if a[x86_afs.size] == u16:
+                            a[x86_afs.size] = u32
+                            if a[x86_afs.ad]:
+                                a[x86_afs.ad] = u32
+                            
+        else:
+            self.mnemo_mode = u32
+                  
+        log.info('eval2: %s'%str(args_eval))
+
+        modifs = dict([[x, None] for x in [w8, se, sw, ww, sg, dr, cr, ft, w64, sd, wd]])
+        modifs[sw] = False
+
+
+        #spot dr/cr regs
+        for a in args_eval:
+            for x in a:
+                if type(x) in [int, long] and x>=0x100:
+                    tmp = a[x]
+                    for y in mask_drcrsg:
+                        if x & mask_drcrsg[y]:
+                            modifs[y] = True
+                    
+
+        candidate_out = []
+        for c in candidate:
+
+            if (modifs[cr] or c.modifs[cr]) and modifs[cr] != c.modifs[cr]:
+                continue
+            if (modifs[dr] or c.modifs[dr]) and modifs[dr] != c.modifs[dr]:
+                continue
+
+            if (modifs[sg] or c.modifs[sg]) and modifs[sg] != c.modifs[sg]:
+                continue
+            
+
+            args_sample = [dict(x) for x in args_eval]
+
+            afs, dibs = c.afs, c.rm
+            log.debug(c)
+
+            parsed_args = []
+            parsed_val = [{}]
+            out_opc = [c.opc[:]]
+            opc_add = []
+
+            good_c = True
+            dib_out = []
+            for dib in dibs:
+                if dib in [u08, s08, u16, s16, u32, s32]:
+                    index_im = [-1, 0][afs == noafs]
+                    
+                    if len(args_sample)<=0:
+                        good_c = False
+                        break
+                    if not x86_afs.imm in args_sample[index_im] or args_sample[index_im][x86_afs.ad]:
+                        log.debug("not imm 1")
+                        good_c = False
+                        break
+
+                    
+                    if self.mnemo_mode !=u32:
+                        if dib == u32:
+                            dib = u16
+                        if dib == s32:
+                            dib = s16
+
+                    size = dib
+
+                    v = check_imm_size(args_sample[index_im][x86_afs.imm], size)
+                    if v == None:
+                        log.debug("cannot encode this val in size %s %x!"%(size, args_sample[index_im][x86_afs.imm]))
+                        good_c= False
+                        break
+
+                    args_sample[index_im][x86_afs.size] = size
+                    args_sample[index_im][x86_afs.imm] = tab_size2int[size](v)
+                    
+
+                    opc_add.append({x86_afs.size:size, x86_afs.imm:args_sample[index_im][x86_afs.imm]})
+                    r = args_sample[index_im]
+                    del args_sample[index_im]
+                    dib_out.append(r)
+                    
+                elif dib in [im1, im3]:
+                    if x86_afs.imm in args_sample[-1] and args_sample[-1][x86_afs.imm] =={im1:1,im3:3}[dib]:
+                        dib_out.append(args_sample.pop())
+                    else:
+                        log.debug("not im val fixed")
+                        good_c = False
+                        break
+                    
+                elif dib in [imm, ims]:
+                    if len(args_sample)<=0:
+                        good_c = False
+                        break
+                    if not x86_afs.imm in args_sample[-1] or args_sample[-1][x86_afs.ad]:
+                        log.debug("not imm 2")
+                        good_c = False
+                        break
+                    taille, fmt, t = x86mndb.get_im_fmt(c.modifs, self.mnemo_mode, dib)
+                    r = args_sample.pop()
+                    v = check_imm_size(r[x86_afs.imm], t)
+                    if v == None:
+                        log.debug("cannot encode this val in size %s %x!"%(t, int(r[x86_afs.imm])))
+                        good_c= False
+                        break
+                    r[x86_afs.imm] = tab_size2int[t](v)
+                    opc_add.append({x86_afs.size:t, x86_afs.imm:r[x86_afs.imm]})
+
+                    if c.modifs[se]:
+                        r[x86_afs.size] = r[x86_afs.size]
+                        r[x86_afs.imm] = tab_size2int[r[x86_afs.size]](r[x86_afs.imm])
+                    dib_out.append(r)
+
+
+
+                elif dib == rmr:
+                    continue
+                elif dib == r_eax:
+                    if not args_sample or args_sample[0][x86_afs.ad]:
+                        log.debug("not r_eax1")
+                        good_c = False
+                        break
+                    size = args_sample[0][x86_afs.size]
+                
+                    if not x86mndb.check_size_modif(size, c.modifs):
+                        log.debug(' bad reg size')
+                        good_c = False
+                        break
+                    if c.modifs[sw]:
+                        index = 1
+                        if len(args_sample) !=2:
+                            raise ValueError("sw in r_eax zarb")
+                    else:
+                        index = 0
+                    if not x86_afs.reg_dict[x86_afs.r_eax] in args_sample[index]:
+                        log.debug("not r_eax2")
+                        good_c = False
+                        break
+                    #add front
+                    if size == x86_afs.u32:
+                        args_sample[index][x86_afs.size] = self.mnemo_mode
+                    r = args_sample[index]
+                    del(args_sample[index])
+                    if len(args_sample) and not c.modifs[sw]:
+                        parsed_args.append(r)
+                    else:
+                        dib_out.append(r)                    
+
+
+                elif dib in [r_cl, r_dx]:
+                    index_im = [-1, 0][afs == noafs]
+                    dib_tmp = dict(dib)
+                    del(dib_tmp[x86_afs.size])
+                    del(args_sample[index_im][x86_afs.size])
+                    #XXX in al, dx => spot 16 bit manip; concat 66 bug
+                    if dib_tmp != args_sample[index_im]:
+                        log.debug("not r_cl d_dx")
+                        good_c = False
+                        break
+
+                    r = args_sample[index_im]
+                    del args_sample[index_im] 
+                    dib_out.append(r)
+
+                elif dib == mim:
+                    if len(args_sample)<=0:
+                        good_c = False
+                        break
+                    if not x86_afs.imm in args_sample[0] or not x86_afs.ad in args_sample[0] or not args_sample[0][x86_afs.ad]:
+                        log.debug("not mim")
+                        good_c = False
+                        break
+
+                    for k in args_sample[0]:
+                        if not k in [x86_afs.imm, x86_afs.ad, x86_afs.size]:
+                            log.debug("mim: cannot encode reg ")
+                            good_c = False
+                            break
+                    
+                    a_mem = {x86_afs.size:u32, x86_afs.imm:uint32(args_sample[0][x86_afs.imm])}
+                    opc_add.append(a_mem)
+                    del args_sample[0]
+                    a_pmem = dict(a_mem)
+                    a_pmem[x86_afs.ad] = u32
+                    parsed_args.append(a_pmem)
+                    
+                else:
+                    raise ValueError('bad dib!!%X'%dib)
+            
+            if not good_c:
+                continue
+
+            log.debug("***pass dib***")
+            log.debug(modifs)
+
+            if afs in [d0, d1, d2, d3, d4, d5, d6, d7]:
+                if len(args_sample)!=1:
+                    log.debug(str(c)+' bad arg num1')
+                    continue
+                if args_sample[0][x86_afs.ad]:
+                    size = args_sample[0][x86_afs.ad]
+                    if not c.modifs[sd]  == None:
+                        size = {x86_afs.u16:x86_afs.u16, x86_afs.u32:x86_afs.u32, x86_afs.f32:x86_afs.f32, x86_afs.f64:x86_afs.f64}[size]
+                else:
+                    size = args_sample[0][x86_afs.size]                        
+                if not x86mndb.check_size_modif(size, c.modifs):
+                    log.debug(' bad size digit')
+                    continue
+                
+                
+                a = dict(args_sample[-1])
+                out_opc, parsed_val = x86mndb.forge_opc(out_opc, a)
+                if out_opc == None or parsed_val == None:
+                    log.debug('cannot encode opc')
+                    continue
+                    
+                parsed_args.append(args_sample.pop())
+            elif afs == reg:
+                if len(args_sample)!=1:
+                    log.debug(str(c)+' bad arg num')
+                    continue
+                if  args_sample[0][x86_afs.ad]:
+                    log.debug(' address in reg')
+                    continue
+                size = args_sample[0][x86_afs.size]
+                if not x86mndb.check_size_modif(size, c.modifs):
+                    log.debug(' bad size reg')
+                    continue
+
+                a = args_sample[-1]
+                k = [x for x in a.keys() if type(x) in [long, int]]
+                if a[x86_afs.ad] or x86_afs.imm in a or len(k)!=1:
+                    log.debug('bad a2 %s'%str(a))
+                    continue
+                out_opc[0][-1]+=k[0]
+                parsed_args.append(args_sample.pop())
+                
+            elif afs == noafs or (afs == cond and rmr in c.rm and len(args_sample)==2):
+                if rmr in c.rm:
+                    if len(args_sample)!=2:
+                        log.debug(str(c)+' bad arg num')
+                        continue    
+                    if c.modifs[sw] and args_sample[1][x86_afs.ad]:
+                        log.debug(' bad sw rmr 1')
+                        continue
+                    if not c.modifs[sw] and args_sample[0][x86_afs.ad]:
+                        log.debug(' bad sw rmr 2')
+                        continue
+                    
+                    for i in range(2):
+                        if not args_sample[i][x86_afs.ad] and x86_afs.imm in args_sample[i]:
+                            good_c = False
+                            log.debug('Imm in rmr')
+                            break
+
+                    if not good_c:
+                        continue
+
+                    size = []
+                    for x in xrange(2):
+                        size.append(args_sample[x][x86_afs.size])
+
+                    if not (imm in dibs or ims in dibs):
+                        if c.modifs[sw]:
+                            size.reverse()
+                            
+                        if c.modifs[se]!=None:
+                            if size[1] != [x86_afs.u08, x86_afs.u16][c.modifs[se]]:
+                                log.debug(' bad size se rmr')
+                                continue
+                        elif not x86mndb.check_size_modif(size[0], c.modifs):
+                            log.debug(' bad size rmr')
+                            continue
+    
+
+                    #reg, modr
+                    a1 = dict(args_sample[-1])
+                    a2 = dict(args_sample[-2])
+                    args_sample = args_sample[:-2]
+
+
+                    
+                    if c.modifs[sw]:
+                        tmp_order = [a2,a1]
+                    else:
+                        tmp_order = [a1,a2]
+
+                    for y in mask_drcrsg:
+                        if not modifs[y]:
+                            continue
+                        for x in tmp_order[1]:
+                            if not type(x) in [int, long]:
+                                continue
+                            if not x&mask_drcrsg[y]:
+                                log.debug('cr dr sg not found in reg')
+                                good_c = False
+                                break
+                            tmp = tmp_order[1][x]
+                            del(tmp_order[1][x])
+                            tmp_order[1][x&0xFF] = tmp
+                            
+
+                    if not good_c:
+                        continue
+
+
+                        
+                    out_opc, parsed_val = x86mndb.forge_opc(out_opc, *tmp_order)
+                    if out_opc == None or parsed_val == None:
+                        log.debug('cannot encode opc')
+                        continue
+                    tmp_o = [a2,a1]
+                    if c.modifs[se] and size[0] !=size[1]:
+                        size[1] = size[0]
+                    if size[0] !=size[1] and name !='movzx':
+                        if tmp_order[0][x86_afs.ad]:
+                            size[1] = size[0]
+                        else:
+                            log.debug('uncompatible size in rmr')
+                            continue
+
+                    for i in range(2):
+                        tmp_o[-1][x86_afs.size] = size[i]
+                    parsed_args+=tmp_o
+                    
+                    
+            elif afs == cond:
+                if rmr in c.rm:
+                    if len(args_sample)!=1:
+                        log.debug(str(c)+' bad arg num cond rmr')
+                        continue
+                    if args_sample[0][x86_afs.ad]:
+                        size = args_sample[0][x86_afs.ad]
+                    else:
+                        size = args_sample[0][x86_afs.size]
+                    
+                    a = dict(args_sample[-1])
+                    add_out_opc, parsed_val = x86mndb.forge_opc([[0]], a)
+                    if add_out_opc == None or parsed_val == None:
+                        log.debug('cannot encode opc')
+                        continue
+                    parsed_args.append(args_sample.pop())
+                    out_opc[0]+=add_out_opc[0]
+
+                    
+                    
+            else:
+                raise ValueError('erf ', afs)
+
+            for do in dib_out:
+                parsed_args.append(do)
+
+            if len(args_sample):
+                log.debug('too many args!')
+                continue
+
+
+            if self.mnemo_mode == u16:
+                
+                for a in parsed_args:
+                    if not x86_afs.size in a:
+                        a[x86_afs.size] = u16
+                        continue
+                    if a[x86_afs.size] == u32:
+                        a[x86_afs.size] = u16
+                        if a[x86_afs.ad]:
+                            a[x86_afs.ad] = u16
+
+
+            log.debug( "ok")
+            log.debug(out_opc)
+            log.debug(parsed_val)
+            log.debug(parsed_args)
+            for i in range(len(out_opc)):
+                candidate_out.append((c, parsed_args, (out_opc[i], parsed_val[i], opc_add), self.mnemo_mode))
+        return prefix, candidate_out
+    
+    def _asm(self, l, symbol_off_out):
+        log.debug("asm: %s"%l)
+        prefix, candidate_out = self.asm_parse(l)
+
+        symbol_off = []
+        log.info("selected candidate for:")
+        log.info(l)
+        hex_candidate = []
+        for c,eat_arg,opc_o, mnemo_mode in candidate_out:
+            log.info(str(c)+' '+str(eat_arg)+' '+str(opc_o))
+            out_opc = prefix[:]
+            out_opc += opc_o[0]
+            val_add = [opc_o[1]]+opc_o[2]
+
+            out_byte = reduce(lambda x,y: x+chr(y), out_opc, "")
+            for c in val_add:
+                if c == {}:
+                    continue
+                if c[x86_afs.size] in [u08, s08, u16, s16, u32, s32]:
+                    out_byte+=struct.pack(x86_afs.dict_size[c[x86_afs.size]], int(c[x86_afs.imm]))
+                else:
+                    raise ValueError('bad size in asm! %s'%str(c))
+
+            #XXX hack for reloc gen
+            has_symb = None
+            for ea in eat_arg:
+                if x86_afs.ad in ea and ea[x86_afs.ad]:
+                    has_symb = len(out_byte)-4
+            symbol_off.append(has_symb)
+
+            hex_candidate.append(out_byte)
+            log.info( hexdump(out_byte))
+        if not len(hex_candidate):
+            log.warning('cannot asm %s'%str(l))
+        all_candidate = zip(hex_candidate, symbol_off)
+        all_candidate.sort(cmp = lambda x,y:len(x[0])-len(y[0]))
+        hex_candidate = [x[0] for x in all_candidate]
+        for x in all_candidate:
+            symbol_off_out.append(x[1])
+            
+        return hex_candidate
+
+
+x86mnemo = x86_mn
+
+if __name__ == '__main__':
+    test_out = []
+    log.setLevel(logging.DEBUG)
+
+    instr = x86mnemo.dis('DB 28'.replace(' ', '').decode('hex'), admode=x86_afs.u32)
+    print instr
+    print instr.arg
+    print instr.l
+    fds
+
+    instr = x86mnemo.dis('DB 6D 08'.replace(' ', '').decode('hex'), admode=x86_afs.u32)
+    print instr
+    print instr.arg
+    print instr.l
+    fds
+
+    instr = x86mnemo.dis('C7 44 24 08 00 00 00 00'.replace(' ', '').decode('hex'), admode=x86_afs.u32)
+    print instr
+    print instr.arg
+    print instr.l
+    fds
+
+    instr = x86mnemo.dis('F0 65 0F B1 0D 84 00 00 00'.replace(' ', '').decode('hex'), admode=x86_afs.u32)
+    print instr
+    print instr.arg
+    print instr.l
+    fds
+
+    instr = x86mnemo.dis('F0 65 83 0D 84 00 00 00 10'.replace(' ', '').decode('hex'), admode=x86_afs.u32)
+    print instr
+    print instr.arg
+    print instr.l
+    fds
+
+    instr = x86mnemo.dis('65 C7 05 28 02 00 00 FF FF FF FF'.replace(' ', '').decode('hex'), admode=x86_afs.u32)
+    print instr
+    print instr.arg
+    fds
+
+    instr = x86mnemo.dis('66ab'.decode('hex'), admode=x86_afs.u32)
+    print instr
+    print instr.arg
+    fds
+
+    instr = x86mnemo.dis('6681384D5A0000'.decode('hex'), admode=x86_afs.u32)
+    print instr
+    print instr.arg
diff --git a/miasm/arch/ia32_reg.py b/miasm/arch/ia32_reg.py
new file mode 100644
index 00000000..9c49691e
--- /dev/null
+++ b/miasm/arch/ia32_reg.py
@@ -0,0 +1,159 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+class afs_desc:
+    def __init__(self):
+
+        self.noad = "no_ad"
+        self.ad = "ad"
+
+        self.ad8 = "ad8"
+        self.ad16 = "ad16"
+        self.ad32 = "ad32"
+        self.segm = "segm"
+
+        self.size = "size"
+
+        self.symb = "symb__intern__"
+
+        self.imm = "imm"
+        self.s08 = "s08"
+        self.u08 = "u08"
+        self.u16 = "u16"
+        self.s16 = "s16"
+        self.u32 = "u32"
+        self.s32 = "s32"
+        self.s32 = "s32"
+
+        self.f32 = "f32"
+        self.f64 = "f64"
+        self.fpu = "fpu"
+        
+        self.im1 = "im1"
+        self.im3 = "im3"
+        self.ims = "ims"
+        self.mim = "mim"
+
+        self.size_seg = "size_seg"
+
+        self.dict_size = {self.imm:'imm',
+                          self.s08:'b',
+                          self.u08:'B',
+                          self.s16:'h',
+                          self.u16:'H',
+                          self.s32:'i',
+                          self.u32:'I',
+                          }
+                          
+
+        
+        self.r_eax = "eax"
+        self.r_ecx = "ecx"
+        self.r_edx = "edx"
+        self.r_ebx = "ebx"
+        self.r_esp = "esp"
+        self.r_ebp = "ebp"
+        self.r_esi = "esi"
+        self.r_edi = "edi"
+        
+        self.r_dr0 = "dr0"
+        self.r_dr1 = "dr1"
+        self.r_dr2 = "dr2"
+        self.r_dr3 = "dr3"
+        self.r_dr4 = "dr4"
+        self.r_dr5 = "dr5"
+        self.r_dr6 = "dr6"
+        self.r_dr7 = "dr7"
+        
+        self.r_cr0 = "cr0"
+        self.r_cr1 = "cr1"
+        self.r_cr2 = "cr2"
+        self.r_cr3 = "cr3"
+        self.r_cr4 = "cr4"
+        self.r_cr5 = "cr5"
+        self.r_cr6 = "cr6"
+        self.r_cr7 = "cr7"
+        
+        self.r_ax = "ax"
+        self.r_cx = "cx"
+        self.r_dx = "dx"
+        self.r_bx = "bx"
+        self.r_sp = "sp"
+        self.r_bp = "bp"
+        self.r_si = "si"
+        self.r_di = "di"
+             
+        self.r_al = "al"
+        self.r_cl = "cl"
+        self.r_dl = "dl"
+        self.r_bl = "bl"
+        self.r_ah = "ah"
+        self.r_ch = "ch"
+        self.r_dh = "dh"
+        self.r_bh = "bh"
+
+
+        self.r_es = "es"
+        self.r_cs = "cs"
+        self.r_ss = "ss"
+        self.r_ds = "ds"
+        self.r_fs = "fs"
+        self.r_gs = "gs"
+
+        self.reg_list8 =[self.r_al,  self.r_cl,  self.r_dl,  self.r_bl,
+                         self.r_ah,  self.r_ch,  self.r_dh,  self.r_bh]
+        self.reg_list16=[self.r_ax,  self.r_cx,  self.r_dx,  self.r_bx,
+                         self.r_sp,  self.r_bp,  self.r_si,  self.r_di]
+        self.reg_list32=[self.r_eax, self.r_ecx, self.r_edx, self.r_ebx,
+                         self.r_esp, self.r_ebp, self.r_esi, self.r_edi]
+  
+        self.reg_dr=     [self.r_dr0, self.r_dr1, self.r_dr2, self.r_dr3,
+                          self.r_dr4, self.r_dr5, self.r_dr6, self.r_dr7]
+
+        self.reg_cr=     [self.r_cr0, self.r_cr1, self.r_cr2, self.r_cr3,
+                          self.r_cr4, self.r_cr5, self.r_cr6, self.r_cr7]
+
+        self.reg_sg=     [self.r_es,  self.r_cs,  self.r_ss,  self.r_ds,
+                         self.r_fs,  self.r_gs,   None,       None]
+
+        self.reg_flt =  ["st%d"%i for i in range(8)]
+        
+        self.reg_dict = {}
+        for i in range(8):
+            self.reg_dict[self.reg_list8[i]] = i
+        for i in range(8):
+            self.reg_dict[self.reg_list16[i]] = i
+        for i in range(8):
+            self.reg_dict[self.reg_list32[i]] = i
+        for i in range(8):
+            self.reg_dict[self.reg_flt[i]] = i
+        for i in range(8):
+            self.reg_dict[self.reg_cr[i]] = i+0x100
+        for i in range(8):
+            self.reg_dict[self.reg_dr[i]] = i+0x200
+        for i in range(8):
+            self.reg_dict[self.reg_sg[i]] = i+0x400
+            
+        
+
+        self.x86_prefix = [0xF0, 0xF2, 0xF3,
+                           0x2E, 0x36, 0x3E, 0x26, 0x64, 0x65,
+                           0x66, 
+                           0x67]
+        
+
+x86_afs = afs_desc()
diff --git a/miasm/arch/ia32_sem.py b/miasm/arch/ia32_sem.py
new file mode 100644
index 00000000..013c0f31
--- /dev/null
+++ b/miasm/arch/ia32_sem.py
@@ -0,0 +1,2136 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+from miasm.expression.expression import *
+from miasm.arch.ia32_reg import *
+from miasm.arch.ia32_arch import *
+
+
+EXCEPT_PRIV_INSN = 1<<7
+reg_eax = 'eax'
+reg_ebx = 'ebx'
+reg_ecx = 'ecx'
+reg_edx = 'edx'
+reg_esp = 'esp'
+reg_ebp = 'ebp'
+reg_eip = 'eip'
+reg_esi = 'esi'
+reg_edi = 'edi'
+reg_eflag = 'eflag'
+reg_tmp1 = 'tmp1'
+
+reg_zf = 'zf'
+reg_nf = 'nf'
+reg_pf = 'pf'
+reg_of = 'of'
+reg_cf = 'cf'
+reg_tf = 'tf'
+reg_if = 'i_f'
+reg_df = 'df'
+reg_af = 'af'
+reg_iopl='iopl_f'
+reg_nt = 'nt'
+reg_rf = 'rf'
+reg_vm = 'vm'
+reg_ac = 'ac'
+reg_vif= 'vif'
+reg_vip= 'vip'
+reg_id = 'i_d'
+
+
+reg_es = "es"
+reg_cs = "cs"
+reg_ss = "ss"
+reg_ds = "ds"
+reg_fs = "fs"
+reg_gs = "gs"
+
+reg_dr0 = 'dr0'
+reg_dr1 = 'dr1'
+reg_dr2 = 'dr2'
+reg_dr3 = 'dr3'
+reg_dr4 = 'dr4'
+reg_dr5 = 'dr5'
+reg_dr6 = 'dr6'
+reg_dr7 = 'dr7'
+
+reg_cr0 = 'cr0'
+reg_cr1 = 'cr1'
+reg_cr2 = 'cr2'
+reg_cr3 = 'cr3'
+reg_cr4 = 'cr4'
+reg_cr5 = 'cr5'
+reg_cr6 = 'cr6'
+reg_cr7 = 'cr7'
+
+
+reg_tsc1 = "tsc1"
+reg_tsc2 = "tsc2"
+
+reg_float_c0 = 'float_c0'
+reg_float_c1 = 'float_c1'
+reg_float_c2 = 'float_c2'
+reg_float_c3 = 'float_c3'
+reg_float_stack_ptr = "float_stack_ptr"
+reg_float_control = 'reg_float_control'
+
+
+reg_float_st0 = 'float_st0'
+reg_float_st1 = 'float_st1'
+reg_float_st2 = 'float_st2'
+reg_float_st3 = 'float_st3'
+reg_float_st4 = 'float_st4'
+reg_float_st5 = 'float_st5'
+reg_float_st6 = 'float_st6'
+reg_float_st7 = 'float_st7'
+
+
+
+#commonly used
+init_eax = ExprId("init_eax", is_term=True)
+init_ebx = ExprId("init_ebx", is_term=True)
+init_ecx = ExprId("init_ecx", is_term=True)
+init_edx = ExprId("init_edx", is_term=True)
+init_esi = ExprId("init_esi", is_term=True)
+init_edi = ExprId("init_edi", is_term=True)
+init_esp = ExprId("init_esp", is_term=True)
+init_ebp = ExprId("init_ebp", is_term=True)
+
+
+
+
+init_tsc1 = ExprId("init_tsc1")
+init_tsc2 = ExprId("init_tsc2")
+
+init_cr0 = ExprId("init_cr0")
+
+
+init_zf    = ExprId("init_zf")
+init_nf    = ExprId("init_nf")
+init_pf    = ExprId("init_pf")
+init_of    = ExprId("init_of")
+init_cf    = ExprId("init_cf")
+init_tf    = ExprId("init_tf")
+init_i_f   = ExprId("init_i_f")
+init_df    = ExprId("init_df")
+init_af    = ExprId("init_af")
+init_iopl  = ExprId("init_iopl")
+init_nt    = ExprId("init_nt")
+init_rf    = ExprId("init_rf")
+init_vm    = ExprId("init_vm")
+init_ac    = ExprId("init_ac")
+init_vif   = ExprId("init_vif")
+init_vip   = ExprId("init_vip")
+init_i_d   = ExprId("init_i_d")
+init_tsc1  = ExprId("init_tsc1")
+init_tsc2  = ExprId("init_tsc2")
+
+
+
+eax = ExprId(reg_eax)
+ebx = ExprId(reg_ebx)
+ecx = ExprId(reg_ecx)
+edx = ExprId(reg_edx)
+esp = ExprId(reg_esp)
+ebp = ExprId(reg_ebp)
+eip = ExprId(reg_eip)
+esi = ExprId(reg_esi)
+edi = ExprId(reg_edi)
+
+
+r_al = eax[:8]
+r_cl = ecx[:8]
+r_dl = edx[:8]
+r_bl = ebx[:8]
+r_ah = eax[8:16]
+r_ch = ecx[8:16]
+r_dh = edx[8:16]
+r_bh = ebx[8:16]
+
+r_ax = eax[:16]
+r_bx = ebx[:16]
+r_cx = ecx[:16]
+r_dx = edx[:16]
+r_sp = esp[:16]
+r_bp = ebp[:16]
+r_ip = eip[:16]
+r_si = esi[:16]
+r_di = edi[:16]
+
+
+dr0 = ExprId(reg_dr0)
+dr1 = ExprId(reg_dr1)
+dr2 = ExprId(reg_dr2)
+dr3 = ExprId(reg_dr3)
+dr4 = ExprId(reg_dr4)
+dr5 = ExprId(reg_dr5)
+dr6 = ExprId(reg_dr6)
+dr7 = ExprId(reg_dr7)
+
+cr0 = ExprId(reg_cr0)
+cr1 = ExprId(reg_cr1)
+cr2 = ExprId(reg_cr2)
+cr3 = ExprId(reg_cr3)
+cr4 = ExprId(reg_cr4)
+cr5 = ExprId(reg_cr5)
+cr6 = ExprId(reg_cr6)
+cr7 = ExprId(reg_cr7)
+
+
+eflag= ExprId(reg_eflag)
+tmp1= ExprId(reg_tmp1)
+zf = ExprId(reg_zf, size=1)
+nf = ExprId(reg_nf, size=1)
+pf = ExprId(reg_pf, size=1)
+of = ExprId(reg_of, size=1)
+cf = ExprId(reg_cf, size=1)
+tf = ExprId(reg_tf , size=1)
+i_f= ExprId(reg_if , size=1)
+df = ExprId(reg_df , size=1)
+af = ExprId(reg_af , size=1)
+iopl=ExprId(reg_iopl,size=2)
+nt = ExprId(reg_nt , size=1)
+rf = ExprId(reg_rf , size=1)
+vm = ExprId(reg_vm , size=1)
+ac = ExprId(reg_ac , size=1)
+vif= ExprId(reg_vif, size=1)
+vip= ExprId(reg_vip, size=1)
+i_d= ExprId(reg_id , size=1)
+
+es = ExprId(reg_es, size = 16)
+cs = ExprId(reg_cs, size = 16)
+ss = ExprId(reg_ss, size = 16)
+ds = ExprId(reg_ds, size = 16)
+fs = ExprId(reg_fs, size = 16)
+gs = ExprId(reg_gs, size = 16)
+
+tsc1 = ExprId(reg_tsc1, size = 32)
+tsc2 = ExprId(reg_tsc2, size = 32)
+
+float_c0 = ExprId(reg_float_c0)
+float_c1 = ExprId(reg_float_c1)
+float_c2 = ExprId(reg_float_c2)
+float_c3 = ExprId(reg_float_c3)
+float_stack_ptr = ExprId(reg_float_stack_ptr)
+float_control = ExprId(reg_float_control)
+                          
+float_st0 = ExprId(reg_float_st0)
+float_st1 = ExprId(reg_float_st1)
+float_st2 = ExprId(reg_float_st2)
+float_st3 = ExprId(reg_float_st3)
+float_st4 = ExprId(reg_float_st4)
+float_st5 = ExprId(reg_float_st5)
+float_st6 = ExprId(reg_float_st6)
+float_st7 = ExprId(reg_float_st7)
+
+
+
+init_regs = {
+eax:init_eax,
+ebx:init_ebx,
+ecx:init_ecx,
+edx:init_edx,
+esi:init_esi,
+edi:init_edi,
+esp:init_esp,
+ebp:init_ebp,
+zf:init_zf,
+nf:init_nf,
+pf:init_pf,
+of:init_of,
+cf:init_cf,
+tf:init_tf,
+i_f:init_i_f,
+df:init_df,
+af:init_af,
+iopl:init_iopl,
+nt:init_nt,
+rf:init_rf,
+vm:init_vm,
+ac:init_ac,
+vif:init_vif,
+vip:init_vip,
+i_d:init_i_d,
+tsc1:init_tsc1,
+tsc2:init_tsc2,
+}
+
+all_registers = [
+    eax ,
+    ebx ,
+    ecx ,
+    edx ,
+    esp ,
+    ebp ,
+    eip ,
+    esi ,
+    edi ,
+    dr0, 
+    dr1, 
+    dr2, 
+    dr3, 
+    dr4, 
+    dr5, 
+    dr6, 
+    dr7, 
+    
+    eflag,
+    tmp1,
+    zf ,
+    nf ,
+    pf ,
+    of ,
+    cf ,
+    tf ,
+    i_f,
+    df ,
+    af ,
+    iopl,
+    nt ,
+    rf ,
+    vm ,
+    ac ,
+    vif,
+    vip,
+    i_d,
+    
+    es ,
+    cs ,
+    ss ,
+    ds ,
+    fs ,
+    gs ,
+    
+    tsc1 ,
+    tsc2 ,
+    
+    float_c0 ,
+    float_c1 ,
+    float_c2 ,
+    float_c3 ,
+    float_stack_ptr ,
+    float_control ,
+    
+    float_st0 ,
+    float_st1 ,
+    float_st2 ,
+    float_st3 ,
+    float_st4 ,
+    float_st5 ,
+    float_st6 ,
+    float_st7 ,
+
+    ]
+
+tab_intsize = {8:int8,
+               16:int16,
+               32:int32,
+               64:int64
+               }
+tab_uintsize ={8:uint8,
+               16:uint16,
+               32:uint32,
+               64:uint64
+               }
+
+tab_afs_int ={x86_afs.u08:uint8,
+              x86_afs.u16:uint16,
+              x86_afs.u32:uint32,
+              }
+"""
+http://www.emulators.com/docs/nx11_flags.htm
+
+CF(A+B) = (((A XOR B) XOR D) < 0) XOR (((A XOR D) AND NOT (A XOR B)) < 0)
+CF(A-B) = (((A XOR B) XOR D) < 0) XOR (((A XOR D) AND (A XOR B)) < 0)
+
+OF(A+B) = ((A XOR D) AND NOT (A XOR B)) < 0
+OF(A-B) = ((A XOR D) AND (A XOR B)) < 0
+"""
+
+def get_op_msb(a):
+    cast_int = tab_uintsize[a.get_size()]
+    return ExprOp('==', ExprInt(cast_int(1)), ExprOp('>>', a, ExprInt(cast_int(a.get_size()-1))))
+
+
+def update_flag_zf(a):
+    cast_int = tab_uintsize[a.get_size()]
+    return [ExprAff(zf, ExprOp('==', a, ExprInt(cast_int(0))))]
+
+def update_flag_nf(a):
+    return [ExprAff(nf, ExprOp('&', get_op_msb(a), ExprInt(tab_uintsize[a.get_size()](1))))]
+
+def update_flag_pf(a):
+    return [ExprAff(pf, ExprOp('parity', a))]
+
+def update_flag_af(a):
+    return [ExprAff(af, ExprOp('==', ExprOp('&', a, ExprInt(tab_uintsize[a.get_size()](0x10))), ExprInt(tab_uintsize[a.get_size()](0x10))))]
+
+def update_flag_znp(a):
+    e = []
+    e+=update_flag_zf(a)
+    e+=update_flag_nf(a)
+    e+=update_flag_pf(a)
+    return e
+
+def update_flag_logic(a):
+    e = []
+    e+=update_flag_znp(a)
+    e.append(ExprAff(of, ExprInt(uint32(0))))
+    e.append(ExprAff(cf, ExprInt(uint32(0))))
+    return e
+
+def update_flag_arith(a):
+    e = []
+    e+=update_flag_znp(a)
+    return e
+
+
+def check_ops_msb(a, b, c):
+    if not a or not b or not c or a!=b or a!=c:
+        raise 'bad ops size %s %s %s'%(str(a), str(b), str(c))
+
+def arith_flag(a, b, c):
+    a_s, b_s, c_s = a.get_size(), b.get_size(), c.get_size()
+    check_ops_msb(a_s, b_s, c_s)
+    a_s, b_s, c_s = get_op_msb(a), get_op_msb(b), get_op_msb(c)
+    return a_s, b_s, c_s
+
+
+#checked: ok for adc add because of b & c before +cf
+def update_flag_add_cf(cast_int, a, b, c):
+    return ExprAff(cf, get_op_msb((a ^ b) ^ c) ^ get_op_msb((a ^ c) & ExprOp('!', (a ^ b))))
+
+def update_flag_add_of(cast_int, a, b, c):
+    return ExprAff(of, get_op_msb(((a ^ c) & ExprOp('!', (a ^ b)))))
+
+
+
+#checked: ok for sbb add because of b & c before +cf
+def update_flag_sub_cf(cast_int, a, b, c):
+    return ExprAff(cf, get_op_msb((a ^ b) ^ c) ^ get_op_msb((a ^ c) & (a ^ b)))
+
+
+def update_flag_sub_of(cast_int, a, b, c):
+    return ExprAff(of, get_op_msb(((a ^ c) & (a ^ b))))
+
+
+    
+
+
+#z = x+y (+cf?)
+def update_flag_add(x, y, z):
+    cast_int = tab_uintsize[z.get_size()]
+    e = []
+    e.append(update_flag_add_cf(cast_int, x, y, z))
+    e.append(update_flag_add_of(cast_int, x, y, z))    
+    return e
+
+#z = x-y (+cf?)
+def update_flag_sub(x, y, z):
+    cast_int = tab_uintsize[z.get_size()]
+    e = []
+    e.append(update_flag_sub_cf(cast_int, x, y, z))
+    e.append(update_flag_sub_of(cast_int, x, y, z))
+    return e
+
+
+def mov(a, b):
+    return [ExprAff(a, b)]
+
+def xchg(a, b):
+    e = []
+    e.append(ExprAff(a, b))
+    e.append(ExprAff(b, a))
+    return e
+
+def movzx(a, b):
+    return [ExprAff(a, ExprCompose([ExprSliceTo(ExprInt(uint32(0)), b.get_size(), a.get_size()), ExprSliceTo(b, 0, b.get_size())]))]
+
+def movsx(a, b):
+    return [ExprAff(a, ExprCompose([ExprSliceTo(ExprCond(ExprOp('==', get_op_msb(b), ExprInt(uint32(1))),
+                                                         ExprInt(uint32(0xffffffff)),
+                                                         ExprInt(uint32(0))),
+                                                b.get_size(), a.get_size()),
+                                    ExprSliceTo(b,
+                                                0, b.get_size())]))]
+
+def lea(a, b):
+    return [ExprAff(a, b.arg)]
+
+def add(a, b):
+    e= []
+    c = ExprOp('+', a, b)
+    e+=update_flag_arith(c)
+    e+=update_flag_af(c)
+    e+=update_flag_add(a, b, c)
+    e.append(ExprAff(a, c))
+    return e
+
+def xadd(a, b):
+    e= []
+    c = ExprOp('+', b, a)
+    e+=update_flag_arith(c)
+    e+=update_flag_af(c)
+    e+=update_flag_add(b, a, c)
+    e.append(ExprAff(b, a))
+    e.append(ExprAff(a, c))
+    return e
+
+def adc(a, b):
+    e= []
+    c = ExprOp('+',
+               a,
+               ExprOp('+',
+                      b,
+                      ExprCompose([ExprSliceTo(ExprInt(uint32(0)), 1, a.get_size()), ExprSliceTo(cf, 0, 1)])))
+    e+=update_flag_arith(c)
+    e+=update_flag_af(c)
+    e+=update_flag_add(a, b, c)
+    e.append(ExprAff(a, c))
+    return e
+
+def sub(a, b):
+    e= []
+    c = ExprOp('-', a, b)
+    e+=update_flag_arith(c)
+    e+=update_flag_af(c)
+    e+=update_flag_sub(a, b, c)
+    e.append(ExprAff(a, c))
+    return e
+
+#a-(b+cf)
+def sbb(a, b):
+    e= []
+    c = ExprOp('-',
+               a,
+               ExprOp('+',
+                      b,
+                      ExprCompose([ExprSliceTo(ExprInt(uint32(0)), 1, a.get_size()), ExprSliceTo(cf, 0, 1)])))
+    e+=update_flag_arith(c)
+    e+=update_flag_af(c)
+    e+=update_flag_sub(a, b, c)
+    e.append(ExprAff(a, c))
+    return e
+
+def neg(b):
+    e= []
+    cast_int = tab_uintsize[b.get_size()]
+    a = ExprInt(cast_int(0))
+    
+    c = ExprOp('-', a, b)
+    e+=update_flag_arith(c)
+    e+=update_flag_sub(a, b, c)
+    e+=update_flag_af(c)
+    e.append(ExprAff(b, c))
+    return e
+
+def l_not(b):
+    e= []
+    cast_int = tab_uintsize[b.get_size()]
+    c = ExprOp('!', b)
+    e.append(ExprAff(b, c))
+    return e
+
+
+def l_cmp(a, b):
+    e= []
+    c = ExprOp('-', a, b)
+    e+=update_flag_arith(c)
+    e+=update_flag_sub(a, b, c)
+    e+=update_flag_af(c)
+    return e
+
+def xor(a, b):
+    e= []
+    c = ExprOp('^', a, b)
+    e+=update_flag_logic(c)
+    e.append(ExprAff(a, c))
+    return e
+
+def l_or(a, b):
+    e= []
+    c = ExprOp('|', a, b)
+    e+=update_flag_logic(c)
+    e.append(ExprAff(a, c))
+    return e
+
+def l_and(a, b):
+    e= []
+    c = ExprOp('&', a, b)
+    e+=update_flag_logic(c)
+    e.append(ExprAff(a, c))
+    return e
+
+def l_test(a, b):
+    e= []
+    c = ExprOp('&', a, b)
+    e+=update_flag_logic(c)
+    return e
+
+def l_rol(a, b):
+    e= []
+    cast_int = tab_uintsize[a.get_size()]
+    c = ExprOp('<<<', a, b)
+    
+    new_cf = ExprOp("&", c ,ExprInt(cast_int(1)))
+    e.append(ExprAff(cf, new_cf))
+    ### hack (only valid if b=1)
+    e.append(ExprAff(of, ExprOp("^", get_op_msb(c), new_cf)))
+    e.append(ExprAff(a, c))
+    return e
+
+def l_ror(a, b):
+    e= []
+    c = ExprOp('>>>', a, b)
+    
+    e.append(ExprAff(cf, get_op_msb(c)))
+    ### hack (only valid if b=1): when count == 1: a = msb-1(dest)
+    e.append(ExprAff(of, ExprOp("^", get_op_msb(c), get_op_msb(a))))
+    e.append(ExprAff(a, c))
+    return e
+
+def rcl(a, b):
+    e= []
+    c = ExprOp('<<<c_rez', a, b, cf)
+    new_cf = ExprOp('<<<c_cf', a, b, cf)
+
+    e.append(ExprAff(cf, new_cf))
+    ### hack (only valid if b=1)
+    e.append(ExprAff(of, ExprOp("^", get_op_msb(c), new_cf)))
+    e.append(ExprAff(a, c))
+    return e
+
+def rcr(a, b):
+    e= []
+    c = ExprOp('>>>c_rez', a, b, cf)
+    new_cf = ExprOp('>>>c_cf', a, b, cf)
+
+    e.append(ExprAff(cf, new_cf))
+    ### hack (only valid if b=1)
+    e.append(ExprAff(of, ExprOp("^", get_op_msb(a), get_op_msb(c))))
+    e.append(ExprAff(a, c))
+    
+    return e
+
+def sar(a, b):
+    e= []
+    cast_int = tab_uintsize[a.get_size()]
+    cast_intb = tab_uintsize[b.get_size()]
+    
+    shifter = ExprOp('&',b, ExprInt(cast_intb(0x1f)))
+    c = ExprOp('a>>', a, shifter)
+
+    new_cf = ExprOp('&',
+                    ExprInt(cast_int(1)),
+                    ExprOp('a>>',
+                           a,
+                           ExprOp('-',
+                                  shifter,
+                                  ExprInt(cast_intb(1))
+                                  )
+                           
+                           )
+                    )
+    
+    e.append(ExprAff(cf, ExprCond(shifter,
+                                  new_cf,
+                                  cf)
+                     )
+             )
+    e.append(ExprAff(of, ExprInt(cast_int(0))))
+    e+=update_flag_znp(c)
+    e.append(ExprAff(a, c))
+    return e
+
+def shr(a, b):
+    e= []
+    cast_int = tab_uintsize[a.get_size()]
+    cast_intb = tab_uintsize[b.get_size()]
+    shifter = ExprOp('&',b, ExprInt(cast_intb(0x1f)))
+    c = ExprOp('>>', a, shifter)
+
+    new_cf = ExprOp('&',
+                    ExprInt(cast_int(1)),
+                    ExprOp('>>',
+                           a,
+                           ExprOp('-',
+                                  shifter,
+                                  ExprInt(cast_intb(1))
+                                  )
+                           
+                           )
+                    )
+    
+    e.append(ExprAff(cf, ExprCond(shifter,
+                                  new_cf,
+                                  cf)
+                     )
+             )
+    
+    e.append(ExprAff(of, get_op_msb(a)))
+    e+=update_flag_znp(c)
+    e.append(ExprAff(a, c))
+    return e
+
+def shrd_cl(a, b):
+    e= []
+    cast_int = tab_uintsize[a.get_size()]
+    cast_intb = tab_uintsize[b.get_size()]
+
+    shifter = ExprOp('&',ecx, ExprInt(cast_intb(0x1f)))
+    
+    c = ExprOp('|',
+                ExprOp('>>', a, shifter),
+                ExprOp('<<', b, ExprOp('-',
+                                        ExprInt(cast_int(a.get_size())),
+                                        shifter)
+                                        )
+              )
+
+    new_cf = ExprOp('&',
+                    ExprInt(cast_int(1)),
+                    ExprOp('>>',
+                           a,
+                           ExprOp('-',
+                                  shifter,
+                                  ExprInt(cast_intb(1))
+                                  )
+                           
+                           )
+                    )
+    e.append(ExprAff(cf, ExprCond(shifter,
+                                  new_cf,
+                                  cf)
+                     )
+             )
+    e.append(ExprAff(of, get_op_msb(a)))
+    e+=update_flag_znp(c)
+    e.append(ExprAff(a, c))
+    return e
+
+def shrd(a, b, c):
+    e= []
+    cast_int = tab_uintsize[a.get_size()]
+    cast_intb = tab_uintsize[b.get_size()]
+
+    shifter = c
+
+    d = ExprOp('|',
+                ExprOp('>>', a, shifter),
+                ExprOp('<<', b, ExprOp('-',
+                                        ExprInt(cast_int(a.get_size())),
+                                        shifter)
+                                        )
+              )
+
+    new_cf = ExprAff(cf, ExprOp('&',
+                                ExprInt(cast_int(1)),
+                                ExprOp('>>',
+                                       a,
+                                       ExprOp('-',
+                                              shifter,
+                                              ExprInt(cast_intb(1))
+                                              )
+                                       )
+                                )
+                     )
+    e.append(ExprAff(cf, ExprCond(shifter,
+                                  new_cf,
+                                  cf)
+                     )
+             )
+    e.append(ExprAff(of, get_op_msb(a)))
+    e+=update_flag_znp(d)
+    e.append(ExprAff(a, d))
+    return e
+
+def sal(a, b):
+    e= []
+    cast_int = tab_uintsize[a.get_size()]
+    cast_intb = tab_uintsize[b.get_size()]
+    shifter = ExprOp('&',b, ExprInt(cast_intb(0x1f)))
+    
+    c = ExprOp('a<<', a, shifter)
+    new_cf = ExprOp('&',
+                    ExprInt(cast_int(1)),
+                    ExprOp('>>',
+                           a,
+                           ExprOp('-',
+                                  ExprInt(cast_intb(a.get_size())),
+                                  shifter
+                                  )
+                           
+                           )
+                    )
+    
+    e.append(ExprAff(cf, ExprCond(shifter,
+                                  new_cf,
+                                  cf)
+                     )
+             )
+    e+=update_flag_znp(c)
+    e.append(ExprAff(of, ExprOp('^', get_op_msb(c), new_cf)))
+    e.append(ExprAff(a, c))
+    return e
+
+def shl(a, b):
+    e= []
+    cast_int = tab_uintsize[a.get_size()]
+    cast_intb = tab_uintsize[b.get_size()]
+    shifter = ExprOp('&',b, ExprInt(cast_intb(0x1f)))
+    
+    c = ExprOp('<<', a, shifter)
+    new_cf = ExprOp('&',
+                    ExprInt(cast_int(1)),
+                    ExprOp('>>',
+                           a,
+                           ExprOp('-',
+                                  ExprInt(cast_intb(a.get_size())),
+                                  shifter
+                                  )
+                           
+                           )
+                    )
+    e.append(ExprAff(cf, ExprCond(shifter,
+                                  new_cf,
+                                  cf)
+                     )
+             )
+    e+=update_flag_znp(c)
+    e.append(ExprAff(of, ExprOp('^', get_op_msb(c), new_cf)))
+    e.append(ExprAff(a, c))
+    return e
+
+def shld_cl(a, b):
+    e= []
+    cast_int = tab_uintsize[a.get_size()]
+    cast_intb = tab_uintsize[b.get_size()]
+    shifter = ExprOp('&',ecx, ExprInt(cast_int(0x1f)))
+    
+    c = ExprOp('|',
+            ExprOp('<<', a, shifter),
+            ExprOp('>>', b, ExprOp('-',
+                                    ExprInt(cast_int(a.get_size())),
+                                    shifter)
+                                    )
+          )
+
+    new_cf = ExprOp('&',
+                    ExprInt(cast_int(1)),
+                    ExprOp('>>',
+                           a,
+                           ExprOp('-',
+                                  ExprInt(cast_intb(a.get_size())),
+                                  shifter
+                                  )
+                           
+                           )
+                    )
+    e.append(ExprAff(cf, ExprCond(shifter,
+                                  new_cf,
+                                  cf)
+                     )
+             )
+    e+=update_flag_znp(c)
+    e.append(ExprAff(of, ExprOp('^', get_op_msb(c), new_cf)))
+    e.append(ExprAff(a, c))
+    return e
+
+
+#XXX todo ###
+def cmc():
+    return     [ExprAff(cf, ExprOp('==', cf, ExprInt(uint32(0))))]
+
+def clc():
+    return     [ExprAff(cf, ExprInt(uint32(0)))]
+
+def stc():
+    return     [ExprAff(cf, ExprInt(uint32(1)))]
+
+def cld():
+    return     [ExprAff(df, ExprInt(uint32(0)))]
+
+def std():
+    return     [ExprAff(df, ExprInt(uint32(1)))]
+
+def cli():
+    return     [ExprAff(i_f, ExprInt(uint32(0)))]
+
+def sti():
+    return     [ExprAff(ExprId('vmcpu.vm_exception_flags'), ExprInt(uint32(1<<7)))]
+
+def inc(a):
+    e= []
+    b = ExprInt(tab_uintsize[a.get_size()](1))
+    c = ExprOp('+', a, b)
+    e+=update_flag_arith(c)
+    e+=update_flag_af(c)
+
+    cast_int = tab_uintsize[c.get_size()]
+    e.append(update_flag_add_of(cast_int, a, b, c))    
+    e.append(ExprAff(a, c))
+    return e
+
+
+def dec(a):
+    e= []
+    b = ExprInt(tab_uintsize[a.get_size()](-1))
+    c = ExprOp('+', a, b)
+    e+=update_flag_arith(c)
+    e+=update_flag_af(c)
+
+    cast_int = tab_uintsize[c.get_size()]
+    e.append(update_flag_add_of(cast_int, a, b, c))    
+    e.append(ExprAff(a, c))
+    return e
+
+def push(a):
+    e= []
+    s = a.get_size()
+    if not s in [16,32]:
+        raise 'bad size stacker!'
+    c = ExprOp('-', esp, ExprInt(uint32(s/8)))
+    e.append(ExprAff(esp, c))
+    e.append(ExprAff(ExprMem(c, s), a))
+    return e
+    
+def pop(a):
+    e= []
+    s = a.get_size()
+    if not s in [16,32]:
+        raise 'bad size stacker!'
+    new_esp = ExprOp('+', esp, ExprInt(uint32(s/8)))
+    e.append(ExprAff(esp, new_esp))
+    #XXX FIX XXX for pop [esp]
+    if isinstance(a, ExprMem):
+        a =a.reload_expr({esp:new_esp})
+    e.append(ExprAff(a, ExprMem(esp, s)))
+    return e
+
+def sete(a):
+    e = []
+    e.append(ExprAff(a, ExprCond(ExprOp('==', zf, ExprInt(uint32(1))), ExprInt(tab_uintsize[a.get_size()](1)), ExprInt(tab_uintsize[a.get_size()](0)))))
+    return e
+
+def setnz(a):
+    e = []
+    e.append(ExprAff(a, ExprCond(ExprOp('==', zf, ExprInt(uint32(0))), ExprInt(tab_uintsize[a.get_size()](1)), ExprInt(tab_uintsize[a.get_size()](0)))))
+    return e
+
+def setl(a):
+    e = []
+    e.append(ExprAff(a, ExprCond(ExprOp('==', ExprOp('==', nf, of), ExprInt(uint32(0))), ExprInt(tab_uintsize[a.get_size()](1)), ExprInt(tab_uintsize[a.get_size()](0)))))
+    return e
+
+def setg(a):
+    e = []
+    e.append(ExprAff(a, ExprCond(ExprOp("&", ExprOp('==', zf, ExprInt(uint32(0))), ExprOp('==', nf, of)), ExprInt(tab_uintsize[a.get_size()](1)), ExprInt(tab_uintsize[a.get_size()](0)))))
+    return e
+
+def setge(a):
+    e = []
+    e.append(ExprAff(a, ExprCond(ExprOp('==', nf, of), ExprInt(tab_uintsize[a.get_size()](1)), ExprInt(tab_uintsize[a.get_size()](0)))))
+    return e
+
+
+def seta(a):
+    e = []
+    e.append(ExprAff(a, ExprCond(ExprOp('&', ExprOp('==', cf, ExprInt(uint32(0))), ExprOp('==', zf, ExprInt(uint32(0)))), ExprInt(tab_uintsize[a.get_size()](1)), ExprInt(tab_uintsize[a.get_size()](0)))))
+    return e
+
+def setb(a):
+    e = []
+    e.append(ExprAff(a, ExprCond(ExprOp('==', cf, ExprInt(uint32(1))), ExprInt(tab_uintsize[a.get_size()](1)), ExprInt(tab_uintsize[a.get_size()](0)))))
+    return e
+
+def setns(a):
+    e = []
+    e.append(ExprAff(a, ExprCond(ExprOp('==', nf, ExprInt(uint32(0))), ExprInt(tab_uintsize[a.get_size()](1)), ExprInt(tab_uintsize[a.get_size()](0)))))
+    return e
+
+def sets(a):
+    e = []
+    e.append(ExprAff(a, ExprCond(ExprOp('==', nf, ExprInt(uint32(1))), ExprInt(tab_uintsize[a.get_size()](1)), ExprInt(tab_uintsize[a.get_size()](0)))))
+    return e
+
+
+def seto(a): 
+    e= []
+    e.append(ExprAff(a, ExprCond(ExprOp('==', of, ExprInt(uint32(1))), ExprInt(tab_uintsize[a.get_size()](1)), ExprInt(tab_uintsize[a.get_size()](0)))))
+    return e
+
+
+def bswap(a):
+    e = []
+    c = ExprCompose([ExprSliceTo(ExprOp('&', ExprInt(tab_uintsize[a.get_size()](0xFF)), a),                                 24, 32),
+                     ExprSliceTo(ExprOp('>>', ExprOp('&', ExprInt(tab_uintsize[a.get_size()](0xFF00)), a), ExprInt(uint32(8))),     16, 24),
+                     ExprSliceTo(ExprOp('>>', ExprOp('&', ExprInt(tab_uintsize[a.get_size()](0xFF0000)), a), ExprInt(uint32(16))),  8 , 16),
+                     ExprSliceTo(ExprOp('>>', ExprOp('&', ExprInt(tab_uintsize[a.get_size()](0xFF000000)), a), ExprInt(uint32(24))),0 , 8 ),
+                     ])
+    e.append(ExprAff(a, c))
+    return e
+
+def cmpsb():
+    e= []
+    e+=l_cmp(ExprMem(esi, 8), ExprMem(edi, 8))
+    e.append(ExprAff(edi, ExprCond(df, ExprOp('-', edi, ExprInt(uint32(1))), ExprOp('+', edi, ExprInt(uint32(1))))))
+    e.append(ExprAff(esi, ExprCond(df, ExprOp('-', esi, ExprInt(uint32(1))), ExprOp('+', esi, ExprInt(uint32(1))))))
+    return e
+
+def cmpsw():
+    e= []
+    e+=l_cmp(ExprMem(esi, 16), ExprMem(edi, 16))
+    e.append(ExprAff(edi, ExprCond(df, ExprOp('-', edi, ExprInt(uint32(2))), ExprOp('+', edi, ExprInt(uint32(2))))))
+    e.append(ExprAff(esi, ExprCond(df, ExprOp('-', esi, ExprInt(uint32(2))), ExprOp('+', esi, ExprInt(uint32(2))))))
+    return e
+
+def cmpsd():
+    e= []
+    e+=l_cmp(ExprMem(esi), ExprMem(edi))
+    e.append(ExprAff(edi, ExprCond(df, ExprOp('-', edi, ExprInt(uint32(4))), ExprOp('+', edi, ExprInt(uint32(4))))))
+    e.append(ExprAff(esi, ExprCond(df, ExprOp('-', esi, ExprInt(uint32(4))), ExprOp('+', esi, ExprInt(uint32(4))))))
+    return e
+
+def scasb():
+    e= []
+    e+=l_cmp(eax[0:8], ExprMem(edi, 8))
+    e.append(ExprAff(edi, ExprCond(df, ExprOp('-', edi, ExprInt(uint32(1))), ExprOp('+', edi, ExprInt(uint32(1))))))
+    return e
+
+def scasw():
+    e= []
+    e+=l_cmp(eax[0:16], ExprMem(edi, 16))
+    e.append(ExprAff(edi, ExprCond(df, ExprOp('-', edi, ExprInt(uint32(2))), ExprOp('+', edi, ExprInt(uint32(2))))))
+    return e
+
+def scasd():
+    e= []
+    e+=l_cmp(eax, ExprMem(edi))
+    e.append(ExprAff(edi, ExprCond(df, ExprOp('-', edi, ExprInt(uint32(4))), ExprOp('+', edi, ExprInt(uint32(4))))))
+    return e
+
+
+def compose_eflag(s = 32):
+    args = []
+
+    regs = [cf, ExprInt(uint32(1)), pf, ExprInt(uint32(0)), af, ExprInt(uint32(0)), zf, nf, tf, i_f, df, of]
+    for i in xrange(len(regs)):
+        args.append(ExprSliceTo(regs[i],i, i+1))
+
+    args.append(ExprSliceTo(iopl,12, 14))
+
+    if s == 32:
+        regs = [nt, ExprInt(uint32(0)), rf, vm, ac, vif, vip, i_d]
+    elif s == 16:
+        regs = [nt, ExprInt(uint32(0))]
+    else:
+        fdsfsdf
+    for i in xrange(len(regs)):
+        args.append(ExprSliceTo(regs[i],i+14, i+15))
+    if s == 32:
+        args.append(ExprSliceTo(ExprInt(uint32(0)),22, 32))
+                
+    return ExprCompose(args)
+
+    
+
+def pushfd():
+    return push(compose_eflag())
+
+def pushfw():
+    return push(compose_eflag(16))
+    
+def popfd():
+    tmp = ExprMem(esp)
+    e = []
+    e.append(ExprAff(cf, ExprSlice(tmp, 0, 1)))
+    e.append(ExprAff(pf, ExprSlice(tmp, 2, 3)))
+    e.append(ExprAff(af, ExprSlice(tmp, 4, 5)))
+    e.append(ExprAff(zf, ExprSlice(tmp, 6, 7)))
+    e.append(ExprAff(nf, ExprSlice(tmp, 7, 8)))
+    e.append(ExprAff(tf, ExprSlice(tmp, 8, 9)))
+    e.append(ExprAff(i_f,ExprSlice(tmp, 9, 10)))
+    e.append(ExprAff(df, ExprSlice(tmp, 10, 11)))
+    e.append(ExprAff(of, ExprSlice(tmp, 11, 12)))
+    e.append(ExprAff(iopl, ExprSlice(tmp, 12, 14)))
+    e.append(ExprAff(nt, ExprSlice(tmp, 14, 15)))
+    e.append(ExprAff(rf, ExprSlice(tmp, 16, 17)))
+    e.append(ExprAff(vm, ExprSlice(tmp, 17, 18)))
+    e.append(ExprAff(ac, ExprSlice(tmp, 18, 19)))
+    e.append(ExprAff(vif,ExprSlice(tmp, 19, 20)))
+    e.append(ExprAff(vip,ExprSlice(tmp, 20, 21)))
+    e.append(ExprAff(i_d,ExprSlice(tmp, 21, 22)))
+    e.append(ExprAff(esp, ExprOp('+', esp, ExprInt(uint32(4)))))
+         
+    return e
+
+def pushad():
+    e = []
+    s = 32
+    if not s in [16,32]:
+        raise 'bad size stacker!'
+    
+    regs = [eax, ecx, edx, ebx, esp, ebp, esi, edi]
+    for i in xrange(len(regs)):
+        c = ExprOp('+', esp, ExprInt(uint32(-(s/8)*(i+1))))
+        e.append(ExprAff(ExprMem(c, s), regs[i]))
+    e.append(ExprAff(esp, c))
+    return e
+
+def popad():
+    e = []
+    s = 32
+    if not s in [16,32]:
+        raise 'bad size stacker!'
+    regs = [eax, ecx, edx, ebx, esp, ebp, esi, edi]
+    regs.reverse()
+    for i in xrange(len(regs)):
+        if regs[i] == esp:
+            continue
+        c = ExprOp('+', esp, ExprInt(uint32((s/8)*i)))
+        e.append(ExprAff(regs[i], ExprMem(c, s)))
+        
+    c = ExprOp('+', esp, ExprInt(uint32((s/8)*(i+1))))
+    e.append(ExprAff(esp, c))
+    
+    return e
+
+
+def call(a, b): 
+    e= []
+    c = ExprOp('+', esp, ExprInt(uint32(-4)))    
+    e.append(ExprAff(esp, c))
+    e.append(ExprAff(ExprMem(c), a))
+    e.append(ExprAff(eip, b))
+    return e
+
+def ret(a = ExprInt(uint32(0))):
+    e = []
+    e.append(ExprAff(esp, ExprOp('+', esp, ExprOp('+', ExprInt(uint32(4)), a))))
+    e.append(ExprAff(eip, ExprMem(esp)))
+
+    
+    return e
+
+def leave():
+    e = []
+    e.append(ExprAff(ebp, ExprMem(ebp)))
+    e.append(ExprAff(esp, ExprOp('+', ExprInt(uint32(4)), ebp)))
+    return e
+
+def enter(a,b):
+    #XXX 32 bit...
+    e = []
+    e.append(ExprAff(ExprMem(esp), ebp))
+    e.append(ExprAff(ebp, ExprOp("-", esp, ExprInt(uint32(4)))))
+    e.append(ExprAff(esp, ExprOp('-', esp, 
+                                      ExprOp("+", a, ExprInt(uint32(4)))
+                                )
+                    )
+            )
+    return e
+
+def jmp(a): 
+    e= []
+    e.append(ExprAff(eip, a))
+    return e
+
+def jz(a, b): 
+    e= []
+    e.append(ExprAff(eip, ExprCond(ExprOp('==', zf, ExprInt(uint32(1))), b, a)))
+    return e
+
+def jnz(a, b): 
+    e= []
+    e.append(ExprAff(eip, ExprCond(ExprOp('==', zf, ExprInt(uint32(0))), b, a)))
+    return e
+
+def jp(a, b): 
+    e= []
+    e.append(ExprAff(eip, ExprCond(ExprOp('==', pf, ExprInt(uint32(1))), b, a)))
+    return e
+
+def jnp(a, b): 
+    e= []
+    e.append(ExprAff(eip, ExprCond(ExprOp('==', pf, ExprInt(uint32(0))), b, a)))
+    return e
+
+def ja(a, b): 
+    e= []
+    e.append(ExprAff(eip, ExprCond(ExprOp('&', ExprOp('==', cf, ExprInt(uint32(0))), ExprOp('==', zf, ExprInt(uint32(0)))), b, a)))
+    return e
+
+def jae(a, b): 
+    e= []
+    e.append(ExprAff(eip, ExprCond(ExprOp('==', cf, ExprInt(uint32(0))), b, a)))
+    return e
+
+def jb(a, b): 
+    e= []
+    e.append(ExprAff(eip, ExprCond(ExprOp('==', cf, ExprInt(uint32(1))), b, a)))
+    return e
+
+def jbe(a, b): 
+    e= []
+    e.append(ExprAff(eip, ExprCond(ExprOp('|', ExprOp('==', cf, ExprInt(uint32(1))), ExprOp('==', zf, ExprInt(uint32(1)))), b, a)))
+    return e
+
+def jge(a, b): 
+    e= []
+    e.append(ExprAff(eip, ExprCond(ExprOp('==', nf, of), b, a)))
+    return e
+
+def jg(a, b): 
+    e= []
+    e.append(ExprAff(eip, ExprCond(ExprOp('&', ExprOp('==', zf, ExprInt(uint32(0))), ExprOp('==', nf, of)), b, a)))
+    return e
+
+def jl(a, b): 
+    e= []
+    e.append(ExprAff(eip, ExprCond(ExprOp('==', ExprOp('==', nf, of), ExprInt(uint32(0))), b, a)))
+    return e
+
+def jle(a, b): 
+    e= []
+    e.append(ExprAff(eip, ExprCond(ExprOp('|', zf, ExprOp('==', ExprOp('==', nf, of), ExprInt(uint32(0)))), b, a)))
+    return e
+
+def js(a, b): 
+    e= []
+    e.append(ExprAff(eip, ExprCond(ExprOp('==', nf, ExprInt(uint32(1))), b, a)))
+    return e
+
+def jns(a, b): 
+    e= []
+    e.append(ExprAff(eip, ExprCond(ExprOp('==', nf, ExprInt(uint32(0))), b, a)))
+    return e
+
+def jo(a, b):
+    e= []
+    e.append(ExprAff(eip, ExprCond(of, b, a)))
+    return e
+
+def jno(a, b): 
+    e= []
+    e.append(ExprAff(eip, ExprCond(ExprOp('==', of, ExprInt(uint32(0))), b, a)))
+    return e
+
+
+def loop(a, b): 
+    e= []
+    c = ExprOp('-', ecx, ExprInt(uint32(1)))
+    e.append(ExprAff(ecx, c))
+    e.append(ExprAff(eip, ExprCond(ExprOp('==', ExprInt(uint32(0)), ExprOp('==', c, ExprInt(uint32(0)))), b, a)))
+    return e
+
+def loopne(a, b): 
+    e= []
+    c = ExprOp('-', ecx, ExprInt(uint32(1)))
+    e.append(ExprAff(ecx, c))
+    cond = ExprOp('&',
+                  ExprOp('==', ExprInt(uint32(0)), ExprOp('==', c, ExprInt(uint32(0)))),
+                  ExprOp('==', zf, ExprInt(uint32(0))),
+                  )
+    e.append(ExprAff(eip, ExprCond(cond, b, a)))
+    return e
+
+#XXX size to do; eflag
+def div(a):
+    e= []
+
+    s = a.get_size()
+    if s == 8:
+        s1,s2 = r_ah, r_al
+    elif s == 16:
+        s1,s2 = ExprSlice(edx, 0, 16), ExprSlice(eax, 0, 16)
+    elif s == 32:
+        s1,s2 = edx, eax
+    else:
+        raise ValueError('div arg not impl', a)
+
+    c_d = ExprOp('div%d'%s, s1, s2, a)
+    c_r = ExprOp('rem%d'%s, s1, s2, a)
+
+    #if 8 bit div, only ax is affected
+    if s == 8:
+        e.append(ExprAff(eax[0:16], ExprCompose([ExprSliceTo(c_d, 0, 8), ExprSliceTo(c_r, 8, 16)])))
+    else:
+        e.append(ExprAff(s1, c_r))
+        e.append(ExprAff(s2, c_d))
+    return e
+
+#XXX size to do; eflag
+def idiv(a):
+    e= []
+
+    s = a.get_size()
+
+    if s == 8:
+        s1,s2 = r_ah, r_al
+    elif s == 16:
+        s1,s2 = r_dx, r_ax
+    elif s == 32:
+        s1,s2 = edx, eax
+    else:
+        raise ValueError('div arg not impl', a)
+
+
+    c_d = ExprOp('idiv%d'%s, s1, s2, a)
+    c_r = ExprOp('irem%d'%s, s1, s2, a)
+
+    e.append(ExprAff(s1, c_r))
+    e.append(ExprAff(s2, c_d))
+    return e
+
+#XXX size to do; eflag
+def mul(a):
+    e= []
+    if a.get_size() == 32:
+        c_hi = ExprOp('umul32_hi', eax, a)
+        c_lo = ExprOp('umul32_lo', eax, a)
+        e.append(ExprAff(edx, c_hi))
+        e.append(ExprAff(eax, c_lo))
+
+        e.append(ExprAff(of, ExprCond(ExprOp("==", c_hi, ExprInt(uint32(0))),
+                                      ExprInt(uint32(0)),
+                                      ExprInt(uint32(1)))))
+        e.append(ExprAff(cf, ExprCond(ExprOp("==", c_hi, ExprInt(uint32(0))),
+                                      ExprInt(uint32(0)),
+                                      ExprInt(uint32(1)))))
+
+        
+        
+    elif a.get_size() == 16:
+        c_hi = ExprOp('umul16_hi', r_ax, a)
+        c_lo = ExprOp('umul16_lo', r_ax, a)
+        e.append(ExprAff(r_dx, c_hi))
+        e.append(ExprAff(r_ax, c_lo))
+
+        e.append(ExprAff(of, ExprCond(ExprOp("==", c_hi, ExprInt(uint32(0))),
+                                      ExprInt(uint32(0)),
+                                      ExprInt(uint32(1)))))
+        e.append(ExprAff(cf, ExprCond(ExprOp("==", c_hi, ExprInt(uint32(0))),
+                                      ExprInt(uint32(0)),
+                                      ExprInt(uint32(1)))))
+
+    elif a.get_size() == 8:
+        c = ExprOp('umul08', eax, a)
+        e.append(ExprAff(eax[:16], c))
+        e.append(ExprAff(of, ExprCond(ExprOp("==", eax[8:16], ExprInt(uint32(0))),
+                                      ExprInt(uint32(0)),
+                                      ExprInt(uint32(1)))))
+        e.append(ExprAff(cf, ExprCond(ExprOp("==", eax[8:16], ExprInt(uint32(0))),
+                                      ExprInt(uint32(0)),
+                                      ExprInt(uint32(1)))))
+
+
+
+    
+    return e
+
+#XXX size to do; eflag
+def imul(a, b = None, c = None):
+    e= []
+    if b == None:
+        if a.get_size() == 32:
+            c_hi = ExprOp('imul32_hi', eax, a)
+            c_lo = ExprOp('imul32_lo', eax, a)
+            e.append(ExprAff(edx, c_hi))
+            e.append(ExprAff(eax, c_lo))
+        elif a.get_size() == 16:
+            c_hi = ExprOp('imul16_hi', r_ax, a)
+            c_lo = ExprOp('imul16_lo', r_ax, a)
+            e.append(ExprAff(r_dx, c_hi))
+            e.append(ExprAff(r_ax, c_lo))
+        elif a.get_size() == 8:
+            c = ExprOp('imul08', eax, a)
+            e.append(ExprAff(eax[:16], c))
+            
+    else:
+        if c == None:
+            c = b
+            b = a
+        c = ExprOp('*', b, c)
+        e.append(ExprAff(a, c))
+    return e
+
+
+#XXX 16 bit bug
+def cdq():
+    e = []
+    e.append(ExprAff(edx,
+                     ExprCond(ExprOp('==', ExprOp('&', eax, ExprInt(uint32(0x80000000))), ExprInt(uint32(0))),
+                              ExprInt(uint32(0x0)),
+                              ExprInt(uint32(0xffffffff)))
+                     )
+             )
+    return e
+
+def stosb():
+    e = []
+    e.append(ExprAff(ExprMem(edi, 8), eax[0:8]))
+    e.append(ExprAff(edi, ExprCond(df, ExprOp('-', edi, ExprInt(uint32(1))), ExprOp('+', edi, ExprInt(uint32(1))))))
+    return e
+
+def stosw():
+    e = []
+    e.append(ExprAff(ExprMem(edi, 16), eax[0:16]))
+    e.append(ExprAff(edi, ExprCond(df, ExprOp('-', edi, ExprInt(uint32(2))), ExprOp('+', edi, ExprInt(uint32(2))))))
+    return e
+
+def stosd():
+    e = []
+    e.append(ExprAff(ExprMem(edi), eax))
+    e.append(ExprAff(edi, ExprCond(df, ExprOp('-', edi, ExprInt(uint32(4))), ExprOp('+', edi, ExprInt(uint32(4))))))
+    return e
+
+def lodsb():
+    e = []
+    e.append(ExprAff(eax[0:8], ExprMem(esi, 8)))
+    e.append(ExprAff(esi, ExprCond(df, ExprOp('-', esi, ExprInt(uint32(1))), ExprOp('+', esi, ExprInt(uint32(1))))))
+    return e
+
+def lodsw():
+    e = []
+    e.append(ExprAff(eax[0:16], ExprMem(esi, 16)))
+    e.append(ExprAff(esi, ExprCond(df, ExprOp('-', esi, ExprInt(uint32(2))), ExprOp('+', esi, ExprInt(uint32(2))))))
+    return e
+
+def lodsd():
+    e = []
+    e.append(ExprAff(eax, ExprMem(esi)))
+    e.append(ExprAff(esi, ExprCond(df, ExprOp('-', esi, ExprInt(uint32(4))), ExprOp('+', esi, ExprInt(uint32(4))))))
+    return e
+
+def movsb():
+    e = []
+    e.append(ExprAff(ExprMem(edi, 8), ExprMem(esi, 8)))
+    e.append(ExprAff(edi, ExprCond(df, ExprOp('-', edi, ExprInt(uint32(1))), ExprOp('+', edi, ExprInt(uint32(1))))))
+    e.append(ExprAff(esi, ExprCond(df, ExprOp('-', esi, ExprInt(uint32(1))), ExprOp('+', esi, ExprInt(uint32(1))))))
+    return e
+
+def movsw():
+    e = []
+    e.append(ExprAff(ExprMem(edi, 16), ExprMem(esi, 16)))
+    e.append(ExprAff(edi, ExprCond(df, ExprOp('-', edi, ExprInt(uint32(2))), ExprOp('+', edi, ExprInt(uint32(2))))))
+    e.append(ExprAff(esi, ExprCond(df, ExprOp('-', esi, ExprInt(uint32(2))), ExprOp('+', esi, ExprInt(uint32(2))))))
+    return e
+
+def movsd():
+    e = []
+    e.append(ExprAff(ExprMem(edi), ExprMem(esi)))
+    e.append(ExprAff(edi, ExprCond(df, ExprOp('-', edi, ExprInt(uint32(4))), ExprOp('+', edi, ExprInt(uint32(4))))))
+    e.append(ExprAff(esi, ExprCond(df, ExprOp('-', esi, ExprInt(uint32(4))), ExprOp('+', esi, ExprInt(uint32(4))))))
+    return e
+
+
+def float_pop(avoid_flt = None):
+    e= []
+    if avoid_flt != float_st0:
+        e.append(ExprAff(float_st0, float_st1))
+    if avoid_flt != float_st1:
+        e.append(ExprAff(float_st1, float_st2))
+    if avoid_flt != float_st2:
+        e.append(ExprAff(float_st2, float_st3))
+    if avoid_flt != float_st3:
+        e.append(ExprAff(float_st3, float_st4))
+    if avoid_flt != float_st4:
+        e.append(ExprAff(float_st4, float_st5))
+    if avoid_flt != float_st5:
+        e.append(ExprAff(float_st5, float_st6))
+    if avoid_flt != float_st6:
+        e.append(ExprAff(float_st6, float_st7))
+    if avoid_flt != float_st7:
+        e.append(ExprAff(float_st7, ExprInt(uint32(0))))
+    e.append(ExprAff(float_stack_ptr, ExprOp('-', float_stack_ptr, ExprInt(uint32(1)))))
+    return e
+
+# XXX TODO
+def fcom(a):
+    e = []
+    if isinstance(a, ExprMem):
+        src = ExprOp('mem_%.2d_to_double'%a.get_size(), a)
+    else:
+        src = a
+    
+    e.append(ExprAff(float_c0, ExprOp('fcom_c0', float_st0, src)))
+    e.append(ExprAff(float_c1, ExprOp('fcom_c1', float_st0, src)))
+    e.append(ExprAff(float_c2, ExprOp('fcom_c2', float_st0, src)))
+    e.append(ExprAff(float_c3, ExprOp('fcom_c3', float_st0, src)))
+    return e
+
+def ficom(a):
+    return []
+
+def fcomp(a):
+    e= fcom(a)
+    e+=float_pop()
+    return e
+
+def fld(a):
+    e= []
+    e.append(ExprAff(float_st7, float_st6))
+    e.append(ExprAff(float_st6, float_st5))
+    e.append(ExprAff(float_st5, float_st4))
+    e.append(ExprAff(float_st4, float_st3))
+    e.append(ExprAff(float_st3, float_st2))
+    e.append(ExprAff(float_st2, float_st1))
+    e.append(ExprAff(float_st1, float_st0))
+    e.append(ExprAff(float_st0, a))
+    e.append(ExprAff(float_stack_ptr, ExprOp('+', float_stack_ptr, ExprInt(uint32(1)))))
+    return e
+
+def fst(a):
+    e = []
+    if isinstance(a, ExprMem):
+        src = ExprOp('double_to_mem_%2d'%a.get_size(), float_st0)
+    else:
+        src = float_st0
+
+    
+    e.append(ExprAff(a, src))
+    return e
+
+def fstp(a):
+    e = fst(a)
+    e+=float_pop(a)
+    return e
+
+def fist(a):
+    e = []
+    e.append(ExprAff(a, ExprOp('double_to_int_32', float_st0)))
+    return e
+
+def fistp(a):
+    e = fist(a)
+    e+=float_pop(a)
+    return e
+
+def fild(a):
+
+    #XXXXX
+    src = ExprOp('int_%.2d_to_double'%a.get_size(), a)
+    return fld(src)
+
+def fldz():
+    #XXX
+    return fld(ExprOp('int_32_to_double', ExprInt(uint32(0))))
+    
+def fadd(a):
+    e = []
+    if isinstance(a, ExprMem):
+        src = ExprOp('mem_%.2d_to_double'%a.get_size(), a)
+    else:
+        src = a
+    e.append(ExprAff(float_st0, ExprOp('fadd', float_st0, src)))
+    return e
+
+def fnstsw():
+    dst = eax
+    return [ExprAff(dst, ExprCompose([ExprSliceTo(ExprInt(uint32(0)), 0, 8),
+                                      ExprSliceTo(float_c0, 8, 9),
+                                      ExprSliceTo(float_c1, 9, 10),
+                                      ExprSliceTo(float_c2, 10, 11),
+                                      ExprSliceTo(float_stack_ptr, 11, 14),
+                                      ExprSliceTo(float_c3, 14, 15),
+                                      ExprSliceTo(ExprInt(uint32(0)), 15, 16),
+                                      ExprSliceTo(ExprSlice(dst, 16, dst.get_size()), 16, dst.get_size())
+                                      ]))]
+
+def fnstcw(a):
+    e = []
+    e.append(ExprAff(a, float_control))
+    return e
+
+def fldcw(a):
+    e = []
+    e.append(ExprAff(float_control, a))
+    return e
+
+def fwait():
+    return []
+
+def nop():
+    return []
+
+def hlt():
+    return []
+
+def rdtsc():
+    e = []
+    e.append(ExprAff(eax, tsc1))
+    e.append(ExprAff(edx, tsc2))
+    return e
+
+def cbw(a):
+    e = []
+    cast_int = tab_uintsize[a.get_size()]
+    b = ExprOp('<<', ExprInt(cast_int(-1)),
+                     ExprInt(cast_int(a.get_size()/2)))
+
+    e.append(ExprAff(a, ExprCond( 
+                         ExprOp('==', ExprInt(cast_int(0)),
+                                     ExprOp('&', a, ExprOp('<<',ExprInt(cast_int(1)), 
+                                                                ExprOp('-', ExprInt(cast_int(a.get_size()/2)), 
+                                                                            ExprInt(cast_int(1))
+                                                                      )
+                                                    )
+                                           )
+                               ), 
+                         a,
+                         ExprOp('|', a, b),
+                         )
+            ))
+                   
+    return e
+    
+# XXX TODO
+def daa():
+	return []
+
+def aam(a):
+	return []
+
+def aad(a):
+	return []
+
+def aaa():
+	return []
+
+def bsf(a, b):
+    e = []
+    cast_int = tab_uintsize[b.get_size()]
+    e.append(ExprAff(a, ExprOp('bsf', a, b)))
+    e.append(ExprAff(zf, ExprOp('==', ExprInt(cast_int(0)), b)))
+    return e
+    
+def bsr(a, b):
+    e = []
+    cast_int = tab_uintsize[b.get_size()]
+    e.append(ExprAff(a, ExprOp('bsr', a, b)))
+    e.append(ExprAff(zf, ExprOp('==', ExprInt(cast_int(0)), b)))
+    return e
+
+def arpl(a, b):
+    e= []
+    e.append(ExprAff(ExprId('vmcpu.vm_exception_flags'), ExprInt(uint32(1<<7))))
+    return e
+
+def ins():
+    e= []
+    e.append(ExprAff(ExprId('vmcpu.vm_exception_flags'), ExprInt(uint32(1<<7))))
+    return e
+
+def sidt(a):
+    e = []
+    if not isinstance(a, ExprMem) or a.size!=32:
+      raise 'not exprmem 32bit instance!!'
+    b = a.arg
+    cast_int = tab_uintsize[a.get_size()]
+    print "DEFAULT SIDT ADDRESS %s!!"%str(a)
+    e.append(ExprAff(ExprMem(b, 32), ExprInt(uint32(0xe40007ff))))
+    e.append(ExprAff(ExprMem(ExprOp("+", b, ExprInt(uint32(4))), 32), ExprInt(uint32(0x8245))))
+    return e
+
+
+def cmovz(a, b):
+    e= []
+    e.append(ExprAff(a, ExprCond(ExprOp('==', zf, ExprInt(uint32(1))), b, a)))
+    return e
+def cmovnz(a, b):
+    e= []
+    e.append(ExprAff(a, ExprCond(ExprOp('==', zf, ExprInt(uint32(0))), b, a)))
+    return e
+
+#XXX
+def l_int(a):
+    e= []
+    e.append(ExprAff(ExprId('vmcpu.vm_exception_flags'), ExprInt(uint32(1<<1)))) #SOFT BP
+    return e
+
+def l_sysenter():
+    e= []
+    e.append(ExprAff(ExprId('vmcpu.vm_exception_flags'), ExprInt(uint32(EXCEPT_PRIV_INSN))))
+    return e
+
+#XXX
+def l_outs():
+    e= []
+    e.append(ExprAff(ExprId('vmcpu.vm_exception_flags'), ExprInt(uint32(EXCEPT_PRIV_INSN)))) #SOFT BP
+    return e
+
+# XXX actually, xlat performs al = (ds:[e]bx + ZeroExtend(al))
+def xlat():
+    e= []
+    a = ExprCompose([ExprSliceTo(ExprInt(uint32(0)), 8, 32), ExprSliceTo(eax[0:8], 0, 8)])
+    b = ExprMem(ExprOp('+', ebx, a), 8)
+    e.append(ExprAff(eax[0:8], b))
+    return e
+
+def cpuid():
+    e = []
+    e.append(ExprAff(eax, ExprOp('cpuid', eax, ExprInt(uint32(0)))))
+    e.append(ExprAff(ebx, ExprOp('cpuid', eax, ExprInt(uint32(1)))))
+    e.append(ExprAff(ecx, ExprOp('cpuid', eax, ExprInt(uint32(2)))))
+    e.append(ExprAff(edx, ExprOp('cpuid', eax, ExprInt(uint32(3)))))
+    return e
+
+def bt(a, b):
+    cast_int = tab_uintsize[a.get_size()]
+    e= []
+    c= ExprOp('&', b, ExprInt(cast_int(b.get_size() - 1)))
+    d= ExprOp('>>', a, c)
+    e.append(ExprAff(cf, ExprOp('&', d, ExprInt(cast_int(1)))))
+    return e
+
+def btc(a, b):
+    cast_int = tab_uintsize[a.get_size()]
+    e= []
+    c= ExprOp('&', b, ExprInt(cast_int(b.get_size() - 1)))
+    d= ExprOp('>>', a, c)
+    m= ExprOp('<<', ExprInt(cast_int(1)), b)
+    e.append(ExprAff(cf, ExprOp('&', d, ExprInt(cast_int(1)))))
+    e.append(ExprAff(a, ExprOp('^', a, m)))
+    return e
+
+def bts(a, b):
+    cast_int = tab_uintsize[a.get_size()]
+    e= []
+    c= ExprOp('&', b, ExprInt(cast_int(b.get_size() - 1)))
+    d= ExprOp('>>', a, c)
+    m= ExprOp('<<', ExprInt(cast_int(1)), b)
+    e.append(ExprAff(cf, ExprOp('&', d, ExprInt(cast_int(1)))))
+    e.append(ExprAff(a, ExprOp('|', a, m)))
+    return e
+
+def btr(a, b):
+    cast_int = tab_uintsize[a.get_size()]
+    e= []
+    c= ExprOp('&', b, ExprInt(cast_int(b.get_size() - 1)))
+    d= ExprOp('>>', a, c)
+    m= ExprOp('!', ExprOp('<<', ExprInt(cast_int(1)), b))
+    e.append(ExprAff(cf, ExprOp('&', d, ExprInt(cast_int(1)))))
+    e.append(ExprAff(a, ExprOp('&', a, m)))
+    return e
+
+
+def into():
+    return []
+
+def l_in(a, b):
+    return []
+
+def cmpxchg(a, b, c):
+    e = []
+    cast_int = tab_uintsize[a.get_size()]
+
+    cond = ExprOp('==', a, c )
+    e.append(ExprAff(zf, cond))
+    e.append(ExprAff(c, ExprCond(cond,
+                                 b,
+                                 c)
+                     ))
+    e.append(ExprAff(a, ExprCond(cond,
+                                 a,
+                                 c)
+                     ))
+    return e
+    
+    
+    
+mnemo_func = {'mov': mov,
+              'xchg': xchg,
+              'movzx': movzx,
+              'movsx': movsx,
+              'lea': lea,
+              'add':add,
+              'xadd':xadd,
+              'adc':adc,
+              'sub':sub,
+              'sbb':sbb,
+              'neg':neg,
+              'not':l_not,
+              'cmp':l_cmp,
+              'xor':xor,
+              'or':l_or,
+              'and':l_and,
+              'test':l_test,
+              'rol':l_rol,
+              'ror':l_ror,
+              'rcl':rcl,
+              'rcr':rcr,
+              'sar':sar,
+              'shr':shr,
+              'shrd_cl':shrd_cl,              
+              'sal':sal,
+              'shl':shl,
+              'shld_cl':shld_cl,
+              'cmc':cmc,
+              'clc':clc,
+              'stc':stc,
+              'cld':cld,
+              'std':std,
+              'cli':cli,
+              'sti':sti,
+              'bsf':bsf,
+              'bsr':bsr,
+              'inc':inc,
+              'dec':dec,
+              'push':push,
+              'pop':pop,
+              'sete':sete,
+              'setnz':setnz,
+              'setl':setl,
+              'setg':setg,
+              'setge':setge,
+              'seta':seta,
+              'setb':setb,
+              'setns':setns,
+              'sets':sets,
+              'seto':seto,
+              'bswap':bswap,
+              'cmpsb':cmpsb,
+              'cmpsw':cmpsw,
+              'cmpsd':cmpsd,
+              'scasb':scasb,
+              'scasw':scasw,
+              'scasd':scasd,
+              'pushfd':pushfd,
+              'pushfw':pushfw,
+              'popfd':popfd,
+              'pushad':pushad,
+              'popad':popad,
+              'call':call,
+              'ret':ret,
+              'leave':leave,
+              'enter':enter,
+              'jmp':jmp,
+              'jz':jz,
+              'je':jz,
+              'jnz':jnz,
+              'jp':jp,
+              'jnp':jnp,
+              'ja':ja,
+              'jae':jae,
+              'jb':jb,
+              'jbe':jbe,
+              'jg':jg,
+              'jge':jge,
+              'jl':jl,
+              'jle':jle,
+              'js':js,
+              'jns':jns,
+              'jo':jo,
+              'jno':jno,
+              'loop':loop,
+              'loopne':loopne,
+              'div':div,
+              'mul':mul,
+              'imul':imul,
+              'idiv':idiv,
+              'cdq':cdq,
+              'cbw':cbw,
+              'daa':daa,
+              'aam':aam,
+              'aad':aad,
+              'aaa':aaa,
+              'shrd':shrd,
+              'stosb':stosb,
+              'stosw':stosw,
+              'stosd':stosd,
+              'lodsb':lodsb,
+              'lodsw':lodsw,
+              'lodsd':lodsd,
+              'movsb':movsb,
+              'movsw':movsw,
+              'movsd':movsd,
+              'fcomp':fcomp,
+              'nop':nop,
+              'fnop':nop, #XXX
+              'hlt':hlt,
+              'rdtsc':rdtsc,
+              'fst':fst,
+              'fstp':fstp,
+              'fist':fist,
+              'fistp':fistp,
+              'fld':fld,
+              'fldz':fldz,
+              'fild':fild,
+              'fadd':fadd,
+              'fnstsw':fnstsw,
+              'fnstcw':fnstcw,
+              'fldcw':fldcw,
+              'fwait':fwait,
+              'sidt':sidt,
+              'arpl':arpl,
+              'cmovz':cmovz,
+              'cmove':cmovz,
+              'cmovnz':cmovnz,
+              'int':l_int,
+              'xlat': xlat,
+              'bt':bt,
+              'cpuid':cpuid,
+              'jo': jo,
+              'fcom':fcom,
+              'ficom':ficom,
+              'ins':ins,
+              'btc':btc,
+              'bts':bts,
+              'btr':btr,
+              'into':into,
+              'in':l_in,
+              'outs':l_outs,
+              "sysenter":l_sysenter,
+              "cmpxchg":cmpxchg,
+              }
+
+
+
+class ia32_rexpr:
+
+    noad = "no_ad"
+    ad = "ad"
+
+    ad8 = "ad8"
+    ad16 = "ad16"
+    ad32 = "ad32"
+    segm = "segm"
+
+    size = "size"
+
+    symb = "symb__intern__"
+
+    imm = "imm"
+    s08 = "s08"
+    u08 = "u08"
+    u16 = "u16"
+    s16 = "s16"
+    u32 = "u32"
+    s32 = "s32"
+
+    f32 = "f32"
+    f64 = "f64"
+
+    im1 = "im1"
+    im3 = "im3"
+    ims = "ims"
+    mim = "mim"
+
+
+    dict_size = {imm:'imm',
+                      s08:'b',
+                      u08:'B',
+                      s16:'h',
+                      u16:'H',
+                      s32:'i',
+                      u32:'I',
+                      }
+                      
+
+    
+    r_eax = eax
+    r_ecx = ecx
+    r_edx = edx
+    r_ebx = ebx
+    r_esp = esp
+    r_ebp = ebp
+    r_esi = esi
+    r_edi = edi
+    
+    r_dr0 = dr0
+    r_dr1 = dr1
+    r_dr2 = dr2
+    r_dr3 = dr3
+    r_dr4 = dr4
+    r_dr5 = dr5
+    r_dr6 = dr6
+    r_dr7 = dr7
+    
+    r_cr0 = cr0
+    r_cr1 = cr1
+    r_cr2 = cr2
+    r_cr3 = cr3
+    r_cr4 = cr4
+    r_cr5 = cr5
+    r_cr6 = cr6
+    r_cr7 = cr7
+    
+    r_ax = r_eax[:16]
+    r_cx = r_ecx[:16]
+    r_dx = r_edx[:16]
+    r_bx = r_ebx[:16]
+    r_sp = r_esp[:16]
+    r_bp = r_ebp[:16]
+    r_si = r_esi[:16]
+    r_di = r_edi[:16]
+         
+    r_al = r_eax[:8]
+    r_cl = r_ecx[:8]
+    r_dl = r_edx[:8]
+    r_bl = r_ebx[:8]
+    r_ah = r_eax[8:16]
+    r_ch = r_ecx[8:16]
+    r_dh = r_edx[8:16]
+    r_bh = r_ebx[8:16]
+
+
+    r_es = es
+    r_cs = cs
+    r_ss = ss
+    r_ds = ds
+    r_fs = fs
+    r_gs = gs
+
+    reg_list8 =[r_al,  r_cl,  r_dl,  r_bl,
+                     r_ah,  r_ch,  r_dh,  r_bh]
+    reg_list16=[r_ax,  r_cx,  r_dx,  r_bx,
+                     r_sp,  r_bp,  r_si,  r_di]
+    reg_list32=[r_eax, r_ecx, r_edx, r_ebx,
+                     r_esp, r_ebp, r_esi, r_edi]
+
+    reg_listsg=[r_es,  r_cs,  r_ss,  r_ds,
+                     r_fs,  r_gs]
+    reg_listdr=[r_dr0, r_dr1, r_dr2, r_dr3, r_dr4, r_dr5, r_dr6, r_dr7]
+    reg_listcr=[r_cr0, r_cr1, r_cr2, r_cr3, r_cr4, r_cr5, r_cr6, r_cr7]
+
+    reg_flt = [float_st0, float_st1, float_st2, float_st3, float_st4, float_st5, float_st6, float_st7]
+
+    reg_dict = {}
+    for i in range(8):
+        reg_dict[reg_list8[i]] = i
+    for i in range(8):
+        reg_dict[reg_list16[i]] = i
+    for i in range(8):
+        reg_dict[reg_list32[i]] = i
+    for i in range(8):
+        reg_dict[reg_flt[i]] = i
+
+
+
+def dict_to_Expr(d, modifs = {}, mnemo_mode = x86_afs.u32):
+    size = [x86_afs.u32, x86_afs.u08][modifs[w8]==True]
+    #overwrite w8
+    if modifs[sd]!=None:
+        size = [x86_afs.f32, x86_afs.f64][modifs[sd]==True]
+    if modifs[wd]:
+        size = x86_afs.u16
+
+                
+    tab32 = {ia32_rexpr.u08:ia32_rexpr.reg_list8, ia32_rexpr.u16:ia32_rexpr.reg_list16, ia32_rexpr.u32:ia32_rexpr.reg_list32,ia32_rexpr.f32:ia32_rexpr.reg_flt}
+    tab16 = {ia32_rexpr.u08:ia32_rexpr.reg_list8, ia32_rexpr.u16:ia32_rexpr.reg_list32, ia32_rexpr.u32:ia32_rexpr.reg_list16}
+    ad_size = {ia32_rexpr.u08:ia32_rexpr.u08, ia32_rexpr.u16:ia32_rexpr.u16, ia32_rexpr.u32:ia32_rexpr.u32, ia32_rexpr.f32:ia32_rexpr.u32, ia32_rexpr.f64:ia32_rexpr.u32}
+
+    if is_reg(d):
+        n = [x for x in d if type(x) in [int, long]]
+        if len(n)!=1:
+            raise "bad reg! %s"%str(d)
+        n = n[0]
+        if x86_afs.size in d and d[x86_afs.size] == x86_afs.size_seg :
+            t = ia32_rexpr.reg_listsg
+        elif ia32_rexpr.size in d:
+            my_s = d[x86_afs.size]
+            if my_s == x86_afs.f64:
+                my_s = x86_afs.u32
+            t = tab32[my_s]
+        else:
+            if mnemo_mode == u32:
+                t = tab32[size]
+            else:
+                t = tab16[size]
+        if modifs[dr] and n>0x7:
+            t = ia32_rexpr.reg_listdr
+            n&=7
+        if modifs[cr] and n>0x7:
+            t = ia32_rexpr.reg_listcr
+            n&=7
+        if modifs[sg] and n>0x7:
+            t = ia32_rexpr.reg_listsg
+            n&=7
+        if modifs[sd] is not None:
+            t = tab32[size]
+            n&=7
+        
+        out = t[n]
+    elif is_imm(d):
+        if ia32_rexpr.imm in d:
+            #test bug imm 16b
+            if mnemo_mode == x86_afs.u16:
+                if size == x86_afs.u16:
+                    size = x86_afs.u32
+                else:
+                    size = x86_afs.u16
+        
+            
+            #print d
+            out = ExprInt(tab_afs_int[size](d[ia32_rexpr.imm]))
+        if ia32_rexpr.symb in d:
+            if len(d[ia32_rexpr.symb])!=1:
+                raise "not impl symb diff 1:x",str(d[ia32_rexpr.symb])
+            myname = d[ia32_rexpr.symb].keys()[0]
+            myval = myname.offset
+            if myname.offset == None:
+                return ExprId(myname.name)
+
+
+            #XXX todo hack gen C
+            return ExprInt(uint32(myval))
+            if type(myname)!=str:
+                return ExprId(myname.name)
+            return ExprInt(uint32(myval))
+    elif is_address(d):
+        
+        size = {ia32_rexpr.u08:8, ia32_rexpr.u16:16, ia32_rexpr.u32:32, ia32_rexpr.f32:32, ia32_rexpr.f64:64}[size]
+        
+        if ia32_rexpr.size in d:
+            size = d[ia32_rexpr.size]
+        msize = {ia32_rexpr.u08:8, ia32_rexpr.u16:16, ia32_rexpr.u32:32, ia32_rexpr.f32:32, ia32_rexpr.f64:64}
+        if size in msize:
+            size = msize[size]
+        if ia32_rexpr.segm in d:
+            pass
+        out = []
+        for k in d:
+            if k in [ia32_rexpr.ad, ia32_rexpr.size]:
+                continue
+            elif k in [ia32_rexpr.segm]:
+                if d[k] == 4:
+                    out.append(ExprInt(uint32(0x7FF70000)))
+            elif k == ia32_rexpr.imm:
+                out.append(ExprInt(d[k]))
+            elif type(k) in [int, long]:
+                if d[k] ==1:
+                    out.append(ia32_rexpr.reg_list32[k])
+                else:
+                    out.append(ExprOp('*', ExprInt(uint32(d[k])), ia32_rexpr.reg_list32[k]))
+            elif k == ia32_rexpr.symb:
+                print 'warning: symbol.. in mem look', d[k]
+                out.append(ExprId(str(d[k].items()[0][0].name)))
+            else:
+                raise 'strange ad componoant: %s'%str(d)
+        if not out:
+            raise 'arg zarb expr %s'%str(d)
+        e = out[0]
+        for o in out[1:]:
+            e = ExprOp('+', e, o)
+        out = ExprMem(e, size)
+        
+    else:
+        raise 'unknown arg %s'%str(d)
+    return out
+
+
+
diff --git a/miasm/arch/ppc_arch.py b/miasm/arch/ppc_arch.py
new file mode 100644
index 00000000..8cb66b2d
--- /dev/null
+++ b/miasm/arch/ppc_arch.py
@@ -0,0 +1,2294 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+import shlex
+import struct
+
+from miasm.core.bin_stream import bin_stream
+
+
+def hex2bin(op):
+    out = []
+    for i in xrange(31, -1, -1):
+        out.append(str((op>>i)&1))
+    for i in xrange(32, -1,  -4):
+        out[i:i] = ' '
+    return "".join(out)
+
+def myrol(v, r):
+    return ((v&0xFFFFFFFFL)>>r)  | ((v << (32-r))&0xFFFFFFFFL)
+
+def str2imm(i):
+    if i.startswith('0x') or i.startswith('-0x'):
+        d =16
+    else:
+        d = 10
+    try:
+        a = int(i, d)
+    except:
+        return False
+    return a
+    
+def imm2str(i):
+    if type(i) in [int, long]:
+        if i<0:
+            return "-0x%x"%-i
+        else:
+            return "0x%x"%i
+    return str(i)
+
+def is_imm(i):
+    return type(str2imm(i)) is not bool
+
+class bm_meta(type):
+    def __new__(cls, name, bases, odct):
+        if name is "bm":
+            return type.__new__(cls, name, bases, odct)
+        dct = {'fbits':None, 'l':None, "p_property":[], "checkinv" : False}
+        dct.update(odct)
+
+        pname = None
+        if name.startswith('bm_'):
+            pname = name[3:]
+            dct["p_property"] = [pname]+dct["p_property"]
+        
+        b = bases[0]
+        
+        dct["check"] = b.check_no
+        l = dct["l"]
+        fbits = dct["fbits"]
+        if fbits:
+            l = len(fbits)
+            allbits = list(fbits)
+            allbits.reverse()
+            fbits = 0
+            fmask = 0
+            while allbits:
+                a = allbits.pop()
+                if a in '01':
+                    a = int(a)
+                fbits<<=1
+                fmask<<=1
+                fbits|=[0, a][type(a) is int]
+                fmask|=[0, 1][type(a) is int]
+            dct["l"] = l
+            dct["fbits"] = fbits
+            #for bm int
+            if pname:
+                dct[pname] = fbits
+            dct['fmask'] = fmask
+            if dct['checkinv']:
+                dct["check"] = b.check_fbits_inv
+            else:
+                dct["check"] = b.check_fbits
+                
+        p_property = dct["p_property"]
+            
+        for p in p_property:
+            dct["get_"+p] = lambda self, p=p:getattr(self, p)
+            dct["set_"+p] = lambda self, p=p:setattr(self, p)
+        return type.__new__(cls, name, bases, dct)
+    
+
+class bm(object):
+    __metaclass__ = bm_meta
+    def __init__(self, parent, off, set_at = True):
+        self.parent = parent
+        self.off = off-self.l
+    def __repr__(self):
+        return "<W-"+str(self.__class__)+str(self.off+self.l-1)+" "+str(self.off)+">"
+    def check_no(self, v):
+        return True
+    def check_fbits(self, v):
+        return (v>>self.off) & self.fmask == self.fbits
+    def check_fbits_inv(self, v):
+        return (v>>self.off) & self.fmask != self.fbits
+
+    def get_val(self, v):
+        return (v>>self.off) & ((1<<self.l)-1)
+    def set_val(self, v = None):
+        
+        if v == None and len(self.p_property) >= 1:
+            p = self.p_property[0]
+            v = getattr(self, p)
+        return (v&((1<<self.l)-1))<<self.off 
+
+    def bin(self):
+        return self.set_val()
+        
+    def parse(self, v):
+        if len(self.p_property) >= 1:
+            p = self.p_property[0]
+            val = self.get_val(v)
+            setattr(self, p, val)
+        return True
+    def setprop(self, val = None):
+        if len(self.p_property) >= 1:
+            p = self.p_property[0]
+            if not hasattr(self, p):
+                setattr(self, p, None)
+
+
+all_bm_int = []
+for i in xrange(0x40):
+    mask_str = hex2bin(i).replace(' ', '')[26:]
+    while mask_str:
+        bstr = "bm_int"+mask_str
+        globals()[bstr] = bm_meta(bstr,(bm,),{"fbits":mask_str})
+        if mask_str[0] !='0':
+            break
+        mask_str = mask_str[1:]
+    
+
+class bm_set_meta(type):
+    def __new__(cls, name, bases, odct):
+        if not 'l' in odct:
+            odct['l'] = 9
+        return type.__new__(cls, name, bases, odct)
+
+
+class bm_set(object):
+    __metaclass__ = bm_set_meta
+    def __init__(self, parent, off):
+        self.parent = parent
+        self.off = 32-off-self.l
+        self.fmask = (1<<self.l)-1
+    def check(self, v):
+        return (v>>self.off) & self.fmask in self.fbits
+    
+
+COND_EQ = 0
+COND_NE = 1
+COND_CS = 2
+COND_CC = 3
+COND_MI = 4
+COND_PL = 5
+COND_VS = 6
+COND_VC = 7
+COND_HI = 8
+COND_LS = 9
+COND_GE = 10
+COND_LT = 11
+COND_GT = 12
+COND_LE = 13
+COND_AL = 14
+COND_NV = 15
+
+class bm_cond(bm):
+    l = 4
+    p_property = ["cond2str", 'str2cond']
+    n = ['EQ', 'NE', 'CS', 'CC', 'MI', 'PL', 'VS', 'VC', 'HI', 'LS', 'GE', 'LT', 'GT', 'LE', 'AL', 'NV']
+
+    def cond2str(self):
+        return self.n[self.cond]
+
+    def str2cond(self, cond):
+        if not cond in self.n:
+            raise ValueError('unknown cond')
+        self.cond = self.n.index(cond)    
+    
+class bm_int000000000(bm):
+    fbits = '000000000'
+
+class bm_accum(bm):
+    l = 1
+    n = ['MUL', 'MLA']
+    def name2str(self):
+        return self.n[self.accum]
+
+    def str2name(self, name):
+        if not name in self.n:
+            raise ValueError('unknown name')
+        self.accum = self.n.index(name)
+
+class bm_immop(bm):
+    l = 1
+
+class bm_opsz(bm):
+    l = 1
+
+class bm_szext(bm):
+    l = 2
+
+class bm_rot(bm):
+    l = 2
+
+class bm_scc(bm):
+    l = 1
+    p_property = ["scc2str"]
+    def scc2str(self):
+        return ['', 'S'][self.scc==1]
+
+class bm_lnk(bm):
+    l = 1
+    p_property = ["lnk2str"]
+    def lnk2str(self):
+        return ['', 'L'][self.lnk==1]
+
+class bm_offs(bm):
+    l = 24
+
+    def parse(self, v):
+        val = self.get_val(v)
+        val<<=2
+        if val & (1<<25):
+            val |=0xFC000000
+        self.offs = val
+        return True
+    def bin(self):
+        v = (self.offs>>2)&0xffffff
+        return self.set_val(v)
+
+class bm_cooff(bm):
+    l = 8
+
+    def parse(self, v):
+        val = self.get_val(v)
+        val<<=2
+        self.cooff = val
+        return True
+    def bin(self):
+        v = (self.cooff>>2)&0xff
+        return self.set_val(v)
+
+class bm_size(bm):
+    l = 1
+    p_property = ["size2str"]
+    def size2str(self):
+        return ['', 'B'][self.size==1]
+
+class bm_tlen(bm):
+    l = 1
+
+class bm_ppndx(bm):
+    l = 1
+
+class bm_updown(bm):
+    l = 1
+
+class bm_psr(bm):
+    l = 1
+
+class bm_wback(bm):
+    l = 1
+
+class bm_ldst(bm):
+    l = 1
+
+class bm_reglist(bm):
+    l = 16
+
+    def parse(self, v):
+        val = self.get_val(v)
+        self.reglist = []
+        for i in xrange(0x10):
+            if val & (1<<i):
+                self.reglist.append(i)
+        return True
+    def bin(self):
+        v = 0
+        for r in self.reglist:
+            v|=(1<<r)
+        return self.set_val(v)
+
+
+class bm_rt(bm):
+    l = 5
+
+class bm_rs(bm):
+    l = 5
+
+class bm_ra(bm):
+    l = 5
+
+class bm_bo(bm):
+    l = 5
+
+class bm_bi(bm):
+    l = 5
+
+class bm_bd(bm):
+    l = 14
+
+class bm_rb(bm):
+    l = 5
+
+class bm_oe(bm):
+    l = 1
+
+class bm_rc(bm):
+    l = 1
+
+class bm_opc5(bm):
+    l = 5
+
+class bm_opc9(bm):
+    l = 9
+
+class bm_opc10(bm):
+    l = 10
+
+class bm_nb(bm):
+    l = 5
+
+class bm_spr(bm):
+    l = 10
+
+class bm_sr(bm):
+    l = 4
+
+class bm_mb(bm):
+    l = 5
+
+class bm_me(bm):
+    l = 5
+
+class bm_sh(bm):
+    l = 5
+
+class bm_to(bm):
+    l = 5
+
+class bm_fra(bm):
+    l = 5
+
+class bm_frb(bm):
+    l = 5
+
+class bm_frc(bm):
+    l = 5
+
+class bm_frt(bm):
+    l = 5
+
+
+
+
+
+
+class bm_simm(bm):
+    l = 16
+
+class bm_uimm(bm):
+    l = 16
+
+class bm_li(bm):
+    l = 24
+
+class bm_aa(bm):
+    l = 1
+
+class bm_lk(bm):
+    l = 1
+
+class bm_bf(bm):
+    l = 3
+
+class bm_bfa(bm):
+    l = 3
+
+class bm_bt(bm):
+    l = 5
+
+class bm_ba(bm):
+    l = 5
+ 
+class bm_bb(bm):
+    l = 5
+           
+class bm_rn(bm):
+    l = 4
+
+
+class bm_rdh(bm):
+    l = 4
+
+class bm_rdl(bm):
+    l = 4
+
+    
+class ppc_mnemo_metaclass(type):
+    global tab_mn
+    def __call__(cls, op, offset = 0):
+        if type(op) in [int, long]:
+            cls = cls.class_from_op(op)
+            i = cls.__new__(cls)
+            i.__init__(op, offset)
+        elif type(op) is str:
+            cls = cls.asm(op)
+            i = cls.__new__(cls)
+            i.__init__(op, 0, False)
+        else:
+            raise ValueError('zarb arg')
+        return i
+        
+    def class_from_op(cls, op):
+        ret = filter(lambda x:x.check(op), tab_mn)
+        if len(ret)==1:
+            return ret[0]
+        raise ValueError('ambiquity %s'%str(ret))
+
+
+    def dis(cls, bin, *kargs):
+        if type(bin) == str:
+            bin = bin_stream(bin)
+        elif not isinstance(bin, bin_stream):
+            raise ValueError('unknown input')
+
+        op = bin.readbs(4)
+        op = struct.unpack('>L', op)[0]
+        return cls(op, bin.offset-4)
+        
+
+    def asm(cls, txt, symbol_reloc_off = []):
+        print txt
+        t = ppc_mn.pre_parse_mnemo(txt)
+        name = t.pop()
+        ret = filter(lambda x:x.check_mnemo(name), tab_mn)
+        if len(ret)!=1:
+            raise ValueError('parse name err %s'%str(ret))
+        cls = ret[0]
+        i = cls.__new__(cls)
+        i.__init__(txt, 0, False)
+        return [struct.pack('>L', i.bin())]
+        
+    def __new__(cls, name, bases, dct):
+        ret_c = type.__new__(cls, name, bases, dct)
+        if name is "ppc_mn":
+            return ret_c
+
+        mask = []
+        if 'mask' in dct:
+            for off in dct['mask']:
+                mc = dct['mask'][off](None, off)#+1)
+                mask.append(mc)
+            
+        mask_orig = dct["mask_list"]
+        ret_c.mask_orig = mask_orig
+        off = 32
+        for m in mask_orig:
+            mc = m(None, off)
+            off-=mc.l
+            mask.append(mc)
+            for pname in m.p_property:
+                pfunc = "get_"+pname
+                p = property(lambda self=ret_c, pname=pname:getattr(getattr(self, "bm_"+pname), pname),
+                             lambda self=ret_c,val=None,pname=pname:setattr(getattr(self, "bm_"+pname), pname, val))
+                
+                setattr(ret_c, pname, p)
+                
+        if off!=0:
+            raise ValueError('invalid mnemonic %d'%off)
+        ret_c.mask_chk = mask
+
+        #gen arg parser/generator if present
+        if 'do_args' in dct:
+            ret_c.args_list = dct['do_args']
+
+            args2str_f = None
+            parse_args_f = None
+            for tmp_cls in bases:
+                if 'gen_args2str' in tmp_cls.__dict__:
+                    args2str_f = tmp_cls.__dict__['gen_args2str']
+                if 'gen_parse_args' in tmp_cls.__dict__:
+                    parse_args_f = tmp_cls.__dict__['gen_parse_args']
+
+            ret_c.args2str = args2str_f
+            ret_c.parse_args = parse_args_f
+
+        return ret_c
+
+    def check(self, op):
+        for m in self.mask_chk:
+            if m.fbits==None:
+                continue
+            if not m.check(op):
+                return False
+        return True
+
+    def check_opts(self, rest):
+        if rest:
+            return False
+        return True
+
+    def check_mnemo(self, mnemo):
+        found = False
+        for n in self.namestr:
+            if mnemo.startswith(n):
+                found = True
+                break
+        if not found:
+            return False
+        rest = mnemo[len(n):]
+        return self.check_opts(rest)
+
+    def pre_parse_mnemo(cls, args):
+        tmp = args.replace(',', ' ')
+        t = []
+        is_minux = False
+        for x in shlex.shlex(tmp):
+            if x == '-':
+                is_minux = True
+                continue
+            if is_minux:
+                x = '-'+x
+                is_minux = False
+            
+            if x == '.':
+                t[-1]+=x
+            else:
+                t.append(x)
+                
+        t.reverse()
+        return t
+    
+    def parse_mnemo(cls, args):
+        t = cls.pre_parse_mnemo(args)
+        t.reverse()
+        return [], t[0], t[1:]
+    
+    def parse_address(self, a):
+        return parse_ad(a)
+    def prefix2hex(self, p):
+        return ""
+
+regs_str = ['R%d'%r for r in xrange(0x20)]
+regs_str[1] = 'SP'
+
+cop_str = ['P%d'%r for r in xrange(0x10)]
+copr_str = ['C%d'%r for r in xrange(0x10)]
+
+crb_str = []
+for i in xrange(0x8):
+    for x in ['LT', 'GT', 'EQ', 'SO']:
+        crb_str.append('CR%d_%s'%(i, x))
+        
+cr_str = ['CR%d'%r for r in xrange(0x8)]
+fpr_str = ['FP%d'%r for r in xrange(0x20)]
+spr_str = ['SPR%d'%r for r in xrange(0x400)]
+spr_str[256] = 'LR'
+spr_str[392] = 'BL'
+spr_str[424] = 'BU'
+spr_str[832] = 'SR0'
+spr_str[864] = 'SR1'
+spr_str[529] = 'IC_CSR'
+spr_str[964] = 'ICTRL'
+spr_str[288] = 'CTR'
+
+sr_str = ['SR%d'%r for r in xrange(0x10)]
+
+all_regs = regs_str+cop_str+copr_str+cr_str+crb_str+fpr_str+spr_str
+
+from ia32_reg import x86_afs
+
+
+def is_symbol(a):
+    if is_imm(a) or a in all_regs:
+        return False
+    return True
+        
+def parse_ad(a):
+    a = a.strip()
+    if is_symbol(a):
+        print 'SYMBOL!', a
+        return {x86_afs.symb:{a:1}}
+    else:
+        return {0x1337:1}
+
+
+def reg2str(r):
+    return regs_str[r]
+def str2reg(r):
+    return regs_str.index(r)
+
+
+def cr2str(r):
+    return cr_str[r]
+def str2cr(r):
+    return cr_str.index(r)
+
+def crb2str(r):
+    return crb_str[r]
+def str2crb(r):
+    return crb_str.index(r)
+
+
+def fpr2str(r):
+    return fpr_str[r]
+def str2fpr(r):
+    return fpr_str.index(r)
+
+def spr2str(r):
+    return spr_str[r]
+def str2spr(r):
+    return spr_str.index(r)
+
+
+def sr2str(r):
+    return sr_str[r]
+def str2sr(r):
+    return sr_str.index(r)
+
+class reg:
+    @classmethod
+    def str(cls, r):
+        return reg2str(r)
+    @classmethod
+    def cls(cls, r):
+        return str2reg(r)
+
+class imm:
+    @classmethod
+    def str(cls, r):
+        return imm2str(r)
+    @classmethod
+    def cls(cls, r):
+        return str2imm(r)
+
+class crb:
+    @classmethod
+    def str(cls, r):
+        return crb2str(r)
+    @classmethod
+    def cls(cls, r):
+        return str2crb(r)
+        
+
+class fpr:
+    @classmethod
+    def str(cls, r):
+        return fpr2str(r)
+    @classmethod
+    def cls(cls, r):
+        return str2fpr(r)
+        
+
+class cr:
+    @classmethod
+    def str(cls, r):
+        return cr2str(r)
+    @classmethod
+    def cls(cls, r):
+        return str2cr(r)    
+
+class spr:
+    @classmethod
+    def str(cls, r):
+        return spr2str(r)
+    @classmethod
+    def cls(cls, r):
+        return str2spr(r)
+
+class sr:
+    @classmethod
+    def str(cls, r):
+        return sr2str(r)
+    @classmethod
+    def cls(cls, r):
+        return str2sr(r)
+
+def args2reduce(args):
+    out = []
+    for a in args:
+        if type(a) is list:
+            out+=args2reduce(a)
+        else:
+            out.append(a)
+    return out
+
+def arglist2str(args):
+    out = ""
+    for a in args:
+        if a in ['[', ']', 'LSL', 'LSR', 'ASR', 'ROR']:
+            out+=a+' '
+        else:
+            out+=a
+            out+=', '
+    if out.endswith(', '):
+        out = out[:-2]
+    return out
+
+
+def args2str(args):
+    return arglist2str(args2reduce(args))
+            
+       
+class ppc_mn(object):
+    mask_list = []
+    __metaclass__ = ppc_mnemo_metaclass
+
+    
+    def gen_args2str(self):
+        args = []
+        for r, t in self.args_list:
+            args.append(t.str(getattr(self, r)))
+        return args
+
+    def gen_parse_args(self, args):
+        for r, t in self.args_list:
+            setattr(self, r, t.cls(args.pop()))
+
+    def __init__(self, op, offset = 0, dis = True):
+        off=32
+        mask = []
+        self.offset = offset
+        self.l = 4
+        self.m = None
+        self.arg = []
+        
+        for m in self.mask_orig:
+            mc = m(self, off)            
+            off-=mc.l
+            for pname in m.p_property:
+                setattr(self, "bm_"+pname, mc)
+            mask.append(mc)
+        self.mask = mask
+        
+        if dis:
+            for m in self.mask:
+                ret = m.parse(op)
+                if not ret:
+                    raise ValueError('cannot parse %.8X'%op)
+        else:
+            for m in self.mask:
+                ret = m.setprop()
+            
+            full_mnemo = ppc_mn.pre_parse_mnemo(op)
+            mnemo = full_mnemo.pop()
+            name, rest = self.parse_name_cond(mnemo)
+            self.name = name
+            self.parse_opts(rest)
+            self.str2name(name)
+
+            mnemo_nosymb = []
+            for a in full_mnemo:
+                if not is_symbol(a) or a in bm_cond.n:
+                    mnemo_nosymb.append(a)
+                    continue
+                print "WARNING asm symb", a
+                mnemo_nosymb.append("0")
+            full_mnemo = mnemo_nosymb
+            
+            self.parse_args(full_mnemo)
+
+    def parse_opts(self, rest):
+        if rest:
+            raise ValueError('should not have rest here ', rest)
+        pass
+    def str2name(self, n):
+        pass
+    
+    def getname(self):
+        name = self.name2str()+self.oe2str()+self.rc2str()
+        return name
+
+    def bin(self):
+        v = 0
+        for m in self.mask:
+            if not m.checkinv:
+                v|=m.bin()
+        return v
+
+    def args2str(self):
+        args = ["NO ARGS"]
+        return args
+
+    def __str__(self):
+        name = self.getname()
+        args = self.args2str()
+        args = args2str(args)
+        return name+" "+args
+
+    def parse_name_cond(self, mnemo):
+        name = None
+        for i, n in enumerate(self.namestr):
+            if mnemo.startswith(n):
+                name = n
+                break
+        if name == None:
+            raise ValueError('cannot parse name')
+
+        rest = mnemo[len(n):]
+        return name, rest
+
+    def oe2str(self):
+        return ""
+    def rc2str(self):
+        return ""
+    
+
+    def breakflow(self):
+        return False
+    def splitflow(self):
+        return False
+    def dstflow(self):
+        return False
+
+    def getnextflow(self):
+        return self.offset+self.l
+
+    def fix_symbol(self, s):
+        pass
+
+
+MN_AND = 0
+MN_EOR = 1
+MN_SUB = 2
+MN_RSB = 3
+MN_ADD = 4
+MN_ADC = 5
+MN_SBC = 6
+MN_RSC = 7
+MN_TST = 8
+MN_TEQ = 9
+MN_CMP = 10
+MN_CMN = 11
+MN_ORR = 12
+MN_MOV = 13
+MN_BIC = 14
+MN_MVN = 15
+
+class ppc_add(ppc_mn):
+    mask_list = [bm_int011111, bm_rt, bm_ra, bm_rb, bm_oe, bm_opc9, bm_rc]
+    namestr = ['ADDE', 'ADDC', 'ADD', 'DIVWU', "DIVW", 'MULLW', 'SUBFC', 'SUBFE', 'SUBF']
+    namsdct = {'ADD':266, 'ADDC':10, 'ADDE':138, 'DIVWU':459, 'DIVW':491, 'MULLW':235, 'SUBFC':8, 'SUBF':40, 'SUBFE':136}
+    mask = {22:bm_set_meta("bm_addopc",(bm_set,),{"fbits":namsdct.values()})}
+
+    strname = dict((x[1], x[0]) for x in namsdct.items())
+
+    do_args = [('rt',reg), ('ra',reg), ('rb',reg)]
+    
+    def name2str(self):
+        return self.strname[self.opc9]
+    def str2name(self, n):
+        self.opc9 = self.namsdct[n]
+    @classmethod
+    def check_opts(cls, rest):
+        if rest in ["", ".", "O", "O."]:
+            return True
+        return False
+
+
+    def parse_opts(self, opts):
+        self.oe = 0
+        self.rc = 0
+        if not opts:
+            return
+        if "O" in opts:
+            self.oe = 1
+        if "." in opts:
+            self.rc = 1
+
+    def oe2str(self):
+        return ['','O'][self.oe==1]
+    def rc2str(self):
+        return ['','.'][self.rc==1]
+
+
+class ppc_addi(ppc_mn):
+    mask_list = [bm_int001110, bm_rt, bm_ra, bm_simm]
+    namestr = ['ADDI', 'LI']
+
+    def name2str(self):
+        if self.ra == 0:
+            return self.namestr[1]
+        return self.namestr[0]
+    
+    def args2str(self):
+        args = []
+        args.append(reg2str(self.rt))
+        if self.ra!=0:
+            args.append(reg2str(self.ra))
+        args.append(imm2str(self.simm))
+        return args
+
+    def parse_args(self, args):
+        self.ra = 0
+        self.rt = str2reg(args.pop())
+        if len(args)==2:
+            self.ra = str2reg(args.pop())
+        self.simm = str2imm(args.pop())
+
+
+
+class ppc_addic(ppc_addi):
+    mask_list = [bm_int001100, bm_rt, bm_ra, bm_simm]
+    namestr = ['ADDIC']
+
+
+class ppc_addicp(ppc_addi):
+    mask_list = [bm_int001101, bm_rt, bm_ra, bm_simm]
+    namestr = ['ADDIC.']
+
+class ppc_addis(ppc_addi):
+    mask_list = [bm_int001111, bm_rt, bm_ra, bm_simm]
+    namestr = ['ADDIS', 'LIS']
+
+
+class ppc_adde(ppc_mn):
+    mask_list = [bm_int011111, bm_rt, bm_ra, bm_int00000, bm_oe, bm_opc9, bm_rc]
+    namestr = {'ADDME':234, 'ADDZE':202, 'NEG':104, 'SUBFME':232, 'SUBFZE':200}
+    
+    mask = {22:bm_set_meta("bm_addeopc",(bm_set,),{"fbits":namestr.values()})}
+    
+    strname = dict((x[1], x[0]) for x in namestr.items())
+
+    do_args = [('rt',reg), ('ra',reg)]
+    
+    def name2str(self):
+        return self.strname[self.opc9]
+    def str2name(self, n):
+        self.opc9 = self.namestr[n]
+    @classmethod
+    def check_opts(cls, rest):
+        if rest in ["", ".", "O", "O."]:
+            return True
+        return False
+
+    def oe2str(self):
+        return ['','O'][self.oe==1]
+    def rc2str(self):
+        return ['','.'][self.rc==1]
+
+    def parse_opts(self, opts):
+        self.oe = 0
+        self.rc = 0
+        if not opts:
+            return
+        if "O" in opts:
+            self.oe = 1
+        if "." in opts:
+            self.rc = 1
+
+
+class ppc_and(ppc_mn):
+    mask_list = [bm_int011111, bm_rs, bm_ra, bm_rb, bm_opc10, bm_rc]
+    namestr = ['ANDC', 'AND', 'EQV', 'NAND', 'NOR', 'ORC', 'OR', 'SLW', 'SRAW', 'SRW', 'XOR']
+    namedct = {'AND':28, 'ANDC':60, 'EQV':284, 'NAND':476, 'NOR':124, 'OR':444, 'ORC':412, 'SLW':24, 'SRAW':792, 'SRW':536, 'XOR':316}
+    mask = {21:bm_set_meta("bm_andopc",(bm_set,),{"fbits":namedct.values(), 'l':10})}
+
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('ra',reg), ('rs',reg), ('rb',reg)]
+    
+    def name2str(self):
+        return self.strname[self.opc10]
+    def str2name(self, n):
+        self.opc10 = self.namedct[n]
+    @classmethod
+    def check_opts(cls, rest):
+        if rest in ["", "."]:
+            return True
+        return False
+
+    def rc2str(self):
+        return ['','.'][self.rc==1]
+    
+
+    def parse_opts(self, opts):
+        self.rc = 0
+        if not opts:
+            return
+        if "." in opts:
+            self.rc = 1
+
+
+class ppc_andip(ppc_mn):
+    mask_list = [bm_int011100, bm_rs, bm_ra, bm_uimm]
+    namestr = ['ANDI.']
+
+    do_args = [('ra',reg), ('rs',reg), ('uimm',imm)]
+
+    
+    def name2str(self):
+        return self.namestr[0]
+
+
+class ppc_andisp(ppc_andip):
+    mask_list = [bm_int011101, bm_rs, bm_ra, bm_uimm]
+    namestr = ['ANDIS.']
+
+class ppc_b(ppc_mn):
+    mask_list = [bm_int010010, bm_li, bm_aa, bm_lk]
+    namestr = ['B']
+    def name2str(self):
+        return self.namestr[0]
+
+    @classmethod
+    def check_opts(cls, rest):
+        if rest in ["", "A", "L", "AL"]:
+            return True
+        return False
+
+    def getname(self):
+        name = "B"
+        if self.aa:
+            name+='A'
+        if self.lk:
+            name+='L'
+        return name
+
+    def args2str(self):
+        args = []
+        if type(self.li) in [int, long]:
+            args.append(imm2str(self.li<<2))
+        else:
+            args.append(str(self.li))
+        return args
+
+    def parse_args(self, args):
+        self.li = str2imm(args.pop())>>2
+
+    def parse_opts(self, opts):
+        self.aa = 0
+        self.lk = 0
+        if not opts:
+            return
+        if "A" in opts:
+            self.aa = 1
+        if "L" in opts:
+            self.lk = 1
+
+
+
+    def breakflow(self):
+        return True
+    def splitflow(self):
+        return self.lk
+    def dstflow(self):
+        return True
+
+    def getdstflow(self):
+        if type(self.li) in [int, long]:
+            li = self.li<<2
+            if li &(0x1<<25):
+                li |=0xFF000000
+            li = struct.unpack('L', struct.pack('L', li))[0]
+            if self.aa:
+                print "absolute jmp! default abs ad  0"
+                dst = (li)&0xFFFFFFFF
+            else:
+                dst = (self.offset+(li))&0xFFFFFFFF
+        else:
+            dst = self.li
+        return [dst]
+
+    def setdstflow(self, dst):
+        if len(dst)==0:
+            return
+        if len(dst)!=1:
+            raise ValueError('should be 1 dst')
+        l = dst[0]
+        self.li = l.name
+
+    def is_subcall(self):
+        return self.lk
+
+    def fixdst(self, lbls, my_offset, is_mem = False):
+        l = self.li
+        if self.aa:
+            self.li = lbls[l]>>2
+        else:
+            self.li = (lbls[l]+4-my_offset)>>2
+        
+
+
+class ppc_bc(ppc_mn):
+    mask_list = [bm_int010000, bm_bo, bm_bi, bm_bd, bm_aa, bm_lk]
+    namestr = ['B']
+    all_tests = ['GE', 'LE', 'NE', 'NS', 'LT', 'GT', 'EQ', 'SO']
+    def name2str(self):
+        return self.namestr[0]
+
+    @classmethod
+    def check_opts(cls, rest):
+        if not rest:
+            return False
+        if rest[0] == 'D':
+            rest = rest[1:]
+            if rest[0] == 'Z':
+                rest = rest[1:]
+            elif rest.startswith('NZ'):
+                rest = rest[2:]
+            else:
+                return False
+        elif rest[0] == 'C':
+            rest = rest[1:]
+        else:
+            if len(rest)>1 and rest[:2] in ppc_bc.all_tests:
+                rest = rest[2:]
+            else:
+                return False
+        if rest in ["", "A", "L", "LA"]:
+            return True
+        return False
+
+    def getname(self):
+        self.bi_parsed = False
+        name = "B"
+        if not self.bo &4:
+            name+="D"
+            if self.bo & 2:
+                name+='Z'
+            else:
+                name+='NZ'
+        elif not self.bo &0x10:
+            index = (self.bo&8)>>1
+            index |= self.bi & 3
+            name+=ppc_bc.all_tests[index]
+            self.bi_parsed = True
+        else:
+            name+='C'
+        if self.aa:
+            name+='A'
+        if self.lk:
+            name+='L'
+            
+        return name
+
+
+    def parse_opts(self, opts):
+        self.bi_done = False
+        
+        self.bo = 0x14
+        self.bi = 0
+        self.aa = 0
+        self.lk = 0
+        if not opts:
+            return
+        if opts[0] == 'D':
+            self.bo&=0x1B
+            opts = opts[1:]
+            if opts[0] == 'Z':
+                self.bo|=2
+                opts = opts[1:]
+            elif opts.startswith('NZ'):
+                self.bo&=0x1d
+                opts = opts[2:]
+        elif opts[0] =='C':
+            pass
+        else:
+            if len(opts)>1 and opts[:2] in ppc_bc.all_tests:
+                self.bi_done = True
+                index = ppc_bc.all_tests.index(opts[:2])
+                inv = index&0x4
+                self.bi = index&0x3
+                if inv:
+                    self.bo|=8
+                else:
+                    self.bo&=0x17
+                self.bo &=0xf
+                opts = opts[2:]
+        if opts == 'C':
+            return
+        if not opts:
+            return
+        if opts[0] == 'L':
+            self.lk = 1
+            opts = opts[1:]
+        if not opts:
+            return
+        if not opts:
+            return
+        if opts == 'A':
+            self.aa = 1
+        return 
+
+    def args2str(self):
+        args = []
+        
+        if not self.bi_parsed:
+            if not self.bo & 0x10:
+                index = (self.bo&8)>>1
+                index |= self.bi & 3
+                a = ppc_bc.all_tests[index]
+                
+                args.append(a)
+            else:
+                pass
+        if self.bi>>2:
+            args.append(cr2str(self.bi>>2))
+        if type(self.bd) in [int, long]:
+            args.append(imm2str(self.bd<<2))
+        else:
+            args.append(str(self.bd))
+        return args
+
+    def parse_args(self, args):
+        if not self.bi_done:
+
+            if args[-1] in ppc_bc.all_tests:
+                self.bo &=0xF
+                
+                a = args.pop()
+                index = ppc_bc.all_tests.index(a)
+                inv = index&0x4
+                self.bi = index&0x3
+                if inv:
+                    self.bo|=8
+                else:
+                    self.bo&=0x17
+            else:
+                self.bo |=0x10
+                
+                pass
+            
+        if len(args) >1:
+            tmp = str2cr(args.pop())
+            self.bi|=tmp<<2
+
+        self.bd = str2imm(args.pop())>>2
+
+    def breakflow(self):
+        return True
+    def splitflow(self):
+        return True
+    def dstflow(self):
+        return True
+
+    def getdstflow(self):
+        if type(self.bd) in [int, long]:
+            li = self.bd<<2
+            if li &(0x1<<15):
+                li |=0xFFFF0000
+            li = struct.unpack('L', struct.pack('L', li))[0]
+            if self.aa:
+                dst = (li)&0xFFFFFFFF
+            else:
+                dst = (self.offset+(li))&0xFFFFFFFF
+        else:
+            dst = self.bd
+        return [dst]
+
+    def setdstflow(self, dst):
+        if len(dst)==0:
+            return
+        if len(dst)!=1:
+            raise ValueError('should be 1 dst')
+        l = dst[0]
+        self.bd = l.name
+
+    def is_subcall(self):
+        return self.lk
+
+    def fixdst(self, lbls, my_offset, is_mem = False):
+        l = self.bd
+        if self.aa:
+            self.bd = lbls[l]>>2
+        else:
+            self.bd = (lbls[l]+4-my_offset)>>2
+
+
+
+class ppc_bctr(ppc_mn):
+    mask_list = [bm_int010011, bm_bo, bm_bi, bm_int00000, bm_opc10, bm_lk]
+    namestr = ['BLR', 'BCTR']
+    namedct = {'BLR':16, 'BCTR':528}
+    mask = {21:bm_set_meta("bm_cmpopc",(bm_set,),{"fbits":namedct.values(), 'l':10})}
+
+    strname = dict((x[1], x[0]) for x in namedct.items())
+    def name2str(self):
+        return self.strname[self.opc10]
+    def str2name(self, n):
+        self.opc10 = self.namedct[n]
+
+    @classmethod
+    def check_opts(cls, rest):
+        if not rest:
+            return True
+        if rest[0] == 'D':
+            rest = rest[1:]
+            if rest[0] == 'Z':
+                rest = rest[1:]
+            elif rest.startswith('NZ'):
+                rest = rest[2:]
+            else:
+                return False
+        elif rest[0] == 'C':
+            rest = rest[1:]
+        else:
+            if len(rest)>1 and rest[:2] in ppc_bc.all_tests:
+                rest = rest[2:]
+            else:
+                return False
+        if rest in ["", "L"]:
+            return True
+        return False
+
+    def getname(self):
+        self.bi_parsed = False
+        name = self.name2str()
+        if not self.bo &4:
+            name+="D"
+            if self.bo & 2:
+                name+='Z'
+            else:
+                name+='NZ'
+        elif not self.bo &0x10:
+            index = (self.bo&8)>>1
+            index |= self.bi & 3
+            name+=ppc_bc.all_tests[index]
+            self.bi_parsed = True
+        else:
+            pass
+            
+        return name
+
+
+
+    def parse_opts(self, opts):
+        self.bi_done = False
+        
+        self.bo = 0x14
+        self.bi = 0
+        self.aa = 0
+        self.lk = 0
+        if not opts:
+            return
+        if opts[0] == 'D':
+            self.bo&=0x1B
+            opts = opts[1:]
+            if opts[0] == 'Z':
+                self.bo|=2
+                opts = opts[1:]
+            elif opts.startswith('NZ'):
+                self.bo&=0x1d
+                opts = opts[2:]
+        elif opts[0] =='C':
+            pass
+        else:
+            if len(opts)>1 and opts[:2] in ppc_bc.all_tests:
+                self.bi_done = True
+                index = ppc_bc.all_tests.index(opts[:2])
+                inv = index&0x4
+                self.bi = index&0x3
+                if inv:
+                    self.bo|=8
+                else:
+                    self.bo&=0x17
+                self.bo &=0xf
+                opts = opts[2:]
+        if opts == 'C':
+            return
+        if not opts:
+            return
+        if opts[0] == 'L':
+            self.lk = 1
+            opts = opts[1:]
+        if not opts:
+            return
+        if not opts:
+            return
+        if opts == 'A':
+            self.aa = 1
+        return 
+
+    def args2str(self):
+        args = []
+        if not self.bi_parsed:
+            if not self.bo & 0x10:
+                    
+                index = (self.bo&8)>>1
+                index |= self.bi & 3
+                a = ppc_bc.all_tests[index]
+                
+                args.append(a)
+            else:
+                pass
+        if self.bi>>2:
+            args.append(cr2str(self.bi>>2))
+        return args
+
+    def parse_args(self, args):
+        if not args:
+            return 
+        if not self.bi_done:
+            if args[-1] in ppc_bc.all_tests:
+                self.bo &=0xF
+                
+                a = args.pop()
+                index = ppc_bc.all_tests.index(a)
+                inv = index&0x4
+                self.bi = index&0x3
+                if inv:
+                    self.bo|=8
+                else:
+                    self.bo&=0x17
+            else:
+                self.bo |=0x10
+                
+                pass
+            
+        if len(args) >1:
+            tmp = str2cr(args.pop())
+            self.bi|=tmp<<2
+
+
+    def breakflow(self):
+        return True
+    def splitflow(self):
+        return False
+    def dstflow(self):
+        return False
+
+    def getdstflow(self):
+        return []
+
+    def setdstflow(self, dst):
+        pass
+    def is_subcall(self):
+        return self.lk
+
+    def fixdst(self, lbls, my_offset, is_mem = False):
+        pass
+
+
+class ppc_cmp(ppc_mn):
+    mask_list = [bm_int011111, bm_bf, bm_int00, bm_ra, bm_rb, bm_opc10, bm_int0]
+    namestr = ['CMPL', 'CMP']
+    namedct = {'CMP':0, 'CMPL':32}
+    mask = {21:bm_set_meta("bm_cmpopc",(bm_set,),{"fbits":namedct.values(), 'l':10})}
+
+    strname = dict((x[1], x[0]) for x in namedct.items())
+    def name2str(self):
+        return self.strname[self.opc10]
+    def str2name(self, n):
+        self.opc10 = self.namedct[n]
+    
+    def args2str(self):
+        args = []
+        if self.bf!=0:
+            args.append(cr2str(self.bf))
+        args.append(reg2str(self.ra))
+        args.append(reg2str(self.rb))
+        return args
+
+    def parse_args(self, args):
+        self.bf = 0
+        if len(args)==3:
+            self.bf = str2cr(args.pop())
+        self.ra = str2reg(args.pop())
+        self.rb = str2reg(args.pop())
+
+
+
+class ppc_cmpli(ppc_mn):
+    mask_list = [bm_int001010, bm_bf, bm_int00, bm_ra, bm_uimm]
+    namestr = ['CMPLI']
+
+    def name2str(self):
+        return self.namestr[0]
+    
+    def args2str(self):
+        args = []
+        if self.bf!=0:
+            args.append(cr2str(self.bf))
+        args.append(reg2str(self.ra))
+        args.append(imm2str(self.uimm))
+        return args
+
+    def parse_args(self, args):
+        self.bf = 0
+        if len(args)==3:
+            self.bf = str2cr(args.pop())
+            
+        self.ra = str2reg(args.pop())
+        self.uimm = str2imm(args.pop())
+
+
+class ppc_cmpi(ppc_mn):
+    mask_list = [bm_int001011, bm_bf, bm_int00, bm_ra, bm_simm]
+    namestr = ['CMPI']
+
+    def name2str(self):
+        return self.namestr[0]
+    
+    def args2str(self):
+        args = []
+        if self.bf!=0:
+            args.append(cr2str(self.bf))
+        args.append(reg2str(self.ra))
+        args.append(imm2str(self.simm))
+        return args
+
+    def parse_args(self, args):
+        self.bf = 0
+        if len(args)==3:
+            self.bf = str2cr(args.pop())
+        self.ra = str2reg(args.pop())
+        self.simm = str2imm(args.pop())
+
+class ppc_cntlzw(ppc_mn):
+    mask_list = [bm_int011111, bm_rs, bm_ra, bm_int00000, bm_opc10, bm_rc]
+    mask = {21:bm_set_meta("bm_cntlzwopc",(bm_set,),{"fbits":[26], 'l':10})}
+    
+    namestr = ['CNTLZW']
+
+    do_args = [('ra',reg), ('rs',reg)]
+
+    def name2str(self):
+        return self.namestr[0]
+
+    def str2name(self, n):
+        self.opc10 = 26
+    
+    @classmethod
+    def check_opts(cls, rest):
+        if rest in ["", "."]:
+            return True
+        return False
+
+    def rc2str(self):
+        return ['','.'][self.rc==1]
+
+    def parse_opts(self, opts):
+        self.rc = 0
+        if not opts:
+            return
+        if "." in opts:
+            self.rc = 1
+
+class ppc_crand(ppc_mn):
+    mask_list = [bm_int010011, bm_bt, bm_ba, bm_bb, bm_opc10, bm_int0]
+    namestr = ['CRANDC', 'CRAND', "CREQV", "CRNAND", "CRNOR", "CRORC", "CROR", "CRXOR"]
+    namedct = {'CRAND':257, 'CRANDC':129, "CREQV":289, "CRNAND":225, "CRNOR":33, "CROR":449, "CRORC":417,
+               "CRXOR":193}
+    mask = {21:bm_set_meta("bm_crandopc",(bm_set,),{"fbits":namedct.values(), 'l':10})}
+
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('bt',crb), ('ba',crb), ('bb',crb)]
+
+    def name2str(self):
+        return self.strname[self.opc10]
+    def str2name(self, n):
+        self.opc10 = self.namedct[n]
+
+
+class ppc_dcb(ppc_crand, ppc_mn):
+    mask_list = [bm_int011111, bm_int00000, bm_ra, bm_rb, bm_opc10, bm_int0]
+    namestr = ['DCBTST', 'DCBST', 'DCBF', 'DCBI', 'DCBT', 'DCBZ', 'ICBI']
+    namedct = {'DCBTST':246, 'DCBST':54, 'DCBF':86, 'DCBI':470, 'DCBT':278, 'DCBZ':1014, 'ICBI':982}
+    mask = {21:bm_set_meta("bm_dcbopc",(bm_set,),{"fbits":namedct.values(), 'l':10})}
+
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('ra',reg), ('rb',reg)]
+    @classmethod
+    def check_opts(cls, rest):
+        if rest in ["", "."]:
+            return True
+        return False
+
+
+class ppc_eciw(ppc_crand, ppc_mn):
+    mask_list = [bm_int011111, bm_rt, bm_ra, bm_rb, bm_opc10, bm_int0]
+    namestr = ['ECIW', 'ECOW', 'LBZUX', 'LBZX', 'LHAUX', 'LHAX', 'LHBR', 'LHZUX', 'LHZUX', 'LHZX',
+               'LSWX', 'STSWX', 'LWARX', 'LWBRX', 'STWBRX', 'LWZX', 'LWZUX', 'STWUX', 'STWX', 'STBUX',
+               'STBX', 'STHBRX', 'STHX', 'STHUX']
+    namedct = {'ECIW':310, 'ECOW':438, 'LBZUX':119, 'LBZX':87, 'LHAUX':375, 'LHAX':343, 'LHBR':790,
+               'LHZUX':311, 'LHZX':279, 'LSWX':533, 'STSWX':661, 'LWARX':20, 'LWBRX':534, 'STWBRX':662,
+               'LWZUX':55, 'LWZX':23, 'STWUX':183, 'STWX':151, 'STBUX':247, 'STBX':215, 'STHBRX':918,
+               'STHX':407, 'STHUX':439}
+    mask = {21:bm_set_meta("bm_eciwopc",(bm_set,),{"fbits":namedct.values(), 'l':10})}
+
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('rt',reg), ('ra',reg), ('rb',reg)]
+
+class ppc_eieio(ppc_mn):
+    mask_list = [bm_int011111, bm_int00000, bm_int00000, bm_int00000, bm_opc10, bm_int0]
+    namestr = ['EIEIO']
+    mask = {21:bm_set_meta("bm_eieioopc",(bm_set,),{"fbits":[854], 'l':10})}
+
+    def name2str(self):
+        return self.namestr[0]
+    def str2name(self, n):
+        self.opc10 = 854
+
+    def __str__(self):
+        name = self.getname()
+        return name
+
+    def parse_args(self, args):
+        pass
+
+class ppc_isync(ppc_eieio):
+    mask_list = [bm_int010011, bm_int00000, bm_int00000, bm_int00000, bm_opc10, bm_int0]
+    namestr = ['ISYNC', 'RFI']
+    namedct = {'ISYNC':150, 'RFI':50}    
+    mask = {21:bm_set_meta("bm_isyncopc",(bm_set,),{"fbits":namedct.values(), 'l':10})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+    def name2str(self):
+        return self.strname[self.opc10]
+    def str2name(self, n):
+        self.opc10 = self.namedct[n]
+
+
+class ppc_exts(ppc_crand, ppc_mn):
+    mask_list = [bm_int011111, bm_rs, bm_ra, bm_int00000, bm_opc10, bm_rc]
+    namestr = ['EXTSB', 'EXTSH', 'EXTSW']
+    namedct = {'EXTSB':954, 'EXTSH':922, 'EXTSW':986}
+    mask = {21:bm_set_meta("bm_extsopc",(bm_set,),{"fbits":namedct.values(), 'l':10})}
+
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('ra',reg), ('rs',reg)]
+
+    def rc2str(self):
+        return ['','.'][self.rc==1]
+
+    def parse_opts(self, opts):
+        self.rc = 0
+        if not opts:
+            return
+        if "." in opts:
+            self.rc = 1
+
+class ppc_lbz(ppc_mn):
+    mask_list = [bm_int100010, bm_rt, bm_ra, bm_simm]
+    namestr = ['LBZ']
+
+    do_args = [('rt',reg), ('ra',reg), ('simm',imm)]
+    
+    def name2str(self):
+        return self.namestr[0]
+
+
+class ppc_lbzu(ppc_lbz, ppc_mn):
+    mask_list = [bm_int100011, bm_rt, bm_ra, bm_uimm]
+    namestr = ['LBZU']
+
+    do_args = [('rt',reg), ('ra',reg), ('uimm',imm)]
+
+class ppc_lha(ppc_lbz):
+    mask_list = [bm_int101010, bm_rt, bm_ra, bm_simm]
+    namestr = ['LHA']
+
+class ppc_lhau(ppc_lbzu):
+    mask_list = [bm_int101011, bm_rt, bm_ra, bm_uimm]
+    namestr = ['LHAU']
+
+class ppc_lhz(ppc_lbz):
+    mask_list = [bm_int101000, bm_rt, bm_ra, bm_simm]
+    namestr = ['LHZ']
+
+class ppc_lhzu(ppc_lbz):
+    mask_list = [bm_int101001, bm_rt, bm_ra, bm_simm]
+    namestr = ['LHZU']
+
+class ppc_lmw(ppc_lbz):
+    mask_list = [bm_int101110, bm_rt, bm_ra, bm_simm]
+    namestr = ['LMW']
+
+class ppc_lfd(ppc_lbz):
+    mask_list = [bm_int110010, bm_rt, bm_ra, bm_simm]
+    namestr = ['LFD']
+
+class ppc_lfdu(ppc_lbz):
+    mask_list = [bm_int110011, bm_rt, bm_ra, bm_simm]
+    namestr = ['LFDU']
+
+class ppc_lfs(ppc_lbz):
+    mask_list = [bm_int110000, bm_rt, bm_ra, bm_simm]
+    namestr = ['LFDS']
+
+class ppc_lfsu(ppc_lbz):
+    mask_list = [bm_int110001, bm_rt, bm_ra, bm_simm]
+    namestr = ['LFSU']
+
+class ppc_lwz(ppc_lbz):
+    mask_list = [bm_int100000, bm_rt, bm_ra, bm_simm]
+    namestr = ['LWZ']
+
+class ppc_lwzu(ppc_lbz):
+    mask_list = [bm_int100001, bm_rt, bm_ra, bm_simm]
+    namestr = ['LWZU']
+
+class ppc_stw(ppc_lbz):
+    mask_list = [bm_int100100, bm_rt, bm_ra, bm_simm]
+    namestr = ['STW']
+
+class ppc_stwu(ppc_lbz):
+    mask_list = [bm_int100101, bm_rt, bm_ra, bm_simm]
+    namestr = ['STWU']
+
+class ppc_stbu(ppc_lbz):
+    mask_list = [bm_int100111, bm_rt, bm_ra, bm_simm]
+    namestr = ['STBU']
+
+
+class ppc_stb(ppc_lbz):
+    mask_list = [bm_int100110, bm_rt, bm_ra, bm_simm]
+    namestr = ['STB']
+
+class ppc_stfd(ppc_lbz, ppc_mn):
+    mask_list = [bm_int110110, bm_rt, bm_ra, bm_simm]
+    namestr = ['STFD']
+
+    do_args = [('rt',fpr), ('ra',reg), ('simm',imm)]
+
+class ppc_stfdu(ppc_lbz, ppc_mn):
+    mask_list = [bm_int110111, bm_rt, bm_ra, bm_simm]
+    namestr = ['STFDU']
+
+    do_args = [('rt',fpr), ('ra',reg), ('simm',imm)]
+
+class ppc_wi(ppc_crand, ppc_mn):
+    mask_list = [bm_int011111, bm_rt, bm_ra, bm_nb, bm_opc10, bm_int0]
+    namestr = ['LSWI', 'STSWI']
+    namedct = {'LSWI':597, 'STSWI':725}
+    mask = {21:bm_set_meta("bm_wiopc",(bm_set,),{"fbits":namedct.values(), 'l':10})}
+
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('rt',reg), ('ra',reg), ('nb',imm)]
+
+
+class ppc_stfdx(ppc_lbz):
+    mask_list = [bm_int011111, bm_rt, bm_ra, bm_rb, bm_opc10, bm_int0]
+    namestr = ['STFDUX', 'STFDX', 'STFIWX', 'STFSUX', 'STFSX']
+    namsdct = {'STFDX':727, 'STFDUX':759, 'STFIWX':983, 'STFSX':663, 'STFSUX':695}
+    mask = {21:bm_set_meta("bm_wiopc",(bm_set,),{"fbits":namsdct.values(), 'l':10})}
+    strname = dict((x[1], x[0]) for x in namsdct.items())
+
+    do_args = [('rt',fpr), ('ra',reg), ('simm',imm)]
+
+class ppc_stfs(ppc_stfd):
+    mask_list = [bm_int110100, bm_rt, bm_ra, bm_simm]
+    namestr = ['STFS']
+
+class ppc_stfsu(ppc_stfd):
+    mask_list = [bm_int110101, bm_rt, bm_ra, bm_simm]
+    namestr = ['STFSU']
+
+class ppc_sth(ppc_lbz):
+    mask_list = [bm_int101100, bm_rt, bm_ra, bm_simm]
+    namestr = ['STH']
+
+class ppc_sthu(ppc_lbz):
+    mask_list = [bm_int101101, bm_rt, bm_ra, bm_simm]
+    namestr = ['STHU']
+
+class ppc_stmw(ppc_stw):
+    mask_list = [bm_int101111, bm_rt, bm_ra, bm_simm]
+    namestr = ['STMW']
+
+
+class ppc_mcrf(ppc_crand, ppc_mn):
+    mask_list = [bm_int010011, bm_bf, bm_int00, bm_bfa, bm_int00, bm_int00000, bm_opc10, bm_int0]
+    namestr = ['MCRFS', 'MCRF' ]
+    namedct = {'MCRFS':64, 'MCRF':0}
+    mask = {21:bm_set_meta("bm_mcrfopc",(bm_set,),{"fbits":namedct.values(), 'l':10})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('bf',cr), ('bfa',cr)]
+
+class ppc_mcrxr(ppc_crand, ppc_mn):
+    mask_list = [bm_int011111, bm_bf, bm_int00, bm_int00000, bm_int00000, bm_opc10, bm_int0]
+    namestr = ['MCRXR' ]
+    mask = {21:bm_set_meta("bm_mcrxropc",(bm_set,),{"fbits":[512], 'l':10})}
+
+    do_args = [('bf',cr)]
+
+
+
+class ppc_mfcr(ppc_crand, ppc_mn):
+    mask_list = [bm_int011111, bm_rt, bm_int00000, bm_int00000, bm_opc10, bm_int0]
+    namestr = ['MFCR', 'MFMSR', 'MTMSR']
+    namedct = {'MFCR':19, 'MFMSR':83, 'MTMSR':146}
+    mask = {21:bm_set_meta("bm_mcrfopc",(bm_set,),{"fbits":namedct.values(), 'l':10})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('rt',reg)]
+
+
+class ppc_mffsx(ppc_cntlzw, ppc_mfcr):
+    mask_list = [bm_int111111, bm_rt, bm_int00000, bm_int00000, bm_opc10, bm_rc]
+    namestr = ['MFFSR']
+    mask = {21:bm_set_meta("bm_mcrxropc",(bm_set,),{"fbits":[583], 'l':10})}
+
+
+class ppc_mtfsb(ppc_exts, ppc_mn):
+    mask_list = [bm_int111111, bm_bt, bm_int00000, bm_int00000, bm_opc10, bm_rc] #XXX TODO bm_bt doc zarb
+    namestr = ['MTFSB0', 'MTFSB1']
+    namedct = {'MTFSB0':70, 'MTFSB1':38}
+    mask = {21:bm_set_meta("bm_mcrfopc",(bm_set,),{"fbits":namedct.values(), 'l':10})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('bt',crb)]
+
+
+class ppc_mfspr(ppc_crand, ppc_mn):
+    mask_list = [bm_int011111, bm_rt, bm_spr, bm_opc10, bm_int0]
+    namestr = ['MFSPR']
+    mask = {21:bm_set_meta("bm_mfspropc",(bm_set,),{"fbits":[339, 371], 'l':10})}#XXX TODO ZARB RETRO COMPAT?
+
+    do_args = [('rt',reg), ('spr',spr)]
+
+    def name2str(self):
+        return self.namestr[0]
+    def str2name(self, n):
+        self.opc10 = 339 #XXX TODO default mnemo
+
+class ppc_mtspr(ppc_mfspr, ppc_mn):
+    mask_list = [bm_int011111, bm_rt, bm_spr, bm_opc10, bm_int0]
+    namestr = ['MTSPR']
+    mask = {21:bm_set_meta("bm_mcrxropc",(bm_set,),{"fbits":[467], 'l':10})}  #XXX TODO ZARB RETRO COMPAT? , 210
+
+    do_args = [('spr',spr), ('rt',reg)]
+    def str2name(self, n):
+        self.opc10 = 467
+
+class ppc_mfsr(ppc_crand, ppc_mn):
+    mask_list = [bm_int011111, bm_rt, bm_int0, bm_sr, bm_int00000, bm_opc10, bm_int0]
+    namestr = ['MFSR', 'MTSR']
+    namedct = {'MFSR':595, 'MTSR':210}
+    mask = {21:bm_set_meta("bm_mcrfopc",(bm_set,),{"fbits":namedct.values(), 'l':10})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('sr',sr), ('rt',reg)]
+
+class ppc_mulhw(ppc_mn):
+    mask_list = [bm_int011111, bm_rt, bm_ra, bm_rb, bm_int0, bm_opc9, bm_rc]
+    namestr = ['MULHWU', 'MULHW']
+    namedct = {'MULHW':75, 'MULHWU':11}
+    mask = {22:bm_set_meta("bm_addopc",(bm_set,),{"fbits":namedct.values()})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('rt',reg), ('ra',reg), ('rb',reg)]
+
+    def name2str(self):
+        return self.strname[self.opc9]
+    def str2name(self, n):
+        self.opc9 = self.namedct[n]
+    def rc2str(self):
+        return ['','.'][self.rc==1]
+
+    def parse_opts(self, opts):
+        self.rc = 0
+        if not opts:
+            return
+        if "." in opts:
+            self.rc = 1
+
+
+class ppc_mulli(ppc_addi):
+    mask_list = [bm_int000111, bm_rt, bm_ra, bm_simm]
+    namestr = ['MULLI']
+
+class ppc_ori(ppc_addi):
+    mask_list = [bm_int011000, bm_rt, bm_ra, bm_simm]
+    namestr = ['ORI']
+
+class ppc_oris(ppc_addi):
+    mask_list = [bm_int011001, bm_rt, bm_ra, bm_simm]
+    namestr = ['ORIS']
+
+
+class ppc_rlwimi(ppc_mn):
+    mask_list = [bm_int010100, bm_rt, bm_ra, bm_sh, bm_mb, bm_me, bm_rc]
+    namestr = ['RLWIMI']
+
+    do_args = [('ra',reg), ('rt',reg), ('sh',imm), ('mb',imm), ('me',imm)]
+
+    def name2str(self):
+        return self.namestr[0]
+    @classmethod
+    def check_opts(cls, rest):
+        if rest in ["", "."]:
+            return True
+        return False
+
+    def rc2str(self):
+        return ['','.'][self.rc==1]
+
+    def parse_opts(self, opts):
+        self.rc = 0
+        if not opts:
+            return
+        if "." in opts:
+            self.rc = 1
+
+class ppc_rlwinm(ppc_rlwimi):
+    mask_list = [bm_int010101, bm_rt, bm_ra, bm_sh, bm_mb, bm_me, bm_rc]
+    namestr = ['RLWINM']
+
+class ppc_rlwnm(ppc_mn):
+    mask_list = [bm_int010111, bm_rt, bm_ra, bm_rb, bm_mb, bm_me, bm_rc]
+    namestr = ['RLWNM']
+
+    do_args = [('ra',reg), ('rt',reg), ('rb',reg), ('mb',imm), ('me',imm)]
+
+
+class ppc_sc(ppc_mn):
+    mask_list = [bm_int010001, bm_offs, bm_int1, bm_int0]
+    namestr = ['SC']
+    def name2str(self):
+        return self.namestr[0]
+
+    def args2str(self):
+        args = []
+        args.append(imm2str(self.offs))
+        return args
+
+
+    
+    def parse_args(self, args):
+        self.offs = 0
+        pass
+
+    def __str__(self):
+        name = self.getname()
+        args = self.args2str()
+        args = args2str(args)
+
+        return name+" "+args
+
+
+class ppc_srawi(ppc_cntlzw, ppc_mn):
+    mask_list = [bm_int011111, bm_rs, bm_ra, bm_sh, bm_opc10, bm_rc]
+    namestr = ['SRAWI']
+    mask = {21:bm_set_meta("bm_srawiopc",(bm_set,),{"fbits":[824], 'l':10})}
+
+    do_args = [('ra',reg), ('rs',reg), ('sh',imm)]
+    
+    def str2name(self, n):
+        self.opc10 = 824
+
+class ppc_subfic(ppc_addi):
+    mask_list = [bm_int001000, bm_rt, bm_ra, bm_simm]
+    namestr = ['SUBFIC']
+
+
+class ppc_sync(ppc_eieio):
+    mask_list = [bm_int011111, bm_int00000, bm_int00000, bm_int00000, bm_opc10, bm_int0]
+    namestr = ['SYNC', 'TLBSYNC']
+    namedct = {'SYNC':598, 'TLBSYNC':566}    
+    mask = {21:bm_set_meta("bm_syncopc",(bm_set,),{"fbits":namedct.values(), 'l':10})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+    def name2str(self):
+        return self.strname[self.opc10]
+    def str2name(self, n):
+        self.opc10 = self.namedct[n]
+
+
+class ppc_tlb(ppc_sync, ppc_mn):
+    mask_list = [bm_int011111, bm_int00000, bm_int00000, bm_rb, bm_opc10, bm_int0]
+    namestr = ['TLBIE', 'TLBID', 'TLBLI']
+    namedct = {'TLBIE':306, 'TLBLD':978, 'TLBLI':1010}
+    mask = {22:bm_set_meta("bm_addopc",(bm_set,),{"fbits":namedct.values()})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('rb',reg)]
+
+class ppc_xori(ppc_addi):
+    mask_list = [bm_int011010, bm_rt, bm_ra, bm_simm]
+    namestr = ['XORI']
+
+class ppc_xoris(ppc_addi):
+    mask_list = [bm_int011011, bm_rt, bm_ra, bm_simm]
+    namestr = ['XORIS']
+
+
+class ppc_tw(ppc_crand, ppc_mn):
+    mask_list = [bm_int011111, bm_to, bm_ra, bm_rb, bm_opc10, bm_int0]
+    namestr = ['TW']
+    namedct = {'TW':4}
+    mask = {21:bm_set_meta("bm_wiopc",(bm_set,),{"fbits":[4], 'l':10})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('to',imm), ('ra',reg), ('rb',reg)]
+
+class ppc_twi(ppc_mn):
+    mask_list = [bm_int000011, bm_to, bm_ra, bm_simm]
+    namestr = ['TWI']
+
+    do_args = [('to',imm), ('ra',reg), ('simm',imm)]
+
+    def name2str(self):
+        return self.namestr[0]
+
+
+
+#FPU
+
+class ppc_fabs(ppc_and, ppc_mn):
+    mask_list = [bm_int111111, bm_frt, bm_int00000, bm_frb, bm_opc10, bm_rc]
+    namestr = ['FABS', 'FCTIWZ', 'FCTIW', 'FMR', 'FNABS', 'FNEG', 'FRSP']
+    namedct = {'FABS':264, 'FCTIWZ':15, 'FCTIW':14, 'FMR':72, 'FMABS':136, 'FNEG':40, 'FRSP':12}
+    mask = {21:bm_set_meta("bm_addopc",(bm_set,),{"fbits":namedct.values(), 'l':10})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('frt',fpr), ('frb',fpr)]
+
+
+class ppc_fdiv(ppc_fabs, ppc_mn):
+    mask_list = [bm_int111111, bm_frt, bm_fra, bm_frb, bm_int00000, bm_opc5, bm_rc]
+    namestr = ['FDIV', 'FSUB', 'FADD']
+    namedct = {'FDIV':18, 'FSUB':20, 'FADD':21}
+    mask = {26:bm_set_meta("bm_fdivopc",(bm_set,),{"fbits":namedct.values(), 'l':5})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('frt',fpr), ('fra',fpr), ('frb',fpr)]
+
+    def name2str(self):
+        return self.strname[self.opc5]
+    def str2name(self, n):
+        self.opc5 = self.namedct[n]
+
+class ppc_fcmp(ppc_fabs, ppc_mn):
+    mask_list = [bm_int111111, bm_bf, bm_int00, bm_fra, bm_frb, bm_opc10, bm_rc]
+    namestr = ['FCMPO', 'FCMPU']
+    namedct = {'FCMPO':32, 'FCMPU':0}
+    mask = {21:bm_set_meta("bm_fcmpopc",(bm_set,),{"fbits":namedct.values(), 'l':10})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('bf',cr), ('fra',fpr), ('frb',fpr)]
+
+
+class ppc_fdivs(ppc_fdiv):
+    mask_list = [bm_int111011, bm_frt, bm_fra, bm_frb, bm_int00000, bm_opc5, bm_rc]
+    namestr = ['FDIVS', 'FSUBS', 'FADDS']
+    namedct = {'FDIVS':18, 'FSUBS':20, 'FADDS':21}
+    mask = {26:bm_set_meta("bm_fdivsopc",(bm_set,),{"fbits":namedct.values(), 'l':5})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+
+class ppc_fmadd(ppc_fdiv, ppc_mn):
+    mask_list = [bm_int111111, bm_frt, bm_fra, bm_frb, bm_frc, bm_opc5, bm_rc]
+    namestr = ['FMADD', 'FMSUB', 'FNMADD', 'FNMSUB', 'FSEL']
+    namedct = {'FMADD':29, 'FMSUB':28, 'FNMADD':31, 'FNMSUB':30, 'FSEL':23}
+    mask = {26:bm_set_meta("bm_fmaddopc",(bm_set,),{"fbits":namedct.values(), 'l':5})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('frt',fpr), ('fra',fpr), ('frb',fpr), ('frc',fpr)]
+
+class ppc_fmadds(ppc_fdiv):
+    mask_list = [bm_int111011, bm_frt, bm_fra, bm_frb, bm_frc, bm_opc5, bm_rc]
+    namestr = ['FMADDS', 'FMSUBS', 'FNMADDS', 'FNMSUBS']
+    namedct = {'FMADDS':29, 'FMSUBS':28, 'FNMADDS':31, 'FNMSUBS':30}
+    mask = {26:bm_set_meta("bm_fmaddsopc",(bm_set,),{"fbits":namedct.values(), 'l':5})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+
+class ppc_fmul(ppc_fdiv, ppc_mn):
+    mask_list = [bm_int111111, bm_frt, bm_fra, bm_int00000, bm_frc, bm_opc5, bm_rc]
+    namestr = ['FMUL']
+    namedct = {'FMUL':25}
+    mask = {26:bm_set_meta("bm_fmulopc",(bm_set,),{"fbits":namedct.values(), 'l':5})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('frt',fpr), ('fra',fpr), ('frc',fpr)]
+
+
+class ppc_fmuls(ppc_fmul):
+    mask_list = [bm_int111011, bm_frt, bm_fra, bm_int00000, bm_frc, bm_opc5, bm_rc]
+    namestr = ['FMULS']
+    namedct = {'FMULS':25}
+    mask = {26:bm_set_meta("bm_fmaddsopc",(bm_set,),{"fbits":namedct.values(), 'l':5})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+
+class ppc_fres(ppc_fdiv, ppc_mn):
+    mask_list = [bm_int111011, bm_frt, bm_int00000, bm_frb, bm_int00000, bm_opc5, bm_rc]
+    namestr = ['FRES']
+    namedct = {'FRES':24}
+    mask = {26:bm_set_meta("bm_fmulopc",(bm_set,),{"fbits":namedct.values(), 'l':5})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+    do_args = [('frt', fpr),('frb', fpr)]
+
+
+class ppc_frsqrte(ppc_fres):
+    mask_list = [bm_int111111, bm_frt, bm_fra, bm_int00000, bm_frc, bm_opc5, bm_rc]
+    namestr = ['FRSQRTE']
+    namedct = {'FRSQRTE':26}
+    mask = {26:bm_set_meta("bm_fmaddsopc",(bm_set,),{"fbits":namedct.values(), 'l':5})}
+    strname = dict((x[1], x[0]) for x in namedct.items())
+
+
+#order is important
+tab_mn = [ppc_addi, ppc_ori, ppc_oris, ppc_xori, ppc_xoris, ppc_addic, ppc_addicp, ppc_addis, ppc_adde, ppc_and,
+          ppc_andip, ppc_andisp, ppc_bctr, ppc_bc, ppc_b, ppc_cmpli, ppc_cmpi, ppc_cmp, ppc_cntlzw,
+          ppc_crand, ppc_dcb, ppc_eciw, ppc_eieio, ppc_exts, ppc_isync, ppc_lfsu, ppc_lfdu, ppc_lfs, ppc_lfd, ppc_lbzu,
+          ppc_lbz, ppc_lhau, ppc_lha, ppc_lhzu, ppc_lhz, ppc_lmw, ppc_wi, ppc_lwzu,
+          ppc_lwz, ppc_stwu, ppc_stw, ppc_stfdu, ppc_stfd, ppc_stfdx, ppc_stfsu,
+          ppc_stfs, ppc_sthu, ppc_sth, ppc_stmw, ppc_stbu, ppc_stb, ppc_mcrxr, ppc_mcrf,
+          ppc_mffsx, ppc_mfspr, ppc_mfcr, ppc_mtfsb, ppc_mtspr, ppc_mfsr, ppc_mulhw, ppc_mulli,
+          ppc_rlwimi, ppc_rlwinm, ppc_rlwnm, ppc_sc, ppc_srawi, ppc_subfic,
+          ppc_sync, ppc_tlb, ppc_add, ppc_twi, ppc_tw,
+
+          ppc_fabs, ppc_fcmp, ppc_fdivs, ppc_fdiv, ppc_fmadds, ppc_fmadd, ppc_fmuls, ppc_fmul,
+          ppc_frsqrte, ppc_fres]
+
+
+
+if __name__ == "__main__":
+ 
+    import struct
+
+    
+    for op in [0x7D4A5214, 0x7FAA4A14, 0x7D615A14]:
+    
+        m = ppc_mn(op)
+        print m
+
+
+    txt = """
+    ADD R10, R10, R10
+    ADDO. R10, R10, R10
+    ADD R29, R10, R9
+    ADD R11, SP, R11
+    LI R10, 0x23
+    LIS R10, 0x23
+    ADDIS R10, R0, 0x23
+    ADDI R10, R0, 0x23
+    ADDI R0, R11, -0x7
+    ADDIC R8, R6, -1
+    ADDIC. R5, R5, -1
+    ADDIS R4, R31, 1
+    ADDME R7, R5
+    AND R11, R11, R4
+    ANDC R11, R11, R3
+    AND. R5, R5, R4
+    ANDI. R30, R30, 0x2e00
+    ANDIS. R11, R3, 0x8000
+    BA 0x1337
+    BL 0x1337
+    B 0x3
+    CMPL CR0, R3, R4
+    CMPL R3, R4
+    CMP  CR0, R3, R4
+    CMP  R3, R4
+    CMPLI CR0, R0, 0x18
+    CMPLI R0, 0x18
+    CMPI CR0, R3, 1
+    CMPI CR0, R28, -1
+    CMPLI CR5, R11, 3
+    CNTLZW R4, R9
+    CRAND CR0_EQ, CR1_EQ, CR2_EQ
+    CRNOR CR5_LT, CR5_LT, CR6_LT
+    DCBT R4, R5
+    DIVWU R0, R29, R10
+    DIVW R0, R12, R11
+    ECIW R0, R0, R0
+    EIEIO
+    EXTSH R11, R3
+    ISYNC
+    LBZ R11, R11, 0x70
+    LBZX R12, R3, R12
+    LHA R3, R31, 2
+    LHAU R3, R31, 2
+    LHZ R3, R5, 0xA
+    LHZX R12, R4, R12
+    LMW R27, SP, 0xC
+    LSWI R7, R12, 4
+    STSWI R7, R11, 4
+    LWZ R0, SP, 0xC
+    STW R0, SP, 8
+    STWU SP, SP, -0x10
+    LWZX R9, R3, R11
+    STWX R7, R9, R8
+    STBX R12, R31, R4
+    STFD FP31, SP, 0x28
+    STFS FP1, R8, 4
+    STH R4, R6, 2
+    STHX R11, R6, R7
+    STMW R27, SP, 0xC
+    MCRF CR0, CR1
+    MFSR SR1, R0
+    MTSR SR1, R0
+    MULHWU R30, R12, R27
+    MULLI R9, R25, 0x90
+    MULLW R10, R26, R10
+    ORI R4, R4, 0x60b6
+    ORIS R3, R3, -1
+    RFI
+    RLWINM R30, R28, 26, 22, 25
+    RLWINM. R10, R3, 0, 21, 21
+    SLW R6, R6, R12
+    SRAWI R11, R11, 1
+    STB R12, SP, 0xC
+    SUBF R4, R5, R4
+    SUBFE R11, R30, R5
+    SUBFIC R3, R7, 0xFF
+    SUBFZE R30, R30
+    SYNC
+    XOR R6, R12, R11
+    XORIS R11, R11, 0x8000
+    FCTIWZ FP0, FP13
+    FNEG FP3, FP1
+    FMR FP1, FP31
+    FRSP FP1, FP13
+    FDIVS FP1, FP2, FP1
+    FSUB FP13, FP13, FP12
+    FSUBS FP11, FP2, FP11
+    FADDS FP1, FP13, FP11
+    FMADD FP1, FP2, FP3, FP4
+    FMADD. FP1, FP2, FP3, FP4
+    FMULS FP13, FP13, FP11
+    FRES FP1, FP2
+    BGE 0x10
+    BLE 0x10
+    BNE 0x10
+    BNS 0x10
+    BLT 0x10
+    BGT 0x10
+    BEQ 0x10
+    BSO 0x10
+    BGE CR1, 0x10
+    BDNZ 0x10
+    BDNZ LE, 0x10
+    BDNZ LE, CR1, 0x10
+    MFSPR R0, LR
+    MTSPR LR, R0
+    BC LE, CR1, 0x10
+    BLE CR1, 0x10
+    BLR
+    BC 0x10
+    FCMPU CR1, FP1, FP3
+    MTFSB0 CR1_LT
+    TW 1, R3, R4
+    TWI 3, R4, 8
+    SC"""
+    
+
+    #    UNDEF 0x1337, 1
+
+    txt = txt.split('\n')[1:]
+    for t in txt:
+        print "___%s___"%t
+        op1 = ppc_mn.asm(t)[0]
+        h = struct.unpack('>L', op1)
+        print "bin: %.8X"%h
+        m = ppc_mn.dis(op1)
+        print "dis:", str(m)
+        token_a = [x for x in shlex.shlex(t)]
+        token_b = [x for x in shlex.shlex(str(m))]
+        token_a = filter(lambda x:not x in ['-', ',', 'CR0'] and not is_imm(x), token_a)
+        token_b = filter(lambda x:not x in ['-', ',', 'CR0'] and not is_imm(x), token_b)
+        print token_a
+        print token_b
+            
+        op2 = ppc_mn.asm(str(m))[0]
+        h = struct.unpack('>L', op2)
+        print "%.8X"%h
+        if op1 !=op2 or (token_a != token_b and not token_b[0] in ['BLE', 'ADDI', 'LI', 'ADDIS', 'LIS']):
+            raise ValueError('bug in self test', t)
+
+    
diff --git a/miasm/core/__init__.py b/miasm/core/__init__.py
new file mode 100644
index 00000000..1fffa08b
--- /dev/null
+++ b/miasm/core/__init__.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+#__all__ = ['ia32_reg']
diff --git a/miasm/core/asmbloc.py b/miasm/core/asmbloc.py
new file mode 100644
index 00000000..7b92fdb6
--- /dev/null
+++ b/miasm/core/asmbloc.py
@@ -0,0 +1,1364 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+import re
+import logging
+import shlex
+import struct
+from numpy import uint8, uint16, uint32, uint64, int8, int16, int32, int64
+from collections import defaultdict
+log_asmbloc = logging.getLogger("asmbloc")
+console_handler = logging.StreamHandler()
+console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
+log_asmbloc.addHandler(console_handler)
+log_asmbloc.setLevel(logging.WARN)
+
+tab_int_size = {int8:8,
+                uint8:8,
+                int16:16,
+                uint16:16,
+                int32:32,
+                uint32:32,
+                int64:64,
+                uint64:64
+                }
+
+
+class asm_label:
+    def __init__(self, name = "", offset = None):
+
+        self.next = "next"
+        self.noattrib = "noattrib"
+        self.fixedblocs = False
+        if type(name) in [int, long]+tab_int_size.keys():
+            name = "loc_%.8X"%int(name)
+        self.name = name
+        self.attrib = self.noattrib
+        if offset == None:
+            self.offset = offset
+        else:
+            self.offset = int(offset)
+
+    def __str__(self):
+        out = "%s: %s"%(self.name, str(self.offset))
+        return out
+    def __repr__(self):
+        rep = '<asmlabel '
+        if self.name:
+            rep+=repr(self.name)+' '
+        rep+='>'
+        return rep
+
+class asm_raw:
+    def __init__(self, raw = ""):
+        self.raw = raw
+    def __str__(self):
+        return repr(self.raw)
+
+        
+class asm_constraint:
+    c_to = "c_to"
+    c_next = "c_next"
+
+    def __init__(self, label = None, c_t = c_to):
+        self.label = label
+        self.c_t = c_t
+
+    def __str__(self):
+        return str(self.label)+'\t'+str(self.c_t)
+
+
+class asm_bloc:
+    def __init__(self, label=None):
+        self.bfrom = []
+        self.bto = []
+        self.lines = []
+        self.label = label
+        self.age = 0
+        
+    def __str__(self):
+        out = str(self.label)+"\n"
+        out+="from ->"
+        for l in self.bfrom:
+            out+="%.8X"%l+" "
+        out+="\n"
+        for l in self.lines:
+            out+=str(l)+'\n'
+        out+="to ->"
+        for l in self.bto:
+            if l == None:
+                out+="Unknown? "
+            else:
+                out+=str(l)+" "
+        return out
+            
+            
+    def addline(self, l):
+        self.lines.append(l)
+    def addfrom(self, l):
+        self.bfrom.append(l)
+    def addto(self, l):
+        self.bto.append(l)
+    
+
+    def split(self, offset, l):
+        i = -1
+        offsets = [x.offset for x in self.lines]
+        if not l.offset in offsets:
+            log_asmbloc.warning( 'cannot split bloc at %X  middle instruction? default middle'%offset)
+            offsets.sort()
+            
+            return None
+        new_bloc = asm_bloc(l)
+        i = offsets.index(offset)
+        self.lines, new_bloc.lines = self.lines[:i],self.lines[i:]
+        new_bloc.bto = self.bto
+        c = asm_constraint(l, asm_constraint.c_next)
+        self.bto = [c]    
+        return new_bloc
+
+    def get_range(self):
+        if len(self.lines):
+            return self.lines[0].offset, self.lines[-1].offset
+        else:
+            return 0,0
+    def get_offsets(self):
+        return [x.offset for x in self.lines]
+
+class asm_symbol_pool:
+    def __init__(self):
+        self.s = {}
+        self.s_offset = {}
+
+
+    def remove(self, l):
+        if l.name in self.s:
+            del(self.s[l.name])
+        if l.offset != None and l.offset in self.s_offset:
+            del(self.s_offset[l.offset])
+
+    def add(self, l):
+        if l.name in self.s:
+            fdsf
+        self.s[l.name] = l
+        self.s_offset[l.offset] = l
+
+    def del_offset(self, l = None):
+        if l:
+            if l.offset in self.s_offset:
+                del(self.s_offset[l.offset])
+            l.offset = None
+        else:
+            self.s_offset = {}
+            for l in self.s:
+                self.s[l].offset = None
+
+    def getby_offset(self, offset):
+        if offset in self.s_offset:
+            return self.s_offset[offset]
+        return None
+
+    def getby_name(self, name):
+        if name in self.s:
+            return self.s[name]
+        return None
+
+    def getby_name_create(self, name):
+        if name in self.s:
+            return self.s[name]
+        else:
+            l = asm_label(name)
+            self.add(l)
+        return l
+
+    def getby_offset_create(self, offset):
+        if offset in self.s_offset:
+            return self.s_offset[offset]
+        else:
+            l = asm_label(offset, offset)
+            self.add(l)
+        return l
+
+
+    def __str__(self):
+        return reduce(lambda x,y: x+str(y)+'\n', [self.s[l] for l in self.s], "")
+
+
+
+
+def dis_bloc(mnemo, pool_bin, cur_bloc, offset, job_done, symbol_pool, dont_dis = [],
+             follow_call = False, patch_instr_symb = True, dontdis_retcall = False,
+             lines_wd = None, amode="u32", sex=0, dis_bloc_callback = None, dont_dis_nulstart_bloc = False):
+    pool_bin.offset = offset
+    
+    lines_cpt = 0
+    
+    while True:
+        lines_cpt+=1
+        if lines_wd !=None and lines_cpt>lines_wd:
+            log_asmbloc.warning( "lines watchdog reached at %X"%int(offset))
+            offsets_to_dis = []
+            break
+
+        if pool_bin.offset in dont_dis:
+            l = symbol_pool.getby_offset_create(pool_bin.offset)
+            c = asm_constraint(l, asm_constraint.c_next)
+            cur_bloc.bto = [c]
+            offsets_to_dis = [pool_bin.offset]
+            break
+        
+        if pool_bin.offset in job_done:
+            #if not pool_bin.offset in symbol_pool.s_offset:
+            #    # XXX bug: we start dis in middle of bb
+            if pool_bin.offset in symbol_pool.s_offset:
+                l = symbol_pool.s_offset[pool_bin.offset]
+                c = asm_constraint(l, asm_constraint.c_next)
+                cur_bloc.bto = [c]
+                offsets_to_dis = [pool_bin.offset]
+                break
+
+        job_done.add(pool_bin.offset)
+        log_asmbloc.debug("dis at %X"%int(pool_bin.offset))
+        if lines_cpt <=1 and dont_dis_nulstart_bloc:
+            off_i = pool_bin.offset
+            c = pool_bin.readbs()
+            pool_bin.offset = off_i
+            if c == "\x00":
+                offsets_to_dis = []
+                log_asmbloc.warning( "bloc start with nul %X"%int(off_i))
+                break
+
+        instr = mnemo.dis(pool_bin, amode, sex)
+        
+        
+        if instr == None:
+            log_asmbloc.warning( "cannot disasm at %X"%int(offset))
+            cur_bloc.bto = []
+            offsets_to_dis = []
+            break
+        
+        log_asmbloc.debug(instr)
+        log_asmbloc.debug(instr.m)
+        log_asmbloc.debug(instr.arg)
+
+        cur_bloc.addline(instr)
+        if not instr.breakflow():
+            continue
+
+        
+        if instr.splitflow() and not (instr.is_subcall() and dontdis_retcall):
+            n = instr.getnextflow()
+            l = symbol_pool.getby_offset_create(n)
+            c = asm_constraint(l, asm_constraint.c_next)
+            cur_bloc.bto.append(c)
+
+        if instr.dstflow():
+            dst = instr.getdstflow()
+            dstn = []
+            for d in dst:
+                if type(d) in [int, long]+tab_int_size.keys():
+                    d = symbol_pool.getby_offset_create(d)
+                dstn.append(d)
+            dst = dstn
+            if len(dst) == 1:
+                if isinstance(dst[0], asm_label):
+                    instr.setdstflow(dst)
+            if (not instr.is_subcall()) or follow_call:
+                cur_bloc.bto+=[asm_constraint(x, asm_constraint.c_to) for x in dst]
+        offsets_to_dis = [x.label.offset for x in cur_bloc.bto if isinstance(x.label, asm_label)]
+        break
+
+    if dis_bloc_callback != None:
+        dis_bloc_callback(cur_bloc, offsets_to_dis, symbol_pool)
+    return offsets_to_dis
+
+
+
+def dis_i(mnemo, pool_bin, offset, symbol_pool):
+    symbol_pool = asm_symbol_pool()
+    dum_l = symbol_pool.getby_offset_create(offset)
+    dum_b = asm_bloc(dum_l)
+    
+    dis_bloc(mnemo, pool_bin, dum_b, offset, set(), symbol_pool, lines_wd = 1)
+    if not dum_b.lines:
+        return None
+    return dum_b.lines[0]
+        
+def split_bloc(all_bloc, symbol_pool, more_ref = None, dis_bloc_callback = None):
+    i = -1
+    err = False
+    if not more_ref:
+        more_ref = []
+    more_ref = [symbol_pool.s_offset[x] for x in more_ref]
+    while i<len(all_bloc)-1:
+        i+=1
+        for n in [x.label for x in all_bloc[i].bto if isinstance(x.label, asm_label)]+ more_ref:
+            if n == None:
+                continue
+            n = n.offset
+            j = -1
+            while j<len(all_bloc)-1 and not err:
+                j+=1
+                a,b = all_bloc[j].get_range()
+                if n >a and n <=b:
+                    l = symbol_pool.getby_offset_create(n)
+                    new_b = all_bloc[j].split(n,l)
+    
+                    log_asmbloc.debug("split bloc %x"%n)
+                    if new_b== None:
+                        log_asmbloc.error("cannot split %x!!"%n)
+                        err = True
+                        break
+                    if dis_bloc_callback:
+                        dis_bloc_callback(new_b, [x.label.offset for x in new_b.bto if isinstance(x.label, asm_label)],
+                                          symbol_pool)
+                    all_bloc.append(new_b)
+            if err:
+                break
+    return all_bloc
+
+def dis_bloc_all(mnemo, pool_bin, offset, job_done, symbol_pool, dont_dis = [],
+                 follow_call = False, patch_instr_symb = True, dontdis_retcall = False,
+                 amode="u32", sex=0 , bloc_wd = None, lines_wd = None, all_bloc = None,
+                 dis_bloc_callback = None, dont_dis_nulstart_bloc = False):
+    log_asmbloc.info("dis bloc all")
+    if all_bloc == None:
+        all_bloc = []
+    todo = [offset]
+
+    bloc_cpt = 0
+    while len(todo):
+        bloc_cpt+=1
+        if bloc_wd !=None and bloc_cpt>bloc_wd:
+            log_asmbloc.debug( "blocs watchdog reached at %X"%int(offset))
+            break
+
+        n = int(todo.pop(0))
+        if n in job_done:
+            continue
+        if n == None:
+            continue
+
+        if n in dont_dis:
+            continue
+        dd_flag = False
+        for dd in dont_dis:
+            if not isinstance(dd, tuple):
+                continue
+            dd_a, dd_b = dd
+            if dd_a <= n < dd_b:
+                dd_flag = True
+                break
+        if dd_flag:
+            continue
+                
+        l = symbol_pool.getby_offset_create(n)
+        cur_bloc = asm_bloc(l)
+        todo += dis_bloc(mnemo, pool_bin, cur_bloc, n, job_done, symbol_pool, dont_dis, follow_call, patch_instr_symb, dontdis_retcall, amode=amode, sex=sex, dis_bloc_callback = dis_bloc_callback, lines_wd = lines_wd, dont_dis_nulstart_bloc = dont_dis_nulstart_bloc)
+        all_bloc.append(cur_bloc)
+
+
+    return split_bloc(all_bloc, symbol_pool, dis_bloc_callback = dis_bloc_callback)
+    
+    #return all_bloc
+
+
+
+def bloc2graph(blocs, label = False, lines = True):
+    #rankdir=LR;
+    out = """
+digraph asm_graph {
+size="80,50";
+node [
+fontsize = "16",
+shape = "box"
+];
+"""
+    for b in blocs:
+        out+='%s [\n'%b.label.name
+        out+='label = "'
+
+        out+=b.label.name+"\\l\\\n"
+        if lines:
+            for l in b.lines:
+                if label:
+                    out+="%.8X "%l.offset
+                out+="%s\\l\\\n"%l
+        out+='"\n];\n'
+
+    for b in blocs:
+        for n in b.bto:
+            if isinstance(n.label, asm_label):
+                out+='%s -> %s [ label = "%s" ];\n'%(b.label.name, n.label.name, n.c_t)
+    out+="}"
+    return out
+
+#this function group asm blocs with next constraints
+def group_blocs(all_bloc):
+    log_asmbloc.info('group_blocs')
+    #group adjacent blocs
+    rest = all_bloc[:]
+    
+    groups_bloc = {}
+    d = dict([(x.label,x) for x in rest])
+    log_asmbloc.debug([str(x.label) for x in rest])
+
+    while rest:
+        b = [rest.pop()]
+        #find recursive son
+        fini =False
+        while not fini:
+            fini=True
+            for c in b[-1].bto:
+                if c.c_t != asm_constraint.c_next:
+                    continue
+                if d[c.label] in rest:
+                    b.append(d[c.label])
+                    rest.remove(d[c.label])
+                    fini =False
+                    break
+        #check if son in group:
+        found_in_group = False
+        for c in b[-1].bto:
+            if c.c_t != asm_constraint.c_next:
+                continue
+            if c.label in groups_bloc:
+                b+=groups_bloc[c.label]
+                del(groups_bloc[c.label])
+                groups_bloc[b[0].label] = b
+                found_in_group = True
+                break
+
+        if not found_in_group:
+            groups_bloc[b[0].label] = b
+
+    #create max label range for bigbloc
+    for l in groups_bloc:
+        l.total_max_l = reduce(lambda x,y: x+y.blen_max, groups_bloc[l], 0)
+        log_asmbloc.debug(("offset totalmax l", l.offset, l.total_max_l))
+        if type(l.offset) in [int, long]+tab_int_size.keys():
+            hof = hex(int(l.offset))
+        else:
+            hof = l.name
+        log_asmbloc.debug(("offset totalmax l", hof, l.total_max_l))
+    
+    return groups_bloc
+
+
+def gen_free_space_intervals(f, dont_erase = []):
+    interval = {}
+    last_offset = 0xFFFFFFFF
+    offset_label = dict([(x.offset_free,x) for x in f])
+    offset_label_order = offset_label.keys()
+    offset_label_order.sort()
+    offset_label_order.append(last_offset)
+    offset_label_order.reverse()
+
+
+    unfree_stop= 0L
+    while len(offset_label_order)>1:
+        offset = offset_label_order.pop()
+        offset_end = offset+f[offset_label[offset]]
+        prev = 0
+        if unfree_stop>offset_end:
+            space = 0
+        else:
+            space = offset_label_order[-1]-offset_end
+            if space <0:
+                space = 0
+            interval[offset_label[offset]] = space
+            if offset_label_order[-1] in offset_label:
+                prev = offset_label[offset_label_order[-1]]
+                prev = f[prev]
+
+        interval[offset_label[offset]] = space
+
+        unfree_stop = max(unfree_stop, offset_end, offset_label_order[-1]+prev)
+
+    return interval
+
+def add_dont_erase(f, dont_erase = []):
+    for a,b in dont_erase:
+        l = asm_label(a, a)
+        l.offset_free = a
+        f[l] = b-a
+    return
+
+
+def del_dis_offset(all_bloc, symbol_pool):
+    for b in all_bloc:
+        symbol_pool.s[b.label.name].offset = None
+
+
+
+def gen_non_free_mapping(group_bloc, dont_erase = []):
+    non_free_mapping = {}
+    non_free_mappingb = {}
+    #calculate free space for bloc placing
+    for g in group_bloc:
+        rest_len = 0
+        g.fixedblocs = False
+        #if a label in the group is fixed
+        diff_offset = 0
+        for b in group_bloc[g]:
+            if not type(b.label.offset) in [int, long]+tab_int_size.keys():
+                diff_offset+=b.blen_max
+                continue
+            g.fixedblocs = True
+            g.offset_free = b.label.offset - diff_offset
+            break
+        if g.fixedblocs:
+            non_free_mapping[g] = g.total_max_l
+
+    log_asmbloc.debug("non free bloc:")
+    log_asmbloc.debug(non_free_mapping)
+    add_dont_erase(non_free_mapping, dont_erase)
+    log_asmbloc.debug("non free more:")
+    log_asmbloc.debug(non_free_mapping)
+    return non_free_mapping
+
+
+
+# if one bloc is fixed in the bloc list, this function
+# will fix other blocs around this one.
+def fix_bloc_around_anchored_bloc(unr_bloc):
+
+    l2b = {}
+    for b in unr_bloc:
+        l2b[b.label] = b
+
+    b_done = set()
+    b_todo = set()
+    b_rest = set()
+    for l in unr_bloc:
+        if l.label.fixedblocs:
+            b_todo.add(l.label)
+        else:
+            b_rest.add(l.label)
+    print b_todo
+    print b_rest
+
+    while b_todo:
+        b = b_todo.pop()
+        print 'testing ', b
+        b_done.add(b)
+        i = unr_bloc.index(l2b[b])
+        if i >0 and unr_bloc[i-1].label in b_rest:
+            unr_bloc[i-1].label.offset = [b, unr_bloc[i-1], -1]
+            unr_bloc[i-1].fixedblocs = True
+            b_todo.add(unr_bloc[i-1].label)
+            b_rest.remove(unr_bloc[i-1].label)
+        if i < len(unr_bloc)-1 and unr_bloc[i+1].label in b_rest:
+            unr_bloc[i+1].label.offset = [b, unr_bloc[i], 1]
+            unr_bloc[i+1].fixedblocs = True
+            b_todo.add(unr_bloc[i+1].label)
+            b_rest.remove(unr_bloc[i+1].label)
+    
+
+
+# place all asmblocs, ordered
+# XXX WARNING, doesn't use dont erase arg!!
+def resolve_symbol_linear(bloc_list, group_bloc, dont_erase = []):
+    print bloc_list
+    log_asmbloc.info('resolve_symbol')
+    log_asmbloc.info(str(dont_erase))
+
+    non_free_mapping = gen_non_free_mapping(group_bloc, dont_erase)
+
+
+
+
+    unr_bloc = []
+
+    for l in bloc_list:
+        unr_bloc+=group_bloc[l]
+
+    l2b = {}
+    for b in unr_bloc:
+        l2b[b.label] = b
+
+        
+    # first, link grouped bloc around fixed labels
+    for g in group_bloc.values():
+        fix_bloc_around_anchored_bloc(g)
+
+
+
+
+    b_done = set()
+    b_todo = set()
+    b_rest = set()
+    for l in unr_bloc:
+        if l.label in bloc_list and l.label.fixedblocs:
+            b_todo.add(l.label)
+        else:
+            b_rest.add(l.label)
+    print b_todo
+    print b_rest
+
+    while b_todo:
+        b = b_todo.pop()
+        print 'testing ', b
+        b_done.add(b)
+        i = unr_bloc.index(l2b[b])
+        if i >0 and unr_bloc[i-1].label in b_rest:
+            unr_bloc[i-1].label.offset = [b, unr_bloc[i-1], -1]
+            b_todo.add(unr_bloc[i-1].label)
+            b_rest.remove(unr_bloc[i-1].label)
+        if i < len(unr_bloc)-1 and unr_bloc[i+1].label in b_rest:
+            unr_bloc[i+1].label.offset = [b, unr_bloc[i], 1]
+            b_todo.add(unr_bloc[i+1].label)
+            b_rest.remove(unr_bloc[i+1].label)
+    print b_todo
+    print b_rest
+    print b_done
+
+    return [(x,0) for x in unr_bloc]
+    
+    bloc_list = []
+    unr_bloc = reduce(lambda x,y: x+group_bloc[y], group_bloc, [])
+    ending_ad = []
+
+    free_interval = gen_free_space_intervals(non_free_mapping)
+    log_asmbloc.debug(free_interval)
+
+    
+        
+#place all asmblocs
+def resolve_symbol(group_bloc, dont_erase = []):
+    log_asmbloc.info('resolve_symbol')
+    log_asmbloc.info(str(dont_erase))
+    
+    bloc_list = []
+    unr_bloc = reduce(lambda x,y: x+group_bloc[y], group_bloc, [])
+    ending_ad = []
+
+    non_free_mapping = gen_non_free_mapping(group_bloc, dont_erase)
+    free_interval = gen_free_space_intervals(non_free_mapping)
+    log_asmbloc.debug(free_interval)
+    
+    
+
+    #first big ones
+    g_tab = [(x.total_max_l,x) for x in group_bloc]
+    g_tab.sort()
+    g_tab.reverse()
+    g_tab = [x[1] for x in g_tab]
+    
+    #g_tab => label of grouped blov
+    #group_bloc => dict of grouped bloc labeled-key
+
+    #first, near callee placing algo
+    for g in g_tab:
+        if g.fixedblocs:
+            continue
+        finish = False
+        for x in group_bloc:
+            if not x in free_interval.keys():
+                continue
+            if free_interval[x]<g.total_max_l:
+                continue
+
+            for b in group_bloc[x]:
+                for c in b.bto:
+                    if c.label == g:
+                        tmp = free_interval[x]-g.total_max_l
+                        log_asmbloc.debug("consumed %d rest: %d"%(g.total_max_l, int(tmp)))
+                        free_interval[g] = tmp
+                        del(free_interval[x])
+                        
+                        g.offset = [group_bloc[x][-1].label, group_bloc[x][-1], 1]                        
+                        g.fixedblocs = True
+                        finish = True
+                        break
+                if finish:
+                    break
+            if finish:
+                break
+
+    #second, bigger in smaller algo
+    for g in g_tab:
+        if g.fixedblocs:
+            continue
+        #chose smaller free_interval first
+        k_tab = [(free_interval[x],x) for x in free_interval]
+        k_tab.sort()
+        k_tab = [x[1] for x in k_tab]
+        #choose free_interval
+        for k in k_tab:
+            if g.total_max_l>free_interval[k]:
+                continue
+            g.offset = [group_bloc[k][-1].label, group_bloc[k][-1], 1]
+            tmp = free_interval[k]-g.total_max_l
+            log_asmbloc.debug("consumed %d rest: %d"%(g.total_max_l, int(tmp)))
+            free_interval[g] = tmp
+            del(free_interval[k])
+
+            g.fixedblocs = True
+            break
+
+    while unr_bloc:
+        #propagate know offset
+        resolving = False
+        i = 0
+        while i < len(unr_bloc):
+            if unr_bloc[i].label.offset == None:
+                i+=1
+                continue
+            resolving = True
+            log_asmbloc.info("bloc %s resolved"%unr_bloc[i].label)
+            bloc_list.append((unr_bloc[i],0))
+            
+            g_found =  None
+            for g in g_tab:
+                if unr_bloc[i] in group_bloc[g]:
+                    if g_found!=None:
+                        raise ValueError('blocin multiple group!!!')
+                    g_found = g
+            my_group = group_bloc[g_found]
+
+            index = my_group.index(unr_bloc[i])
+            if index>0 and my_group[index-1] in unr_bloc:
+                my_group[index-1].label.offset = [unr_bloc[i].label, unr_bloc[i-1], -1]
+            if index <len(my_group)-1 and my_group[index+1] in unr_bloc:
+                my_group[index+1].label.offset = [unr_bloc[i].label, unr_bloc[i], 1]
+    
+            del unr_bloc[i]
+
+        if not resolving:
+            log_asmbloc.warn("cannot resolve symbol! (no symbol fix found)")
+        else:
+            continue
+
+        for g in g_tab:
+            print g
+            if g.fixedblocs:
+                print "fixed"
+            else:
+                print "not fixed"
+        raise ValueError('enable to fix bloc')
+            
+    return bloc_list
+
+
+def calc_symbol_offset(symbol_pool):
+    keys = symbol_pool.s.keys()
+    for l in symbol_pool.s:
+        symbol_pool.s[l].offset_g = symbol_pool.s[l].offset
+        
+    s_to_use = set()
+    s_to_fix = set()
+
+    s_dependent = {}
+
+    for l in symbol_pool.s:
+        if not type(symbol_pool.s[l].offset_g) in [int, long]+tab_int_size.keys():
+            s_to_fix.add(l)
+
+            if not l in symbol_pool.s or symbol_pool.s[l].offset_g == None:
+                raise ValueError("symbol missing?", l)
+            #construct dependant blocs tree
+            s_d = symbol_pool.s[l].offset_g[0]
+            if not s_d.name in s_dependent:
+                s_dependent[s_d.name] = set()
+            s_dependent[s_d.name].add(l)
+        else:
+            s_to_use.add(l)
+
+    s_used = set()
+    total_fixed = 0
+    
+    while s_to_use:
+        s = s_to_use.pop()
+        offset = symbol_pool.s[s].offset_g
+
+        s_fixed = set()
+        if not s in s_dependent:
+            continue
+        for l in s_dependent[s]:
+            if symbol_pool.s[s].offset_g== None:
+                raise ValueError("unknown symbol: %s"%str(s))
+            
+            symbol_pool.s[l].offset_g=offset+symbol_pool.s[l].offset_g[1].blen*symbol_pool.s[l].offset_g[2]
+            s_to_use.add(l)
+            total_fixed+=1
+            s_fixed.add(l)
+
+        for l in s_fixed:
+            s_to_fix.remove(l)
+
+
+def asmbloc(mnemo, all_blocs):
+    #compute max bloc len
+    for b in all_blocs:
+        log_asmbloc.debug('---')
+        blen = 0
+        blen_max = 0
+        for instr in b.lines:
+            if isinstance(instr, asm_raw):
+                candidates = [instr.raw]
+                c = instr.raw
+            elif [True for a in instr.arg if mnemo.has_symb(a)]:
+                testing_arg = [mnemo.fix_symbol(a) for a in instr.arg]
+                sav_a = instr.arg
+                instr.arg = testing_arg
+                candidates=mnemo.asm(str(instr))
+                if not candidates:
+                    raise ValueError('cannot asm:%s'%str(instr))
+                instr.arg = sav_a
+
+                c = candidates[0]
+                blen_max+= len(candidates[-1])-len(candidates[0])
+            else:
+                candidates=mnemo.asm(str(instr))
+                if not candidates:
+                    raise ValueError('cannot asm:%s'%str(instr))
+                c = candidates[0]
+            log_asmbloc.debug(instr)
+            log_asmbloc.debug(candidates)
+            log_asmbloc.debug(repr(c))
+            instr.data = c
+            blen +=len(c)
+
+        b.blen = blen
+        #bloc with max rel values encoded
+        b.blen_max = blen+blen_max
+        log_asmbloc.info("blen: %d max: %d"%(b.blen, b.blen_max))
+        
+
+        
+def asmbloc_final(mnemo, all_blocs, symbol_pool, symb_reloc_off = {}):
+    log_asmbloc.info("asmbloc_final")
+    fini =False
+    #asm with minimal instr len
+    #check if dst label are ok to this encoded form
+    #recompute if not
+    while not fini:
+        fini =True
+        my_symb_reloc_off = {}
+
+        calc_symbol_offset(symbol_pool)
+        #test if bad encoded relative
+        for b,t in all_blocs:
+            offset_i = 0
+            my_symb_reloc_off[b.label] = []
+            for instr in b.lines:
+                if isinstance(instr, asm_raw):
+                    offset_i+=len(instr.data)
+                    continue
+                if not [True for a in instr.arg if mnemo.has_symb(a)]:
+                    offset_i+=len(instr.data)
+                    continue
+
+                sav_a = instr.arg
+
+                if instr.dstflow():
+                    lbls = {}
+                    xxx = instr.getdstflow()
+                    if len(xxx) !=1:
+                        raise ValueError('multi dst ?!')
+                    label = mnemo.get_label(xxx[0])
+                    is_mem = mnemo.is_mem(xxx[0])
+                    lbls[label.name] = label.offset_g
+                    instr.fixdst(lbls, b.label.offset_g+b.blen, is_mem)
+                else:
+                    instr.arg = [mnemo.fix_symbol(a, symbol_pool) for a in instr.arg]
+                symbol_reloc_off = []
+                candidates=mnemo.asm(str(instr), symbol_reloc_off)
+                if not candidates:
+                    raise ValueError('cannot asm:%s'%str(instr))
+                c = candidates[0]
+                instr.arg = sav_a
+                
+                if len(c)>len(instr.data):
+                    #good len, bad offset...XXX
+                    b.blen = b.blen-len(instr.data)+len(c)
+                    instr.data = c
+                    fini=False
+                    break
+                else:
+                    l_dict = dict([[len(x),i] for i, x in enumerate(candidates)])
+                    instr.data = candidates[l_dict[len(instr.data)]]
+
+                if l_dict[len(instr.data)] < len(symbol_reloc_off):
+                    my_s = symbol_reloc_off[l_dict[len(instr.data)]]
+                else:
+                    my_s = None
+
+                if my_s!=None:
+                    my_symb_reloc_off[b.label].append(offset_i+my_s)
+                    
+                offset_i+=len(instr.data)
+    
+    for l in symbol_pool.s:
+        if symbol_pool.s[l].offset_g ==None:
+            fdfd
+    
+    #we have fixed all relative values
+    #recompute good offsets
+    for l in symbol_pool.s:
+        symbol_pool.s[l].offset = symbol_pool.s[l].offset_g
+
+    for a, b in my_symb_reloc_off.items():
+        symb_reloc_off[a] = b
+
+def asm_resolve_final(mnemo, all_bloc, symbol_pool, dont_erase = [], symb_reloc_off = {}, constrain_pos = False):
+    asmbloc(mnemo, all_bloc)
+    bloc_g = group_blocs(all_bloc)
+    if constrain_pos:
+        #XXX
+        print bloc_g
+        bloc_list = [(bcs[0].bloc_num, bcs[0].label) for bcs in bloc_g.values()]
+        bloc_list.sort()
+        bloc_list = [b[1] for b in bloc_list]
+        resolved_b = resolve_symbol_linear(bloc_list, bloc_g, dont_erase)
+    else:
+        resolved_b = resolve_symbol(bloc_g, dont_erase)
+
+    asmbloc_final(mnemo, resolved_b, symbol_pool, symb_reloc_off)
+    
+
+    written_bytes = {}
+    patches = {}
+    for b,t in resolved_b:
+        offset = b.label.offset
+        for i in b.lines:
+            patches[offset] = i.data
+            for c in range(len(i.data)):
+                if offset+c in written_bytes:
+                    raise ValueError("overlapping bytes in asssembly %X"%int(offset))
+                written_bytes[offset+c] = 1
+            offset+=len(i.data)
+
+    return resolved_b, patches
+
+
+def patch_binary(f, resolved_b):
+    written_bytes = {}
+    for b,t in resolved_b:
+        offset = b.label.offset
+        f.seek(offset, 0)
+        for i in b.lines:
+            log_asmbloc.debug("%.8X %-30s %s"%(offset, repr(i.data), str(i)))
+            f.write(i.data)
+            for c in range(len(i.data)):
+                if offset+c in written_bytes:
+                    log_asmbloc.error( "erase allready fixed bytes")
+                written_bytes[offset+c] = 1
+            offset+=len(i.data)
+    return written_bytes
+
+
+def blocs2str(b):
+    out = b.label.name+':\n'
+    for l in b.lines:
+        out+=str(l)+'\n'
+    return out
+
+
+def find_parents(all_bloc, l):
+    p = set()
+    for b in all_bloc:
+        if l in [x.label for x in b.bto if isinstance(x.label, asm_label)]:
+            p.add(b.label)
+    return p
+
+def dead_bloc_rem(all_bloc, symbol_pool, keeped = []):
+    finish = False
+    while not finish:
+        finish = True
+        for b in all_bloc:
+            l = b.label
+            if l in keeped:
+                continue
+            p = find_parents(all_bloc, l)
+            if l in p:
+                p.remove(l)
+            if not len(p):
+                symbol_pool.remove(b.label)
+                all_bloc.remove(b)
+                finish = False
+                print 'del bloc %s'%str(l)
+                break
+                
+            
+
+def getbloc_around(all_bloc, a, level = 3, done = None, blocby_label = None):
+
+    if not blocby_label:
+        blocby_label = {}
+        for b in all_bloc:
+            blocby_label[b.label] = b
+    
+    if done == None:
+        done = set()
+
+    done.add(a)
+    
+    if not level:
+        return done
+    
+    for b in a.parents:
+        b = blocby_label[b]
+        if b in done:
+            continue
+        done.update(getbloc_around(all_bloc, b, level-1, done, blocby_label))
+    for b in a.bto:
+        b = blocby_label[b.label]
+        if b in done:
+            continue
+        done.update(getbloc_around(all_bloc, b, level-1, done, blocby_label))
+    return done
+
+
+def getbloc_parents(all_bloc, a, level = 3, done = None, blocby_label = None):
+
+    if not blocby_label:
+        blocby_label = {}
+        for b in all_bloc:
+            blocby_label[b.label] = b
+    
+    if done == None:
+        done = set()
+
+    done.add(a)
+    
+    if not level:
+        return done
+    
+    for b in a.parents:
+        b = blocby_label[b]
+        if b in done:
+            continue
+        done.update(getbloc_parents(all_bloc, b, level-1, done, blocby_label))
+    return done
+
+#get ONLY level_X parents
+def getbloc_parents_strict(all_bloc, a, level = 3, rez = None, done = None, blocby_label = None):
+
+    if not blocby_label:
+        blocby_label = {}
+        for b in all_bloc:
+            blocby_label[b.label] = b
+    if rez == None:
+        rez = set()
+    if done == None:
+        done = set()
+
+    done.add(a)
+    if level == 0:
+        rez.add(a)
+    
+    if not level:
+        return rez
+    
+    for b in a.parents:
+        b = blocby_label[b]
+        if b in done:
+            continue
+        rez.update(getbloc_parents_strict(all_bloc, b, level-1, rez, done, blocby_label))
+    return rez
+
+
+def bloc_find_path(all_bloc, blocby_label, a, b, path = None, done = None):
+    if path == None:
+        path = []
+    if done == None:
+        done = set()
+
+    all_path = []
+    for x in a.bto:
+        if not isinstance(x.label, asm_label) or not x.label in blocby_label:
+            continue
+        x = blocby_label[x.label]
+
+        if x == b:
+            all_path += [path+[a]]
+            continue
+
+        if x in done:
+            continue
+
+        done.add(a)
+        all_path+=bloc_find_path(all_bloc, blocby_label, x, b, path+[a], done)
+    return all_path
+
+            
+def getblocby_offsetin(all_bloc, o):
+    for b in all_bloc:
+        for l in b.lines:
+            if o == l.offset:
+                return b
+    return None
+
+def getblocby_offsetinr(all_bloc, o):
+    for b in all_bloc:
+        min_ad = None
+        max_ad = None
+        for l in b.lines:
+            if min_ad == None or l.offset < min_ad:
+                min_ad = l.offset
+            if max_ad == None or l.offset > max_ad:#XXX + len l
+                max_ad = l.offset
+        if min_ad <= o <= max_ad:
+            return b
+    return None
+
+        
+def getlineby_offset(all_bloc, o):
+    for b in all_bloc:
+        for l in b.lines:
+            if l.offset == o:
+                return l
+    return None
+
+def getblocby_offset(all_bloc, o):
+    for b in all_bloc:
+        for l in b.lines:
+            if l.offset == o:
+                return b
+    return None
+
+def getblocby_label(all_bloc, l):
+    for b in all_bloc:
+        if b.label == l:
+            return b
+    return None
+
+def bloc_blink(all_bloc):
+    for b in all_bloc:
+        b.parents = find_parents(all_bloc, b.label)
+
+
+def bloc_find_path_next(all_bloc, blocby_label, a, b, path = None):
+    if path == None:
+        path = []
+    if a == b:
+        return [path]
+
+    all_path = []
+    for x in a.bto:
+        if x.c_t != asm_constraint.c_next:
+            continue
+        if not x.label in blocby_label:
+            print 'XXX unknown label'
+            continue
+            
+        x = blocby_label[x.label]
+        all_path+=bloc_find_path_next(all_bloc, blocby_label, x, b, path+[a])
+        #stop if at least one path found
+        if all_path:
+            return all_path
+            
+    return all_path
+                           
+    
+        
+def bloc_merge(all_bloc, symbol_pool, dont_merge = []):
+    i = -1
+    blocby_label = {}
+    for b in all_bloc:
+        blocby_label[b.label] = b
+        b.parents = find_parents(all_bloc, b.label)
+
+    while i<len(all_bloc)-1:
+        i+=1
+        b = all_bloc[i]
+        if b.label in dont_merge:
+            continue
+        p = set(b.parents)
+        #if bloc dont self ref
+        if b.label in p:
+            continue
+        #and bloc has only one parent
+        if len(p) !=1:
+            continue
+        #may merge
+        bpl = p.pop()
+        #bp = getblocby_label(all_bloc, bpl)
+        bp = blocby_label[bpl]
+        #and parent has only one son
+        if len(bp.bto)!=1:
+            continue
+        #and will not create next loop constraint
+        path = bloc_find_path_next(all_bloc, blocby_label, b, bp)
+        if path:
+            continue
+        if bp.lines:
+            l = bp.lines[-1]
+            #jmp opt; jcc opt
+            if l.is_subcall():
+                continue
+            if l.breakflow() and l.dstflow():
+                bp.lines.pop()
+        #merge
+        sons = b.bto[:]
+
+        #update parents
+        for s in b.bto:
+            if not isinstance(s.label, asm_label): continue
+            if s.label.name == None:
+                continue
+            if not s.label in blocby_label:
+                print "unknown parent XXX"
+                continue
+            bs = blocby_label[s.label]
+            for p in list(bs.parents):
+                if p == b.label:
+                    bs.parents.discard(p)
+                    bs.parents.add(bp.label)
+                
+        bp.lines+=b.lines
+        bp.bto = b.bto
+        symbol_pool.remove(b.label)
+        del(all_bloc[i])
+        i = -1
+        
+            
+        
+def extract_sub_graph_of_bloc(all_bloc, b_o):
+    blocby_label = {}
+    for b in all_bloc:
+        blocby_label[b.label] = b
+        b.parents = find_parents(all_bloc, b.label)
+    
+    out = []
+    todo = set([b_o])
+    done = set()
+
+    while todo:
+        b = todo.pop()
+        if b in done:
+            continue
+        done.add(b)
+        out.append(b)
+        for c in b.bto:
+            if not isinstance(c.label, asm_label):
+                continue
+            bson = blocby_label[c.label]
+            todo.add(bson)
+    return out
+            
+
+def steal_bytes(in_str, arch_mn, ad, l):
+    in_str.setoffset(ad)
+    lines = []
+    total_bytes = 0
+    erased_asm = ""
+    callx86len = l
+    while total_bytes<callx86len:
+        lines.append(arch_mn.dis(in_str))
+        total_bytes+=lines[-1].l
+        erased_asm+=str(lines[-1])+'\n'
+    return lines, total_bytes
+        
+
+
+
+def dis_multi_func(in_str, mn, symbol_pool, ad, dont_dis = [], follow_call = False, dontdis_retcall = False, amode="u32", sex=0, dis_bloc_callback  =None ):
+    todo = ad[:]
+    done = set()
+    
+    
+    all_bloc = []
+    job_done = set()
+
+    call_ad = set(ad)
+    
+    while todo:
+        ad = todo.pop()
+        if ad in done:
+            continue
+        done.add(ad)
+        all_bloc__ = dis_bloc_all(mn, in_str, ad, job_done, symbol_pool, dont_dis, follow_call, False, dontdis_retcall, all_bloc = all_bloc, amode=amode, sex=sex, dis_bloc_callback = dis_bloc_callback )
+    
+        for b in all_bloc:
+            if not b.lines:
+                #XXX not lines in bloc ???
+                continue
+            l = b.lines[-1]
+            if not l.m.name.startswith('call'): continue
+            dst = mnemo.get_label(l.args[0])
+            if not dst: continue
+    
+            todo.append(dst)
+            call_ad.add(dst)
+    
+    
+        #all_bloc_funcs[ad] = all_bloc
+    all_bloc = split_bloc(all_bloc, symbol_pool, more_ref = call_ad)
+        
+    return all_bloc
+
+def dis_one_bloc(in_str, mnemo, ad):
+    job_done = set()
+    symbol_pool = asm_symbol_pool()
+    all_bloc = dis_bloc_all(mnemo, in_str, ad, job_done, symbol_pool, bloc_wd = 1)
+    if len(all_bloc) != 1:
+        return None
+    return all_bloc[0]
+    
+
+def dis_bloc_simple(mnemo, in_str, ad, **kargs):
+    job_done = set()
+    symbol_pool = asm_symbol_pool()
+    if not "job_done" in kargs:
+        kargs["job_done"] = job_done
+    if not "symbol_pool" in kargs:
+        kargs["symbol_pool"] = symbol_pool
+    all_bloc = dis_bloc_all(mnemo, in_str, ad,  **kargs)
+    return all_bloc
+
+
+def dis_bloc_ia32(in_str, ad, **kargs):
+    from miasm.arch.ia32_arch import x86_mn
+
+    job_done = set()
+    symbol_pool = asm_symbol_pool()
+
+    if not "job_done" in kargs:
+        kargs["job_done"] = job_done
+    if not "symbol_pool" in kargs:
+        kargs["symbol_pool"] = symbol_pool
+    all_bloc = dis_bloc_all(x86_mn, in_str, ad, **kargs)
+    return all_bloc
+
+nx = None
+try:
+    import networkx as nx
+except:
+    pass
+
+if nx:
+    def is_isomorph(all_bloc1, all_bloc2):
+        
+        G1=nx.DiGraph()
+        G2=nx.DiGraph()
+
+        for b in all_bloc1:
+            G1.add_node(b.label)
+            for t in b.bto:
+                G1.add_edge(b.label, t.label)
+        for b in all_bloc2:
+            G2.add_node(b.label)
+            for t in b.bto:
+                G2.add_edge(b.label, t.label)
+
+        GM = nx.GraphMatcher(G1,G2)
+        is_isom = GM.is_isomorphic()
+        return GM.is_isomorphic(), GM.mapping
+        
diff --git a/miasm/core/bin_stream.py b/miasm/core/bin_stream.py
new file mode 100644
index 00000000..c8e64c8d
--- /dev/null
+++ b/miasm/core/bin_stream.py
@@ -0,0 +1,101 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+class bin_stream_mother(type):
+    def __call__(self, *arg):
+        if arg and arg[0].__class__ in [str]:
+            cls = bin_stream_str
+        elif arg and type(arg[0]) is file:
+            cls = bin_stream_file
+        else:
+            cls = bin_stream_str
+
+        i = cls.__new__(cls, cls.__name__, cls.__bases__, cls.__dict__)
+        i.__init__(*arg)
+        return i
+
+
+class bin_stream(object):
+    __metaclass__ = bin_stream_mother
+    def __init__(self, *args, **kargs):
+        pass
+    def __repr__(self):
+        return "<%s !!>"%self.__class__.__name__
+
+    def hexdump(self, offset, l):
+        return
+
+    
+        
+class bin_stream_str(bin_stream):
+    def __init__(self, bin ="", offset = 0L):
+        if offset>len(bin):
+            raise IOError
+        self.bin = bin
+        self.offset = offset
+        self.l = len(bin)
+        if "is_addr_in" in self.bin.__class__.__dict__:
+            self.is_addr_in = lambda ad:self.bin.is_addr_in(ad)
+            
+
+    def readbs(self, l=1):
+        if self.offset+l>self.l:
+            raise IOError
+        self.offset+=l
+        return self.bin[self.offset-l:self.offset]
+
+    def writebs(self, l=1):
+        raise ValueError('writebs unsupported')
+
+    def __str__(self):
+        out =  self.bin[self.offset:]
+        return out
+    def setoffset(self, val):
+        val = val & 0xFFFFFFFF
+        self.offset = val
+
+class bin_stream_file(bin_stream):
+    def __init__(self, bin, offset=0L):
+        self.bin = bin
+        self.bin.seek(0, 2)
+        self.l = self.bin.tell()
+        self.offset = offset
+
+        
+                
+    def getoffset(self):
+        return self.bin.tell()
+
+    def setoffset(self, val):
+        val = val & 0xFFFFFFFF
+        self.bin.seek(val)
+        
+    offset = property(getoffset, setoffset)
+
+    def readbs(self, l=1):
+        if self.offset+l>self.l:
+            raise IOError
+        return self.bin.read(l)
+
+    def writebs(self, l=1):
+        if self.offset+l>self.l:
+            raise IOError
+        return self.bin.write(l)
+
+    def __str__(self):
+        return str(self.bin)
+
diff --git a/miasm/core/memory_pool.py b/miasm/core/memory_pool.py
new file mode 100644
index 00000000..a0ddaf1b
--- /dev/null
+++ b/miasm/core/memory_pool.py
@@ -0,0 +1,283 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+import array
+import struct
+import cPickle
+import StringIO
+from numpy import uint32
+
+from elfesteem import *
+
+
+class mempool:
+    def gen_pad(x):
+        if x>0:
+            return '\x00'*x
+        else:
+            return ''
+    def __init__(self, start, stop, perm = "RW", data = {}, name = "", extern_func  = {}):
+        self.start = start
+        self.stop = stop
+        self.extern_func = extern_func
+        self.perm_R = "R" in perm
+        self.perm_W = "W" in perm
+        self.perm_X = "X" in perm
+        self.name = name
+        
+        my_data = array.array('B')
+
+        if type(data) is dict:
+            pad = stop-start
+            pass
+            
+        elif type(data) is file:
+            pos = data.tell()
+            data.seek(0, 2)
+            end = data.tell()
+            data.seek(pos)
+            pad = stop-start - (end-pos)
+            if pad>0:
+                my_data = my_data.fromfile(data, end-pos)
+            else:
+                my_data = my_data.fromfile(f, stop-start)
+        else:
+            pad = stop-start - len(data)
+            my_data.fromstring(str(data))
+
+        
+        my_data.extend([0 for x in xrange(pad)])
+        self.data = my_data
+
+    def __str__(self):
+        return repr(self)+'<%.8X-%.8X>'%(int(self.start),int(self.stop))+"-R"[self.perm_R]+"-W"[self.perm_W]+"-X"[self.perm_X]+" "+self.name
+
+    def has_extern(self, address):
+        if address in self.extern_func:
+            return self.extern_func[address]
+        return False
+
+    def get_b(self, x):
+        return self.data[int(uint32(x))-self.start]
+    def get_w(self, x):
+        return struct.unpack('H', self.data[int(uint32(x))-self.start:int(uint32(x))-self.start+2].tostring())[0]
+    def get_d(self, x):
+        return struct.unpack('L', self.data[int(uint32(x))-self.start:int(uint32(x))-self.start+4].tostring())[0]
+    def get_data(self, x, l):
+        return self.data[int(uint32(x))-self.start:int(uint32(x))-self.start+l]
+    
+    def set_b(self, x, v):
+        self.data[int(uint32(x))-self.start] = int(v)
+    def set_w(self, x, v):
+        i = map(ord, struct.pack('H', int(v)))
+        i.reverse()
+        for j in xrange(2):
+            self.data[int(uint32(x))-self.start+j] = i.pop()
+    def set_d(self, x, v):
+        i = map(ord, struct.pack('L', int(v)))
+        i.reverse()
+        for j in xrange(4):
+            self.data[int(uint32(x))-self.start+j] = i.pop()
+    def set_data(self, x, v):
+        for i, c in enumerate(v):
+            self.data[int(uint32(x))-self.start+i] = ord(c)
+            
+    def to_file(self, f):
+        if type(f) is str:
+            f = open(f,"w")
+        my_data = self.data
+        self.data = self.data.tostring()
+        cPickle.dump(self, f)
+        self.data = my_data
+    
+    @staticmethod
+
+    def from_file(f):
+        if type(f) is str:
+            f = open(f,"r")
+        m = cPickle.load(f)
+        my_data = array.array('B')
+        my_data.fromstring(m.data)
+        m.data = my_data
+        return m
+
+class mempool_manager:
+    def __init__(self, mems = []):
+        self._mems = mems
+
+    def __str__(self):
+        out = repr(self)+'\n'
+        out += reduce(lambda x,y:x+str(y)+'\n', self._mems, "")
+        return out[:-1]
+
+    def get_mems(self):
+        return self._mems
+    
+    def set_mems(self):
+        tmp = [[m.start, m.stop] for m in self._mems]
+        for m in tmp:
+            if m[0]>m[1]:
+                raise 'stop inf start: %s'%str(m)
+        for i, m in enumerate(tmp[:-1]):
+            if m[1] > tmp[i+1][0]:
+                raise 'overlapping mems: %s %s'%(str(m), str(tmp[i+1])) 
+        
+        return self._mems
+    
+    mems = property(get_mems, set_mems)
+    
+    def get_mem_pool(self, x):
+        x = int(uint32(x))
+        for m in self._mems:
+            if x >=m.start and x <m.stop:
+                return m
+        raise 'unknown mem', str(x)
+        
+
+    def get_b(self, x):
+        m = self.get_mem_pool(x)
+        return m.get_b(x)
+
+    def get_w(self, x):
+        m = self.get_mem_pool(x)
+        try:
+            return m.get_w(x)
+        except:
+            pass
+        out = ""
+        for i in xrange(2):
+            m = self.get_mem_pool(x+i)
+            out+=chr(m.get_b(x+i))
+        return struct.unpack('H', out)[0]
+        
+    def get_d(self, x):
+        m = self.get_mem_pool(x)
+        try:
+            return m.get_d(x)
+        except:
+            pass
+        out = ""
+        for i in xrange(4):
+            m = self.get_mem_pool(x+i)
+            out+=chr(m.get_b(x+i))
+        return struct.unpack('L', out)[0]
+        
+    def get_data(self, x, l):
+        m = self.get_mem_pool(x)
+        try:
+            return m.get_data(x,l)
+        except:
+            pass
+        out = ""
+        for i in xrange(l):
+            m = self.get_mem_pool(x+i)
+            out+=chr(m.get_b(x+i))
+        return out
+        
+    def set_b(self, x, v):
+        m = self.get_mem_pool(x)
+        m.set_b(x,v)
+
+    def set_w(self, x, v):
+        m = self.get_mem_pool(x)
+        try:
+            m.set_w(x, v)
+            return
+        except:
+            pass
+        i = map(ord, struct.pack('H', int(v)))
+        i.reverse()
+        for j in xrange(2):
+            m = self.get_mem_pool(x+j)
+            m.set_b(x+j, i.pop())
+
+    def set_d(self, x, v):
+        m = self.get_mem_pool(x)
+        try:
+            m.set_d(x, v)
+            return
+        except:
+            pass
+        i = map(ord, struct.pack('L', int(v)))
+        i.reverse()
+        print hex(int(x)), i
+        for j in xrange(4):
+            m = self.get_mem_pool(x+j)
+            print j, m
+            m.set_b(x+j, i.pop())
+            print 'iii'
+
+    def set_data(self, x, v):
+        m = self.get_mem_pool(x)
+        try:
+            m.set_data(x, v)
+            return
+        except:
+            pass
+        for i, c in enumerate(v):
+            m = self.get_mem_pool(x+i)
+            m.set_b(x+i, ord(c))
+            
+
+    def to_file(self, f):
+        if type(f) is str:
+            f = open(f,"w")
+        for m in self._mems:
+            m.to_file(f)
+    
+    @staticmethod
+
+    def from_file(f):
+        if type(f) is str:
+            f = open(f,"r")
+        mems = []
+        while True:
+            try:
+                mems.append(mempool.from_file(f))
+            except:
+                break
+        return mempool_manager(mems)
+
+
+def load_pe(e, loadhdr=False):
+    mems = []
+    if loadhdr:
+      hdr = open(fname, 'rb').read(0x1000)
+      mems.append(mempool(e.NThdr.ImageBase,
+                            e.NThdr.ImageBase+0x1000,
+                            'RWX', hdr, "PE HDR"))
+    for section in e.SHList:
+        section_size = max(section.rawsize,section.size)
+        section_size = (section_size+0xfff)&~0xfff
+        mems.append(mempool(e.NThdr.ImageBase+section.addr,
+                            e.NThdr.ImageBase+section.addr+section_size,
+                            'RWX', section.data, section.name.replace('\x00', ' ')))
+
+    return mems
+
+
+def load_from_pe(pe):
+    
+    mems = []
+    for section in pe.SHList:
+        section_size = max(section.rawsize,section.size)
+        section_size = (section_size+0xfff)&~0xfff
+        mems.append(mempool(pe.NThdr.ImageBase+section.addr,
+                            pe.NThdr.ImageBase+section.addr+section_size,
+                            'RWX', section.data, section.name.replace('\x00', ' ')))
+
+    return mems
diff --git a/miasm/core/parse_ad.py b/miasm/core/parse_ad.py
new file mode 100644
index 00000000..be2e5a38
--- /dev/null
+++ b/miasm/core/parse_ad.py
@@ -0,0 +1,343 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+from miasm.arch.ia32_reg import x86_afs
+from numpy import int32, uint32
+
+def dict_add(a, b):
+    tmp = dict(a)
+    for k in b:
+        #special case 
+        if k == x86_afs.symb:
+            if k in tmp:
+                tmp[k] = dict_add(tmp[k], b[k])
+            else:
+                tmp[k] = dict(b[k])
+            continue
+        #normal case 
+        if k in tmp:
+            tmp[k]+=b[k]
+        else:
+            tmp[k] = b[k]
+        if tmp[k]==0:
+            del(tmp[k])
+    return tmp
+
+def dict_sub(a, b):
+    tmp = dict(a)
+    for k in b:
+        #special case 
+        if k == x86_afs.symb:
+            if k in tmp:
+                tmp[k] = dict_sub(tmp[k], b[k])
+            else:
+                tmp[k] = dict({},b[k])
+            continue
+        #normal case
+        if k in tmp:
+            tmp[k]-=b[k]
+        else:
+            tmp[k] = -b[k]
+        if tmp[k]==0:
+            del(tmp[k])
+    return tmp
+
+def dict_mul(a, b):
+    if a.keys() == [x86_afs.imm]:
+        ret = {}
+        for k in b:
+            if k == x86_afs.symb:
+                ret[k] = dict_mul({x86_afs.imm:a[x86_afs.imm]}, b[k])
+            else:
+                ret[k] = a[x86_afs.imm]*b[k]
+        return ret
+    if b.keys() == [x86_afs.imm]:
+        ret = {}
+        for k in a:
+            if k == x86_afs.symb:
+                ret[k] = dict_mul({x86_afs.imm:b[x86_afs.imm]}, a[k])
+            else:
+                ret[k] = b[x86_afs.imm]*a[k]
+        return ret
+    
+    raise 'bad dict mul %s'%(str(a)+str(b))
+
+keywords = ("BYTE", "WORD", "DWORD", "SINGLE", "DOUBLE",
+            "ES", "CS", "SS", "DS", "FS", "GS",
+            "PTR")
+
+
+tokens = keywords +(
+    'NUMBER',
+    'PLUS','MINUS','TIMES','DIVIDE','EQUALS',
+    'LPAREN','RPAREN','LBRA','RBRA', 'COLON',
+    'OFFSET','NAME', 
+    )
+
+# Tokens
+
+t_PLUS    = r'\+'
+t_MINUS   = r'-'
+t_TIMES   = r'\*'
+t_DIVIDE  = r'/'
+t_EQUALS  = r'='
+t_LPAREN  = r'\('
+t_RPAREN  = r'\)'
+t_LBRA  = r'\['
+t_RBRA  = r'\]'
+t_COLON    = r':'
+t_OFFSET  = r'OFFSET'
+
+def t_NAME(t):
+    r'[a-zA-Z_][a-zA-Z0-9_]*'
+    if t.value.upper() in keywords:
+        t.type = t.value.upper()
+        t.value = t.value.lower()
+    return t
+
+
+
+def t_NUMBER(t):
+    r'((((0x)|(0X))[0-9a-fA-F]+)|(\d+))'
+    try:
+        if t.value.startswith("0x") or t.value.startswith("0X"):
+            t.value = int(t.value, 16)
+        else:
+            t.value = int(t.value)
+    except ValueError:
+        print("Integer value too large %d", t.value)
+        t.value = 0
+    return t
+
+# Ignored characters
+t_ignore = " \t"
+
+def t_newline(t):
+    r'\n+'
+    t.lexer.lineno += t.value.count("\n")
+    
+def t_error(t):
+    print("Illegal character '%s'" % t.value[0])
+    t.lexer.skip(1)
+
+
+# Build the lexer
+import ply.lex as lex
+lex.lex()
+
+
+precedence = (
+    ('left','PLUS','MINUS'),
+    ('left','TIMES','DIVIDE'),
+    ('right','UMINUS'),
+    )
+
+def p_expression_1(t):
+    '''expression : '''
+    return {}
+def p_expression_2(t):
+    '''expression : expression PLUS expression
+                  | expression MINUS expression
+                  | expression TIMES expression
+                  | expression DIVIDE expression'''
+
+    if t[2] == '+':
+        t[0] = dict_add(t[1], t[3])
+    elif t[2] == '-':
+        t[0] = dict_sub(t[1], t[3])
+    elif t[2] == '*':
+        t[0] = dict_mul(t[1], t[3])
+    elif t[2] == '/':
+        raise 'bad op'
+    else:
+        raise 'bad op'
+
+
+def p_expression_3(t):
+    '''expression : LPAREN expression RPAREN'''
+    t[0] = t[2]
+
+def p_expression_4(t):
+    '''expression : OFFSET expression '''
+    t[0] = t[2]
+
+def p_expression_5(t):
+    '''expression : MINUS expression  %prec UMINUS'''
+    t[0] = dict([[k,-t[2][k]] for k in t[2]])
+
+def p_expression_6(t):
+    '''expression :  NUMBER'''
+    t[0] = {x86_afs.imm:int(int32(uint32(int(t[1]))))}
+
+
+#"[@?_a-zA-Z\.$][?\.a-zA-Z0-9_@$]*"
+def p_expression_8(t):
+    '''expression : NAME'''
+    if t[1] in x86_afs.reg_list32:
+        size = x86_afs.u32
+    elif t[1] in x86_afs.reg_list16:
+        size = x86_afs.u16
+    elif t[1] in x86_afs.reg_list8:
+        size = x86_afs.u08
+    elif t[1] in x86_afs.reg_flt:
+        size = x86_afs.f32
+    elif t[1] in x86_afs.reg_dr:
+        size = x86_afs.u32
+    elif t[1] in x86_afs.reg_cr:
+        size = x86_afs.u32
+    elif t[1] in x86_afs.reg_sg:
+        size = x86_afs.u32
+        
+        
+    else:
+        #raise 'bad reg size'
+        t[0] = {x86_afs.symb:{t[1]:1}}
+        return
+    t[0] ={x86_afs.reg_dict[t[1]]:1, x86_afs.size : size}
+
+def p_PTRSIZE(t):
+    '''PTRSIZE : BYTE
+               | WORD
+               | DWORD
+               | SINGLE
+               | DOUBLE
+                 '''
+    t[0] = t[1]
+
+def p_PTRMEM(t):
+    '''PTRMEM : PTR'''
+    t[0] = t[1]
+
+
+
+
+
+
+
+def p_OPTSEG(t):
+    '''OPTSEG :  ES
+               | CS
+               | SS
+               | DS
+               | FS
+               | GS
+                 '''
+    t[0] = t[1]
+
+def p_opt_seg_1(t):
+    '''opt_seg : OPTSEG COLON '''
+    t[0] = {x86_afs.segm:x86_afs.reg_sg.index(t[1])}
+
+def p_expression_9(t):
+    '''expression : PTRSIZE PTRMEM LBRA expression RBRA
+                  | PTRSIZE PTRMEM opt_seg LBRA expression RBRA  '''
+    size = t[1]
+    if len(t) == 6:
+        index = 4
+    else:
+        index = 5
+    if size=='byte':
+        t[index][x86_afs.ad] = x86_afs.u08
+    elif size == 'word':
+        t[index][x86_afs.ad] = x86_afs.u16
+    elif size == 'dword':
+        t[index][x86_afs.ad] = x86_afs.u32
+    elif size == 'single':
+        t[index][x86_afs.ad] = x86_afs.f32
+    elif size == 'double':
+        t[index][x86_afs.ad] = x86_afs.f64
+    else:
+        raise 'bad address size'
+    if len(t) !=6:
+        t[index].update(t[3])
+    t[0] = t[index]
+
+def p_expression_10(t):
+    '''expression : LBRA expression RBRA
+                  | opt_seg LBRA expression RBRA '''
+    if len(t) == 4:
+        t[2][x86_afs.ad] = x86_afs.u32
+        t[0] = t[2]
+    else:
+        t[3][x86_afs.ad] = x86_afs.u32
+        t[3].update(t[1])
+        t[0] = t[3]
+
+def parse_ad(a):
+    tmp_dict = {}
+    l = yacc.parse(a)
+
+    if not x86_afs.ad in l:
+        l[x86_afs.ad] = False
+    else:
+        l[x86_afs.size] = l[x86_afs.ad]
+        
+    if not x86_afs.size in l:
+        l[x86_afs.size] = x86_afs.u32
+        
+        
+
+    return l
+
+import ply.yacc as yacc
+yacc.yacc()
+
+def ad_to_generic(a):
+    
+    #opt imm
+    out = []
+    to_add = []
+    #generic ad size
+    if a[x86_afs.ad]:
+        a[x86_afs.ad] = True
+
+        
+        #imm can always be encoded in u32
+        to_add.append({x86_afs.imm:x86_afs.u32})
+
+        if  x86_afs.imm in a:
+            if a[x86_afs.imm] >=0 and a[x86_afs.imm] <=0xFF:
+                to_add.append({x86_afs.imm:x86_afs.u08})
+            if a[x86_afs.imm] >=-128 and a[x86_afs.imm] <128:
+                to_add.append({x86_afs.imm:x86_afs.s08})
+        else:
+            to_add.append({x86_afs.imm:x86_afs.u08})
+            to_add.append({x86_afs.imm:x86_afs.s08})
+
+
+    if not x86_afs.imm in a:
+        out.append(a)
+    else:
+        i = a[x86_afs.imm]
+        if i<128 and i >= -128:
+            to_add.append({x86_afs.imm:x86_afs.s08})
+        if i<=0xFF and i >=0 :
+            to_add.append({x86_afs.imm:x86_afs.u08})
+            
+    for kv in to_add:
+        tmp = dict(a)
+        tmp.update(kv)
+        out.append(tmp)
+
+    out_unik = []
+    for o in out:
+        if not o in out_unik:
+            out_unik.append(o)
+
+    return out_unik
+ 
+
diff --git a/miasm/core/parse_asm.py b/miasm/core/parse_asm.py
new file mode 100644
index 00000000..64618626
--- /dev/null
+++ b/miasm/core/parse_asm.py
@@ -0,0 +1,232 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+from miasm.core.asmbloc import *
+from shlex import shlex
+
+
+declarator = {'byte':'B', 'long':'I'}
+def guess_next_new_label(symbol_pool, gen_label_index = 0):
+    i = 0
+    while True:
+        l = asm_label(i)
+        i+=1
+        if not l.name in symbol_pool.s:
+            return l
+        
+    
+def parse_txt(mnemo, txt, symbol_pool = None, gen_label_index = 0):
+    if symbol_pool == None:
+        symbol_pool = asm_symbol_pool()
+
+    lines_text = []
+    lines_data = []
+    lines_bss  = []
+
+    lines=lines_text
+    #parse each line
+    for line in txt.split('\n'):
+        #empty
+        if re.match(r'\s*$', line):
+            continue
+        #comment
+        if re.match(r'\s*;\S*', line):
+            continue
+        #directive
+        if re.match(r'\s*\.', line):
+            r =  re.match(r'\s*\.(\S+)', line)
+            directive = r.groups()[0]
+            if directive == 'text':
+                lines = lines_text
+                continue
+            if directive == 'data':
+                lines = lines_data
+                continue
+            if directive == 'bss':
+                lines = lines_bss
+                continue
+            if directive in ['string', 'ascii']:
+                #XXX HACK
+                line = line.replace(r'\n', '\n').replace(r'\r', '\r')
+                raw = line[line.find(r'"')+1:line.rfind(r"'")]
+                if directive == 'string':
+                    raw+="\x00"
+                lines.append(asm_raw(raw))
+                continue
+            if directive == 'ustring':
+                #XXX HACK
+                line = line.replace(r'\n', '\n').replace(r'\r', '\r')
+                raw = line[line.find(r'"')+1:line.rfind(r"'")]+"\x00"
+                raw = "".join(map(lambda x:x+'\x00', raw))
+                lines.append(asm_raw(raw))
+                continue
+            if directive in declarator:
+                data_raw = [x for x in shlex(line[r.end():]) if not x in ',']
+                data_int = []
+                for b in data_raw:
+                    if re.search(r'0x', b):
+                        data_int.append(int(b, 16))
+                    else:
+                        data_int.append(int(b))
+                raw = reduce(lambda x,y:x+struct.pack(declarator[directive], y), data_int, "")
+                lines.append(asm_raw(raw))
+                continue
+            if directive == 'split': #custom command
+                lines.append(asm_raw(line.strip()))
+                continue
+            
+            raise "unknown directive %s"%str(directive)
+        
+        #label
+        r = re.match(r'\s*(\S+)\s*:', line)
+        if r:
+            l = r.groups()[0]
+            l = symbol_pool.getby_name_create(l)
+            lines.append(l)
+            continue
+        
+        #code
+        if ';' in line:
+            line = line[:line.find(';')]
+        prefix, name, args = mnemo.parse_mnemo(line)
+        #print prefix, name, args
+        args = [mnemo.parse_address(a) for a in args]
+        #pool symbols
+        for a in args:
+
+            if mnemo.has_symb(a):
+                symbs = mnemo.get_symbols(a)
+                symbs_dct = {}
+                for s, count in symbs:
+                    if isinstance(s, asm_label):
+                        continue
+                    l = symbol_pool.getby_name_create(s)
+                    symbs_dct[s] = l
+                mnemo.names2symbols(a, symbs_dct)
+
+
+
+
+        if mnemo.rebuilt_inst:
+            candidates=dict([[len(x),x] for x in mnemo.asm(line)])
+            if not candidates:
+                raise ValueError('cannot asm %s'%str(line))
+            c = candidates[min(candidates.keys())]
+            c+=mnemo.prefix2hex(prefix)
+            instr = mnemo.dis(c)
+        else:
+            instr = mnemo.asm_instr(line)
+        instr.arg = args
+        lines.append(instr)
+
+    log_asmbloc.info( "___pre asm oki___")
+    #make blocs
+    #gen_label_index = 0
+
+
+    
+    all_blocs_sections = []
+    bloc_num = 0
+    for lines in [lines_text, lines_data, lines_bss]:
+        state = 0
+        i = 0
+        all_blocs = []
+        all_blocs_sections.append(all_blocs)
+
+        bloc_to_nlink = None
+        block_may_link = False
+        while i <len(lines):
+            #no current bloc
+            if state == 0:
+                if not isinstance(lines[i], asm_label):
+                    l = guess_next_new_label(symbol_pool)
+                    symbol_pool.add(l)
+                    lines[i:i] = [l]
+                else:
+                    l = lines[i]
+                    b = asm_bloc(l)
+                    b.bloc_num = bloc_num
+                    bloc_num+=1
+                    all_blocs.append(b)
+                    state = 1
+                    i+=1
+                    if bloc_to_nlink:
+                        bloc_to_nlink.addto(asm_constraint(b.label, asm_constraint.c_next))
+                        bloc_to_nlink = None
+                
+            #in bloc
+            elif state == 1:
+                #asm_raw
+                if isinstance(lines[i], asm_raw):
+                    if lines[i].raw.startswith('.split'):
+                        state = 0
+                        block_may_link = False
+                        i+=1
+                    else:
+                        b.addline(lines[i])
+                        i+=1
+                #asm_label
+                elif isinstance(lines[i], asm_label):
+                    if block_may_link:
+                        b.addto(asm_constraint(lines[i], asm_constraint.c_next))
+                        block_may_link = False
+                    state = 0
+                #instruction
+                else:
+                    b.addline(lines[i])
+                    if lines[i].dstflow():
+                        mydst = lines[i].arg
+
+                        if len(mydst)==1 and mnemo.get_symbols(mydst[0]):
+                            arg = dict(mydst[0])
+                            symbs = mnemo.get_symbols(arg)
+                            """
+                            TODO XXX redo this (as many miasm parts)
+                            """
+                            l = symbs[0][0]
+                            lines[i].setdstflow([l])
+                            b.addto(asm_constraint(l, asm_constraint.c_to))
+                            
+                        # TODO XXX redo this really
+
+                        if not lines[i].breakflow() and i+1 < len(lines):
+                            if isinstance(lines[i+1], asm_label):
+                                l = lines[i+1]
+                            else:
+                                l = guess_next_new_label(symbol_pool)
+                                symbol_pool.add(l)
+                                lines[i+1:i+1] = [l]
+                        else:
+                            state = 0
+
+                        if lines[i].splitflow():
+                            bloc_to_nlink = b
+                    if not lines[i].breakflow() or lines[i].splitflow():
+                        block_may_link = True
+                    else:
+                        block_may_link = False
+                            
+                    
+                    i+=1        
+    
+    
+                        
+    
+    for b in all_blocs_sections[0]:
+        log_asmbloc.info( b)
+
+    return all_blocs_sections, symbol_pool
diff --git a/miasm/expression/__init__.py b/miasm/expression/__init__.py
new file mode 100644
index 00000000..fbabaacf
--- /dev/null
+++ b/miasm/expression/__init__.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
diff --git a/miasm/expression/expression.py b/miasm/expression/expression.py
new file mode 100644
index 00000000..4e4563c7
--- /dev/null
+++ b/miasm/expression/expression.py
@@ -0,0 +1,754 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+from numpy import uint8, uint16, uint32, uint64, int8, int16, int32, int64
+tip = 'tip'
+
+
+float_stack = 'float_stack'
+float_stack_ptr = 'float_stack_ptr'
+
+def slice_rest(size, start, stop):
+    if start >=size or stop > size: raise 'bad slice rest %s %s %s'%(str(size), str(start), str(stop))
+    if start == stop: return [(0,size)]
+    rest = []
+    if start !=0:
+        rest.append((0, start))
+    if stop < size:
+        rest.append((stop, size))
+
+    return rest
+        
+tab_int_size = {int8:8,
+                uint8:8,
+                int16:16,
+                uint16:16,
+                int32:32,
+                uint32:32,
+                int64:64,
+                uint64:64
+                }
+
+my_size_mask = {1:1, 8:0xFF, 16:0xFFFF, 32:0xFFFFFFFF,  64:0xFFFFFFFFFFFFFFFFL}
+
+
+
+def get_missing_interval(all_intervals, i_min = 0, i_max = 32):
+    my_intervals = all_intervals[:]
+    my_intervals.sort()
+    my_intervals.append((i_max, i_max))
+
+    missing_i = []
+    last_pos = i_min
+    for start, stop in my_intervals:
+        if last_pos  != start:
+            missing_i.append((last_pos, start))
+        last_pos = stop
+        
+    return missing_i
+
+
+class Expr:
+    is_term = False
+    is_simp = False
+    is_eval = False
+    def __init__(self, arg):
+        self.arg = arg
+    def __str__(self):
+        return str(self.arg)
+    def __getitem__(self, i):
+        if not isinstance(i, slice):
+            print i
+            raise "bad slice"
+        start, stop, step = i.indices(0x1337BEEF)
+        return ExprSlice(self, start, stop)
+    def get_r(self, mem_read=False):
+        return self.arg.get_r(mem_read)
+    def get_w(self):
+        return self.arg.get_w()
+    def get_size(self):
+        return arg.get_size()
+    def __repr__(self):
+        return "<%s 0x%x>"%(self.__class__.__name__, id(self))
+    def __ne__(self, a):
+        return not self.__eq__(a)
+
+    def toC(self):
+        print self
+        fdsfs
+        return self.arg.toC()
+
+    def __add__(self, a):
+        return ExprOp('+', self, a)
+    def __sub__(self, a):
+        return ExprOp('-', self, a)
+    def __div__(self, a):
+        return ExprOp('/', self, a)
+    def __mul__(self, a):
+        return ExprOp('*', self, a)
+    def __lshift__(self, a):
+        return ExprOp('<<', self, a)
+    def __rshift__(self, a):
+        return ExprOp('>>', self, a)
+    def __xor__(self, a):
+        return ExprOp('^', self, a)
+    def __or__(self, a):
+        return ExprOp('|', self, a)
+    def __and__(self, a):
+        return ExprOp('&', self, a)
+        
+class ExprTop(Expr):
+    def __init__(self, e=None):
+        self.e = e
+        pass
+    def __str__(self):
+        return "top(%s)"%str(self.e)
+    def get_r(self, mem_read=False):
+        raise ValueError("get_r on TOP")
+    def get_w(self):
+        raise ValueError("get_r on TOP")
+    def get_size(self):
+        raise ValueError("get_size on TOP")
+    def reload_expr(self, g = {}):
+        return ExprTop(self.e)
+    def __eq__(self, a):
+        return isinstance(a, ExprTop)
+    def __hash__(self):
+        return 0x1337beef
+            
+    def toC(self):
+        raise ValueError('cannot toC TOP')
+
+
+class ExprInt(Expr):
+    def __init__(self, arg):
+        if not type(arg) in tab_int_size:
+            raise 'arg must by numpy int! %s'%str(arg)
+        self.arg = arg
+    def __str__(self):
+        if self.arg < 0:
+            return str("-0x%X"%-int(self.arg&0xffffffffffffffffL))
+        else:
+            return str("0x%X"%int(self.arg&0xffffffffffffffffL))
+    def get_r(self, mem_read=False):
+        return set()
+    def get_w(self):
+        return set()
+    def get_size(self):
+        return 8*self.arg.nbytes
+    def reload_expr(self, g = {}):
+        return ExprInt(self.arg)
+    def __contains__(self, e):
+        return self == e
+    def replace_expr(self, g = {}):
+        if self in g:
+            return g[self]
+        return self
+    def __eq__(self, a):
+        if not isinstance(a, ExprInt):
+            return False
+        return self.arg == a.arg
+    def __hash__(self):
+        return hash(self.arg)
+    def __repr__(self):
+        return Expr.__repr__(self)[:-1]+" 0x%X>"%int(self.arg&0xffffffffffffffffL)
+
+    def toC(self):
+        return str(self)
+
+
+class ExprId(Expr):
+    def __init__(self, name, size = 32, is_term = False):
+        self.name, self.size = name, size
+        self.is_term = is_term
+    def __str__(self):
+        return str(self.name)
+    def get_r(self, mem_read=False):
+        return set([self])
+    def get_w(self):
+        return set([self])
+    def get_size(self):
+        return self.size
+    def reload_expr(self, g = {}):
+        if self in g:
+            return g[self]
+        else:
+            return ExprId(self.name, self.size)
+        if self in g:
+            return g[self]
+        return self
+    def __contains__(self, e):
+        return self == e
+    def replace_expr(self, g = {}):
+        if self in g:
+            return g[self]
+        return self
+    def __eq__(self, a):
+        if not isinstance(a, ExprId):
+            return False
+        if self.name == a.name and self.size != a.size:
+            fdsfdsfdsdsf
+        return self.name == a.name and self.size == a.size
+    def __hash__(self):
+        return hash(self.name)
+    def __repr__(self):
+        return Expr.__repr__(self)[:-1]+" %s>"%self.name
+
+    def toC(self):
+        return str(self)
+
+memreg = ExprId('MEM')
+
+
+
+class ExprAff(Expr):
+    def __init__(self, dst, src):
+        
+        #if dst is slice=> replace with id make composed src
+        if isinstance(dst, ExprSlice):
+            self.dst = dst.arg
+            rest = [ExprSliceTo(ExprSlice(dst.arg, *r), *r) for r in slice_rest(dst.arg.size, dst.start, dst.stop)]
+            all_a = [(dst.start, ExprSliceTo(src, dst.start, dst.stop))]+ [(x.start, x) for x in rest]
+            all_a.sort()
+            self.src = ExprCompose([x[1] for x in all_a])
+        else:
+            self.dst, self.src = dst,src
+            
+    def __str__(self):
+        return "%s = %s"%(str(self.dst), str(self.src))
+    def get_r(self, mem_read=False):
+        return self.src.get_r(mem_read)
+    def get_w(self):
+        if isinstance(self.dst, ExprMem):
+            return set([self.dst]) #[memreg]
+        else:
+            return self.dst.get_w()
+    #return dst size? XXX
+    def get_size(self):
+        return self.dst.get_size()
+    def reload_expr(self, g = {}):
+        if self in g:
+            return g[self]
+        dst = self.dst
+        if isinstance(dst, Expr):
+            dst = self.dst.reload_expr(g)
+        src = self.src
+        if isinstance(src, Expr):
+            src = self.src.reload_expr(g)
+        
+        return ExprAff(dst, src )
+    def __contains__(self, e):
+        return self == e or self.src.__contains__(e) or self.dst.__contains__(e)
+    def replace_expr(self, g = {}):
+        if self in g:
+            return g[self]
+        dst = self.dst.replace_expr(g)
+        src = self.src.replace_expr(g)
+        return ExprAff(dst, src)
+        
+    def __eq__(self, a):
+        if not isinstance(a, ExprAff):
+            return False
+        return self.src == a.src and self.dst == a.dst
+    def __hash__(self):
+        return hash(self.dst)^hash(self.src)
+
+    def toC(self):
+        return "%s = %s"%(self.dst.toC(), self.src.toC())
+
+
+    #XXX /!\ for hackish expraff to slice
+    def get_modified_slice(self):
+        dst = self.dst
+        if not isinstance(self.src, ExprCompose):
+            raise ValueError("get mod slice not on expraff slice", str(self))
+        modified_s = []
+        for x in self.src.args:
+            if x.arg.arg != dst or x.start != x.arg.start or x.stop != x.arg.stop:
+                modified_s.append(x)
+
+        return modified_s
+
+
+class ExprCond(Expr):
+    def __init__(self, cond, src1, src2):
+        self.cond, self.src1, self.src2 = cond, src1, src2
+    def __str__(self):
+        return "%s?(%s,%s)"%(str(self.cond), str(self.src1), str(self.src2))
+    def get_r(self, mem_read=False):
+        out=self.cond.get_r(mem_read).union(self.src1.get_r(mem_read)).union(self.src2.get_r(mem_read))
+        return out
+    def get_w(self):
+        return set()
+    #return src1 size? XXX
+    def get_size(self):
+        return self.src1.get_size()
+    def reload_expr(self, g = {}):
+        src1 = self.src1
+        if isinstance(src1, Expr):
+            src1 = self.src1.reload_expr(g)
+        src2 = self.src2
+        if isinstance(src2, Expr):
+            src2 = self.src2.reload_expr(g)
+        cond = self.cond
+        if isinstance(cond, Expr):
+            cond = self.cond.reload_expr(g)
+        return ExprCond(cond, src1, src2 )
+    def replace_expr(self, g = {}):
+        if self in g:
+            return g[self]
+        cond = self.cond.replace_expr(g)
+        src1 = self.src1.replace_expr(g)
+        src2 = self.src2.replace_expr(g)
+        return ExprCond(cond, src1, src2 )
+    def __contains__(self, e):
+        return self == e or self.cond.__contains__(e) or self.src1.__contains__(e) or self.src2.__contains__(e)
+
+
+    def __eq__(self, a):
+        if not isinstance(a, ExprCond):
+            return False
+        return self.cond == a.cond and self.src1 == a.src1 and self.src2 == a.src2
+    def __hash__(self):
+        return hash(self.cond)^hash(self.src1)^hash(self.src2)
+        
+    def toC(self):
+        return "(%s?%s:%s)"%(self.cond.toC(), self.src1.toC(), self.src2.toC())
+        
+    
+class ExprMem(Expr):
+    def __init__(self, arg, size = 32):
+        if not isinstance(arg, Expr): raise 'arg must be expr'
+        self.arg, self.size = arg, size
+    def __str__(self):
+        return "@%d[%s]"%(self.size, str(self.arg))
+    def get_r(self, mem_read=False):
+        if mem_read:
+            return set(self.arg.get_r(mem_read).union(set([self])))
+        else:
+            return set([self])
+    def get_w(self):
+        return set([self]) #[memreg]
+    def get_size(self):
+        return self.size
+    def reload_expr(self, g = {}):
+        arg = self.arg
+        if isinstance(arg, Expr):
+            arg = self.arg.reload_expr(g)
+        
+
+        return ExprMem(arg, self.size )
+    def __contains__(self, e):
+        return self == e or self.arg.__contains__(e)
+
+    def replace_expr(self, g = {}):
+        if self in g:
+            return g[self]
+        arg = self.arg.replace_expr(g)
+        return ExprMem(arg, self.size )
+
+    def __eq__(self, a):
+        if not isinstance(a, ExprMem):
+            return False
+        return self.arg == a.arg and self.size == a.size
+    def __hash__(self):
+        return hash(self.arg)^hash(self.size)
+
+    def toC(self):
+        return "MEM_LOOKUP_%.2d(%s)"%(self.size, self.arg.toC())
+
+    
+class ExprOp(Expr):
+    def __init__(self, op, *args):
+        self.op, self.args = op, args
+    def __str__(self):
+        if len(self.args) == 2:
+            return '('+str(self.args[0]) + ' ' + self.op + ' ' + str(self.args[1]) + ')'
+        elif len(self.args)> 2:
+            return self.op + '(' + ', '.join([str(x) for x in self.args]) + ')'
+        else:
+            return reduce(lambda x,y:x+' '+str(y), self.args, '('+str(self.op))+')'
+    def get_r(self, mem_read=False):
+        return reduce(lambda x,y:x.union(y.get_r(mem_read)), self.args, set())
+    def get_w(self):
+        raise ValueError('op cannot be written!', self)
+    #return 1st arg size XXX
+    def get_size(self):
+        a = self.args[0].get_size()
+        if len(self.args)>1:
+            if not a:
+                a = self.args[1].get_size()
+        return a
+    def reload_expr(self, g = {}):
+        args = []
+        for a in self.args:
+            if isinstance(a, Expr):
+                args.append(a.reload_expr(g))
+            else:
+                args.append(a)    
+        
+        return ExprOp(self.op, *args )
+    def __contains__(self, e):
+        if self == e:
+            return True
+        for a in self.args:
+            if  a.__contains__(e):
+                return True
+        return False
+    def replace_expr(self, g = {}):
+        if self in g:
+            return g[self]
+        args = []
+        for a in self.args:
+            args.append(a.replace_expr(g))
+        return ExprOp(self.op, *args )
+
+    def __eq__(self, a):
+        if not isinstance(a, ExprOp):
+            return False
+        if self.op !=a.op:
+            return False
+        if len(self.args) != len(a.args):
+            return False
+        for i, x in enumerate(self.args):
+            if not x == a.args[i]:
+                return False
+        return True
+    def __hash__(self):
+        h = hash(self.op)
+        for a in self.args:
+            h^=hash(a)
+        return h
+
+    def toC(self):
+        dct_shift= {'a>>':"right_arith",
+                    '>>':"right_logic",
+                    '<<':"left_logic",
+                    'a<<':"left_logic"}
+        dct_rot = {'<<<':'rot_left',
+                   '>>>':'rot_right'}
+        if len(self.args)==1:
+            if self.op == 'parity':
+                return "parity(%s&0x%x)"%(self.args[0].toC(), my_size_mask[self.args[0].get_size()])
+            elif self.op == '!':
+                return "(~ %s)&0x%x"%(self.args[0].toC(), my_size_mask[self.args[0].get_size()])
+            elif self.op in ['int_32_to_double', 'int_64_to_double']:
+                return "%s(%s)"%(self.op, self.args[0].toC())
+            elif self.op == 'double_to_int_32':
+                return "%s(%s)"%(self.op, self.args[0].toC())
+            elif self.op in ['mem_32_to_double', 'mem_64_to_double']:
+                return "%s(%s)"%(self.op, self.args[0].toC())
+            elif self.op.startswith("double_to_mem_"):
+                return "%s(%s)"%(self.op, self.args[0].toC())
+            else:
+                fsdfdsf
+                return '('+str(self.op)+self.args[0].toC()+')'
+        elif len(self.args)==2:
+            if self.op == "==":
+                return '(((%s&0x%x) == (%s&0x%x))?1:0)'%(self.args[0].toC(), my_size_mask[self.args[0].get_size()], self.args[1].toC(), my_size_mask[self.args[1].get_size()])
+            elif self.op in dct_shift:
+                return 'shift_%s_%.2d(%s , %s)'%(dct_shift[self.op],
+                                                 self.args[0].get_size(),
+                                                 self.args[0].toC(),
+                                                 self.args[1].toC())
+            elif self.op in ['+', '-', '*', '^', '&', '|']:
+                return '(((%s&0x%x) %s (%s&0x%x))&0x%x)'%(self.args[0].toC(),
+                                                          my_size_mask[self.args[0].get_size()],
+                                                          str(self.op),
+                                                          self.args[1].toC(),
+                                                          my_size_mask[self.args[1].get_size()],
+                                                          my_size_mask[self.args[0].get_size()])
+            elif self.op in dct_rot:
+                return '(%s(%s, %s, %s) &0x%x)'%(dct_rot[self.op],
+                                                 self.args[0].get_size(),
+                                                 self.args[0].toC(), 
+                                                 self.args[1].toC(),
+                                                 my_size_mask[self.args[0].get_size()])
+
+            elif self.op == '*lo':
+                return 'mul_lo_op(%s, %s, %s)' %(
+                            self.args[0].get_size(),
+                            self.args[0].toC(),
+                            self.args[1].toC())
+
+            elif self.op == 'umul32_lo':
+                return 'mul_lo_op(%s, %s, %s)' %(
+                            self.args[0].get_size(),
+                            self.args[0].toC(),
+                            self.args[1].toC())
+
+            elif self.op == 'imul32_lo':
+                return 'imul_lo_op_%s(%s, %s)' %(
+                            self.args[0].get_size(),
+                            self.args[0].toC(),
+                            self.args[1].toC())
+            elif self.op == 'imul32_hi':
+                return 'imul_hi_op_%s(%s, %s)' %(
+                            self.args[0].get_size(),
+                            self.args[0].toC(),
+                            self.args[1].toC())
+
+            elif self.op == '*hi':
+                return 'mul_hi_op(%s, %s, %s)' %(
+                            self.args[0].get_size(),
+                            self.args[0].toC(),
+                            self.args[1].toC())
+
+            elif self.op == 'umul32_hi':
+                return 'mul_hi_op(%s, %s, %s)' %(
+                            self.args[0].get_size(),
+                            self.args[0].toC(),
+                            self.args[1].toC())
+            elif self.op == 'umul08':
+                return 'mul_hi_op(%s, %s, %s)' %(
+                            self.args[0].get_size(),
+                            self.args[0].toC(),
+                            self.args[1].toC())
+
+            elif self.op in ['bsr', 'bsf']:
+                return 'my_%s(%s, %s)'%(self.op,
+                                 self.args[0].toC(),
+                                 self.args[1].toC())
+            elif self.op in ['imul08']:
+                return 'my_%s(%s, %s)'%(self.op,
+                                        self.args[0].toC(),
+                                        self.args[1].toC())
+            elif self.op.startswith('cpuid'):
+                return "%s(%s, %s)"%(self.op, self.args[0].toC(), self.args[1].toC())
+            elif self.op.startswith("fcom"):
+                return "%s(%s, %s)"%(self.op, self.args[0].toC(), self.args[1].toC())
+            elif self.op.startswith("fadd"):
+                return "%s(%s, %s)"%(self.op, self.args[0].toC(), self.args[1].toC())
+            else:
+                print self.op
+                raise ValueError('unknown op!!', str(self.op))
+
+        elif len(self.args)==3:
+            dct_div= {'div8':"div_op",
+                      'div16':"div_op",
+                      'div32':"div_op",
+                      'idiv32':"div_op", #XXX to test
+                      'rem8':"rem_op",
+                      'rem16':"rem_op",
+                      'rem32':"rem_op",
+                      'irem32':"rem_op", #XXX to test
+                      '<<<c_rez':'rcl_rez_op',
+                      '<<<c_cf':'rcl_cf_op',
+                      '>>>c_rez':'rcr_rez_op',
+                      '>>>c_cf':'rcr_cf_op',
+                      
+                      }
+            if not self.op in dct_div:
+                fsdff
+
+            return '(%s(%s, %s, %s, %s) &0x%x)'%(dct_div[self.op],
+                                                 self.args[0].get_size(),
+                                                 self.args[0].toC(), 
+                                                 self.args[1].toC(),
+                                                 self.args[2].toC(),
+                                                 my_size_mask[self.args[0].get_size()])
+        else:
+            
+            raise ValueError('not imple', str(self))
+        
+
+    
+class ExprSlice(Expr):
+    def __init__(self, arg, start, stop):
+        self.arg, self.start, self.stop = arg, start, stop
+    def __str__(self):
+        return "%s[%d:%d]"%(str(self.arg), self.start, self.stop)
+    def get_r(self, mem_read=False):
+        return self.arg.get_r(mem_read)
+    def get_w(self):
+        return self.arg.get_w()
+    def get_size(self):
+        return self.stop-self.start
+    def reload_expr(self, g = {}):
+        arg = self.arg.reload_expr(g)
+
+        return ExprSlice(arg, self.start, self.stop )
+    def __contains__(self, e):
+        if self == e:
+            return True
+        for a in self.args:
+            if  a.__contains__(e):
+                return True
+        return False
+
+    def replace_expr(self, g = {}):
+        if self in g:
+            return g[self]
+        arg = self.arg.replace_expr(g)
+        return ExprSlice(arg, self.start, self.stop )
+
+    def __eq__(self, a):
+        if not isinstance(a, ExprSlice):
+            return False
+        return self.arg == a.arg and self.start == a.start and self.stop == a.stop
+
+    def __hash__(self):
+        return hash(self.arg)^hash(self.start)^hash(self.stop)
+
+    def toC(self):
+        return "((%s>>%d) & ((0xFFFFFFFF>>(32-%d))))"%(self.arg.toC(), self.start, self.stop-self.start)
+
+    
+class ExprSliceTo(Expr):
+    def __init__(self, arg, start, stop):
+        self.arg, self.start, self.stop = arg, start, stop
+    def __str__(self):
+        return "%s_to[%d:%d]"%(str(self.arg), self.start, self.stop)
+    def get_r(self, mem_read=False):
+        return self.arg.get_r(mem_read)
+    def get_w(self):
+        return self.arg.get_w()
+    def get_size(self):
+        return self.stop-self.start
+    def reload_expr(self, g = {}):
+        if isinstance(self.arg, Expr):
+            arg = self.arg.reload_expr(g)
+        else:
+            arg = self.arg
+
+        return ExprSliceTo(arg, self.start, self.stop )
+    def __contains__(self, e):
+        return self == e or self.arg.__contains__(e)
+
+    def replace_expr(self, g = {}):
+        if self in g:
+            return g[self]
+        arg = self.arg.replace_expr(g)
+        return ExprSliceTo(arg, self.start, self.stop)
+
+    def __eq__(self, a):
+        if not isinstance(a, ExprSliceTo):
+            return False
+        return self.arg == a.arg and self.start == a.start and self.stop == a.stop
+    def __hash__(self):
+        return hash(self.arg)^hash(self.start)^hash(self.stop)
+
+    def toC(self):
+        return "((%s & (0xFFFFFFFF>>(32-%d))) << %d)"%(self.arg.toC(), self.stop-self.start, self.start)
+
+class ExprCompose(Expr):
+    def __init__(self, args):
+        self.args = args
+    def __str__(self):
+        return '('+', '.join([str(x) for x in self.args])+')'
+    def get_r(self, mem_read=False):
+        return reduce(lambda x,y:x.union(y.get_r(mem_read)), self.args, set())
+    def get_w(self):
+        return reduce(lambda x,y:x.union(y.get_r(mem_read)), self.args, set())
+    def get_size(self):
+        return max([x.stop for x in self.args]) - min([x.start for x in self.args])
+    def reload_expr(self, g = {}):
+        args = []
+        for a in self.args:
+            if isinstance(a, Expr):
+                args.append(a.reload_expr(g))
+            else:
+                args.append(a)    
+
+        return ExprCompose(args )
+    def __contains__(self, e):
+        if self == e:
+            return True
+        for a in self.args:
+            if  a.__contains__(e):
+                return True
+        return False
+
+    def replace_expr(self, g = {}):
+        if self in g:
+            return g[self]
+        args = []
+        for a in self.args:
+            args.append(a.replace_expr(g))
+        return ExprCompose(args )
+
+    def __eq__(self, a):
+        if not isinstance(a, ExprCompose):
+            return False
+        if not len(self.args) == len(a.args):
+            return False
+        for i, x in enumerate(self.args):
+            if not x == a.args[i]:
+                return False
+        return True
+    def __hash__(self):
+        h = 0
+        for a in self.args:
+            h^=hash(a)
+        return h
+
+    def toC(self):
+        out = ' | '.join([x.toC() for x in self.args])
+        return '('+out+')'
+        
+                       
+class set_expr:
+    def __init__(self, l = []):
+        self._list = []
+        for a in l:
+            self.add(a)
+        
+    def add(self, a):
+        astr = str(a)
+        for x in self._list:
+            if str(x) == astr:
+                return
+        self._list.append(a)
+        
+    def discard(self, a):
+        astr = str(a)
+        for x in self._list:
+            if str(x) == astr:
+                self._list.remove(x)
+                return True
+        return False
+    
+    def remove(self ,a):
+        if not self.discard(a):
+            raise ValueError('value not found %s'%str(a))
+
+    
+    def update(self, list_a):
+        if not isinstance(list_a, list) and not isinstance(list_a, set):
+            raise ValueError('arg must be list or set')
+        for a in list_a:
+            self.add(a)
+
+    def __contains__(self, a):
+        astr = str(a)
+        for x in self._list:
+            if astr == str(x):
+                return True
+        return False
+    def __str__(self):
+        o = []
+        o.append('[')
+        for x in self._list:
+            o.append(str(x))
+        o.append(']')
+        return " ".join(o)
+        
+    def __repr__(self):
+        return "set_expr["+", ".join([str(x) for x in self._list])+"]"
+
+    def __iter__(self):
+        return self._list.__iter__()
diff --git a/miasm/expression/expression_eval_abstract.py b/miasm/expression/expression_eval_abstract.py
new file mode 100644
index 00000000..7140da1d
--- /dev/null
+++ b/miasm/expression/expression_eval_abstract.py
@@ -0,0 +1,797 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+from miasm.expression.expression import *
+import struct
+import logging 
+import cPickle
+import numpy
+from miasm.expression.expression_helper import *
+
+
+
+numpy.seterr(over='ignore', under='ignore')
+
+mymaxuint = {8:0xFFL,
+             16:0xFFFFL,
+             32:0xFFFFFFFFL,
+             64:0xFFFFFFFFFFFFFFFFL    
+             }
+
+
+#expression evaluation in integer domain
+
+tab_int_size = {int8:8,
+                uint8:8,
+                int16:16,
+                uint16:16,
+                int32:32,
+                uint32:32,
+                int64:64,
+                uint64:64
+                }
+
+tab_intsize = {8:int8,
+               16:int16,
+               32:int32,
+               64:int64
+               }
+tab_uintsize ={8:uint8,
+               16:uint16,
+               32:uint32,
+               64:uint64
+               }
+
+tab_u2i = {uint8:int8,
+           uint16:int16,
+           uint32:int32}
+
+
+class eval_abs:
+    dict_size = {
+        1:'B',
+        2:'H',
+        4:'I',
+        }
+
+    def parity(self, a):
+        tmp = (a)&0xFFL
+        cpt = 1
+        while tmp!=0:
+            cpt^=tmp&1
+            tmp>>=1
+        return cpt
+        
+    def my_bsf(self, a, default_val=0):
+        tmp = 0
+        for i in xrange(32):
+            if a & (1<<i):
+                return i
+        
+        return default_val
+    def my_bsr(self, a, op_size, default_val = 0):
+        tmp = 0
+        for i in xrange(op_size-1, -1, -1):
+            if a & (1<<i):
+                return i
+        
+        return default_val
+            
+        
+    def __init__(self, vars, func_read = None, func_write = None, log = None):
+        self.pool = {}
+        for v in vars:
+            self.pool[v] = vars[v]
+        self.func_read = func_read
+        self.func_write = func_write
+        if log == None:
+            log = logging.getLogger("expr_eval_int")
+            console_handler = logging.StreamHandler()
+            console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
+            log.addHandler(console_handler)
+            log.setLevel(logging.WARN)
+        self.log = log
+
+    def to_file(self, f):
+        if type(f) is str:
+            f = open(f,"w")
+        self.log = None
+        cPickle.dump(self, f)
+    
+    @staticmethod
+
+    def from_file(f, g):
+        if type(f) is str:
+            f = open(f,"r")
+        m = cPickle.load(f)
+        log = logging.getLogger("expr_eval_int")
+        console_handler = logging.StreamHandler()
+        console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
+        log.addHandler(console_handler)
+        log.setLevel(logging.WARN)
+        m.log = log
+        new_pool = {}
+        for x in m.pool:
+            
+            if not str(x) in g:
+                xx = ExprId(str(x))
+                g[str(xx)] = xx
+            else:
+                xx = x
+            
+            xx = x
+            print repr(g[str(xx)]), g[str(xx)]
+            
+            if isinstance(m.pool[x], Expr):
+                new_pool[g[str(xx)]] = m.pool[x].reload_expr(g)
+            else:
+                new_pool[g[str(xx)]] = m.pool[x]
+                
+        m.pool = new_pool
+        return m
+
+    def find_mem_by_addr(self, e):
+        for k in self.pool:
+            if not isinstance(k, ExprMem):
+                continue
+            if k.arg != e:
+                continue
+            return k
+        return None
+
+
+    def is_mem_in_target(self, e, t):
+        ex = ExprOp('-', e.arg, t.arg)
+        ex = expr_simp(self.eval_expr(ex, {}))
+        if not isinstance(ex, ExprInt):
+            return None
+        ptr_diff = int32(ex.arg)
+        if ptr_diff <0:
+            return False
+        if ptr_diff + e.size/8 <= t.size/8:
+            return True
+        return False
+
+    def substract_mems(self, a, b):
+        ex = ExprOp('-', b.arg, a.arg)
+        ex = expr_simp(self.eval_expr(ex, {}))
+        if not isinstance(ex, ExprInt):
+            return None
+        ptr_diff = int32(ex.arg)
+        out = []
+        if ptr_diff <0:
+            #    [a     ]
+            #[b      ]XXX
+            
+            sub_size = b.size + ptr_diff*8
+            if sub_size >= a.size:
+                pass
+            else:
+                ex = ExprOp('+', a.arg, ExprInt(uint32(sub_size)))
+                ex = expr_simp(self.eval_expr(ex, {}))
+                
+                rest_ptr = ex
+                rest_size = a.size - sub_size
+    
+                val = self.pool[a][sub_size:a.size]
+                out = [(ExprMem(rest_ptr, rest_size), val)]
+        else:
+            #[a         ]
+            #XXXX[b   ]YY
+
+            #[a     ]
+            #XXXX[b     ]
+
+            out = []
+            #part X
+            if ptr_diff >0:
+                val = self.pool[a][0:ptr_diff*8]
+                out.append((ExprMem(a.arg, ptr_diff*8), val))
+            #part Y
+            if ptr_diff*8+b.size <a.size:
+                
+                ex = ExprOp('+', b.arg, ExprInt(uint32(b.size/8)))
+                ex = expr_simp(self.eval_expr(ex, {}))
+
+                rest_ptr = ex
+                rest_size = a.size - (ptr_diff*8 + b.size)
+                val = self.pool[a][ptr_diff*8 + b.size:a.size]
+                out.append((ExprMem(ex, val.get_size()), val))
+            
+            
+        return out    
+
+    #give mem stored overlapping requested mem ptr
+    def get_mem_overlapping(self, e):
+        if not isinstance(e, ExprMem):
+            raise ValueError('mem overlap bad arg')
+        ov = []
+        
+        for k in self.pool:
+            if not isinstance(k, ExprMem):
+                continue
+            ex = ExprOp('-', k.arg, e.arg)
+            ex = expr_simp(self.eval_expr(ex, {}))
+            if not isinstance(ex, ExprInt):
+                continue
+            ptr_diff = int32(ex.arg)
+            if ptr_diff >=0 and ptr_diff < e.size/8:
+                ov.append((-ptr_diff, k))
+            elif ptr_diff <0 and ptr_diff + k.size/8>0:
+                ov.append((-ptr_diff, k))
+
+        return ov
+                
+    def eval_expr(self, e, eval_cache):
+        if e.is_term:
+            return e
+        if e.is_eval:
+            return e
+        ret = self.eval_expr_no_cache(e, eval_cache)
+        ret.is_eval = True
+        return ret
+        
+
+
+    def eval_op_plus(self, args, op_size, cast_int):
+        ret_value = args[0] + args[1]
+        return ret_value
+
+    def eval_op_minus(self, args, op_size, cast_int):
+        ret_value = args[0] - args[1]
+        return ret_value
+    
+    def eval_op_mult(self, args, op_size, cast_int):
+        ret_value = (args[0] * args[1])
+        return ret_value
+
+    def eval_op_div(self, args, op_size, cast_int):
+        a = uint64(args[0])
+        b = uint64(args[1])
+        c = uint64(args[2])
+        if c == 0:
+            raise ValueError('div by 0')
+        big = (a<<uint64(op_size))+b
+        ret_value =  big/c
+        if ret_value>mymaxuint[op_size]:raise ValueError('Divide Error')
+        return ret_value
+
+    def eval_op_rem(self, args, op_size, cast_int):
+        a = uint64(args[0])
+        b = uint64(args[1])
+        c = uint64(args[2])
+        if c == 0:
+            raise ValueError('div by 0')
+        big = (a<<uint64(op_size))+b
+        ret_value =  big-c*(big/c) 
+        if ret_value>mymaxuint[op_size]:raise ValueError('Divide Error')        
+        return ret_value
+
+    def eval_op_idiv(self, args, op_size, cast_int):
+        a = uint64(args[0])
+        b = uint64(args[1])
+        c = int64(tab_u2i[cast_int](args[2]))
+        if c == 0:
+            raise ValueError('div by 0')
+        big = (a<<uint64(op_size))+b
+        big = tab_intsize[op_size*2](big)
+        ret_value =  big/c
+        try:
+            ret_value = tab_u2i[cast_int](ret_value)
+        except:
+            raise ValueError('Divide Error')
+        return ret_value
+
+    def eval_op_irem(self, args, op_size, cast_int):
+        a = uint64(args[0])
+        b = uint64(args[1])
+        c = int64(tab_u2i[cast_int](args[2]))
+        if c == 0:
+            raise ValueError('div by 0')
+        big = (a<<uint64(op_size))+b
+        big = tab_intsize[op_size*2](big)
+        ret_value =  big/c
+        try:
+            ret_value = tab_u2i[cast_int](ret_value)
+        except:
+            raise ValueError('Divide Error')
+        ret_value = big-ret_value*c
+        return ret_value
+
+    def eval_op_mulhi(self, args, op_size, cast_int):
+        a = uint64(args[0])
+        b = uint64(args[1])
+        ret_value =  (a*b) >> uint64(op_size)
+        return ret_value
+
+    def eval_op_mullo(self, args, op_size, cast_int):
+        a = uint64(args[0])
+        b = uint64(args[1])
+        ret_value =  (a*b) & mymaxuint[op_size]
+        return ret_value
+
+    def eval_op_eq(self, args, op_size, cast_int):
+        ret_value =  [0, 1][int(args[0] == args[1])]
+        return ret_value
+
+    def eval_op_inf(self, args, op_size, cast_int):
+        ret_value =  [0, 1][int(args[0] < args[1])]
+        return ret_value
+
+    def eval_op_and(self, args, op_size, cast_int):
+        ret_value = (args[0] & args[1])
+        return ret_value
+
+    def eval_op_or(self, args, op_size, cast_int):
+        ret_value = (args[0] | args[1])
+        return ret_value
+
+    def eval_op_xor(self, args, op_size, cast_int):
+        ret_value = (args[0] ^ args[1])
+        return ret_value
+
+    def eval_op_not(self, args, op_size, cast_int):
+        ret_value = (args[0] ^ tab_uintsize[op_size](mymaxuint[op_size]))
+        return ret_value
+
+    def eval_op_rotl(self, args, op_size, cast_int):
+        r = args[1]&0x1F
+        r %=op_size
+        ret_value = ((args[0]<<r) & mymaxuint[op_size]) | ((args[0] & mymaxuint[op_size]) >> (op_size-r))
+        return ret_value
+
+    def eval_op_rotr(self, args, op_size, cast_int):
+        r = args[1]&0x1F
+        r %=op_size
+        ret_value = ((args[0] & mymaxuint[op_size])>>r)  | ((args[0] << (op_size-r)) & mymaxuint[op_size])
+        return ret_value
+
+    def eval_op_rotl_wflag(self, args, op_size, cast_int):
+        r = args[1]&0x1F
+        r %=op_size+1
+        r = uint64(r)
+        op_size = uint64(op_size)
+        tmpa = uint64((args[0]<<1) | args[2])
+        rez = (tmpa<<r) | (tmpa >> (op_size+uint64(1)-r))
+        return rez
+
+    def eval_op_rotl_wflag_rez(self, args, op_size, cast_int):
+        return self.eval_op_rotl_wflag(args, op_size, cast_int)>>1
+    def eval_op_rotl_wflag_cf(self, args, op_size, cast_int):
+        return self.eval_op_rotl_wflag(args, op_size, cast_int)&1
+
+    def eval_op_rotr_wflag(self, args, op_size, cast_int):
+        r = args[1]&0x1F
+        r %=op_size+1
+        r = uint64(r)
+        op_size = uint64(op_size)
+        tmpa = uint64((args[0]<<1) | args[2])
+        rez = (tmpa>>r)  | (tmpa << (op_size+uint64(1)-r))
+        return rez
+    
+    def eval_op_rotr_wflag_rez(self, args, op_size, cast_int):
+        return self.eval_op_rotr_wflag(args, op_size, cast_int)>>1
+    def eval_op_rotr_wflag_cf(self, args, op_size, cast_int):
+        return self.eval_op_rotr_wflag(args, op_size, cast_int)&1
+
+    def eval_op_lshift(self, args, op_size, cast_int):
+        r = args[1]#&0x1F
+        ret_value = ((args[0] &mymaxuint[op_size])<<r)
+        return ret_value
+    
+    def eval_op_rshift(self, args, op_size, cast_int):
+        r = args[1]#&0x1F
+        ret_value = ((args[0]&mymaxuint[op_size])>>r)
+        return ret_value
+
+    def eval_op_arshift(self, args, op_size, cast_int):
+        r = args[1]#&0x1F
+        if args[0]>=0:
+            ret_value = ((args[0]&mymaxuint[op_size])>>r)
+        else:
+            ret_value = -((-args[0])>>r)
+        return ret_value
+
+
+    def eval_op_bsf(self, args, op_size, cast_int):
+        ret_value = self.my_bsf(args[1], args[0])
+        return ret_value
+
+    def eval_op_bsr(self, args, op_size, cast_int):
+        ret_value = self.my_bsr(args[1], op_size, args[0])
+        return ret_value
+
+    def eval_op_parity(self, args, op_size, cast_int):
+        ret_value = self.parity(args[0])
+        return ret_value
+
+    def eval_op_int_32_to_double(self, args, op_size, cast_int):
+        print args[0]
+        return ExprTop()
+        b = struct.pack('L', args[0])
+        print repr(b)
+        b = struct.unpack('f', b)[0]
+        print b
+        raise ValueError('not impl yet')
+        ret_value = args[0]
+        return ret_value
+
+    def objbyid_default0(self, args, op_size, cast_int):
+        return ExprOp("objbyid_default0", ExprInt(cast_int(args[0])))
+
+
+    
+    deal_op = {'+':eval_op_plus,
+               '-':eval_op_minus,
+               '*':eval_op_mult,
+               '/div':eval_op_div,
+               '/rem':eval_op_rem,
+               '/idiv':eval_op_idiv,
+               '/irem':eval_op_irem,
+               '*hi':eval_op_mulhi,
+               '*lo':eval_op_mullo,
+               '==':eval_op_eq,
+               '<':eval_op_inf,
+               '&':eval_op_and,
+               '|':eval_op_or,
+               '^':eval_op_xor,
+               '!':eval_op_not,
+               '<<<':eval_op_rotl,
+               '>>>':eval_op_rotr,
+               '<<<c_rez':eval_op_rotl_wflag_rez,
+               '<<<c_cf':eval_op_rotl_wflag_cf,
+               '<<':eval_op_lshift,
+               '>>':eval_op_rshift,
+               'a>>':eval_op_arshift,
+               'bsf':eval_op_bsf,
+               'bsr':eval_op_bsr,
+               'parity':eval_op_parity,
+               'int_32_to_double':eval_op_int_32_to_double,
+
+               #XXX
+               'objbyid_default0':objbyid_default0,
+               }
+    
+    op_size_no_check = ['<<<', '>>>', 'a<<', '>>', '<<',
+                        '<<<c_rez', '<<<c_cf', 
+                        '>>>c_rez', '>>>c_cf',]
+
+
+    def eval_ExprId(self, e, eval_cache = {}):
+        if not e in self.pool:
+            return ExprTop(e)
+        return self.pool[e]
+
+    def eval_ExprInt(self, e, eval_cache = {}):
+        return e
+    
+    def eval_ExprMem(self, e, eval_cache = {}):
+        a_val = expr_simp(self.eval_expr(e.arg, eval_cache))
+        if isinstance(a_val, ExprTop):
+            #XXX hack test
+            ee =   ExprMem(e.arg, e.size)
+            ee.is_term = True
+            return ee
+        
+        
+        a = expr_simp(ExprMem(a_val, size = e.size))
+        if a in self.pool:
+            return self.pool[a]
+        
+        tmp = None
+        #test if mem lookup is known
+        for k in self.pool:
+            if not isinstance(k, ExprMem):
+                continue
+            if a_val == k.arg:
+                tmp = k
+                break
+        if tmp == None:
+
+            v = self.find_mem_by_addr(a_val)
+            if not v:
+                out = []
+                ov = self.get_mem_overlapping(a)
+                off_base = 0
+                ov.sort()
+                ov.reverse()
+                for off, x in ov:
+                    if off >=0:
+                        m = min(a.get_size(), x.get_size()-off*8)
+                        ee = ExprSlice(self.pool[x], off*8, off*8 + m)
+                        ee = expr_simp(ee)
+                        out.append(ExprSliceTo(ee, off_base, off_base+ee.get_size()))
+                        off_base += ee.get_size()
+                    else:
+                        m = min(a.get_size()+off*8, x.get_size())
+                        ee = ExprSlice(self.pool[x], 0, m)
+                        ee = expr_simp(ee)
+                        out.append(ExprSliceTo(ee, off_base, off_base+ee.get_size()))
+                        off_base += ee.get_size()
+                if out:
+                    ee = ExprSlice(ExprCompose(out), 0, a.get_size())
+                    ee = expr_simp(ee)
+                    return ee
+            if self.func_read and isinstance(a.arg, ExprInt):
+                return self.func_read(self, a)
+            else:
+                #XXX hack test
+                a.is_term = True
+                return a
+        
+        #eq lookup
+        if a.size == k.size:
+            return self.pool[tmp]
+        
+        #bigger lookup
+        if a.size > k.size:
+            rest = a.size
+            ptr = a_val
+            out = []
+            ptr_index = 0
+            while rest:
+                v = self.find_mem_by_addr(ptr)
+                if v == None:
+                    raise ValueError("cannot find %s in mem"%str(ptr))
+
+                if (rest-v.size) >=0:
+                    val = self.pool[v]
+                    diff_size = v.size
+                else:
+                    diff_size = v.size-rest
+                    val = self.pool[v][0:diff_size]
+                    
+                val = ExprSliceTo(val, ptr_index, ptr_index+diff_size)
+                
+                out.append(val)
+                ptr_index+=diff_size
+                rest -= diff_size
+                ptr = expr_simp(self.eval_expr(ExprOp('+', ptr, ExprInt(uint32(v.size/8))), eval_cache))
+            e = expr_simp(ExprCompose(out))
+            return e
+        
+        #part lookup
+        tmp = expr_simp(ExprSlice(self.pool[tmp], 0, a.size))
+        
+        return tmp
+    
+    def eval_ExprOp(self, e, eval_cache = {}):
+        args = []
+        for a in e.args:
+            b = expr_simp(self.eval_expr(a, eval_cache))
+            if isinstance(b, ExprTop):
+                return ExprTop()
+            args.append(b)
+        #Very agresive, but should work
+        for a in args:
+            if isinstance(a, ExprTop):
+                return ExprTop()
+        
+        for a in args:
+            if not isinstance(a, ExprInt):
+                return ExprOp(e.op, *args)
+        
+        args = [a.arg for a in args]
+        
+        types_tab = [type(a) for a  in args]
+        if types_tab.count(types_tab[0]) != len(args) and not e.op in self.op_size_no_check:
+            raise 'invalid cast %s %s'%(str(types_tab), str(args))
+        
+        cast_int = types_tab[0]
+        op_size = tab_int_size[types_tab[0]]
+        
+
+        ret_value = self.deal_op[e.op](self, args, op_size, cast_int)
+        if isinstance(ret_value, Expr):
+            return ret_value
+        return ExprInt(cast_int(ret_value))
+                   
+    def eval_ExprCond(self, e, eval_cache = {}):
+        cond = self.eval_expr(e.cond, eval_cache)
+        src1 = self.eval_expr(e.src1, eval_cache)
+        src2 = self.eval_expr(e.src2, eval_cache)
+
+        if isinstance(cond, ExprTop):
+            return ExprCond(e.cond, src1, src2)
+        
+        if isinstance(cond, ExprInt):
+            if cond.arg == 0:
+                return src2
+            else:
+                return src1
+        return ExprCond(cond, src1, src2)
+       
+    def eval_ExprSlice(self, e, eval_cache = {}):
+        arg = expr_simp(self.eval_expr(e.arg, eval_cache))
+        if isinstance(arg, ExprTop):
+            return ExprTop()
+        
+        if isinstance(arg, ExprMem):
+            if e.start == 0 and e.stop == arg.size:
+                return arg
+                
+            return ExprSlice(arg, e.start, e.stop)
+        if isinstance(arg, ExprTop):
+            return ExprTop()
+        if isinstance(arg, ExprId):
+            return ExprSlice(arg, e.start, e.stop)
+        if isinstance(arg, ExprInt):
+            return expr_simp(ExprSlice(arg, e.start, e.stop))
+        if isinstance(arg, ExprCompose):
+            to_add = []
+            return ExprSlice(arg, e.start, e.stop)
+        return ExprSlice(arg, e.start, e.stop)
+            
+    def eval_ExprCompose(self, e, eval_cache = {}):
+        args = []
+        for a in e.args:
+            aa = self.eval_expr(a.arg, eval_cache)
+            if isinstance(aa, ExprTop):
+                return ExprTop()
+            else:
+                args.append(aa)
+        for a in args:
+            if isinstance(a, ExprTop):
+                return ExprTop()
+        is_int = True
+        is_int_cond = 0
+        for x in args:
+            if isinstance(x, ExprInt):
+                continue
+            is_int = False
+            if not isinstance(x, ExprCond) or not (isinstance(x.src1, ExprInt) and isinstance(x.src2, ExprInt)):
+                is_int_cond+=3
+                continue
+            is_int_cond+=1
+                
+        
+        if not is_int and is_int_cond!=1:
+            uu = ExprCompose([ExprSliceTo(a, e.args[i].start, e.args[i].stop) for i, a in enumerate(args)])
+            return uu
+
+        if not is_int:
+            rez = 0L
+            total_bit = 0
+            
+            for i in xrange(len(e.args)):
+                if isinstance(args[i], ExprInt):
+                    a = args[i].arg
+
+                    mask = (1<<(e.args[i].stop-e.args[i].start))-1
+                    a&=mask
+                    a<<=e.args[i].start
+                    total_bit+=e.args[i].stop-e.args[i].start
+                    rez|=a
+                else:
+                    a = args[i]
+                    mask = (1<<(e.args[i].stop-e.args[i].start))-1
+                    total_bit+=e.args[i].stop-e.args[i].start
+                    mycond, mysrc1, mysrc2 = a.cond, a.src1.arg&mask, a.src2.arg&mask
+                    cond_i = i
+                    
+            mysrc1|=rez
+            mysrc2|=rez
+            
+            
+            
+            if total_bit in tab_uintsize:
+                return self.eval_expr(ExprCond(mycond, ExprInt(tab_uintsize[total_bit](mysrc1)), ExprInt(tab_uintsize[total_bit](mysrc2))), eval_cache)
+            else:
+                raise 'cannot return non rounb bytes rez! %X %X'%(total_bit, rez)
+                    
+                
+        
+        rez = 0L
+        total_bit = 0
+        for i in xrange(len(e.args)):
+            a = args[i].arg
+            mask = (1<<(e.args[i].stop-e.args[i].start))-1
+            a&=mask
+            a<<=e.args[i].start
+            total_bit+=e.args[i].stop-e.args[i].start
+            rez|=a
+        if total_bit in tab_uintsize:
+            return ExprInt(tab_uintsize[total_bit](rez))
+        else:
+            raise 'cannot return non rounb bytes rez! %X %X'%(total_bit, rez)
+        
+    def eval_ExprTop(self, e, eval_cache = {}):
+        return e
+    
+    def eval_expr_no_cache(self, e, eval_cache = {}):
+        c = e.__class__
+        deal_class = {ExprId: self.eval_ExprId,
+                      ExprInt: self.eval_ExprInt,
+                      ExprMem: self.eval_ExprMem,
+                      ExprOp: self.eval_ExprOp,
+                      ExprCond:self.eval_ExprCond,
+                      ExprSlice: self.eval_ExprSlice,
+                      ExprCompose:self.eval_ExprCompose,
+                      ExprTop:self.eval_ExprTop,
+                      }
+        return deal_class[c](e, eval_cache)
+
+    def get_instr_mod(self, exprs):
+        pool_out = {}
+        
+        eval_cache = {}
+        
+        for e in exprs:
+            if not isinstance(e, ExprAff):
+                raise TypeError('not affect', str(e))
+            
+            src = self.eval_expr(e.src, eval_cache)
+            if isinstance(e.dst, ExprMem):
+                a = self.eval_expr(e.dst.arg, eval_cache)
+                a = expr_simp(a)
+                #search already present mem
+                tmp = None
+                #test if mem lookup is known
+                tmp = ExprMem(a, e.dst.size)
+                dst = tmp
+                if self.func_write and isinstance(dst.arg, ExprInt):
+                    self.func_write(self, dst, src, pool_out)
+                else:
+                    pool_out[dst] = src
+                
+            elif isinstance(e.dst, ExprId):
+                pool_out[e.dst] = src
+            elif isinstance(e.dst, ExprTop):
+                raise ValueError("affect in ExprTop")
+            else:
+                raise ValueError("affected zarb", str(e.dst))
+                
+
+        return pool_out    
+
+    def eval_instr(self, exprs):
+        tmp_ops = self.get_instr_mod(exprs)
+        cste_propag = True
+        mem_dst = []
+        for op in tmp_ops:
+            if isinstance(op, ExprMem):
+                ov = self.get_mem_overlapping(op)
+                for off, x in ov:
+                    diff_mem = self.substract_mems(x, op)
+                    del(self.pool[x])
+                    for xx, yy in diff_mem:
+                        self.pool[xx] = yy
+                tmp = expr_simp(tmp_ops[op])
+                    
+                if isinstance(expr_simp(op.arg), ExprTop):
+                    raise ValueError('xx')
+                    continue
+            else:
+                tmp = tmp_ops[op]
+                tmp = expr_simp(tmp)
+
+            if isinstance(tmp, ExprInt) and isinstance(op, ExprId) and op.name in ['zf','nf', 'pf', 'of', 'cf', 'df']:
+                tmp = ExprInt(uint32(tmp.arg))
+            self.pool[op] = tmp
+            if isinstance(op, ExprMem):
+                mem_dst.append(op)
+
+            
+        return mem_dst
+
+    def get_reg(self, r):
+        return self.eval_expr(self.pool[r], {})
+        
+
+
+
+
diff --git a/miasm/expression/expression_helper.py b/miasm/expression/expression_helper.py
new file mode 100644
index 00000000..c6bcfa8e
--- /dev/null
+++ b/miasm/expression/expression_helper.py
@@ -0,0 +1,646 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+from miasm.expression.expression import *
+
+tab_size_int = {8:uint8,
+                16:uint16,
+                32:uint32,
+                64:uint64,
+                }
+
+tab_max_uint = {8:uint8(0xFF), 16:uint16(0xFFFF), 32:uint32(0xFFFFFFFF), 64:uint64(0xFFFFFFFFFFFFFFFFL)}
+
+
+def parity(self, a):
+    tmp = (a)&0xFFL
+    cpt = 1
+    while tmp!=0:
+        cpt^=tmp&1
+        tmp>>=1
+    return cpt
+
+def merge_sliceto_slice(args):
+    sources = {}
+    non_slice = {}
+    sources_int = {}
+    for a in args:
+        if isinstance(a.arg, ExprInt):
+            sources_int[a.start] = a
+        elif isinstance(a.arg, ExprSlice):
+            if not a.arg.arg in sources:
+                sources[a.arg.arg] = []
+            sources[a.arg.arg].append(a)
+        else:
+            non_slice[a.start] = a
+
+
+    #find max stop to determine size
+    max_size = None
+    for a in args:
+        if max_size == None or max_size < a.stop:
+            max_size = a.stop
+        
+    
+
+    #first simplify all num slices
+    
+    final_sources = []
+    sorted_s = []
+    for x in sources_int.values():
+        #mask int
+        v = x.arg.arg & ((1<<(x.stop-x.start))-1)
+        x.arg.arg = v
+        sorted_s.append((x.start, x))
+    sorted_s.sort()
+    while sorted_s:
+
+        start, v = sorted_s.pop()
+        out = expr_replace(v, {})
+
+
+        while sorted_s:
+            if sorted_s[-1][1].stop != start:
+                break
+            
+            start = sorted_s[-1][1].start
+
+            a = uint64((int(out.arg.arg) << (out.start - start )) + sorted_s[-1][1].arg.arg)
+            out.arg = ExprInt(uint32(a))
+            sorted_s.pop()
+            out.start = start
+
+        out_type = tab_size_int[max_size]
+        out.arg.arg = out_type(out.arg.arg)
+        final_sources.append((start, out))
+        
+    final_sources_int = final_sources
+    
+    #check if same sources have corresponding start/stop
+    #is slice AND is sliceto
+    simp_sources = []
+    for s, args in sources.items():
+        final_sources = []
+        sorted_s = []
+        for x in args:
+            sorted_s.append((x.start, x))
+        sorted_s.sort()
+        while sorted_s:
+            start, v = sorted_s.pop()
+            out = expr_replace(v, {})
+            while sorted_s:
+                if sorted_s[-1][1].stop != start:
+                    break
+                if sorted_s[-1][1].arg.stop != out.arg.start:
+                    break
+                
+                start = sorted_s[-1][1].start
+                out.arg.start = sorted_s[-1][1].arg.start
+                sorted_s.pop()
+            out.start = start
+
+            final_sources.append((start, out))
+        
+        simp_sources+=final_sources
+
+    simp_sources+= final_sources_int
+
+    for i, v in non_slice.items():
+        simp_sources.append((i, v))
+    
+    simp_sources.sort()
+    
+    simp_sources = [x[1] for x in simp_sources]
+    return simp_sources
+    
+    
+def expr_simp(e):
+    if e.is_simp:
+        return e
+    e = expr_simp_w(e)
+    e.is_simp = True
+    return e
+
+def expr_simp_w(e):
+    if isinstance(e, ExprTop):
+        return e
+    if isinstance(e, ExprInt):
+        return e
+    elif isinstance(e, ExprId):
+        return e
+    elif isinstance(e, ExprAff):
+        return ExprAff(expr_simp(e.dst), expr_simp(e.src))
+    elif isinstance(e, ExprCond):
+        c = expr_simp(e.cond)
+        if isinstance(c, ExprInt):
+            print e
+            fdsfsdf
+            if c == 0:
+                return expr_simp(e.src2)
+            else:
+                return expr_simp(e.src1)
+                
+        return ExprCond(expr_simp(e.cond), expr_simp(e.src1), expr_simp(e.src2))
+    elif isinstance(e, ExprMem):
+        if isinstance(e.arg, ExprTop):
+            return ExprTop()
+        return ExprMem(expr_simp(e.arg), size = e.size)
+    elif isinstance(e, ExprOp):
+        op, args = e.op, list(e.args)
+        if ExprTop() in args:
+            return ExprTop()
+        #int OP int => int
+        if e.op in ['+', '-', '*', '|', '&', '^', '>>', '<<'] and isinstance(args[0], ExprInt) and isinstance(args[1], ExprInt) :
+            if args[0].get_size() != args[1].get_size():
+                raise ValueError("diff size! %s"%(str(e)))
+            if e.op == '+':
+                o = args[0].arg + args[1].arg
+            elif e.op == '-':
+                o = args[0].arg - args[1].arg
+            elif e.op == '*':
+                o = args[0].arg * args[1].arg
+            elif e.op == '|':
+                o = args[0].arg | args[1].arg
+            elif e.op == '&':
+                o = args[0].arg & args[1].arg
+            elif e.op == '^':
+                o = args[0].arg ^ args[1].arg
+            elif e.op == '>>':
+                o = args[0].arg >> args[1].arg
+            elif e.op == '<<':
+                o = args[0].arg << args[1].arg
+            else:
+                raise ValueError("zarb op %s"%str(e))
+            z = ExprInt(tab_size_int[args[0].get_size()](o))
+            return z
+
+        #int OP xx => xx OP int
+        if e.op in ['+', '*', '|', '&', '^']:
+            if isinstance(e.args[0], ExprInt) and not isinstance(e.args[1], ExprInt):
+                op, args= e.op, [e.args[1], e.args[0]]
+        #A+0 =>A
+        if op in ['+', '-', '|', "^", "<<", ">>"]:
+            if isinstance(args[0], ExprInt) and args[0].arg == 0 and not op in ['-', "<<", ">>"]:
+                return expr_simp(args[1])
+            if isinstance(args[1], ExprInt) and args[1].arg == 0:
+                return expr_simp(args[0])
+
+        #A&0 =>0
+        if op in ['&']:
+            if isinstance(args[1], ExprInt) and args[1].arg == 0:
+                return args[1]
+
+        #A-(-123) =>A+123    
+        if op == '-' and isinstance(args[1], ExprInt) and int32(args[1].arg)<0 :
+            op = '+'
+            args[1] = ExprInt(-args[1].arg)
+
+        #A+(-123) =>A-123    
+        if op == '+' and isinstance(args[1], ExprInt) and int32(args[1].arg)<0 :
+            op = '-'
+            args[1] = ExprInt(-args[1].arg)
+            #fdsfs
+        #A+3+2 => A+5
+        if op in ['+', '-'] and isinstance(args[1], ExprInt) and isinstance(args[0], ExprOp) and args[0].op in ['+', '-'] and isinstance(args[0].args[1], ExprInt):
+            op1 = op
+            op2 = args[0].op
+            if op1 == op2:
+                op = op1
+                args1 = args[0].args[1].arg + args[1].arg
+            else:
+                op = op2
+                args1 = args[0].args[1].arg - args[1].arg
+                    
+                
+                #if op == '-':
+                #    args1 = -args1
+            args0 = args[0].args[0]
+            args = [args0, ExprInt(args1)]
+
+        #0 - (a-b) => b-a
+        if op == '-' and isinstance(args[0], ExprInt) and args[0].arg == 0 and isinstance(args[1], ExprOp) and args[1].op == "-":
+            return expr_simp(args[1].args[1] - args[1].args[0])
+            
+        #a<<< x <<< y => a <<< (x+y) (ou <<< >>>)
+        if op in ['<<<', '>>>'] and isinstance(args[1], ExprInt) and isinstance(args[0], ExprOp) and args[0].op in ['<<<', '>>>'] and isinstance(args[0].args[1], ExprInt):
+            op1 = op
+            op2 = args[0].op
+            if op1 == op2:
+                op = op1
+                args1 = args[0].args[1].arg + args[1].arg
+            else:
+                op = op2
+                args1 = args[0].args[1].arg - args[1].arg
+                    
+            args0 = args[0].args[0]
+            args = [args0, ExprInt(args1)]
+
+
+        #a >>> 0 => a (ou <<<)
+        if op in ['<<<', '>>>'] and isinstance(args[1], ExprInt) and args[1].arg == 0:
+            e = expr_simp(args[0])
+            return e
+
+        #((a >>> b) <<< b) => a
+        if op in ['<<<', '>>>'] and isinstance(args[0], ExprOp) and args[0].op in ['<<<', '>>>'] and args[1] == args[0].args[1]:
+            oo = op, args[0].op
+            if oo in [('<<<', '>>>'), ('>>>', '<<<')]:
+                
+                e = expr_simp(args[0].args[0])
+                return e
+                
+
+        #( a + int1 ) - (b+int2) => a - (b+ (int1-int2))
+        if op in ['+', '-'] and isinstance(args[0], ExprOp) and args[0].op in ['+', '-'] and isinstance(args[1], ExprOp) and args[1].op in ['+', '-'] and isinstance(args[0].args[1], ExprInt) and isinstance(args[1].args[1], ExprInt):
+            op1 = op
+            op2 = args[0].op
+            op3 = args[1].op
+
+            if op1 == op2:
+                m_op = "+"
+            else:
+                m_op = "-"
+            e = ExprOp(op1,
+                       args[0].args[0],
+                       ExprOp(m_op,
+                              ExprOp(op3,
+                                     args[1].args[0],
+                                     args[1].args[1]
+                                     ),
+                              args[0].args[1]
+                              )
+                       )
+            e = expr_simp(e)
+            
+            return e
+
+        #(a - (a + XXX)) => 0-XXX
+        if op in ['-'] and isinstance(args[1], ExprOp) and args[1].op in ['+', '-'] and args[1].args[0] == args[0]:
+            if op == args[1].op:
+                m_op = "+"
+            else:
+                m_op = "-"
+
+            z = ExprInt(tab_size_int[args[1].args[1].get_size()](0))
+            e = ExprOp(m_op,
+                       z,
+                       args[1].args[1])
+            e = expr_simp(e)
+            
+            return e
+
+
+        #((a +- XXX) -a) => 0+-XXX
+        if op in ['-'] and isinstance(args[0], ExprOp) and args[0].op in ['+', '-'] and args[0].args[0] == args[1]:
+            m_op = args[0].op
+
+            z = ExprInt(tab_size_int[args[0].args[1].get_size()](0))
+            e = ExprOp(m_op,
+                       z,
+                       args[0].args[1])
+            e = expr_simp(e)
+            
+            return e
+
+        #  ((a ^ b) ^ a) => b (or commut)
+        if op in ['^'] and isinstance(args[0], ExprOp) and args[0].op in ['^']:
+            rest_a = None
+            if args[0].args[0] == args[1]:
+                rest_a = args[0].args[1]
+            elif args[0].args[1] == args[1]:
+                rest_a = args[0].args[0]
+            if rest_a != None:
+                e = expr_simp(rest_a)
+                return e
+        #  (a ^ (a ^ b) ) => b (or commut)
+        if op in ['^'] and isinstance(args[1], ExprOp) and args[1].op in ['^']:
+            rest_a = None
+            if args[1].args[0] == args[0]:
+                rest_a = args[1].args[1]
+            elif args[1].args[1] == args[0]:
+                rest_a = args[1].args[0]
+            if rest_a != None:
+                e = expr_simp(rest_a)
+                return e
+
+
+        #  ((a + b) - b) => a (or commut)
+        if op in ['-'] and isinstance(args[0], ExprOp) and args[0].op in ['+']:
+            rest_a = None
+            if args[0].args[1] == args[1]:
+                rest_a = args[0].args[0]
+                e = expr_simp(rest_a)
+                return e
+
+        #  ((a - b) + b) => a (or commut)
+        if op in ['+'] and isinstance(args[0], ExprOp) and args[0].op in ['-']:
+            rest_a = None
+            if args[0].args[1] == args[1]:
+                rest_a = args[0].args[0]
+                e = expr_simp(rest_a)
+                return e
+        
+        # a<<< a.size => a
+        if op in ['<<<', '>>>'] and isinstance(args[1], ExprInt) and args[1].arg == args[0].get_size():
+            return expr_simp(args[0])
+        
+        #!!a => a
+        if op == '!' and isinstance(args[0], ExprOp) and args[0].op == '!':
+            new_e = args[0].args[0]
+            return expr_simp(new_e)
+
+        #! (!X + int) => X - int
+        if op == '!' and isinstance(args[0], ExprOp) and args[0].op in ['+', '-'] and isinstance(args[0].args[0], ExprOp) and args[0].args[0].op == '!':
+            if args[0].op == '+':
+                op = '-'
+            else:
+                op = '+'
+            return expr_simp(ExprOp(op, args[0].args[0].args[0], args[0].args[1]))
+
+        # ((a (op1+-) int)  (op2+-) b) => ((a (op2) b) op1 int))
+        if op in ['+', '-'] and isinstance(args[0], ExprOp) and args[0].op in ['+', '-'] and not isinstance(args[1], ExprInt) and args[0].op in ['+', '-'] and isinstance(args[0].args[1], ExprInt):
+            op1 = op
+            op2 = args[0].op
+            e = ExprOp(op2,
+                       ExprOp(op1,
+                              args[0].args[0],
+                              args[1])
+                       ,
+                       args[0].args[1])
+            return expr_simp(e)
+        
+        
+        if op == "&" and isinstance(args[0], ExprOp) and args[0].op == '!' and isinstance(args[1], ExprOp) and args[1].op == '!' and isinstance(args[0].args[0], ExprOp) and args[0].args[0].op == '&' and isinstance(args[1].args[0], ExprOp) and args[1].args[0].op == '&':
+
+            ##############1 
+            a1 = args[0].args[0].args[0]
+            if isinstance(a1, ExprOp) and a1.op == '!':
+                a1 = a1.args[0]
+            elif isinstance(a1, ExprInt):
+                a1 = ExprInt(~a1.arg)
+            else:
+                a1 = None
+
+            b1 = args[0].args[0].args[1]
+            if isinstance(b1, ExprOp) and b1.op == '!':
+                b1 = b1.args[0]
+            elif isinstance(b1, ExprInt):
+                b1 = ExprInt(~b1.arg)
+            else:
+                b1 = None
+    
+
+            a2 = args[1].args[0].args[0]
+            b2 = args[1].args[0].args[1]
+
+
+            if a1 != None and b1 != None and a1 == a2 and b1 == b2:
+                new_e = ExprOp('^', a1, b1)
+                return expr_simp(new_e)
+
+            ################2
+            a1 = args[1].args[0].args[0]
+            if isinstance(a1, ExprOp) and a1.op == '!':
+                a1 = a1.args[0]
+            elif isinstance(a1, ExprInt):
+                a1 = ExprInt(~a1.arg)
+            else:
+                a1 = None
+
+            b1 = args[1].args[0].args[1]
+            if isinstance(b1, ExprOp) and b1.op == '!':
+                b1 = b1.args[0]
+            elif isinstance(b1, ExprInt):
+                b1 = ExprInt(~b1.arg)
+            else:
+                b1 = None
+    
+
+            a2 = args[0].args[0].args[0]
+            b2 = args[0].args[0].args[1]
+
+
+            if a1 != None and b1 != None and a1 == a2 and b1 == b2:
+                new_e = ExprOp('^', a1, b1)
+                return expr_simp(new_e)
+        
+
+        # (x & mask) >> shift whith mask < 2**shift => 0
+        if op == ">>" and isinstance(args[1], ExprInt) and isinstance(args[0], ExprOp) and args[0].op == "&":
+            if isinstance(args[0].args[1], ExprInt) and 2**args[1].arg >= args[0].args[1].arg:
+                return ExprInt(tab_size_int[args[0].get_size()](0))
+
+        #! (compose a b c) => (compose !a !b !c)
+        if op == '!' and isinstance(args[0], ExprCompose):
+            args = [ExprSliceTo(ExprOp('!', x.arg), x.start, x.stop) for x in args[0].args]
+            new_e = ExprCompose(args)
+            return expr_simp(new_e)
+        #!a[0:X] => (!a)[0:X]
+        if op == '!' and isinstance(args[0], ExprSlice):
+            new_e = ExprSlice(ExprOp('!', args[0].arg), args[0].start, args[0].stop)
+            return expr_simp(new_e)
+
+        
+        #! int
+        if op == '!' and isinstance(args[0], ExprInt):
+            a = args[0]
+            e = ExprInt(tab_max_uint[a.get_size()]^a.arg)
+            return e
+        
+        #a^a=>0 | a-a =>0
+        if op in ['^', '-'] and args[0] == args[1]:
+            tmp =  ExprInt(tab_size_int[args[0].get_size()](0))
+            return tmp
+
+        #a & a => a   or a | a => a
+        if op in ['&', '|'] and args[0] == args[1]:
+            return expr_simp(args[0])
+        # int == int => 0 or 1
+        if op == '==' and isinstance(args[0], ExprInt) and isinstance(args[1], ExprInt):
+            if args[0].arg == args[1].arg:
+                return ExprInt(tab_size_int[args[0].get_size()](1))
+            else:
+                return ExprInt(tab_size_int[args[0].get_size()](0))
+        #( a|int == 0)  => 0  wirh int != 0
+        if op == '==' and isinstance(args[1], ExprInt) and args[1].arg ==0 :
+            if isinstance(args[0], ExprOp) and args[0].op == '|' and isinstance(args[0].args[1], ExprInt) and \
+               args[0].args[1].arg != 0:
+                return ExprInt(tab_size_int[args[0].get_size()](0))
+                                     
+
+        if op == 'parity' and isinstance(args[0], ExprInt):
+            fsdfsdf
+            return ExprInt(tab_size_int[args[0].get_size()](parity(args[0].arg)))
+        
+        new_e = ExprOp(op, *[expr_simp(x) for x in args])
+        if new_e == e:
+            return new_e
+        else:
+            return expr_simp(new_e)
+
+    #Slice(int) => new_int
+    elif isinstance(e, ExprSlice):
+        arg = expr_simp(e.arg)
+
+        if isinstance(arg, ExprTop):
+            return ExprTop()
+        elif e.start == 0 and e.stop == 32 and arg.get_size() == 32:
+            return arg
+
+        elif isinstance(arg, ExprInt):
+            total_bit = e.stop-e.start
+            mask = uint64((uint64(1)<<(e.stop-e.start))-1)
+            if total_bit in tab_size_int:
+                return ExprInt(tab_size_int[total_bit]((uint64((arg.arg)>>e.start)) & mask))
+            else:
+                return ExprInt(type(arg.arg)((uint64((arg.arg)>>e.start)) & mask))
+        elif isinstance(arg, ExprSlice):
+            if e.stop-e.start > arg.stop-arg.start:
+                raise ValueError('slice in slice: getting more val', str(e))
+            
+            new_e = ExprSlice(expr_simp(arg.arg), e.start + arg.start, e.start + arg.start + (e.stop - e.start))
+            return expr_simp(new_e)
+        elif isinstance(arg, ExprCompose):
+            for a in arg.args:
+                if a.start <= e.start and a.stop>=e.stop:
+                    new_e = a.arg[e.start-a.start:e.stop-a.start]
+                    new_e = expr_simp(new_e)
+                    return new_e
+        elif isinstance(arg, ExprOp) and e.start == 0:
+            #if (op ..)[0:X] and op result is good size, skip slice
+            if e.stop == arg.get_size():
+                return expr_simp(arg)
+            return ExprSlice(arg, e.start, e.stop)
+        elif isinstance(arg, ExprMem) and e.start == 0 and arg.size == e.stop:
+            e = expr_simp(arg)
+            return e
+        #XXXX hum, is it safe?
+        elif isinstance(arg, ExprMem) and e.start == 0 and arg.size > e.stop and e.stop %8 == 0:
+            e = expr_simp(ExprMem(e.arg.arg, size = e.stop))
+            return e
+
+
+
+        
+        return ExprSlice(arg, e.start, e.stop)
+    elif isinstance(e, ExprSliceTo):
+        if isinstance(e.arg, ExprTop):
+            return ExprTop()
+        if isinstance(e.arg, ExprSlice) and e.arg.start == 0:
+            return expr_simp(ExprSliceTo(expr_simp(e.arg.arg), e.start, e.stop))
+
+        #(.., a[0:X], ..) _to[Y:Z] with X > Z-Y => a[0:X]_to[Y:Z]
+        if isinstance(e.arg, ExprCompose) and len(e.arg.args) >1:
+            s = e.get_size()
+            for a in e.arg.args:
+                if a.start == 0 and a.stop >= s:
+                    return expr_simp(ExprSliceTo(ExprCompose([a]), e.start, e.stop))
+
+
+            
+        return ExprSliceTo(expr_simp(e.arg), e.start, e.stop)
+    elif isinstance(e, ExprCompose):
+        #(.., a_to[x:y], a[:]_to[y:z], ..) => (.., a[x:z], ..)
+        e = ExprCompose([expr_simp(x) for x in e.args])
+        args = []
+        i = -1
+        simp = False
+        while i+1 < len(e.args):
+            i+=1
+            if not args:
+                args.append(e.args[i])
+                continue
+            if args[-1].stop != e.args[i].start:
+                continue
+            if not isinstance(e.args[i].arg, ExprSlice):
+                continue
+            if isinstance(args[-1].arg, ExprSlice):
+                a = args[-1]
+            else:
+                a = ExprSliceTo(ExprSlice(args[-1].arg, 0, args[-1].arg.get_size()), args[-1].start, args[-1].stop)
+            if a.arg.arg != e.args[i].arg.arg:
+                continue
+            if a.stop != e.args[i].start:
+                continue
+            args[-1] = ExprSliceTo(e.args[i].arg.arg, a.start, e.args[i].stop)
+            simp = True
+
+        if simp:
+            return expr_simp(ExprCompose(args))
+            
+            
+        
+        all_top = True
+        for a in e.args:
+            if not isinstance(a, ExprTop):
+                all_top = False
+                break
+        if all_top:
+            return ExprTop()
+        if ExprTop() in e.args:
+            return ExprTop()
+        
+        args = merge_sliceto_slice(e.args)
+        if len(args) == 1:
+            a = args[0]
+            if isinstance(a.arg, ExprInt):
+                if a.arg.get_size() != a.stop:
+                    print a, a.arg.get_size(), a.stop
+                    raise ValueError("cast in compose!", e)
+                return a.arg
+            
+            uu = expr_simp(a.arg)
+            return uu
+        if len(args) != len(e.args):
+            return expr_simp(ExprCompose(args))
+        else:
+            return ExprCompose(args)
+    
+    else:
+        raise 'bad expr'
+
+
+def expr_cmp(e1, e2):
+    return str(e1) == str(e2)
+
+#replace id by another in expr
+def expr_replace(e, repl):
+    if isinstance(e, ExprInt):
+        return e
+    elif isinstance(e, ExprId):
+        if e in repl:
+            return repl[e]
+        return e
+    elif isinstance(e, ExprAff):
+        return ExprAff(expr_replace(e.dst, repl), expr_replace(e.src, repl))
+    elif isinstance(e, ExprCond):
+        return ExprCond(expr_replace(e.cond, repl), expr_replace(e.src1, repl), expr_replace(e.src2, repl))
+    elif isinstance(e, ExprMem):
+        return ExprMem(expr_replace(e.arg, repl), size = e.size)
+    elif isinstance(e, ExprOp):
+        return ExprOp(e.op, *[expr_replace(x, repl) for x in e.args])
+    elif isinstance(e, ExprSlice):
+        return ExprSlice(expr_replace(e.arg, repl), e.start, e.stop)
+    elif isinstance(e, ExprSliceTo):
+        return ExprSliceTo(expr_replace(e.arg, repl), e.start, e.stop)
+    elif isinstance(e, ExprCompose):
+        return ExprCompose([expr_replace(x, repl) for x in e.args])
+    else:
+        raise 'bad expr'
+    
+    
+    
diff --git a/miasm/graph/__init__.py b/miasm/graph/__init__.py
new file mode 100644
index 00000000..fbabaacf
--- /dev/null
+++ b/miasm/graph/__init__.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
diff --git a/miasm/graph/graph_qt.py b/miasm/graph/graph_qt.py
new file mode 100755
index 00000000..c47159c7
--- /dev/null
+++ b/miasm/graph/graph_qt.py
@@ -0,0 +1,806 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+import sys
+import math
+from PyQt4 import QtGui
+from PyQt4 import QtCore
+
+
+from PyQt4.Qt import QTextEdit
+from PyQt4.Qt import QPlainTextEdit
+from PyQt4.Qt import QMouseEvent
+from PyQt4.Qt import QTextCursor
+from PyQt4.Qt import QEvent
+from PyQt4.Qt import Qt
+
+app = None
+from grandalf.graphs import *
+from grandalf.layouts import SugiyamaLayout, VertexViewer
+from grandalf.routing import *
+
+from miasm.core import asmbloc
+def __init__(self, w = 40, h = 40, data = None):
+    self.w = w
+    self.h = h
+VertexViewer.__init__ = __init__
+
+class HighlightingRule():
+    def __init__( self, pattern, format ):
+        self.pattern = pattern
+        self.format = format
+
+
+def gen_syntax_rules():
+    highlightingRules = []
+    number = QtGui.QTextCharFormat()
+    label = QtGui.QTextCharFormat()
+    my_id = QtGui.QTextCharFormat()
+    highlight_word = QtGui.QTextCharFormat()
+
+
+    # hex number
+    brushg = QtGui.QBrush( Qt.green, Qt.SolidPattern )
+    pattern = QtCore.QRegExp( "0x[0-9a-fA-F]+" )
+    pattern.setMinimal( False )
+    number.setForeground( brushg )
+    rule = HighlightingRule( pattern, number )
+    highlightingRules.append( rule )
+
+    
+    pattern = QtCore.QRegExp( "\b[0-9]+\b" )
+    pattern.setMinimal( False )
+    number.setForeground( brushg )
+    rule = HighlightingRule( pattern, number )
+    highlightingRules.append( rule )
+    
+
+    #label
+    brushb = QtGui.QBrush( Qt.blue, Qt.SolidPattern )
+    pattern = QtCore.QRegExp( "[0-9a-zA-Z_\.]+:$" )
+    pattern.setMinimal( False )
+    label.setForeground( brushb )
+    rule = HighlightingRule( pattern, label )
+    highlightingRules.append( rule )
+
+    #label
+    brushb = QtGui.QBrush( Qt.blue, Qt.SolidPattern )
+    pattern = QtCore.QRegExp( "[0-9a-zA-Z_\.]+:" )
+    pattern.setMinimal( False )
+    my_id.setForeground( brushb )
+    rule = HighlightingRule( pattern, my_id )
+    highlightingRules.append( rule )
+
+    return highlightingRules
+
+
+syntax_rules = gen_syntax_rules()
+
+
+class MyHighlighter( QtGui.QSyntaxHighlighter ):
+    def __init__( self, parent ):
+        QtGui.QSyntaxHighlighter.__init__( self, parent )
+        self.parent = parent
+
+
+        self.highlightingRules = syntax_rules
+
+
+
+
+
+    def highlightBlock( self, text ):
+        for rule in self.highlightingRules:
+            expression = QtCore.QRegExp( rule.pattern )
+            index = expression.indexIn( text )
+            while index >= 0:
+                length = expression.matchedLength()
+                self.setFormat( index, length, rule.format )
+                index = text.indexOf( expression, index + length )
+        self.setCurrentBlockState( 0 )
+
+
+border_l = 10
+font_w = 7
+font_h = 16
+scale_x = 20.6#2.5
+scale_y = 20.6#2.5
+
+title_h = font_h
+font_size = 8
+
+zoom_lvl = 1.0
+pan_lvl = 120
+
+mfont = QtGui.QFont("Monospace", 8)
+
+
+def getTextwh(txt):
+    l = txt.split('\n')
+    h = len(l)
+    w = max(map(lambda x:len(x), l))
+    return w, h
+
+
+def getTextwh_font(txt, zoom, font):
+    l = txt.split('\n')
+    max_c = max(map(lambda x:len("X"+x+"X"), l))
+    w_max = -1
+
+    r  = QtGui.QFontMetrics(font).boundingRect(QtCore.QRect(), 0, txt)
+    w_max, h_max = r.width(), r.height()
+    return w_max+30, h_max+20+len(l)*1
+
+
+class graph_edge(QtGui.QGraphicsItem):
+    def __init__(self, min_x, min_y, max_x, max_y, pts, color, end_angle, my_splines):
+        QtGui.QGraphicsItem.__init__(self)
+        self.min_x = min_x
+        self.min_y = min_y
+        self.max_x = max_x
+        self.max_y = max_y
+        self.pts = pts
+        self.color = color
+        self.setZValue(-1)
+        self.end_angle = end_angle
+        self.my_splines = my_splines
+    def boundingRect(self):
+        return QtCore.QRectF(self.min_x, self.min_y, self.max_x, self.max_y)
+
+    def paint(self, painter, option, unused_widget):
+        painter.setPen(self.color)
+        brush = QtGui.QBrush(self.color)
+        brush.setStyle(QtCore.Qt.SolidPattern)
+        painter.setBrush(brush)
+                       
+        for i, p1 in enumerate(self.pts[:-1]):
+            p2 = self.pts[i+1]
+            painter.drawLine(*(p1 + p2))
+    
+        a = -self.end_angle-math.pi
+        d_a = 0.3
+        p3 = p2[0]+10*math.cos(a-d_a), p2[1]-10*math.sin(a-d_a)
+        p4 = p2[0]+10*math.cos(a+d_a), p2[1]-10*math.sin(a+d_a)
+        p5 = p2
+
+
+        painter.drawPolygon(QtCore.QPoint(*p2), QtCore.QPoint(*p3), QtCore.QPoint(*p4), QtCore.QPoint(*p5) )
+    
+class node_asm_bb(QTextEdit):
+    def __init__(self, txt, mainwin):
+        self.txt = txt
+        self.mainwin = mainwin
+        QTextEdit.__init__(self)
+        self.setText(self.txt)
+        self.setFont(mfont)
+        self.setReadOnly(True)
+
+
+
+
+
+    def setpos(self, x, y, w, h):
+        self.p_x = x
+        self.p_y = y
+        self.p_w = w
+        self.p_h = h
+
+        self.setFixedWidth(self.p_w)
+        self.setFixedHeight(self.p_h)
+
+        self.move(self.p_x, self.p_y)
+        self.setFont(mfont)
+        self.setCurrentFont(mfont)
+
+
+    def get_word_under_cursor(self):
+        cursor = self.textCursor()
+        cursor.clearSelection()
+        a, b = cursor.selectionStart () , cursor.selectionEnd ()
+        print a, b
+        #if only click, get word
+        cut_char = [' ', "\t", "\n"]
+        if a == b:
+            while not self.txt[a] in cut_char:
+                a-=1
+                if a <0:
+                    break
+            a +=1
+            
+            while b <len(self.txt) and not self.txt[b] in cut_char:
+                b+=1
+        print a, b
+        print self.txt[a:b]
+        w = self.txt[a:b]
+        return w
+
+    def mousePressEvent(self, event):
+
+        if event.button() == Qt.RightButton:
+            # Rewrite the mouse event to a left button event so the cursor is
+            # moved to the location of the pointer.
+            event = QMouseEvent(QEvent.MouseButtonPress, event.pos(),
+                                Qt.LeftButton, Qt.LeftButton, Qt.NoModifier)
+
+        QTextEdit.mousePressEvent(self, event)
+        cursor = self.textCursor()
+        
+
+    def mouseDoubleClickEvent(self,mouseEvent):
+        print "DOUBLE"
+        w = self.get_word_under_cursor()
+        app.postEvent(self.mainwin,MyEvent(w))
+
+    def contextMenuEvent(self, event):
+        global app
+        w = self.get_word_under_cursor()
+        menu = QtGui.QMenu(self)
+        goto_ad = menu.addAction("sel: "+w)
+        goto_ad.triggered.connect(lambda:app.postEvent(self.mainwin,MyEvent(w)))
+        
+        menu.addAction("Copy")
+        menu.addAction("Paste")
+        menu.exec_(event.globalPos())
+    
+    def paintEvent(self, e):
+        if self.mainwin.view.graphicsView.zoom > -600:
+            QTextEdit.paintEvent(self, e)
+        
+        
+
+
+class View(QtGui.QFrame):
+
+    def __init__(self, name, parent=None):
+        QtGui.QFrame.__init__(self, parent)
+
+        self.setFrameStyle(QtGui.QFrame.Sunken | QtGui.QFrame.StyledPanel)
+
+        self.graphicsView= myQGraphicsView(parent)
+        self.graphicsView.setRenderHint(QtGui.QPainter.Antialiasing, False)
+        self.graphicsView.setDragMode(QtGui.QGraphicsView.RubberBandDrag)
+        self.graphicsView.setViewportUpdateMode(
+            QtGui.QGraphicsView.SmartViewportUpdate)
+
+        size = self.style().pixelMetric(QtGui.QStyle.PM_ToolBarIconSize)
+        iconSize = QtCore.QSize(size, size)
+
+        # Label layout
+        labelLayout = QtGui.QHBoxLayout()
+        self.label = QtGui.QLabel(name)
+        self.antialiasButton = QtGui.QToolButton()
+        self.antialiasButton.setText("Antialiasing")
+        self.antialiasButton.setCheckable(True)
+        self.antialiasButton.setChecked(False)
+
+        # No openGlButton
+        # No printButton
+
+        labelLayout.addWidget(self.label)
+        labelLayout.addStretch()
+        labelLayout.addWidget(self.antialiasButton)
+
+        topLayout = QtGui.QGridLayout()
+        topLayout.addLayout(labelLayout, 0, 0)
+        topLayout.addWidget(self.graphicsView, 1, 0)
+        self.setLayout(topLayout)
+
+        self.connect(self.antialiasButton, QtCore.SIGNAL("toggled(bool)"),
+                     self.toggleAntialiasing)
+        self.setupMatrix()
+
+    def view(self):
+        return self.graphicsView
+
+    def resetView(self):
+        self.setupMatrix()
+        self.graphicsView.ensureVisible(QtCore.QRectF(0, 0, 0, 0))
+
+    def setupMatrix(self):
+        scale = pow(2.0, 0)
+
+        matrix = QtGui.QMatrix()
+        matrix.scale(scale, scale)
+
+        self.graphicsView.setMatrix(matrix)
+
+    def toggleAntialiasing(self):
+        self.graphicsView.setRenderHint(QtGui.QPainter.Antialiasing,
+                                        self.antialiasButton.isChecked())
+
+
+class myQGraphicsView(QtGui.QGraphicsView):
+    def __init__(self, mainwin):
+        QtGui.QGraphicsView.__init__(self)
+        self.view = None
+        self.i_pos = None
+        self.in_move = False
+        self.key_ctrl = False
+        self.zoom = 1.0
+        self.ty = 0.0
+        self.mainwin = mainwin
+
+        
+        self.current_node = None
+        
+
+    def set_view(self, view):
+        self.view = view
+    def mouseMoveEvent(self, mouseEvent):
+        if not self.in_move:
+            QtGui.QGraphicsView.mouseMoveEvent(self, mouseEvent)
+
+            return
+        pt = mouseEvent.pos()
+        x,y = pt.x(), pt.y()
+
+        diff_x, diff_y = self.i_pos[0] - x, self.i_pos[1] - y 
+        scroll_v =     self.verticalScrollBar()
+        scroll_h =     self.horizontalScrollBar()
+
+
+        pos_v = scroll_v.value()
+        pos_h = scroll_h.value()
+
+        pos_h += diff_x
+        pos_v += diff_y
+
+        scroll_v.setValue(pos_v)
+        scroll_h.setValue(pos_h)
+        self.i_pos = x, y
+
+    def mousePressEvent(self, mouseEvent):
+
+        QtGui.QGraphicsView.mousePressEvent(self, mouseEvent)
+        if mouseEvent.button() == QtCore.Qt.LeftButton :
+            pt = mouseEvent.pos()
+            i = self.itemAt(pt)
+            if not i or isinstance(i, graph_edge):
+                x,y = pt.x(), pt.y()
+                self.i_pos = x, y
+                self.in_move = True
+            elif isinstance(i, QtGui.QGraphicsProxyWidget) and isinstance(i.widget(), node_asm_bb):
+                #if another node has selected text
+                #clear it
+                if self.current_node:
+                    cursor = self.current_node.textCursor()
+                    cursor.clearSelection()
+                    self.current_node.setTextCursor(cursor)
+                self.current_node = i.widget()
+
+
+
+
+    def mouseReleaseEvent(self, mouseEvent):
+        QtGui.QGraphicsView.mouseReleaseEvent(self, mouseEvent)
+        if mouseEvent.button() == QtCore.Qt.LeftButton :
+            self.in_move = False
+
+
+    def keyPressEvent( self, event ):
+        key = event.key()
+        print "press", hex(key)
+        if key == 0x1000021: #ctrl
+            self.key_ctrl = True
+
+
+        elif key == 0x1000005: #enter
+            if self.mainwin.history_cur < len(self.mainwin.history_ad)-1:
+                self.mainwin.history_cur +=1
+            app.postEvent(self.mainwin,MyEvent(self.mainwin.history_ad[self.mainwin.history_cur]))
+            
+        elif key == 0x1000000: #esc
+            if self.mainwin.history_cur>0:
+                self.mainwin.history_cur -= 1
+            app.postEvent(self.mainwin,MyEvent(self.mainwin.history_ad[self.mainwin.history_cur]))
+
+        elif self.key_ctrl and key in  [43, 45]: # - +
+            if key == 43:
+                self.zoom +=100
+            elif key == 45:
+                self.zoom -=100
+            scale = pow(2.0, (self.zoom /600.0))
+            matrix = QtGui.QMatrix()
+            matrix.scale(scale, scale)
+            
+            self.setMatrix(matrix)
+            
+        elif key in [0x1000012, 0x1000014]:
+            if key == 0x1000012:
+                diff_x = 20
+            else:
+                diff_x = -20
+            scroll_h =     self.horizontalScrollBar()            
+            pos_h = scroll_h.value()
+            pos_h += diff_x
+            scroll_h.setValue(pos_h)
+
+        elif key in [0x1000013, 0x1000015]:
+            if key == 0x1000013:
+                diff_y = -20
+            else:
+                diff_y = 20
+            scroll_v =     self.verticalScrollBar()            
+            pos_v = scroll_v.value()
+            pos_v += diff_y
+            scroll_v.setValue(pos_v)
+
+    def keyReleaseEvent( self, event ):
+        key = event.key()
+        print "relea", hex(key)
+        if key == 0x1000021: #ctrl
+            self.key_ctrl = False
+
+    def wheelEvent(self, event):
+        #XXX bug if maximize win
+        mp_x, mp_y = event.pos().x(), event.pos().y()
+        delta = event.delta()
+
+        scroll_v =     self.verticalScrollBar()
+
+
+
+        if self.key_ctrl:
+            self.zoom +=delta
+        else:
+            pos_v = scroll_v.value()
+            pos_v -= delta  
+            scroll_v.setValue(pos_v)
+
+
+        scale = pow(2.0, (self.zoom /600.0))
+        matrix = QtGui.QMatrix()
+        matrix.scale(scale, scale)
+
+        self.setMatrix(matrix)
+
+
+
+
+
+class MainWindow(QtGui.QWidget):
+
+    def __init__(self, ad = None, all_bloc = [], label = False, dis_callback = None):
+        QtGui.QWidget.__init__(self, parent = None)
+
+        QtGui.QShortcut(QtGui.QKeySequence("Ctrl+Q"), self, self.close)
+        self.label = label
+        self.ad = ad
+        self.all_bloc = all_bloc
+        self.dis_callback = dis_callback
+        self.history_ad = []
+        self.history_cur = -1
+
+        view = View("Graph view", self)
+        self.view = view
+
+        self.populateScene(ad, all_bloc)
+
+        view.view().setScene(self.scene)
+
+        layout = QtGui.QHBoxLayout()
+        layout.addWidget(view)
+        self.setLayout(layout)
+
+        self.setWindowTitle("Miasm Disasm")
+
+
+        self.i_pos = None
+        self.drop_mouse_event = False
+        
+
+
+    def pos2graphpos(self, x, y):
+        o_x = self.zoom*x + self.add_x
+        o_y = self.zoom*y + self.add_y
+        return o_x, o_y
+    def graphpos2pos(self, x, y):
+        o_x = (x-self.add_x)/self.zoom
+        o_y = (y-self.add_y)/self.zoom
+        return o_x, o_y
+
+    def auto_zoom(self):
+        if self.max_x == self.min_x:
+            z1 = 1
+        else:
+            z1 = self.size().width()/(self.max_x - self.min_x)
+        if self.max_y == self.min_y:
+            z2 = 1
+        else:
+            z2 = self.size().height()/(self.max_y - self.min_y)
+
+        self.zoom = min(z1, z2)
+        self.zoom = max(0.1, self.zoom)
+        #self.zoom*=0.8
+        self.zoom_l = math.log(self.zoom)
+
+        print self.min_x
+        print self.min_y
+        print self.max_x
+        print self.max_y
+
+        self.add_x = self.size().width()/2.0 - ((self.max_x+self.min_x)/2.0) * self.zoom
+        self.add_y = self.size().height()/2.0 - ((self.max_y+self.min_y)/2.0) * self.zoom
+
+        print self.zoom
+        print self.add_x, self.add_y
+        for e in self.editor.values():
+            e.zoom(self.zoom)
+
+
+
+
+    def graph_from_asmbloc(self, ad, all_bloc):
+        V = {}
+        E = []
+        for b in all_bloc:
+            if self.label:
+                V[b.label] = Vertex(str(b.label.name) +":\n"+"\n".join(["%.8X  "%x.offset + str(x) for x in b.lines]))
+            else:
+                V[b.label] = Vertex(str(b.label.name) +":\n"+"\n".join([str(x) for x in b.lines]))
+        for b in all_bloc:
+            for c in b.bto:
+                if not isinstance(c.label, asmbloc.asm_label):
+                    continue
+                data = QtCore.Qt.black
+                if c.c_t == asmbloc.asm_constraint.c_to:
+                    if b.lines and b.lines[-1].splitflow():
+                        data = QtCore.Qt.green
+                    else:
+                        data = QtCore.Qt.blue
+                else:
+                    data = QtCore.Qt.red
+                ###
+                if b.label in V and c.label in V:
+                    E.append(Edge(V[b.label], V[c.label], data = data))
+        h = asmbloc.getblocby_offset(all_bloc, ad)
+        if h:
+            hdr = V[h.label]
+        else:
+            hdr = None
+        V =  V.values()
+        g = Graph(V,E)
+        return hdr, g, V, E
+        
+    def graph_from_v_e(self, ad, all_bloc):
+        v_hdr, v_dct, edges = all_bloc
+        V = {}
+        E = []
+        for v_id, c in v_dct.items():
+            V[v_id] = Vertex(str(c))
+        for a, b in edges:
+            data = QtCore.Qt.black
+            E.append(Edge(V[a], V[b], data = data))
+        hdr = V[v_hdr]
+        V =  V.values()
+        g = Graph(V,E)
+
+        
+        return hdr, g, V, E
+
+
+    def add_new_bloc(self, ad, all_bloc = []):
+        print 'add_new_bloc', ad
+        if isinstance(ad, str):
+            if ad.startswith('loc_'):
+                ad = int(ad[4:12], 16)
+            elif ad.startswith('0x'):
+                ad = int(ad, 16)
+            else:
+                print 'BAD AD'
+                return
+        #print hex(ad)
+
+        if not self.history_ad or (self.history_cur == len(self.history_ad)-1 and ad != self.history_ad[-1]):
+            print 'add hist'
+            self.history_ad.append(ad)
+            self.history_cur +=1
+        
+
+        print "AD", hex(ad)
+
+        for b in self.scene_blocs:
+            b.widget().destroy()
+            self.scene.removeItem(b)
+        self.scene_blocs = []
+        for e in self.scene_edges:
+            self.scene.removeItem(e)
+        self.scene_edges = []
+        self.scene.clear()
+
+        if not all_bloc:
+            print 'DIS', hex(ad)
+            all_bloc = self.dis_callback(ad)
+            g = asmbloc.bloc2graph(all_bloc)
+            open("graph.txt" , "w").write(g)
+
+
+        if isinstance(all_bloc, list):
+            hdr, g, V, E = self.graph_from_asmbloc(ad, all_bloc)
+        else:
+            hdr, g, V, E = self.graph_from_v_e(ad, all_bloc)
+        index = 0
+
+        print 'g ok'
+        print 'vertex: ', len(g.C), len(g.C[index].sV), 'edges:', len(g.C[index].sE)
+        print 'hdr', hdr
+        
+        nn = node_asm_bb("toto", self)
+        mfont = nn.currentFont()
+        class defaultview(object):
+            def __init__(self, data = None):
+                self.data = data
+                if not data:
+                    self.w, self.h = 80,40
+                else:
+                    self.data = self.data.replace('\t', ' '*4)
+                    s = self.data.split('\n')
+                    w, h = getTextwh_font(self.data, 1, mfont)
+                    self.h = h
+                    self.w = w
+
+            self.l = []
+            l = []
+            def setpath(self, l):
+                self.l = l
+        for v in V: v.view = defaultview(v.data)
+        for e in E: e.view = defaultview()
+        min_x = None
+        min_y = None
+        max_pos_x = 0
+        max_pos_y = 0
+
+        for index in xrange(len(g.C)):
+
+            gr = g.C[index]
+            
+            if False:#dr  and hdr in g.C[index].sV:
+                r = [hdr]
+            else:
+                r = filter(lambda x: len(x.e_in())==0, gr.sV)
+                if not r:
+                    print 'no roots!'
+                    r = [gr.sV.o[0]]
+            r.sort()
+            
+            L = g.C[index].get_scs_with_feedback(r)
+    
+            sug = SugiyamaLayout(g.C[index])
+            sug.xspace = 40
+            sug.yspace = 40
+    
+            sug.init_all(roots=r,inverted_edges=filter(lambda x:x.feedback, g.C[index].sE))
+            sug.route_edge = route_with_nurbs
+            sug.draw(1)
+
+            min_pos_x = None
+            #compute min pos x
+            for n in g.C[index].sV:
+                pos = n.view.xy
+                if min_pos_x == None or pos[0] - n.view.w/2 < min_pos_x:
+                    min_pos_x = pos[0]- n.view.w/2
+    
+
+            new_max_pos_x = max_pos_x
+            first_pos = None
+            for n in g.C[index].sV:
+                pos = n.view.xy
+                if not first_pos:
+                    first_pos = pos
+                
+                e = node_asm_bb(n.data, self)
+                e.h = MyHighlighter(e)
+                p_x = pos[0] - n.view.w/2 + max_pos_x - min_pos_x
+                p_y = pos[1] - n.view.h/2
+                e.setpos(p_x, p_y, n.view.w, n.view.h)
+                if p_x + n.view.w > new_max_pos_x:
+                    new_max_pos_x = p_x + n.view.w
+                wproxy = self.scene.addWidget(e)
+                self.scene_blocs.append(wproxy)
+    
+                e.show()
+    
+            for e in g.C[index].sE:
+                min_x = None
+                min_y = None
+                max_x = None
+                max_y = None
+                end_angle = None
+                try:
+                    end_angle = e.view.head_angle
+                except:
+                    pass
+                if not  e.view.l:
+                    p1 = e.v[0].view.xy
+                    p2 = e.v[1].view.xy
+
+                    
+                    for p in [p1, p2]:
+                        if min_x == None or p[0] < min_x:
+                            min_x = p[0]
+                        if max_x == None or p[0] > max_x:
+                            max_x = p[0]
+    
+                        if min_y == None or p[1] < min_y:
+                            min_y = p[1]
+                        if max_y == None or p[1] > max_y:
+                            max_y = p[1]
+                    pts = [p1, p2]
+                else:
+                    for p in e.view.l:
+                        x, y = p[0] + max_pos_x, p[1]
+                        p = x, y
+
+                        if min_x == None or p[0] < min_x:
+                            min_x = p[0]
+                        if max_x == None or p[0] > max_x:
+                            max_x = p[0]
+    
+                        if min_y == None or p[1] < min_y:
+                            min_y = p[1]
+                        if max_y == None or p[1] > max_y:
+                            max_y = p[1]
+                    pts = e.view.l
+                for i, p in enumerate(pts):
+                    x, y = p[0] + max_pos_x - min_pos_x, p[1]
+                    p = x, y
+                    pts[i] = p
+                e = graph_edge(min_x, min_y, max_x, max_y, pts, e.data, end_angle, e.view.splines)
+                
+                self.scene.addItem(e)
+                self.scene_edges.append(e)
+
+            max_pos_x = new_max_pos_x
+
+    
+        if first_pos:
+            self.view.view().centerOn(first_pos[0], first_pos[1])
+
+        
+
+    def populateScene(self, ad, all_bloc):
+        self.scene = QtGui.QGraphicsScene()
+        self.scene.setBackgroundBrush(QtGui.QBrush(QtGui.QColor(230, 250, 250, 255)))
+        self.scene_blocs = []
+        self.scene_edges = []
+
+        self.add_new_bloc(ad, all_bloc)
+        self.ad = ad
+
+    def customEvent(self,event):
+        self.add_new_bloc(event.ad)
+        
+
+class MyEvent(QEvent):
+    """ """
+ 
+    def __init__(self,ad):
+        """ """
+        QEvent.__init__(self,QEvent.User)
+        self.ad = ad
+
+
+def graph_blocs(ad, all_bloc, label = False, dis_callback = None):
+    global app
+    app = QtGui.QApplication(sys.argv)
+    g = MainWindow(ad, all_bloc, label, dis_callback)
+    g.show()
+    app.exec_()
+    app.quit()
+    app = None
diff --git a/miasm/tools/__init__.py b/miasm/tools/__init__.py
new file mode 100644
index 00000000..fbabaacf
--- /dev/null
+++ b/miasm/tools/__init__.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
diff --git a/miasm/tools/codenat.py b/miasm/tools/codenat.py
new file mode 100644
index 00000000..6711f802
--- /dev/null
+++ b/miasm/tools/codenat.py
@@ -0,0 +1,160 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+import os
+import sys
+try:
+    from Crypto.Hash import MD5
+except ImportError:
+    print "cannot find crypto MD5, skipping"
+    
+from  ctypes import *
+from miasm.tools.to_c_helper import *
+from miasm.tools.emul_lib import libcodenat_interface    
+
+# interrupt with eip update after instr
+EXCEPT_CODE_AUTOMOD = (1<<0)
+EXCEPT_SOFT_BP = (1<<1)
+
+# interrupt with eip at instr
+EXCEPT_UNK_MEM_AD = (1<<2)
+EXCEPT_THROW_SEH = (1<<3)
+EXCEPT_UNK_EIP = (1<<4)
+EXCEPT_ACCESS_VIOL = (1<<5)
+EXCEPT_INT_DIV_BY_ZERO = (1<<6)
+EXCEPT_PRIV_INSN = (1<<7)
+EXCEPT_ILLEGAL_INSN = (1<<8)
+
+
+
+
+EXCEPTION_BREAKPOINT = 0x80000003
+EXCEPTION_ACCESS_VIOLATION = 0xc0000005
+EXCEPTION_INT_DIVIDE_BY_ZERO = 0xc0000094
+EXCEPTION_PRIV_INSTRUCTION = 0xc0000096
+EXCEPTION_ILLEGAL_INSTRUCTION = 0xc000001d
+
+
+PAGE_READ  = 1
+PAGE_WRITE = 2
+PAGE_EXEC  = 4
+
+
+
+class bloc_nat:
+    def __init__(self, offset = 0, b = None, module_c = None, log_mn = False, log_regs = False):
+        self.b = b
+        self.module_c = module_c
+
+blocs_nat = {}
+
+def gen_C_module(c_source):
+    
+    lib_name = 'emul_cache/out_'+MD5.new(c_source).hexdigest()
+    lib_dir = os.path.dirname(os.path.realpath(__file__))
+    lib_dir = os.path.join(lib_dir, 'emul_lib')
+
+    a = None
+    try:
+        aa = os.stat(lib_name+'.so')
+        a = cdll.LoadLibrary('./%s.so'%lib_name)
+    except:
+        a = None
+    if a == None:    
+        open(lib_name+'.c', 'w').write(c_source)
+
+        gcc_opts =  " -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes "
+        gcc_opts += " -fPIC -I/usr/include/python2.6  "
+        os.system('gcc -c '+gcc_opts + ' -L%s -lcodenat -lpython2.6 %s.c -o %s.o'%(lib_dir, lib_name, lib_name))
+
+        gcc_opts =  ' -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions '
+        gcc_opts += ' -L%s -lcodenat '%lib_dir
+        gcc_opts_end = ' -Wl,-rpath,%s '%lib_dir
+        os.system('gcc ' + gcc_opts + '%s.o -o %s.so '%(lib_name, lib_name) + gcc_opts_end)
+        
+        a = cdll.LoadLibrary('%s.so'%lib_name)
+
+    return a
+
+
+def del_bloc_in_range(known_blocs, ad1, ad2):
+    bloc_out = {}
+    for ad in known_blocs:
+        bn = known_blocs[ad]
+        # XXX no lines in bloc?
+        if not bn.b.lines:
+            continue
+        
+        if bn.b.lines[0].offset>=ad2 or bn.b.lines[-1].offset + bn.b.lines[-1].l <= ad1:
+            #bloc_out.append(b)
+            bloc_out[ad] = bn
+        else:
+            #print 'inv bloc', bn.b.label
+            pass
+    
+    return bloc_out
+
+
+
+
+def vm_save_state(fname):
+    vmem = vm_get_all_memory()
+    return vmem
+    #XXX
+
+
+
+
+libcntcc = None
+def codenat_tcc_load():
+    global libcntcc
+    from distutils.sysconfig import get_python_inc
+    import emul_lib.libcodenat_tcc as libcntcc
+    lib_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "emul_lib")
+    lib_path = os.path.join(lib_dir, 'libcodenat_tcc.so')
+    libpath = libcodenat_interface.__file__
+    libdir = os.path.dirname(libpath)
+    print libpath
+    print libdir
+    libcntcc.tcc_set_emul_lib_path(libdir, libpath, get_python_inc())
+    
+def codenat_tcc_init():
+    global libcntcc
+    if libcntcc == None:
+        codenat_tcc_load()
+
+def codenat_tcc_compil(func_name, func_code):
+    global libcntcc
+    c = libcntcc.tcc_compil(func_name, func_code)
+    return c
+
+def codenat_tcc_exec(a):
+    global libcntcc
+    oo = libcntcc.tcc_exec_bloc(a)
+    return oo
+
+def rr():
+    pass
+
+class tcc_code():
+    def __init__(self, c):
+        self.c = c
+        self.func = lambda :libcntcc.tcc_exec_bloc(self.c)
+
+def gen_C_module_tcc(f_name, c_source):
+    mcode = codenat_tcc_compil(f_name, c_source)    
+    return tcc_code(mcode)
diff --git a/miasm/tools/emul_helper.py b/miasm/tools/emul_helper.py
new file mode 100755
index 00000000..e91e8c1e
--- /dev/null
+++ b/miasm/tools/emul_helper.py
@@ -0,0 +1,679 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+from miasm.arch.ia32_sem import *
+from miasm.expression.expression_helper import *
+from miasm.core.memory_pool import *
+from miasm.core import asmbloc
+import StringIO
+import zlib
+
+from miasm.expression.expression_eval_abstract import *
+
+log_emu_helper = logging.getLogger("emu.helper")
+console_handler = logging.StreamHandler()
+console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
+log_emu_helper.addHandler(console_handler)
+log_emu_helper.setLevel(logging.WARN)
+
+def hexdump(a, offset = 0):
+    out ="" 
+    for i,c in enumerate(a):
+        if i%0x10==0:
+            out+="\n%.8X "%(offset+i)
+            
+        out+="%.2X "%ord(c)
+    return out
+      
+
+def tohex(a):
+        
+    try:
+        a = int(a)
+    except:
+        return a
+    if a <0:
+        a = struct.pack('l', a)
+    else:
+        a = struct.pack('L', a)
+    a = struct.unpack('L', a)[0]
+    return hex(a)
+    
+
+jcc = ['jz', 'je', 'jnz', 'jp', 'jnp', 'jg', 'jge', 'ja', 'jae', 'jb', 'jbe', 'jl', 'jle', 'js', 'jns', 'jo', 'jno', 'loop', 'loopne']
+
+def dump_pool(p):
+    log_emu_helper.error('/-------------\\')
+    for x in p:
+        log_emu_helper.error(str(x)+' '+tohex(str(p[x])))
+    log_emu_helper.error('\\_____________/')
+
+def dump_reg(p):
+    out = " "*20
+    for x in [eax, ebx, ecx, edx, esi, edi, esp, ebp, zf]:
+        if isinstance(p[x], ExprInt):
+            out+=str(x)+' %.8X  '%int(p[x].arg)
+        else:
+            out+=str(x)+' %s  '%p[x]
+                      
+    return out
+
+
+def dump_mem(p):
+    out = []
+    todo = []
+    kk = p.keys()
+    kk.sort()
+    for x in kk:
+        if isinstance(x, ExprMem):
+            todo.append(x)
+    todo.sort()
+    for x in todo:
+        out.append('%s    %s'%(str(x), str(p[x])))
+                      
+    return "\n".join(out)
+
+def mem_read(evaluator, env, src_address, mem_size):
+    if not isinstance(src_address, ExprInt):
+        dump_pool(evaluator.pool)
+        raise "cannot read", str(src_address)
+    src_address_l = int(src_address.arg)
+    try:
+        
+        if mem_size == 32:
+            ret = uint32(env.get_d(src_address_l))
+        elif mem_size == 16:
+            ret = uint16(env.get_w(src_address_l))
+        elif mem_size == 8:
+            ret = uint8(env.get_b(src_address_l))
+        else:
+            raise 'unknown size read', str(src_address.nbytes)
+        log_emu_helper.debug("=>read @(%X)(%.8X)"%(src_address_l, int(ret)))
+        return ExprInt(ret)
+    except:
+        dump_pool(evaluator.pool)
+        raise ValueError('read bug at 0x%X'%int(src_address_l))
+
+def mem_write(evaluator, env, mem_size, dst_address, src_val, pool_out = None):
+    if not isinstance(dst_address, ExprInt) or not isinstance(src_val, ExprInt):
+        dump_pool(evaluator.pool)
+        raise ValueError("cannot write %s %s"%(str(dst_address), str(src_val)))
+    dst_address_l = int(dst_address.arg)
+    src_val = src_val.arg
+    try:
+        log_emu_helper.debug("=>write @(%X)(%.8X)"%(dst_address_l, int(src_val)))
+        if mem_size == 32:
+            env.set_d(dst_address_l, src_val&0xffffffff)
+        elif mem_size == 16:
+            env.set_w(dst_address_l, src_val&0xffff)
+        elif mem_size == 8:
+            env.set_b(dst_address_l, src_val&0xff)
+        else:
+            raise 'unknown size write', str(dst_address.nbytes)
+    except:
+        dump_pool(evaluator.pool)
+        raise' write bug'
+
+  
+        
+    
+ 
+###XXX for eval int 
+def get_instr_expr_args(name, modifs, mnemo_mode, args, my_eip):
+    for a in args:
+        if type(a) in [int, long]:
+            raise ValueError('int deprec in args')
+
+
+    if name in ['jmp']:
+        if isinstance(args[0], ExprInt):
+            e = mnemo_func[name](ExprOp('+', my_eip, args[0]))
+        else:
+            e = mnemo_func[name](*args)
+    elif name in jcc:
+        e = mnemo_func[name](my_eip, ExprOp('+', my_eip, args[0]))
+    elif name in ['call']:
+        if isinstance(args[0], ExprInt):# or is_imm(args[0]):
+            e = mnemo_func[name](my_eip, ExprOp('+', my_eip, args[0]))
+        else:
+            e = mnemo_func[name](my_eip, args[0])
+    else:
+        e = mnemo_func[name](*args)
+    return e
+
+###XXX for eval int 
+def get_instr_expr(l, my_eip, args = None):
+    if args==None:args = []
+    for x in l.arg:
+        args.append(dict_to_Expr(x, l.m.modifs, l.mnemo_mode))
+    l.arg_expr = args
+    return get_instr_expr_args(l.m.name, l.m.modifs, l.mnemo_mode, args, my_eip)
+
+
+
+###XXX for eval abs
+def get_instr_expr_args(name, modifs, mnemo_mode, args, my_eip):
+    for a in args:
+        if type(a) in [int, long]:
+            raise ValueError('int deprec in args')
+
+
+    if name in ['jmp']:
+        if isinstance(args[0], ExprInt):
+            e = mnemo_func[name](args[0])
+        else:
+            e = mnemo_func[name](*args)
+    elif name in jcc:
+        e = mnemo_func[name](my_eip, args[0])
+    elif name in ['call']:
+        e = mnemo_func[name](my_eip, args[0])
+    else:
+        e = mnemo_func[name](*args)
+    return e
+
+###XXX for eval abs
+def get_instr_expr(l, my_eip, args = None):
+    if args==None:args = []
+    for x in l.arg:
+        args.append(dict_to_Expr(x, l.m.modifs, l.mnemo_mode))
+    l.arg_expr = args
+    return get_instr_expr_args(l.m.name, l.m.modifs, l.mnemo_mode, args, my_eip)
+
+
+
+
+
+def emul_expr(machine, e, my_eip):
+    mem_dst = machine.eval_instr(e)
+
+    if eip in machine.pool:
+        if isinstance(machine.pool[eip], ExprCond):
+            pass
+        my_eip = machine.eval_expr(eip, {})
+        del machine.pool[eip]
+    return my_eip, mem_dst
+
+def emul_bloc(machine, bloc):
+    return emul_lines(machine, bloc.lines)
+
+
+
+def emul_lines(machine, lines):
+    my_eip = None
+    for l in lines:
+        my_eip = ExprInt(uint32(l.offset))
+
+        args = []
+        my_eip.arg+=uint32(l.l)
+        ex = get_instr_expr(l, my_eip, args)
+        my_eip, mem_dst = emul_full_expr(ex, l, my_eip, None, machine)
+
+        for k in machine.pool:
+            machine.pool[k] = expr_simp(machine.pool[k])
+
+    return my_eip
+
+
+
+def emul_imp_init(machine, libbase = 0xCCC00000, malloc_next_ad = 0xEEE00000):
+    #for loadlibrary & getprocaddress emul
+    machine.lib_bases = {}
+    machine.lib_bases_func_index = {}
+    machine.lib_base = libbase    
+    machine.func_loaded = {}
+
+    #for malloc & free emul
+    machine.malloc_next_ad = malloc_next_ad;
+    
+    
+def emul_loadlibrary(machine, env):
+    my_esp = machine.eval_expr(machine.pool[esp], {})
+    libname_ad = env.get_d(my_esp+4)
+    libname = ""
+    l = 0
+    while True:
+        libname+=chr(env.get_b(libname_ad+l))
+        l+=1
+        if libname[-1]=='\x00':
+            break
+
+    machine.lib_bases[machine.lib_base] = libname
+    machine.lib_bases_func_index[machine.lib_base] = machine.lib_base+1
+    machine.eval_instr(mov(eax, ExprInt(uint32(machine.lib_base))))
+
+    machine.lib_base+=0x1000
+    print "emul loadlib %X, %s"%(libname_ad, libname[:-1])
+    log.info("emul loadlib %X, %s"%(libname_ad, libname))
+    machine.eval_instr(ret(ExprInt(uint32(4))))
+    my_eip = machine.eval_expr(machine.pool[eip], {})
+    del machine.pool[eip]
+    return my_eip
+
+def emul_getprocaddress(machine, env):
+    my_esp = machine.eval_expr(machine.pool[esp], {})
+    libbase_ad = env.get_d(my_esp+4)
+    funcname_ad = env.get_d(my_esp+8)
+    funcname = ""
+    l = 0
+    while True:
+        funcname+=chr(env.get_b(funcname_ad+l))
+        l+=1
+        if funcname[-1]=='\x00':
+            break
+
+    log.info("emul getprocaddress %X, %s"%(libbase_ad, funcname))
+    print "emul getprocaddress %X, %s"%(libbase_ad, funcname[:-1])
+
+    if not libbase_ad in machine.lib_bases:
+        log.debug(machine.lib_bases)
+        raise 'unknown base lib! %s'%str(libbase_ad)
+    func_ad = machine.lib_bases_func_index[libbase_ad]
+    
+    machine.lib_bases_func_index[libbase_ad]+=1
+    machine.eval_instr(mov(eax, ExprInt(uint32(func_ad))))
+
+    machine.func_loaded[func_ad] = funcname
+
+    machine.eval_instr(ret(ExprInt(uint32(8))))
+    my_eip = machine.eval_expr(machine.pool[eip], {})
+    del machine.pool[eip]
+    return my_eip
+
+def hook_import_func(env, imported_func, start_address_hook = 0xAABB0000):
+    func_hook_ptr = {}
+    for f in imported_func:
+        env.set_d(f, start_address_hook)
+        func_hook_ptr[start_address_hook] = imported_func[f]
+        start_address_hook+=0x10000
+        
+    return func_hook_ptr
+
+def dump_imp(machine):
+
+     log_emu_helper.warn('_'*10)
+     for l in machine.lib_bases:
+         log_emu_helper.warn("%.8X %s"%(l, machine.lib_bases[l]))
+
+     log_emu_helper.warn('_'*10)
+     for f in machine.func_loaded:
+         log_emu_helper.warn("%.8X %s"%(f, machine.func_loaded[f]))
+
+
+def emul_malloc(machine, env):
+    my_esp = machine.get_reg(esp)
+    pool_type =env.get_d(my_esp+0x4)
+    alloc_size =env.get_d(my_esp+0x8)
+    tag =env.get_d(my_esp+0xc)
+    
+    machine.eval_instr(ret(ExprInt(uint32(0xc))))
+    my_eip = machine.eval_expr(machine.pool[eip], {})
+    del machine.pool[eip]
+    
+    ret_alloc_ad = machine.malloc_next_ad
+    m_data = mempool(machine.malloc_next_ad, machine.malloc_next_ad+alloc_size, 'RW', name = "malloc %.8X"%alloc_size)
+    machine.malloc_next_ad += ((alloc_size+0xFFF)&(~0xFFF))
+    
+    log.warn('alloc(%X) tag %X poolt %X from %X esp %X ret %X:'%(int(alloc_size), int(tag), int(pool_type), int(my_eip), int(my_esp), int(machine.malloc_next_ad)))
+    machine.eval_instr(mov(eax, ExprInt(uint32(ret_alloc_ad))))
+    
+    env.mems.append(m_data)
+    log.warn(str(env))
+    return my_eip
+
+def emul_free(machine, env):
+    my_esp = machine.get_reg(esp)
+    address_free =env.get_d(my_esp+4)
+
+    machine.eval_instr(ret(ExprInt(uint32(4))))
+    my_eip = machine.eval_expr(machine.pool[eip], {})
+    del machine.pool[eip]
+
+    log.warn('free(%X) from %X esp %X:'%(int(address_free), int(my_eip), int(my_esp)))
+
+    if address_free !=0:
+        m = env.get_mem_pool(address_free)
+        if not m:
+            raise 'cannot find freeing mem!'
+        env.mems.remove(m)
+    log.warn(str(env))
+    return my_eip
+
+
+def emul_pitfall(machine, env):
+    raise 'func not impl!'
+
+
+def emul_heapcreate(machine, env):
+    my_esp = machine.get_reg(esp)
+    floptions =env.get_d(my_esp+4)
+    dwinitialsize =env.get_d(my_esp+8)
+    dwmaximumsize =env.get_d(my_esp+12)
+    
+    machine.eval_instr(ret(ExprInt(uint32(12))))
+    my_eip = machine.eval_expr(machine.pool[eip], {})
+    del machine.pool[eip]
+    
+    
+    log.warn('heapcreate(%X %X %X) from %X esp %X ret %X:'%(floptions, dwinitialsize, dwmaximumsize, int(my_eip), my_esp, 0xdeadcafe))
+    machine.eval_instr(mov(eax, ExprInt(uint32(0xdeadcafe))))
+    
+    return my_eip
+    
+def emul_heapalloc(machine, env):
+    my_esp = machine.get_reg(esp)
+    hheap =env.get_d(my_esp+4)
+    dwflags =env.get_d(my_esp+8)
+    alloc_size =env.get_d(my_esp+12) 
+   
+    machine.eval_instr(ret(ExprInt(uint32(12))))
+    my_eip = machine.eval_expr(machine.pool[eip], {})
+    del machine.pool[eip]
+    
+    ret_alloc_ad = machine.malloc_next_ad
+    m_data = mempool(machine.malloc_next_ad, machine.malloc_next_ad+alloc_size, 'RW', name = "heapalloc %.8X"%alloc_size)
+    machine.malloc_next_ad += ((alloc_size+0xFFF)&(~0xFFF))
+    
+    log.warn('heapalloc(%X %X %X) from %X esp %X ret %X:'%(hheap, dwflags, alloc_size, int(my_eip), my_esp, machine.malloc_next_ad))
+    machine.eval_instr(mov(eax, ExprInt(uint32(ret_alloc_ad))))
+    
+    env.mems.append(m_data)
+    log.warn(str(env))
+    return my_eip
+
+#VirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect)
+def emul_virtualprotect(machine, env):
+    my_esp = machine.eval_expr(machine.pool[esp], {})
+    lpaddress = env.get_d(my_esp+4)
+    dwsize = env.get_d(my_esp+8)
+    flnewprotect = env.get_d(my_esp+12)
+    lpfloldprotect = env.get_d(my_esp+16)
+
+    #XXX return 1??
+    machine.eval_instr(mov(eax, ExprInt(uint32(1))))
+
+    log.info("emul virtualprotect %X, %X %X %X"%(lpaddress, dwsize, flnewprotect, lpfloldprotect))
+    machine.eval_instr(ret(ExprInt(uint32(16))))
+    #dump_pool(machine.pool)
+    my_eip = machine.eval_expr(machine.pool[eip], {})
+    del machine.pool[eip]
+    return my_eip
+
+def emul_virtualalloc(machine, env):
+    my_esp = machine.get_reg(esp)
+    lpaddress =env.get_d(my_esp+4)
+    alloc_size =env.get_d(my_esp+8)
+    flallocationtype =env.get_d(my_esp+12) 
+    flprotect =env.get_d(my_esp+16) 
+   
+    machine.eval_instr(ret(ExprInt(uint32(16))))
+    my_eip = machine.eval_expr(machine.pool[eip], {})
+    del machine.pool[eip]
+    
+    ret_alloc_ad = machine.malloc_next_ad
+    m_data = mempool(machine.malloc_next_ad, machine.malloc_next_ad+alloc_size, 'RW', name = "virtualalloc %.8X"%alloc_size)
+    machine.malloc_next_ad += ((alloc_size+0xFFF)&(~0xFFF))
+    
+    log.warn('virtualalloc(%X %X %X %X) from %X esp %X ret %X:'%(lpaddress, alloc_size, flallocationtype, flprotect, int(my_eip), my_esp, machine.malloc_next_ad))
+    machine.eval_instr(mov(eax, ExprInt(uint32(ret_alloc_ad))))
+    
+    env.mems.append(m_data)
+    log.warn(str(env))
+    return my_eip
+
+
+def emul_virtualfree(machine, env):
+    my_esp = machine.get_reg(esp)
+    address_free =env.get_d(my_esp+4)
+    dwsize =env.get_d(my_esp+8)
+    dwfreetype =env.get_d(my_esp+12)
+    
+    
+
+    machine.eval_instr(ret(ExprInt(uint32(12))))
+    my_eip = machine.eval_expr(machine.pool[eip], {})
+    del machine.pool[eip]
+
+    log.warn('virtualfree(%X %X %X) from %X esp %X:'%(address_free, dwsize, swfreetype, int(my_eip), my_esp))
+
+    if address_free !=0:
+        m = env.get_mem_pool(address_free)
+        if not m:
+            raise 'cannot find freeing mem!'
+        env.mems.remove(m)
+    log.warn(str(env))
+    return my_eip
+
+
+
+def emul_getmodulehandlea(machine, env):
+    my_esp = machine.eval_expr(machine.pool[esp], {})
+    libname_ad = env.get_d(my_esp+4)
+    libname = ""
+    l = 0
+    while True:
+        libname+=chr(env.get_b(libname_ad+l))
+        l+=1
+        if libname[-1]=='\x00':
+            break
+
+
+    machine.eval_instr(ret(ExprInt(uint32(4))))
+    my_eip = machine.eval_expr(machine.pool[eip], {})
+    del machine.pool[eip]
+
+
+    log.info("emul loadlib (%X), %s from %X"%(libname_ad, libname, my_eip))
+
+    if False:#libname.startswith("kernel32.dll"):
+        machine.eval_instr(mov(eax, ExprInt(uint32(0x7C800000))))
+    else:
+        machine.eval_instr(mov(eax, ExprInt(uint32(0x0))))
+        log.warn("unknown lib: %s"%str(libname))
+        
+    log.warn(str(env))
+
+    return my_eip
+
+def emul_kddisabledebugger(machine, env):
+    my_esp = machine.get_reg(esp)
+    
+    machine.eval_instr(ret())
+    my_eip = machine.eval_expr(machine.pool[eip], {})
+    del machine.pool[eip]
+    
+    
+    log.warn('emul_kddisabledebugger from %X esp %X '%(int(my_eip), int(my_esp)))
+    machine.eval_instr(mov(eax, ExprInt(uint32(0))))
+    
+    log.warn(str(env))
+    return my_eip
+    
+    
+    
+def sav_machine(machine, env, my_eip, snap_fmt_name):
+
+    print 'SAVE**************tsc: %.10d***************'%machine.pool[tsc1].arg
+    machine.pool[eip] = my_eip
+    env_s = StringIO.StringIO()
+    env.to_file(env_s)
+    env_s.flush()
+    fname = snap_fmt_name+".env" 
+    open(fname%(machine.pool[tsc1].arg), 'wb').write(zlib.compress(env_s.getvalue(), 9))
+    machine_s = StringIO.StringIO()
+    machine.to_file(machine_s)
+    machine_s.flush()
+    fname = snap_fmt_name+".machine"
+    open(fname%(machine.pool[tsc1].arg), 'wb').write(zlib.compress(machine_s.getvalue(), 9))
+    del machine.pool[eip]
+    
+    
+def load_machine(snap_fmt_name, step):
+
+    fname = snap_fmt_name+".env" 
+    env_s = StringIO.StringIO(zlib.decompress(open(fname%step, 'rb').read()))
+    env = mempool_manager.from_file(env_s)
+    fname = snap_fmt_name+".machine"        
+    machine_s = StringIO.StringIO(zlib.decompress(open(fname%step, 'rb').read()))
+    machine = eval_int.from_file(machine_s, globals())
+    my_eip = machine.pool[eip]
+    del machine.pool[eip]
+    print 'LOAD**************tsc: %.10X***************'%machine.pool[tsc1].arg
+    print "machine eip: %.8X"%int(my_eip.arg)
+    
+    return machine, env, my_eip
+     
+def emul_full_expr(e, l, my_eip, env, machine):
+    if ((not 0xF2 in l.prefix) and (not 0xF3 in l.prefix)) or \
+           not l.m.name[:-1] in ["ins", "outs", "movs", "lods", "stos", "cmps", "scas"]:
+        my_eip, mem_dst = emul_expr(machine, e, my_eip)
+    else:
+        #rep mnemo
+        #XXX HACK 16 bit
+        if 0x66 in l.prefix and l.m.name[-1]== "d":
+            raise "not impl 16 bit string"
+        zf_w = zf in reduce(lambda x,y:x+y, [list(x.get_w()) for x in e], [])
+        
+        while True:
+
+            my_ecx = machine.eval_expr(machine.pool[ecx], {})
+            if not isinstance(my_ecx, ExprInt):# in tab_int_size:#[int, long]:
+                raise "cannot eval counter....", str(machine.pool[ecx])
+            if l.mnemo_mode== u16:
+                my_ecx.arg&=0xFFFF
+            if my_ecx.arg ==0:
+                break
+
+            my_esi = machine.eval_expr(machine.pool[esi], {})
+            my_edi = machine.eval_expr(machine.pool[edi], {})
+            tmp,mem_dst =  emul_expr(machine, e, my_eip)
+            
+            machine.eval_instr(mov(ecx, ExprOp('-', my_ecx, ExprInt(uint32(1)))))
+            machine.eval_expr(machine.pool[ecx], {})
+
+            if zf_w :
+                my_zf = machine.eval_expr(machine.pool[zf], {})
+                if 0xF3 in l.prefix and my_zf == 0:
+                    break
+                if 0xF2 in l.prefix and my_zf == 1:
+                    break
+
+            machine.pool[tsc1].arg+=uint32(1)
+
+    return my_eip, mem_dst
+    
+
+def guess_func_destack(all_bloc):
+    ret_destack = None
+    for b in all_bloc:
+        l = b.lines[-1]
+        if not l.m.name.startswith('ret'):
+            continue
+        if len(l.arg) == 0:
+            a = 0  
+        elif len(l.arg) ==1:
+            a = l.arg[0][x86_afs.imm]
+        else:
+            continue
+        if ret_destack!=None:
+            if a != ret_destack:
+                print 'found diff ret unstack', ret_destack, a
+                return None, None
+            else:
+                continue
+        ret_destack = a
+
+
+    if ret_destack !=None:
+        return True, ret_destack
+
+    #try func wrapper
+    if len(all_bloc)!= 1:
+        return None, None
+    l = all_bloc[0].lines[-1]
+    if not l.m.name.startswith('jmp') or len(l.arg) !=1:
+        return None, None
+
+    a = l.arg[0]
+    print hex(l.offset), a, type(a)
+
+    if not x86_afs.imm in a or not x86_afs.ad in a or not a[x86_afs.ad]:
+        return None, None
+
+    return False, a[x86_afs.imm]
+
+
+def digest_allbloc_instr(all_bloc):
+    instrs = {}
+    g = asmbloc.bloc2graph(all_bloc)
+    open("graph_b.txt" , "w").write(g)
+
+
+    #test duplicated blocs
+    unik_blobs = {}
+    for b in all_bloc:
+        if not b.label in unik_blobs:
+            unik_blobs[b.label] = []
+        unik_blobs[b.label].append(b)
+
+
+    for lbl, blcs in unik_blobs.items():
+        if len(blcs) ==1:
+            continue
+        tmp = blcs.pop()
+        for b in blcs:
+            if str(tmp) != str(b):
+                print tmp
+                print b
+                raise ValueError('diff bloc in same label')
+            all_bloc.remove(b)
+        
+    for b in all_bloc:
+        for l in b.lines:
+            if l.offset in instrs:
+                log.warn(('zarb: dup instr', (hex(l.offset), str(l))))
+                if str(instrs[l.offset][0]) != str(l):
+                    raise ValueError('dup instr@ with different instr', (str(l), str(instrs[l.offset][0])))
+            args = []
+            ex = get_instr_expr(l, ExprInt(uint32(l.offset+l.l)), args)
+
+                
+            instrs[l.offset] = (l, ex)
+    return instrs
+
+
+def x86_machine():
+    machine = eval_abs({esp:init_esp, ebp:init_ebp, eax:init_eax, ebx:init_ebx, ecx:init_ecx, edx:init_edx, esi:init_esi, edi:init_edi,
+                        cs:ExprInt(uint32(9)),
+                        zf :  init_zf,  nf :  init_nf, pf : init_pf,
+                        of :  init_of, cf :  init_cf, tf : init_tf,
+                        i_f:  init_i_f, df :  init_df, af : init_af,
+                        iopl: init_iopl, nt :  init_nt, rf : init_rf,
+                        vm :  init_vm, ac :  init_ac, vif: init_vif,
+                        vip:  init_vip, i_d:  init_i_d,tsc1: init_tsc1,
+                        tsc2: init_tsc2,
+                        dr7:ExprInt(uint32(0)),
+                        cr0:init_cr0,
+                        #my_ret_addr:my_ret_addri
+                        
+                        },
+                       #mem_read_wrap,
+                       #mem_write_wrap,
+                       
+                       )
+    return machine
diff --git a/miasm/tools/emul_lib/Makefile b/miasm/tools/emul_lib/Makefile
new file mode 100644
index 00000000..5365160b
--- /dev/null
+++ b/miasm/tools/emul_lib/Makefile
@@ -0,0 +1,20 @@
+CFLAGS=-Wall  -I/usr/include/python2.6 -lpython2.6
+CC = gcc
+all: libcodenat.so libcodenat_tcc.so libcodenat_interface.so
+
+libcodenat_interface.so: libcodenat_interface.c
+	$(CC) $(CFLAGS) -shared -o $@ $<  -lm -lcodenat -L`pwd` -Wl,-rpath,`pwd`
+
+libcodenat.so: libcodenat.c
+	$(CC) $(CFLAGS) -shared -o $@ $<  -lm 
+
+libcodenat_tcc.so: libcodenat_tcc.c 
+	$(CC) $(CFLAGS) -shared -o $@ $<  -ldl  /usr/lib/i386-linux-gnu/libtcc.a
+
+
+
+test: main.o libcodenat.a
+	$(CC) $< $(CFLAGS)  -L. -L/usr/lib -lcodenat -lpython2.6
+
+clean:
+	rm -f libcodenat.so libcodenat_interface.so libcodenat_interface.o libcodenat.o a.out libcodenat_tcc.o libcodenat_tcc.so
diff --git a/miasm/tools/emul_lib/__init__.py b/miasm/tools/emul_lib/__init__.py
new file mode 100644
index 00000000..fbabaacf
--- /dev/null
+++ b/miasm/tools/emul_lib/__init__.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
diff --git a/miasm/tools/emul_lib/libcodenat.c b/miasm/tools/emul_lib/libcodenat.c
new file mode 100644
index 00000000..c670224d
--- /dev/null
+++ b/miasm/tools/emul_lib/libcodenat.c
@@ -0,0 +1,1305 @@
+/*
+** Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License along
+** with this program; if not, write to the Free Software Foundation, Inc.,
+** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+//#include <Python.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#include <stdint.h>
+
+#include "queue.h"
+#include "libcodenat.h"
+
+
+
+
+
+struct memory_page_list_head memory_page_pool;
+struct code_bloc_list_head code_bloc_pool;
+
+//#define RAISE(errtype,msg) { PyErr_SetString(errtype,msg); RE_RAISE; }
+//#define RE_RAISE           { Py_XDECREF(string); return NULL; }
+//#define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;}
+
+/*
+unsigned int eax, ebx, ecx, edx, esi, edi, esp, ebp, eip;
+unsigned int zf, nf, pf, of, cf, af, df;
+
+unsigned int eax_new, ebx_new, ecx_new, edx_new, esi_new, edi_new, esp_new, ebp_new, eip_new;
+unsigned int zf_new, nf_new, pf_new, of_new, cf_new, af_new, df_new;
+unsigned int tf, i_f, iopl_f, nt, rf, vm, ac, vif, vip, i_d;
+unsigned int tf_new, i_f_new, iopl_f_new, nt_new, rf_new, vm_new, ac_new, vif_new, vip_new, i_d_new;
+
+unsigned int my_tick = 0;
+
+unsigned int reg_float_control;
+
+unsigned int cond;
+
+
+unsigned int ds;
+
+
+unsigned int vm_exception_flags = 0;
+unsigned int vm_exception_flags_new = 0;
+
+
+unsigned int vm_last_write_ad = 0;
+unsigned int vm_last_write_size = 0;
+*/
+
+vm_cpu_t vmcpu;
+
+/****************memory manager**************/
+
+unsigned int min_page_ad = 0x22000000;
+
+extern unsigned int *code_addr_tab;
+
+//LIST_HEAD(memory_page_list_head, memory_page_node) memory_page_pool;
+//LIST_HEAD(code_bloc_list_head, code_bloc_node) code_bloc_pool;
+
+
+unsigned int code_bloc_pool_ad_min;
+unsigned int code_bloc_pool_ad_max;
+
+#define MAX_MEMORY_PAGE_POOL_TAB 0x100000
+#define MEMORY_PAGE_POOL_MASK_BIT 12
+#define PAGE_SIZE (1<<MEMORY_PAGE_POOL_MASK_BIT)
+struct memory_page_node *memory_page_pool_tab[MAX_MEMORY_PAGE_POOL_TAB];
+
+
+#define MIN(a,b)  (((a)<(b))?(a):(b))
+#define MAX(a,b)  (((a)>(b))?(a):(b))
+
+
+
+
+
+
+
+
+
+
+
+
+void dump_gpregs(void)
+{
+	printf("eip %.8X eax %.8X ebx %.8X ecx %.8X edx %.8X\nesi %.8X edi %.8X esp %.8X ebp %.8X\nmy_tick %X\n", 
+	       vmcpu.eip, vmcpu.eax, vmcpu.ebx, vmcpu.ecx, vmcpu.edx, vmcpu.esi, vmcpu.edi, vmcpu.esp, vmcpu.ebp,
+	       vmcpu.my_tick);
+}
+
+struct memory_page_node * get_memory_page_from_address(unsigned int ad)
+{
+	struct memory_page_node * mpn;
+#if 1
+	mpn = memory_page_pool_tab[ad>>MEMORY_PAGE_POOL_MASK_BIT];
+	if ( mpn && (mpn->ad <= ad) && (ad < mpn->ad + mpn->size))
+		return mpn;
+
+	printf("cannot find address!! %X\n", ad);
+	dump_memory_page_pool();	
+	dump_gpregs();
+	//exit(-1);
+	vmcpu.vm_exception_flags |= EXCEPT_ACCESS_VIOL;
+
+	return NULL;
+#else
+
+	//printf("search for page ad: %X\n", ad);
+	LIST_FOREACH(mpn, &memory_page_pool, next){
+		if ((mpn->ad <= ad) && (ad < mpn->ad + mpn->size))
+			return mpn;
+	}
+	printf("cannot find address!! %X\n", ad);
+	dump_memory_page_pool();	
+	dump_gpregs();
+	//exit(-1);
+	vmcpu.vm_exception_flags |= EXCEPT_ACCESS_VIOL;
+	return NULL;
+#endif
+}
+
+
+
+
+static inline unsigned long long memory_page_read(unsigned int my_size, unsigned int ad)
+{
+	struct memory_page_node * mpn;
+	unsigned char * addr;
+	unsigned long long ret = 0;
+
+
+	mpn = get_memory_page_from_address(ad);
+	if (!mpn)
+		return 0;
+
+	if ((mpn->access & PAGE_READ) == 0){
+		printf("access to non readable page!! %X\n", ad);
+		vmcpu.vm_exception_flags |= EXCEPT_ACCESS_VIOL;
+		return 0;
+	}
+	addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad];
+
+	/* read fits in a page */
+	if (ad - mpn->ad + my_size/8 <= mpn->size){
+		switch(my_size){
+		case 8:
+			ret = *((unsigned char*)addr)&0xFF;
+			break;
+		case 16:
+			ret = *((unsigned short*)addr)&0xFFFF;
+			ret = Endian16_Swap(ret);
+			break;
+		case 32:
+			ret = *((unsigned int*)addr)&0xFFFFFFFF;
+			ret = Endian32_Swap(ret);
+			break;
+		case 64:
+			ret = *((unsigned long long*)addr)&0xFFFFFFFFFFFFFFFFULL;
+			ret = Endian64_Swap(ret);
+			break;
+		default:
+			exit(0);
+			break;
+			
+		}
+	}
+	/* read is multiple page wide */
+	else{
+		unsigned int new_size = my_size;
+		printf("read multiple page! %X %X\n", ad, new_size);
+		dump_memory_page_pool();	
+		while (new_size){
+			ret <<=8;
+			mpn = get_memory_page_from_address(ad);
+			if (!mpn)
+				return 0;
+			addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad];
+			ret = *((unsigned char*)addr)&0xFF;
+			new_size -= 8;
+			ad ++;
+		}
+		switch(my_size){
+		case 8:
+			ret = ret;
+			break;
+		case 16:
+			ret = Endian16_Swap(ret);
+			break;
+		case 32:
+			ret = Endian32_Swap(ret);
+			break;
+		case 64:
+			ret = Endian64_Swap(ret);
+			break;
+		default:
+			exit(0);
+			break;
+		}
+	}
+	return ret;
+}
+
+static inline void memory_page_write(unsigned int my_size, unsigned int ad, unsigned long long src)
+{
+	struct memory_page_node * mpn;
+	unsigned char * addr;
+
+	mpn = get_memory_page_from_address(ad);
+	if (!mpn)
+		return;
+
+	if ((mpn->access & PAGE_WRITE) == 0){
+		printf("access to non writable page!! %X\n", ad);
+		vmcpu.vm_exception_flags |= EXCEPT_ACCESS_VIOL;
+	
+		return ;
+	}
+
+	addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad];
+
+	/* write fits in a page */
+	if (ad - mpn->ad + my_size/8 <= mpn->size){
+		switch(my_size){
+		case 8:
+			*((unsigned char*)addr) = src&0xFF;
+			break;
+		case 16:
+			src = Endian16_Swap(src);
+			*((unsigned short*)addr) = src&0xFFFF;
+			break;
+		case 32:
+			src = Endian32_Swap(src);
+			*((unsigned int*)addr) = src&0xFFFFFFFF;
+			break;
+		case 64:
+			src = Endian64_Swap(src);
+			*((unsigned long long*)addr) = src&0xFFFFFFFFFFFFFFFFULL;
+			break;
+		default:
+			exit(0);
+			break;
+		}
+	}
+	/* write is multiple page wide */
+	else{
+		printf("write multiple page! %X %X\n", ad, my_size);
+		dump_memory_page_pool();	
+		switch(my_size){
+
+		case 8:
+			src = src;
+			break;
+		case 16:
+			src = Endian16_Swap(src);
+			break;
+		case 32:
+			src = Endian32_Swap(src);
+			break;
+		case 64:
+			src = Endian64_Swap(src);
+			break;
+		default:
+			exit(0);
+			break;
+		}
+		
+		while (my_size){
+			mpn = get_memory_page_from_address(ad);
+			if (!mpn)
+				return;
+
+			addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad];
+			*((unsigned char*)addr) = src&0xFF;
+			my_size -= 8;
+			ad ++;
+		}
+		
+	}
+}
+
+
+
+inline void check_write_code_bloc(unsigned int my_size, unsigned int addr)
+{
+	struct code_bloc_node * cbp;
+	
+	vmcpu.vm_last_write_ad = addr;
+	vmcpu.vm_last_write_size = my_size;
+
+	//if(vmcpu.my_tick> my_tick)
+	//	printf("M_WRITE %2d %.8X %.8X\n", my_size, addr, src);
+	if (!(addr + my_size/8 <= code_bloc_pool_ad_min || addr >=code_bloc_pool_ad_max)){
+		LIST_FOREACH(cbp, &code_bloc_pool, next){
+			if ((cbp->ad_start <= addr + my_size/8) && (addr < cbp->ad_stop)){
+				printf("self modifying code %.8X %.8X from approx %X\n", addr, my_size, vmcpu.eip);
+				vmcpu.vm_exception_flags |= EXCEPT_CODE_AUTOMOD;
+				break;
+			}
+		}
+	}
+
+}
+
+void MEM_WRITE(unsigned int my_size, unsigned int addr , unsigned int src)
+{
+	struct code_bloc_node * cbp;
+
+	vmcpu.vm_last_write_ad = addr;
+	vmcpu.vm_last_write_size = my_size;
+
+	//if(vmcpu.my_tick> my_tick)
+	//	printf("M_WRITE %2d %.8X %.8X\n", my_size, addr, src);
+	if (!(addr + my_size/8 <= code_bloc_pool_ad_min || addr >=code_bloc_pool_ad_max)){
+		LIST_FOREACH(cbp, &code_bloc_pool, next){
+			if ((cbp->ad_start <= addr + my_size/8) && (addr < cbp->ad_stop)){
+				printf("self modifying code %.8X %.8X from approx %X\n", addr, my_size, vmcpu.eip);
+				vmcpu.vm_exception_flags |= EXCEPT_CODE_AUTOMOD;
+				break;
+			}
+		}
+	}
+
+	memory_page_write(my_size, addr, src);
+}
+
+void MEM_WRITE_08(unsigned int addr , unsigned char src)
+{
+	check_write_code_bloc(8, addr);	
+	memory_page_write(8, addr, src);
+}
+
+void MEM_WRITE_16(unsigned int addr , unsigned short src)
+{
+	check_write_code_bloc(16, addr);	
+	memory_page_write(16, addr, src);
+}
+
+void MEM_WRITE_32(unsigned int addr , unsigned int src)
+{
+	check_write_code_bloc(32, addr);	
+	memory_page_write(32, addr, src);
+}
+
+void MEM_WRITE_64(unsigned int addr , unsigned long long src)
+{
+	check_write_code_bloc(64, addr);	
+	memory_page_write(64, addr, src);
+}
+
+
+unsigned int MEM_LOOKUP(unsigned int my_size, unsigned int addr)
+{
+    unsigned int ret;
+    ret = memory_page_read(my_size, addr);
+    //if(vmcpu.my_tick> my_tick)
+    //printf("M_READ  %2d %.8X %.8X\n", my_size, addr, ret);
+    return ret;
+}
+
+unsigned char MEM_LOOKUP_08(unsigned int addr)
+{
+    unsigned char ret;
+    ret = memory_page_read(8, addr);
+    return ret;
+}
+
+unsigned short MEM_LOOKUP_16(unsigned int addr)
+{
+    unsigned short ret;
+    ret = memory_page_read(16, addr);
+    return ret;
+}
+
+unsigned int MEM_LOOKUP_32(unsigned int addr)
+{
+    unsigned int ret;
+    ret = memory_page_read(32, addr);
+    return ret;
+}
+
+unsigned long long MEM_LOOKUP_64(unsigned int addr)
+{
+    unsigned long long ret;
+    ret = memory_page_read(64, addr);
+    return ret;
+}
+
+
+
+
+void MEM_WRITE_08_PASSTHROUGH(unsigned int addr, unsigned char src)
+{
+	*((unsigned char*)addr) = src;
+}
+
+void MEM_WRITE_16_PASSTHROUGH(unsigned int addr, unsigned short src)
+{
+	*((unsigned short*)addr) = Endian16_Swap(src);
+}
+
+void MEM_WRITE_32_PASSTHROUGH(unsigned int addr, unsigned int src)
+{
+	*((unsigned int*)addr) = Endian32_Swap(src);
+}
+
+void MEM_WRITE_64_PASSTHROUGH(unsigned int addr, unsigned long long src)
+{
+	*((unsigned long long*)addr) = Endian64_Swap(src);
+}
+
+
+unsigned char MEM_LOOKUP_08_PASSTHROUGH(unsigned int addr)
+{
+	unsigned char ret;
+	ret = *((unsigned char*)addr);
+	return ret;
+}
+
+unsigned short MEM_LOOKUP_16_PASSTHROUGH(unsigned int addr)
+{
+	unsigned short ret;
+	ret = *((unsigned short*)addr);
+	return Endian16_Swap(ret);
+}
+
+unsigned int MEM_LOOKUP_32_PASSTHROUGH(unsigned int addr)
+{
+	unsigned int ret;
+	ret = *((unsigned int*)addr);
+	return Endian32_Swap(ret);
+}
+
+unsigned long long MEM_LOOKUP_64_PASSTHROUGH(unsigned int addr)
+{
+	unsigned long long ret;
+	ret = *((unsigned long long*)addr);
+	return Endian64_Swap(ret);
+}
+
+
+
+void vm_throw(unsigned long flags)
+{
+	vmcpu.vm_exception_flags |= flags;
+}
+
+inline unsigned int parity(unsigned int a)
+{
+    unsigned int tmp, cpt;
+
+    tmp = a&0xFF;
+    cpt = 1;
+    while (tmp!=0){
+        cpt^=tmp&1;
+        tmp>>=1;
+        }
+    return cpt;
+}
+
+
+int shift_right_arith(unsigned int size, int a, unsigned int b)
+{
+    int i32_a;
+    short i16_a;
+    char i8_a;
+    switch(size){
+        case 8:
+            i8_a = a;
+            return (i8_a >> b)&0xff;
+        case 16:
+            i16_a = a;
+            return (i16_a >> b)&0xffff;
+        case 32:
+            i32_a = a;
+            return (i32_a >> b)&0xffffffff;
+        default:
+            printf("inv size in shift %d\n", size);
+            exit(0);
+    }
+}
+/*
+int shift_right_arith_08(int a, unsigned int b)
+{
+	char i8_a;
+	i8_a = a;
+	return (i8_a >> b)&0xff;
+}
+
+int shift_right_arith_16(int a, unsigned int b)
+{
+	short i16_a;
+	i16_a = a;
+	return (i16_a >> b)&0xffff;
+}
+
+int shift_right_arith_32(int a, unsigned int b)
+{
+	int i32_a;
+	i32_a = a;
+	return (i32_a >> b)&0xffffffff;
+}
+*/
+unsigned int shift_right_logic(unsigned int size, unsigned int a, unsigned int b)
+{
+    unsigned int u32_a;
+    unsigned short u16_a;
+    unsigned char u8_a;
+    switch(size){
+        case 8:
+            u8_a = a;
+            return (u8_a >> b)&0xff;
+        case 16:
+            u16_a = a;
+            return (u16_a >> b)&0xffff;
+        case 32:
+            u32_a = a;
+            return (u32_a >> b)&0xffffffff;
+        default:
+            printf("inv size in shift %d\n", size);
+            exit(0);
+    }
+}
+/*
+int shift_right_logic_08(unsigned int a, unsigned int b)
+{
+	unsigned char u8_a;
+	u8_a = a;
+	return (u8_a >> b)&0xff;
+}
+
+int shift_right_logic_16(unsigned int a, unsigned int b)
+{
+	unsigned short u16_a;
+	u16_a = a;
+	return (u16_a >> b)&0xffff;
+}
+
+int shift_right_logic_32(unsigned int a, unsigned int b)
+{
+	unsigned int u32_a;
+	u32_a = a;
+	return (u32_a >> b)&0xffffffff;
+}
+*/
+int shift_left_logic(unsigned int size, unsigned int a, unsigned int b)
+{
+    switch(size){
+        case 8:
+            return (a<<b)&0xff;
+        case 16:
+            return (a<<b)&0xffff;
+        case 32:
+            return (a<<b)&0xffffffff;
+        default:
+            printf("inv size in shift %d\n", size);
+            exit(0);
+    }
+}
+/*
+int shift_left_logic_O8(unsigned int a, unsigned int b)
+{
+	return (a<<b)&0xff;
+}
+
+int shift_left_logic_16(unsigned int a, unsigned int b)
+{
+	return (a<<b)&0xffff;
+}
+
+int shift_left_logic_32(unsigned int a, unsigned int b)
+{
+	return (a<<b)&0xffffffff;
+}
+*/
+
+unsigned int mul_lo_op(unsigned int size, unsigned int a, unsigned int b)
+{
+	unsigned int mask;
+
+	switch (size) {
+		case 8: mask = 0xff; break;
+		case 16: mask = 0xffff; break;
+		case 32: mask = 0xffffffff; break;
+		default: printf("inv size in mul %d\n", size); exit(0);
+	}
+
+	a &= mask;
+	b &= mask;
+	return ((long long)a * (long long) b) & mask;
+}
+
+unsigned int mul_hi_op(unsigned int size, unsigned int a, unsigned int b)
+{
+	unsigned long long res = 0;
+	unsigned int mask;
+
+	switch (size) {
+		case 8: mask = 0xff; break;
+		case 16: mask = 0xffff; break;
+		case 32: mask = 0xffffffff; break;
+		default: printf("inv size in mul %d\n", size); exit(0);
+	}
+
+	a &= mask;
+	b &= mask;
+	res = ((unsigned long long)a * (unsigned long long)b);
+	return (res >> 32) & mask;
+}
+
+
+unsigned int imul_lo_op_08(char a, char b)
+{
+	return a*b;
+}
+
+unsigned int imul_lo_op_16(short a, short b)
+{
+	return a*b;
+}
+
+unsigned int imul_lo_op_32(int a, int b)
+{
+	return a*b;
+}
+
+int imul_hi_op_08(char a, char b)
+{
+	long long res = 0;
+	res = a*b;
+	return res>>8;
+}
+
+int imul_hi_op_16(short a, short b)
+{
+	long long res = 0;
+	res = a*b;
+	return res>>16;
+}
+
+int imul_hi_op_32(int a, int b)
+{
+	long long res = 0;
+	res = a*b;
+	return res>>32;
+}
+
+
+
+unsigned int div_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c)
+{
+    long long int num;
+    if (c == 0)
+    {
+	    vmcpu.vm_exception_flags |= EXCEPT_INT_DIV_BY_ZERO;
+	    return 0;
+    }
+    num = ((long long)a << size) + b;
+    num/=(long long)c;
+    return num;
+}
+
+unsigned int rem_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c)
+{
+    long long int num;
+
+    if (c == 0)
+    {
+	    vmcpu.vm_exception_flags |= EXCEPT_INT_DIV_BY_ZERO;
+	    return 0;
+    }
+
+    num = ((long long )a << size) + b;
+    num = (long long)num-c*(num/c);
+    return num;
+}
+
+
+int rot_left(unsigned int size, unsigned int a, unsigned int b)
+{
+    unsigned int tmp;
+
+    b = b&0x1F;
+    b %= size;
+    switch(size){
+        case 8:
+            tmp = (a << b) | ((a&0xFF) >> (size-b));
+            return tmp&0xff;
+        case 16:
+            tmp = (a << b) | ((a&0xFFFF) >> (size-b));
+            return tmp&0xffff;
+        case 32:
+            tmp = (a << b) | ((a&0xFFFFFFFF) >> (size-b));
+            return tmp&0xffffffff;
+        default:
+            printf("inv size in rotleft %d\n", size);
+            exit(0);
+    }
+}
+
+int rot_right(unsigned int size, unsigned int a, unsigned int b)
+{
+    unsigned int tmp;
+
+    b = b&0x1F;
+    b %= size;
+    switch(size){
+        case 8:
+            tmp = ((a&0xFF) >> b) | (a << (size-b));
+            return tmp&0xff;
+        case 16:
+            tmp = ((a&0xFFFF) >> b) | (a << (size-b));
+            return tmp&0xffff;
+        case 32:
+            tmp = ((a&0xFFFFFFFF) >> b) | (a << (size-b));
+            return tmp&0xffffffff;
+        default:
+            printf("inv size in rotleft %d\n", size);
+            exit(0);
+    }
+}
+
+
+int rcl_rez_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf)
+{
+    unsigned long long tmp;
+
+    tmp = (cf << size) | a;
+
+    size++;
+    b = b&0x1F;
+    b %= size;
+
+    switch(size){
+        case 8+1:
+            tmp = (tmp << b) | ((tmp&0x1FF) >> (size-b));
+            return tmp&0xff;
+        case 16+1:
+            tmp = (tmp << b) | ((tmp&0x1FFFF) >> (size-b));
+            return tmp&0xffff;
+        case 32+1:
+            tmp = (tmp << b) | ((tmp&0x1FFFFFFFFULL) >> (size-b));
+            return tmp&0xffffffff;
+        default:
+            printf("inv size in rclleft %d\n", size);
+            exit(0);
+    }
+}
+
+int rcr_rez_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf)
+{
+	return rcl_rez_op(size, a, size+1-b, cf);
+
+}
+
+
+int rcl_cf_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf)
+{
+    unsigned long long tmp;
+
+    tmp = (cf<< size) | a;
+
+    size++;
+    b = b&0x1F;
+    b %= size;
+
+    switch(size){
+        case 8+1:
+            tmp = (tmp << b) | ((tmp&0x1FF) >> (size-b));
+            return (tmp>>8)&1;
+        case 16+1:
+            tmp = (tmp << b) | ((tmp&0x1FFFF) >> (size-b));
+            return (tmp>>16)&1;
+        case 32+1:
+            tmp = (tmp << b) | ((tmp&0x1FFFFFFFFULL) >> (size-b));
+            return (tmp>>32)&1;
+        default:
+            printf("inv size in rclleft %d\n", size);
+            exit(0);
+    }
+}
+
+int rcr_cf_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf)
+{
+	return rcl_cf_op(size, a, size+1-b, cf);
+}
+unsigned int my_bsr(unsigned int a, unsigned int b)
+{
+	int i;
+
+        for (i=31; i>=0; i--){
+		if (b & (1<<i))
+			return i;
+	}
+	return a;
+}
+
+unsigned int my_bsf(unsigned int a, unsigned int b)
+{
+	int i;
+
+        for (i=0; i<32; i++){
+		if (b & (1<<i))
+			return i;
+	}
+	return a;
+}
+
+
+unsigned int my_imul08(unsigned int a, unsigned int b)
+{
+	char a08, b08;
+	short a16;
+
+	a08 = a&0xFF;
+	b08 = b&0xFF;
+	a16 = a08*b08;
+	return (int)a16;
+}
+
+
+
+unsigned int cpuid(unsigned int a, unsigned int reg_num)
+{
+	if (reg_num >3){
+		printf("zarb cpuid reg %x\n", reg_num);
+		exit(-1);
+	}
+
+	if (a == 0){
+		switch(reg_num){
+		case 0:
+			return 0xa;
+		case 1:
+			return 0x756E6547;
+		case 2:
+			return 0x6C65746E;
+		case 3:
+			return 0x49656E69;
+		}
+	}
+
+	else if (a == 1){
+		switch(reg_num){
+		case 0:
+			return 0x000006FB;
+		case 1:
+			return 0x02040800;
+		case 2:
+			return 0x0004E3BD;
+		case 3:
+			return 0xBFEBFBFF;
+		}
+	}
+	else{
+		printf("WARNING zarb cpuid index %X!\n", a);
+		//exit(-1);
+	}
+	
+	return 0;
+}
+
+
+double mem_32_to_double(unsigned int m)
+{
+	float f;
+	double d;
+
+	f = *((float*)&m);
+	d = f;
+	return d;
+}
+
+
+double mem_64_to_double(unsigned long long m)
+{
+	double d;
+	d = *((double*)&m);
+	return d;
+}
+
+double int_32_to_double(unsigned int m)
+{
+	double d;
+
+	d = (double)m;
+	return d;
+}
+
+double int_64_to_double(unsigned long long m)
+{
+	double d;
+
+	d = (double)m;
+	return d;
+}
+
+int double_to_int_32(double d)
+{
+	int i;
+
+	i = (int)d;
+	return i;
+}
+
+double fadd(double a, double b)
+{
+	double c;
+	c = a + b;
+	return c;
+}
+
+
+
+unsigned int fcom_c0(double a, double b)
+{
+	if (a>=b)
+		return 0;
+	return 1;
+}
+unsigned int fcom_c1(double a, double b)
+{
+	//XXX
+	return 0;
+}
+unsigned int fcom_c2(double a, double b)
+{
+	return 0;
+}
+unsigned int fcom_c3(double a, double b)
+{
+	if (a==b)
+		return 1;
+	return 0;
+}
+
+
+unsigned int double_to_mem_32(double d)
+{
+	unsigned int m;
+	float f;
+	f = d;
+	m = *((unsigned int*)&f);
+	return m;
+}
+
+unsigned long long double_to_mem_64(double d)
+{
+	unsigned long long m;
+	m = *((unsigned long long*)&d);
+	return m;
+}
+
+struct memory_page_node * create_memory_page_node(unsigned int ad, unsigned int size, unsigned int access)
+{
+	struct memory_page_node * mpn;
+	void* p;
+
+	mpn = malloc(sizeof(*mpn));
+	if (!mpn){
+		printf("cannot alloc mpn\n");
+		exit(-1);
+	}
+	
+	p = malloc(size);
+	if (!p){
+		printf("cannot alloc %d\n", size);
+		exit(-1);
+	}
+	
+	mpn->ad = ad;
+	mpn->size = size;
+	mpn->access = access;
+	mpn->ad_hp = p;
+
+	return mpn;
+}
+
+
+struct code_bloc_node * create_code_bloc_node(unsigned int ad_start, unsigned int ad_stop)
+{
+	struct code_bloc_node * cbp;
+
+	cbp = malloc(sizeof(*cbp));
+	if (!cbp){
+		printf("cannot alloc cbp\n");
+		exit(-1);
+	}
+
+	cbp->ad_start = ad_start;
+	cbp->ad_stop = ad_stop;
+
+	return cbp;
+}
+
+
+void add_code_bloc(struct code_bloc_node* cbp)
+{
+	LIST_INSERT_HEAD(&code_bloc_pool, cbp, next);
+	if (code_bloc_pool_ad_min> cbp->ad_start)
+		code_bloc_pool_ad_min = cbp->ad_start;
+	if (code_bloc_pool_ad_max< cbp->ad_stop)
+		code_bloc_pool_ad_max = cbp->ad_stop;
+}
+
+void dump_code_bloc_pool(void)
+{
+	struct code_bloc_node * cbp;
+
+	LIST_FOREACH(cbp, &code_bloc_pool, next){
+		printf("ad start %.8X ad_stop %.8X\n", 
+		       cbp->ad_start,
+		       cbp->ad_stop);
+	
+	}
+}
+
+
+void init_memory_page_pool(void)
+{
+	unsigned int i;
+	LIST_INIT(&memory_page_pool);
+	for (i=0;i<MAX_MEMORY_PAGE_POOL_TAB; i++)
+		memory_page_pool_tab[i] = NULL;
+	
+}
+
+void init_code_bloc_pool(void)
+{
+	LIST_INIT(&code_bloc_pool);
+	code_bloc_pool_ad_min = 0xffffffff;
+	code_bloc_pool_ad_max = 0;
+}
+
+
+
+void reset_memory_page_pool(void)
+{
+	struct memory_page_node * mpn;
+	unsigned int i;
+
+	while (!LIST_EMPTY(&memory_page_pool)) {
+		mpn = LIST_FIRST(&memory_page_pool);
+		LIST_REMOVE(mpn, next);
+		free(mpn->ad_hp);
+		free(mpn);
+	}
+	for (i=0;i<MAX_MEMORY_PAGE_POOL_TAB; i++)
+		memory_page_pool_tab[i] = NULL;
+
+}
+
+
+void reset_code_bloc_pool(void)
+{
+	struct code_bloc_node * cbp;
+
+
+	while (!LIST_EMPTY(&code_bloc_pool)) {
+		cbp = LIST_FIRST(&code_bloc_pool);
+		LIST_REMOVE(cbp, next);
+		free(cbp);
+	}
+	code_bloc_pool_ad_min = 0xffffffff;
+	code_bloc_pool_ad_max = 0;
+}
+
+void insert_mpn_in_tab(struct memory_page_node* mpn_a)
+{
+	unsigned int i;
+	for (i=mpn_a->ad >> MEMORY_PAGE_POOL_MASK_BIT;i<(mpn_a->ad + mpn_a->size + PAGE_SIZE - 1)>>MEMORY_PAGE_POOL_MASK_BIT; i++){
+		if (memory_page_pool_tab[i] !=NULL){
+			printf("known page in tab\n");
+			exit(1);
+		}
+		memory_page_pool_tab[i] = mpn_a;
+	}
+
+}
+
+void add_memory_page(struct memory_page_node* mpn_a)
+{
+	struct memory_page_node * mpn;
+	struct memory_page_node * lmpn;
+	//unsigned int i;
+	if (LIST_EMPTY(&memory_page_pool)){
+		LIST_INSERT_HEAD(&memory_page_pool, mpn_a, next);
+		insert_mpn_in_tab(mpn_a);
+		return;
+	}
+	LIST_FOREACH(mpn, &memory_page_pool, next){
+		lmpn = mpn;
+		if (mpn->ad < mpn_a->ad)
+			continue;
+		LIST_INSERT_BEFORE(mpn, mpn_a, next);
+		insert_mpn_in_tab(mpn_a);
+		return;
+		
+	}
+	LIST_INSERT_AFTER(lmpn, mpn_a, next);
+	insert_mpn_in_tab(mpn_a);
+
+}
+
+void dump_memory_page_pool()
+{
+	struct memory_page_node * mpn;
+
+	LIST_FOREACH(mpn, &memory_page_pool, next){
+		printf("ad %.8X size %.8X %c%c%c hpad %p\n", 
+		       mpn->ad,
+		       mpn->size,
+		       mpn->access & PAGE_READ? 'R':'_',
+		       mpn->access & PAGE_WRITE? 'W':'_',
+		       mpn->access & PAGE_EXEC? 'X':'_',
+		       mpn->ad_hp
+		       );
+	}
+		
+	
+}
+
+
+
+
+
+
+unsigned int get_memory_page_max_address(void)
+{
+	struct memory_page_node * mpn;
+	unsigned int ad = 0;
+
+	LIST_FOREACH(mpn, &memory_page_pool, next){
+		if (ad < mpn->ad + mpn->size)
+			ad = mpn->ad + mpn->size;
+	}
+	return ad;
+}
+
+unsigned int get_memory_page_max_user_address(void)
+{
+	struct memory_page_node * mpn;
+	unsigned int ad = 0;
+
+	LIST_FOREACH(mpn, &memory_page_pool, next){
+		if (ad < mpn->ad + mpn->size && mpn->ad + mpn->size < 0x80000000)
+			ad = mpn->ad + mpn->size;
+	}
+	return ad;
+}
+
+
+unsigned int get_memory_page_next(unsigned int n_ad)
+{
+	struct memory_page_node * mpn;
+	unsigned int ad = 0;
+	
+	LIST_FOREACH(mpn, &memory_page_pool, next){
+		if (mpn->ad < n_ad)
+			continue;
+
+		if (ad == 0 || mpn->ad <ad)
+			ad = mpn->ad;
+	}
+	
+	return ad;
+	
+}
+
+unsigned int get_memory_page_from_min_ad(unsigned int size)
+{
+	struct memory_page_node * mpn;
+	unsigned int c_ad ;
+	unsigned int min_ad = min_page_ad;
+	int end = 0;
+	/* first, find free min ad */
+    	while (!end){
+		end = 1;
+        	LIST_FOREACH(mpn, &memory_page_pool, next){
+        		c_ad = (mpn->ad + mpn->size+0x1000)&0xfffff000;
+        		if (c_ad <= min_ad)
+        			continue;
+        		if (mpn->ad <= min_ad){
+        			min_ad = c_ad;
+				end = 0;
+        			break;
+        		}
+        		
+        		if (mpn->ad - min_ad < size){
+        			min_ad = c_ad;
+				end = 0;
+        			break;
+        		}
+        	}
+	}
+	return min_ad;
+ }
+
+
+
+
+/********************************************/
+
+void hexdump(char* m, unsigned int l)
+{
+  int i, j, last;
+  last = 0;
+  for (i=0;i<l;i++){
+      if (!(i%0x10) && i){
+      last = i;
+        printf("    ");
+        
+        for (j=-0x10;j<0;j++){
+          if (isprint(m[i+j])){
+            printf("%c", m[i+j]);
+          }
+          else{
+            printf(".");
+          }
+        }
+        printf("\n");
+      }
+      printf("%.2X ", m[i]&0xFF);
+  }
+  
+  l-=last;
+  if (l){
+    
+    for (j=i;j<last+0x10;j++)
+      printf("   ");
+    printf("    ");
+    
+    for (j = 0;l;j++){
+      if (isprint(m[last+j])){
+        printf("%c", m[last+j]);
+      }
+      else{
+        printf(".");
+      }
+      l--;
+    }
+  }  
+  printf("\n");
+
+}
+
+
+
+
+
+void _vm_init_regs()
+{
+    vmcpu.eax = vmcpu.ebx = vmcpu.ecx = vmcpu.edx = vmcpu.esi = vmcpu.edi = vmcpu.esp = vmcpu.ebp = 0;
+    vmcpu.zf = vmcpu.nf = vmcpu.pf = vmcpu.of = vmcpu.cf = vmcpu.af = vmcpu.df = 0;
+    
+    vmcpu.eax_new = vmcpu.ebx_new = vmcpu.ecx_new = vmcpu.edx_new = vmcpu.esi_new = vmcpu.edi_new = vmcpu.esp_new = vmcpu.ebp_new = 0;
+    vmcpu.zf_new = vmcpu.nf_new = vmcpu.pf_new = vmcpu.of_new = vmcpu.cf_new = vmcpu.af_new = vmcpu.df_new = 0;
+    vmcpu.esp = 0;
+}
+
+
+
+unsigned int _get_memory_page_max_address_py(void)
+{
+    unsigned int ret;
+    ret = get_memory_page_max_address();
+    return ret;
+}
+
+unsigned int _get_memory_page_max_user_address_py(void)
+{
+    unsigned int ret;
+    ret = get_memory_page_max_user_address();
+    return ret;
+}
+
+unsigned int _get_memory_page_from_min_ad_py(unsigned int size)
+{
+    unsigned int ret;
+    ret = get_memory_page_from_min_ad(size);
+    return ret;
+}
+
+
+
+
+//#include "libcodenat_interface.c"
diff --git a/miasm/tools/emul_lib/libcodenat.h b/miasm/tools/emul_lib/libcodenat.h
new file mode 100644
index 00000000..351e6210
--- /dev/null
+++ b/miasm/tools/emul_lib/libcodenat.h
@@ -0,0 +1,452 @@
+/*
+** Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License along
+** with this program; if not, write to the Free Software Foundation, Inc.,
+** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#ifndef CODENAT_H
+#define CODENAT_H
+
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define Endian16_Swap(value) \
+      ((((uint16_t)((value) & 0x00FF)) << 8) | \
+         (((uint16_t)((value) & 0xFF00)) >> 8))
+
+#define Endian32_Swap(value) \
+         ((((uint32_t)((value) & 0x000000FF)) << 24) | \
+         (((uint32_t)((value) & 0x0000FF00)) << 8) | \
+         (((uint32_t)((value) & 0x00FF0000)) >> 8) | \
+         (((uint32_t)((value) & 0xFF000000)) >> 24))
+
+#define Endian64_Swap(value)					    \
+                (((((uint64_t)value)<<56) & 0xFF00000000000000ULL)  | \
+                 ((((uint64_t)value)<<40) & 0x00FF000000000000ULL)  | \
+                 ((((uint64_t)value)<<24) & 0x0000FF0000000000ULL)  | \
+                 ((((uint64_t)value)<< 8) & 0x000000FF00000000ULL)  | \
+                 ((((uint64_t)value)>> 8) & 0x00000000FF000000ULL)  | \
+                 ((((uint64_t)value)>>24) & 0x0000000000FF0000ULL)  | \
+                 ((((uint64_t)value)>>40) & 0x000000000000FF00ULL)  | \
+                 ((((uint64_t)value)>>56) & 0x00000000000000FFULL))
+#else
+#define Endian16_Swap(value) (value)
+
+#define Endian32_Swap(value) (value)
+
+#define Endian64_Swap(value) (value)
+#endif
+
+
+
+
+LIST_HEAD(memory_page_list_head, memory_page_node);
+LIST_HEAD(code_bloc_list_head, code_bloc_node);
+
+
+typedef struct {
+	unsigned int eax; 
+	unsigned int ebx;
+	unsigned int ecx;
+	unsigned int edx;
+	unsigned int esi;
+	unsigned int edi;
+	unsigned int esp;
+	unsigned int ebp;
+	unsigned int eip;
+
+	unsigned int zf;
+	unsigned int nf;
+	unsigned int pf;
+	unsigned int of;
+	unsigned int cf;
+	unsigned int af;
+	unsigned int df;
+
+	unsigned int eax_new;
+	unsigned int ebx_new;
+	unsigned int ecx_new;
+	unsigned int edx_new;
+	unsigned int esi_new;
+	unsigned int edi_new;
+	unsigned int esp_new;
+	unsigned int ebp_new;
+	unsigned int eip_new;
+
+	unsigned int zf_new;
+	unsigned int nf_new;
+	unsigned int pf_new;
+	unsigned int of_new;
+	unsigned int cf_new;
+	unsigned int af_new;
+	unsigned int df_new;
+
+	unsigned int tf;
+	unsigned int i_f;
+	unsigned int iopl_f;
+	unsigned int nt;
+	unsigned int rf;
+	unsigned int vm;
+	unsigned int ac;
+	unsigned int vif;
+	unsigned int vip;
+	unsigned int i_d;
+	unsigned int tf_new;
+	unsigned int i_f_new;
+	unsigned int iopl_f_new;
+	unsigned int nt_new;
+	unsigned int rf_new;
+	unsigned int vm_new;
+	unsigned int ac_new;
+	unsigned int vif_new;
+	unsigned int vip_new;
+	unsigned int  i_d_new;
+
+	unsigned int my_tick;
+	
+	
+	
+	unsigned int cond;
+	
+	unsigned int ds;
+	
+	unsigned int vm_exception_flags;
+	unsigned int vm_exception_flags_new;
+	
+	unsigned int vm_last_write_ad;
+	unsigned int vm_last_write_size ;
+
+
+
+	double float_st0;
+	double float_st1;
+	double float_st2;
+	double float_st3;
+	double float_st4;
+	double float_st5;
+	double float_st6;
+	double float_st7;
+
+	double float_st0_new;
+	double float_st1_new;
+	double float_st2_new;
+	double float_st3_new;
+	double float_st4_new;
+	double float_st5_new;
+	double float_st6_new;
+	double float_st7_new;
+
+	unsigned int float_c0;
+	unsigned int float_c1;
+	unsigned int float_c2;
+	unsigned int float_c3;
+
+	unsigned int float_c0_new;
+	unsigned int float_c1_new;
+	unsigned int float_c2_new;
+	unsigned int float_c3_new;
+
+
+	unsigned int float_stack_ptr;
+	unsigned int float_stack_ptr_new;
+
+	unsigned int reg_float_control;
+	unsigned int reg_float_control_new;
+
+
+	unsigned int tsc1;
+	unsigned int tsc2;
+
+	unsigned int cr0;
+	unsigned int cr0_new;
+
+	unsigned int cr3;
+	unsigned int cr3_new;
+
+	
+	//PyObject* known_blocs;
+	
+
+}vm_cpu_t;
+
+
+extern vm_cpu_t vmcpu;
+
+/*
+extern unsigned int eax, ebx, ecx, edx, esi, edi, esp, ebp, eip;
+extern unsigned int zf, nf, pf, of, cf, af, df;
+
+extern unsigned int eax_new, ebx_new, ecx_new, edx_new, esi_new, edi_new, esp_new, ebp_new, eip_new;
+extern unsigned int zf_new, nf_new, pf_new, of_new, cf_new, af_new, df_new;
+extern unsigned int tf, i_f, iopl_f, nt, rf, vm, ac, vif, vip, i_d;
+extern unsigned int tf_new, i_f_new, iopl_f_new, nt_new, rf_new, vm_new, ac_new, vif_new, vip_new, i_d_new;
+
+extern unsigned int my_tick;
+
+extern unsigned int reg_float_control;
+
+
+extern unsigned int cond;
+
+extern unsigned int ds;
+
+extern unsigned int vm_exception_flags;
+extern unsigned int vm_exception_flags_new;
+
+extern unsigned int vm_last_write_ad;
+extern unsigned int vm_last_write_size ;
+*/
+
+typedef struct _memory_page{
+}memory_page;
+
+struct memory_page_node {
+	unsigned int ad;
+	unsigned int size;
+	unsigned int access;
+	void* ad_hp;
+	
+	//memory_page *mp;
+	LIST_ENTRY(memory_page_node)   next;
+};
+
+
+
+struct code_bloc_node {
+	unsigned int ad_start;
+	unsigned int ad_stop;
+	unsigned int ad_code;
+	LIST_ENTRY(code_bloc_node)   next;
+};
+
+
+#define PAGE_READ 1
+#define PAGE_WRITE 2
+#define PAGE_EXEC 4
+
+
+//memory_page* create_memory_page(unsigned int ad, unsigned int size);
+
+//PyObject* _vm_get_exception(unsigned int xcpt);
+
+// interrupt with eip update after instr
+#define EXCEPT_CODE_AUTOMOD (1<<0)
+#define EXCEPT_SOFT_BP (1<<1)
+
+#define EXCEPT_NUM_UDPT_EIP (1<<1)
+
+// interrupt with eip at instr
+#define EXCEPT_UNK_MEM_AD (1<<2)
+#define EXCEPT_THROW_SEH (1<<3)
+#define EXCEPT_UNK_EIP (1<<4)
+#define EXCEPT_ACCESS_VIOL (1<<5)
+#define EXCEPT_INT_DIV_BY_ZERO (1<<6)
+#define EXCEPT_PRIV_INSN (1<<7)
+#define EXCEPT_ILLEGAL_INSN (1<<8)
+
+void dump_gpregs(void);
+void MEM_WRITE(unsigned int my_size, unsigned int addr , unsigned int src);
+unsigned int MEM_LOOKUP(unsigned int my_size, unsigned int addr);
+
+
+void MEM_WRITE_08(unsigned int addr , unsigned char src);
+void MEM_WRITE_16(unsigned int addr , unsigned short src);
+void MEM_WRITE_32(unsigned int addr , unsigned int src);
+void MEM_WRITE_64(unsigned int addr , unsigned long long src);
+
+
+unsigned char MEM_LOOKUP_08(unsigned int addr);
+unsigned short MEM_LOOKUP_16(unsigned int addr);
+unsigned int MEM_LOOKUP_32(unsigned int addr);
+unsigned long long MEM_LOOKUP_64(unsigned int addr);
+
+
+
+
+void MEM_WRITE_08_PASSTHROUGH(unsigned int addr, unsigned char src);
+void MEM_WRITE_16_PASSTHROUGH(unsigned int addr, unsigned short src);
+void MEM_WRITE_32_PASSTHROUGH(unsigned int addr, unsigned int src);
+void MEM_WRITE_64_PASSTHROUGH(unsigned int addr, unsigned long long src);
+unsigned char MEM_LOOKUP_08_PASSTHROUGH(unsigned int addr);
+unsigned short MEM_LOOKUP_16_PASSTHROUGH(unsigned int addr);
+unsigned int MEM_LOOKUP_32_PASSTHROUGH(unsigned int addr);
+unsigned long long MEM_LOOKUP_64_PASSTHROUGH(unsigned int addr);
+
+
+inline unsigned int parity(unsigned int a);
+unsigned int my_imul08(unsigned int a, unsigned int b);
+
+void vm_throw(unsigned long flags);
+int shift_right_arith(unsigned int size, int a, unsigned int b);
+unsigned int shift_right_logic(unsigned int size, unsigned int a, unsigned int b);
+int shift_left_logic(unsigned int size, unsigned int a, unsigned int b);
+/*
+int shift_left_logic_08(unsigned int a, unsigned int b);
+int shift_left_logic_16(unsigned int a, unsigned int b);
+int shift_left_logic_32(unsigned int a, unsigned int b);
+*/
+unsigned int mul_lo_op(unsigned int size, unsigned int a, unsigned int b);
+unsigned int mul_hi_op(unsigned int size, unsigned int a, unsigned int b);
+unsigned int imul_lo_op_08(char a, char b);
+unsigned int imul_lo_op_16(short a, short b);
+unsigned int imul_lo_op_32(int a, int b);
+int imul_hi_op_08(char a, char b);
+int imul_hi_op_16(short a, short b);
+int imul_hi_op_32(int a, int b);
+
+
+unsigned int div_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c);
+unsigned int rem_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c);
+int rot_left(unsigned int size, unsigned int a, unsigned int b);
+int rot_right(unsigned int size, unsigned int a, unsigned int b);
+int rcl_rez_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf);
+int rcl_cf_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf);
+void _vm_init_regs(void);
+
+
+//PyObject* _vm_push_uint32_t(PyObject *item);
+//PyObject* _vm_pop_uint32_t(void);
+////PyObject* _vm_put_str(PyObject *item);
+//PyObject* _vm_set_mem(PyObject *item, PyObject *item_str);
+//PyObject* _vm_set_mem_access(PyObject *addr, PyObject *access);
+//PyObject* _vm_get_str(PyObject *item, PyObject *item_len);
+//PyObject* _vm_add_memory_page(PyObject *item, PyObject *access, PyObject *item_str);
+//PyObject* _vm_add_code_bloc(PyObject *item1, PyObject *item2);//, PyObject *item3);
+//PyObject* _call_pyfunc_from_globals(char* funcname);
+//PyObject* _call_pyfunc_from_eip(void);
+//
+//PyObject* call_pyfunc_from_globals(char* funcname);
+//
+//PyObject* _vm_get_gpreg(void);
+
+typedef struct _reg_dict{
+    char* name;
+    unsigned int* ptr;
+} reg_dict;
+
+extern reg_dict gpreg_dict[];
+//PyObject* _vm_set_gpreg(PyObject *dict);
+
+
+void hexdump(char* m, unsigned int l);
+
+struct code_bloc_node * create_code_bloc_node(unsigned int ad_start, unsigned int ad_stop);
+void add_code_bloc(struct code_bloc_node* cbp);
+
+struct memory_page_node * create_memory_page_node(unsigned int ad, unsigned int size, unsigned int access);//memory_page* mp);
+void init_memory_page_pool(void);
+void init_code_bloc_pool(void);
+void reset_memory_page_pool(void);
+void reset_code_bloc_pool(void);
+void dump_code_bloc_pool(void);
+
+
+
+void add_memory_page(struct memory_page_node* mpn);
+
+void dump_memory_page_pool(void);
+//PyObject* _vm_get_all_memory(void);
+
+
+
+
+/********************************************/
+
+//PyObject* _vm_get_cpu_state(void);
+//PyObject*  _vm_set_cpu_state(PyObject * s_cpustate);
+
+
+//void memory_page_write(unsigned int my_size, unsigned int ad, unsigned int src);
+//unsigned int memory_page_read(unsigned int my_size, unsigned int ad);
+unsigned int get_memory_page_max_address(void);
+unsigned int get_memory_page_max_user_address(void);
+
+
+
+
+void _func_free(void);
+void _func_alloc(void);
+unsigned int _get_memory_page_max_address_py(void);
+unsigned int _get_memory_page_max_user_address_py(void);
+unsigned int _get_memory_page_from_min_ad_py(unsigned int size);
+
+void _func_malloc_memory_page(void);
+void _func_free_memory_page(void);
+void _func_virtualalloc_memory_page(void);
+void _func_virtualfree_memory_page(void);
+void _func_loadlib_fake(void);
+void _func_getproc_fake(void);
+
+
+void func_free(void);
+void func_alloc(void);
+unsigned int get_memory_page_max_address_py(void);
+unsigned int get_memory_page_max_user_address_py(void);
+unsigned int get_memory_page_from_min_ad_py(unsigned int size);
+struct memory_page_node * get_memory_page_from_address(unsigned int ad);
+void func_malloc_memory_page(void);
+void func_free_memory_page(void);
+void func_virtualalloc_memory_page(void);
+void func_virtualfree_memory_page(void);
+void func_loadlib_fake(void);
+void func_getproc_fake(void);
+
+
+//PyObject* _vm_exec_bloc(PyObject* my_eip, PyObject* known_blocs);
+
+unsigned int cpuid(unsigned int a, unsigned int reg_num);
+double int2double(unsigned int m);
+//PyObject* _vm_exec_blocs(PyObject* my_eip);
+
+double fadd(double a, double b);
+unsigned int fcom_c0(double a, double b);
+unsigned int fcom_c1(double a, double b);
+unsigned int fcom_c2(double a, double b);
+unsigned int fcom_c3(double a, double b);
+
+
+
+double mem_32_to_double(unsigned int m);
+double mem_64_to_double(unsigned long long m);
+double int_32_to_double(unsigned int m);
+double int_64_to_double(unsigned long long m);
+int double_to_int_32(double d);
+double fadd(double a, double b);
+unsigned int double_to_mem_32(double d);
+unsigned long long double_to_mem_64(double d);
+
+
+#define shift_right_arith_08(a, b)\
+	((((char)(a)) >> ((unsigned int)(b)))&0xff)
+#define shift_right_arith_16(a, b)\
+	((((short)(a)) >> ((unsigned int)(b)))&0xffff)
+#define shift_right_arith_32(a, b)\
+	((((int)(a)) >> ((unsigned int)(b)))&0xffffffff)
+
+
+#define shift_right_logic_08(a, b)\
+	((((unsigned char)(a)) >> ((unsigned int)(b)))&0xff)
+#define shift_right_logic_16(a, b)\
+	((((unsigned short)(a)) >> ((unsigned int)(b)))&0xffff)
+#define shift_right_logic_32(a, b)\
+	((((unsigned int)(a)) >> ((unsigned int)(b)))&0xffffffff)
+
+
+#define shift_left_logic_08(a, b)\
+	(((a)<<(b))&0xff)
+#define shift_left_logic_16(a, b)\
+	(((a)<<(b))&0xffff)
+#define shift_left_logic_32(a, b)\
+	(((a)<<(b))&0xffffffff)
+
+#endif
diff --git a/miasm/tools/emul_lib/libcodenat_interface.c b/miasm/tools/emul_lib/libcodenat_interface.c
new file mode 100644
index 00000000..c94295b2
--- /dev/null
+++ b/miasm/tools/emul_lib/libcodenat_interface.c
@@ -0,0 +1,1108 @@
+/*
+** Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License along
+** with this program; if not, write to the Free Software Foundation, Inc.,
+** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include <Python.h>
+#include "queue.h"
+#include "libcodenat.h"
+
+#define MIN(a,b)  (((a)<(b))?(a):(b))
+#define MAX(a,b)  (((a)>(b))?(a):(b))
+
+extern struct memory_page_list_head memory_page_pool;
+extern struct code_bloc_list_head code_bloc_pool;
+
+#define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;}
+
+PyObject* _vm_get_exception(unsigned int xcpt)
+{
+	PyObject*p;
+
+	if (!xcpt)
+		p = NULL;
+	else if (xcpt & EXCEPT_CODE_AUTOMOD)
+		p = PyErr_Format( PyExc_RuntimeError, "EXCEPT_CODE_AUTOMOD" );
+	else if (xcpt & EXCEPT_UNK_EIP)
+		p = PyErr_Format( PyExc_RuntimeError, "EXCEPT_UNK_EIP" );
+	else if (xcpt & EXCEPT_UNK_MEM_AD)
+		p = PyErr_Format( PyExc_RuntimeError, "EXCEPT_UNK_MEM_AD" );
+
+	else  p = PyErr_Format( PyExc_RuntimeError, "EXCEPT_UNKNOWN" );
+	
+	return p;
+}
+
+PyObject* _vm_get_all_memory(void)
+{
+    struct memory_page_node * mpn;
+    PyObject *dict;
+    PyObject *dict2;
+
+    PyObject *o;
+
+    dict =  PyDict_New();
+
+    LIST_FOREACH(mpn, &memory_page_pool, next){
+	    /*
+	    printf("ad %.8X size %.8X %c%c%c hpad %p\n", 
+		   mpn->ad,
+		   mpn->size,
+		   mpn->access & PAGE_READ? 'R':'_',
+		   mpn->access & PAGE_WRITE? 'W':'_',
+		   mpn->access & PAGE_EXEC? 'X':'_',
+		   mpn->ad_hp
+		   );
+	    */
+
+	    dict2 =  PyDict_New();
+	    
+	    o = PyString_FromStringAndSize(mpn->ad_hp, mpn->size);
+	    PyDict_SetItemString(dict2, "data", o);
+	    Py_DECREF(o);
+
+	    o = PyInt_FromLong((long)mpn->size);
+	    PyDict_SetItemString(dict2, "size", o);
+	    Py_DECREF(o);
+
+	    o = PyInt_FromLong((long)mpn->access);
+	    PyDict_SetItemString(dict2, "access", o);
+	    Py_DECREF(o);
+	    
+	    o = PyInt_FromLong((long)mpn->ad);
+	    PyDict_SetItem(dict, o, dict2);
+	    Py_DECREF(o);
+	    Py_DECREF(dict2);
+    }
+    return dict;
+}
+
+
+PyObject* _vm_get_gpreg(void)
+{
+    PyObject *dict = PyDict_New();
+    PyObject *o;
+    
+    o = PyInt_FromLong((long)vmcpu.eax);
+    PyDict_SetItemString(dict, "eax", o);
+    Py_DECREF(o);
+    o = PyInt_FromLong((long)vmcpu.ebx);
+    PyDict_SetItemString(dict, "ebx", o);
+    Py_DECREF(o);
+    o = PyInt_FromLong((long)vmcpu.ecx);
+    PyDict_SetItemString(dict, "ecx", o);
+    Py_DECREF(o);
+    o = PyInt_FromLong((long)vmcpu.edx);
+    PyDict_SetItemString(dict, "edx", o);
+    Py_DECREF(o);
+    o = PyInt_FromLong((long)vmcpu.esi);
+    PyDict_SetItemString(dict, "esi", o);
+    Py_DECREF(o);
+    o = PyInt_FromLong((long)vmcpu.edi);
+    PyDict_SetItemString(dict, "edi", o);
+    Py_DECREF(o);
+    o = PyInt_FromLong((long)vmcpu.esp);
+    PyDict_SetItemString(dict, "esp", o);
+    Py_DECREF(o);
+    o = PyInt_FromLong((long)vmcpu.ebp);
+    PyDict_SetItemString(dict, "ebp", o);
+    Py_DECREF(o);
+    o = PyInt_FromLong((long)vmcpu.eip);
+    PyDict_SetItemString(dict, "eip", o);
+    Py_DECREF(o);
+    
+
+    return dict;
+    
+    
+}
+
+reg_dict gpreg_dict[] = { {.name = "eax", .ptr = &(vmcpu.eax)},
+                          {.name = "ebx", .ptr = &(vmcpu.ebx)},
+                          {.name = "ecx", .ptr = &(vmcpu.ecx)},
+                          {.name = "edx", .ptr = &(vmcpu.edx)},
+                          {.name = "esi", .ptr = &(vmcpu.esi)},
+                          {.name = "edi", .ptr = &(vmcpu.edi)},
+                          {.name = "esp", .ptr = &(vmcpu.esp)},
+                          {.name = "ebp", .ptr = &(vmcpu.ebp)},
+                          {.name = "eip", .ptr = &(vmcpu.eip)},
+};
+
+PyObject* _vm_set_gpreg(PyObject *dict)
+{
+    PyObject *d_key, *d_value = NULL;
+    int pos = 0;
+    unsigned int val;
+    unsigned int i, found;
+    
+
+    if(!PyDict_Check(dict))
+        RAISE(PyExc_TypeError, "arg must be dict");
+    
+    while(PyDict_Next(dict, &pos, &d_key, &d_value)){
+        if(!PyString_Check(d_key))
+            RAISE(PyExc_TypeError, "key must be str");
+
+
+	if (PyInt_Check(d_value)){
+		val = (unsigned int)PyInt_AsLong(d_value);
+	}
+	else if (PyLong_Check(d_value)){
+		val = (unsigned int)PyInt_AsUnsignedLongLongMask(d_value);
+	}
+	else{
+		RAISE(PyExc_TypeError,"value must be int");
+	}
+
+
+        found = 0;
+        for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){
+            if (strcmp(PyString_AsString(d_key), gpreg_dict[i].name))
+                continue;
+            *(gpreg_dict[i].ptr) = val;
+            found = 1;
+            break;
+        }
+
+        if (found)
+            continue;
+
+        printf("unkown key: %s\n", PyString_AsString(d_key));
+
+        RAISE(PyExc_ValueError, "unkown reg");
+    }
+    return NULL;
+}
+
+
+PyObject* _vm_add_memory_page(PyObject *item, PyObject *access, PyObject *item_str)
+{
+    unsigned int buf_size;
+    char* buf_data;
+    //char* buf_data_aligned;
+    Py_ssize_t length;
+    int ret = 0x1337beef;
+    unsigned int page_addr;
+    unsigned int page_access;
+
+    struct memory_page_node * mpn;
+
+    if (PyInt_Check(item)){
+        page_addr = (unsigned int)PyInt_AsLong(item);
+    }
+    else if (PyLong_Check(item)){
+        page_addr = (unsigned int)PyInt_AsUnsignedLongLongMask(item);
+    }
+    else{
+        RAISE(PyExc_TypeError,"arg1 must be int");
+    }
+
+
+
+    if (PyInt_Check(access)){
+        page_access = (unsigned int)PyInt_AsLong(access);
+    }
+    else if (PyLong_Check(item)){
+        page_access = (unsigned int)PyInt_AsUnsignedLongLongMask(access);
+    }
+    else{
+        RAISE(PyExc_TypeError,"arg2 must be int");
+    }
+
+
+
+    //printf("add page: %X\n", page_addr);
+
+    if(!PyString_Check(item_str))
+       RAISE(PyExc_TypeError,"arg must be str");
+
+    buf_size = PyString_Size(item_str);
+    //printf("add page %X size: %X\n", page_addr, buf_size);
+
+    PyString_AsStringAndSize(item_str, &buf_data, &length);
+
+
+    mpn = create_memory_page_node(page_addr, buf_size, page_access);
+    memcpy(mpn->ad_hp, buf_data, buf_size);
+    add_memory_page(mpn);
+
+    return PyInt_FromLong((long)ret);
+}
+
+PyObject* _call_pyfunc_from_globals(char* funcname)
+{
+    PyObject  *mod,  *func, *rslt, *globals, *func_globals;
+    
+    printf("getting pyfunc %s\n", funcname);
+    
+    mod = PyEval_GetBuiltins();
+
+    if (!mod) {
+        printf("cannot find module\n");
+        exit(0);
+    }
+    
+    func_globals = PyDict_GetItemString(mod, "globals");
+    if (!func_globals) {
+        printf("cannot find function globals\n");
+        exit(0);
+    }
+    
+    if (!PyCallable_Check (func_globals)) {
+        printf("function not callable\n");
+        exit(0);    
+    }
+
+    globals = PyObject_CallObject (func_globals, NULL);
+    if (!globals) {
+        printf("cannot get globals\n");
+        exit(0);
+    }
+
+    //Py_XDECREF(func_globals);    
+    //Py_XDECREF(mod);    
+
+
+    func = PyDict_GetItemString (globals, funcname);
+    if (!func) {
+        printf("cannot find function %s\n", funcname);
+        exit(0);
+    }
+    
+    if (!PyCallable_Check (func)) {
+        printf("function not callable\n");
+        exit(0);    
+    }
+    
+    rslt = PyObject_CallObject (func, NULL);
+    
+    
+    return rslt;
+}
+
+
+
+PyObject* _call_pyfunc_from_eip(void)
+{
+    PyObject  *mod,  *func, *rslt, *globals, *func_globals;
+    char funcname[0x100];
+
+    printf("getting pybloc %X\n", vmcpu.eip);
+    sprintf(funcname, "bloc_%.8X", vmcpu.eip);
+    printf("bloc name %s\n", funcname);
+    
+    mod = PyEval_GetBuiltins();
+
+    if (!mod) {
+        printf("cannot find module\n");
+        exit(0);
+    }
+    
+    func_globals = PyDict_GetItemString(mod, "globals");
+    if (!func_globals) {
+        printf("cannot find function globals\n");
+        exit(0);
+    }
+    
+    if (!PyCallable_Check (func_globals)) {
+        printf("function not callable\n");
+        exit(0);    
+    }
+
+    globals = PyObject_CallObject (func_globals, NULL);
+    if (!globals) {
+        printf("cannot get globals\n");
+        exit(0);
+    }
+
+    //Py_XDECREF(func_globals);    
+    //Py_XDECREF(mod);    
+
+
+    func = PyDict_GetItemString (globals, funcname);
+    if (!func) {
+        printf("cannot find function %s\n", funcname);
+        exit(0);
+    }
+    
+    if (!PyCallable_Check (func)) {
+        printf("function not callable\n");
+        exit(0);    
+    }
+    
+    rslt = PyObject_CallObject (func, NULL);
+    
+    
+    return rslt;
+}
+
+
+
+
+PyObject* _vm_get_cpu_state(void)
+{
+	PyObject * o;
+	o = PyString_FromStringAndSize((char*)&vmcpu, sizeof(vmcpu));
+	return o;
+
+}
+
+
+PyObject*  _vm_set_cpu_state(PyObject * s_cpustate)
+{
+	unsigned int buf_size;
+	Py_ssize_t length;
+	char* buf;
+    
+	if(!PyString_Check(s_cpustate))
+		RAISE(PyExc_TypeError,"arg must be str");
+	
+	buf_size = PyString_Size(s_cpustate);
+	if (buf_size != sizeof(vmcpu))
+		RAISE(PyExc_TypeError,"bad str len");
+	
+	
+	PyString_AsStringAndSize(s_cpustate, (char**)&buf, &length);
+	memcpy(&vmcpu, buf, length);
+	return PyInt_FromLong((long)0);
+
+}
+
+
+PyObject* _vm_push_uint32_t(int val)
+{
+    vmcpu.esp-=4;
+    MEM_WRITE(32, vmcpu.esp, val);
+
+    return PyInt_FromLong((long)vmcpu.esp);
+}
+
+
+PyObject* _vm_pop_uint32_t(void)
+{
+    unsigned int val;
+    
+    val = MEM_LOOKUP(32, vmcpu.esp);
+    vmcpu.esp+=4;
+
+    return PyInt_FromLong((long)val);;
+}
+
+PyObject* _vm_set_mem(PyObject *addr, PyObject *item_str)
+{
+    unsigned int buf_size;
+    char* buf_data;
+    //char* buf_data_aligned;
+    Py_ssize_t length;
+    int ret = 0x1337;
+    unsigned int val;
+
+    struct memory_page_node * mpn;
+
+    if (PyInt_Check(addr)){
+        val = (unsigned int)PyInt_AsLong(addr);
+    }
+    else if (PyLong_Check(addr)){
+        val = (unsigned int)PyInt_AsUnsignedLongLongMask(addr);
+    }
+    else{
+        RAISE(PyExc_TypeError,"arg1 must be int");
+    }
+
+    printf("set addr: %X\n", val);
+
+    if(!PyString_Check(item_str))
+       RAISE(PyExc_TypeError,"arg must be str");
+
+    buf_size = PyString_Size(item_str);
+    //printf("buf size: %X\n", buf_size);
+
+    PyString_AsStringAndSize(item_str, &buf_data, &length);
+
+    mpn = get_memory_page_from_address(val);
+    //memcpy((void*)val, buf_data, buf_size);
+    memcpy(mpn->ad_hp + (val-mpn->ad), buf_data, buf_size);
+
+    return PyInt_FromLong((long)ret);
+}
+
+
+PyObject* _vm_set_mem_access(PyObject *addr, PyObject *access)
+{
+    int ret = 0x1337beef;
+    unsigned int page_addr;
+    unsigned int page_access;
+
+    struct memory_page_node * mpn;
+
+    if (PyInt_Check(addr)){
+        page_addr = (unsigned int)PyInt_AsLong(addr);
+    }
+    else if (PyLong_Check(addr)){
+        page_addr = (unsigned int)PyInt_AsUnsignedLongLongMask(addr);
+    }
+    else{
+        RAISE(PyExc_TypeError,"arg1 must be int");
+    }
+
+    if (PyInt_Check(access)){
+        page_access = (unsigned int)PyInt_AsLong(access);
+    }
+    else if (PyLong_Check(access)){
+        page_access = (unsigned int)PyInt_AsUnsignedLongLongMask(access);
+    }
+    else{
+        RAISE(PyExc_TypeError,"arg2 must be int");
+    }
+
+    mpn = get_memory_page_from_address(page_addr);
+    mpn->access = page_access;
+    return PyInt_FromLong((long)ret);
+}
+
+
+PyObject* _vm_get_str(PyObject *addr, PyObject *item_len)
+{
+    //unsigned int buf_size;
+    //char* buf_data;
+    //char* buf_data_aligned;
+    //Py_ssize_t length;
+    //int ret;
+    unsigned int buf_addr;
+    unsigned int buf_len;
+    PyObject *obj_out;
+    struct memory_page_node * mpn;
+    char* buf_out;
+    char * addr_tmp;
+    char* addr_out;
+    int off;
+    unsigned int l;
+    unsigned int my_size;
+
+    if (PyInt_Check(addr)){
+        buf_addr = (unsigned int)PyInt_AsLong(addr);
+    }
+    else if (PyLong_Check(addr)){
+        buf_addr = (unsigned int)PyInt_AsUnsignedLongLongMask(addr);
+    }
+    else{
+        RAISE(PyExc_TypeError,"arg1 must be int");
+    }
+
+    if (PyInt_Check(item_len)){
+        buf_len = (unsigned int)PyInt_AsLong(item_len);
+    }
+    else if (PyLong_Check(item_len)){
+        buf_len = (unsigned int)PyInt_AsUnsignedLongLongMask(item_len);
+    }
+    else{
+        RAISE(PyExc_TypeError,"arg must be int");
+    }
+
+    my_size = buf_len;
+
+    buf_out = malloc(buf_len);
+    if (!buf_out){
+	    printf("cannot alloc read\n");
+	    exit(-1);
+    }
+
+    addr_out = buf_out;
+    
+
+
+
+    /* read is multiple page wide */
+    while (my_size){
+	    mpn = get_memory_page_from_address(buf_addr);
+	    if (!mpn){
+		    printf("cannot find page off %X\n", buf_addr);
+		    return 0;
+	    }
+
+
+	    off = buf_addr - mpn->ad;
+	    addr_tmp = &((char*)mpn->ad_hp)[off];
+
+	    l = MIN(my_size, mpn->size - off);
+	    memcpy(addr_out, addr_tmp, l);
+	    my_size -= l;	    
+	    addr_out +=l;
+	    buf_addr +=l;
+    }
+
+    obj_out = PyString_FromStringAndSize(buf_out, buf_len);
+    free(buf_out);    
+    return obj_out;
+}
+
+PyObject * dump_gpregs_py(PyObject* self, PyObject* args)
+{
+	dump_gpregs();
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+PyObject* vm_get_last_write_ad(PyObject* self, PyObject* args)
+{
+	return PyInt_FromLong((long)vmcpu.vm_last_write_ad);
+}
+
+PyObject* vm_get_last_write_size(PyObject* self, PyObject* args)
+{
+	return PyInt_FromLong((long)vmcpu.vm_last_write_size);
+}
+
+
+PyObject* vm_reset_exception(PyObject* self, PyObject* args)
+{
+	vmcpu.vm_exception_flags = 0;	
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+PyObject* vm_get_exception(PyObject* self, PyObject* args)
+{
+	return PyInt_FromLong((long)vmcpu.vm_exception_flags);
+}
+
+PyObject * vm_init_regs(PyObject* self, PyObject* args)
+{
+    _vm_init_regs();
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+PyObject* vm_push_uint32_t(PyObject* self, PyObject *args)
+{
+    PyObject* p;
+    int item;
+    if (!PyArg_ParseTuple(args, "I", &item))
+	    return NULL;
+    p = _vm_push_uint32_t(item);
+    return p;
+}
+
+
+PyObject* vm_pop_uint32_t(PyObject* self, PyObject* args)
+{
+    PyObject* p;
+    p = _vm_pop_uint32_t();
+    return p;
+}
+
+/*
+PyObject* vm_put_str(PyObject *item)
+{
+    PyObject* p;
+    p = _vm_put_str(item);
+    return p;
+}
+*/
+
+PyObject* vm_set_mem(PyObject* self, PyObject* args)
+{
+    PyObject* p;
+    PyObject *addr;
+    PyObject *item_str;
+    if (!PyArg_ParseTuple(args, "OO", &addr, &item_str))
+	    return NULL;
+
+    p = _vm_set_mem(addr, item_str);
+    return p;
+}
+
+PyObject* vm_set_mem_access(PyObject* self, PyObject* args)
+{
+    PyObject* p;
+    PyObject *addr;
+    PyObject *access;
+    if (!PyArg_ParseTuple(args, "OO", &addr, &access))
+	    return NULL;
+
+    p = _vm_set_mem_access(addr, access);
+    return p;
+}
+
+
+PyObject* vm_get_str(PyObject* self, PyObject* args)
+{
+    PyObject* p;
+    PyObject *item;
+    PyObject *item_len;
+    if (!PyArg_ParseTuple(args, "OO", &item, &item_len))
+	    return NULL;
+
+    p = _vm_get_str(item, item_len);
+    return p;
+}
+
+
+PyObject* vm_get_gpreg(PyObject* self, PyObject* args)
+{
+    PyObject* p;
+    p = _vm_get_gpreg();
+    return p;
+}
+
+PyObject* vm_set_gpreg(PyObject *self, PyObject *args)
+{
+	PyObject* dict;
+	if (!PyArg_ParseTuple(args, "O", &dict))
+		return NULL;
+	_vm_set_gpreg(dict);
+	Py_INCREF(Py_None);
+	return Py_None;
+
+}
+
+PyObject* init_memory_page_pool_py(PyObject* self, PyObject* args)
+{
+    init_memory_page_pool();
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+PyObject* init_code_bloc_pool_py(PyObject* self, PyObject* args)
+{
+    init_code_bloc_pool();
+    Py_INCREF(Py_None);
+    return Py_None;
+
+}
+
+PyObject* vm_add_memory_page(PyObject* self, PyObject* args)
+{
+	PyObject *item;
+	PyObject *access;
+	PyObject *item_str;
+	PyObject* p;
+	if (!PyArg_ParseTuple(args, "OOO", &item, &access, &item_str))
+		return NULL;
+	p = _vm_add_memory_page(item, access, item_str);
+	return p;
+}
+
+
+
+PyObject* dump_memory_page_pool_py(PyObject* self, PyObject* args)
+{
+     dump_memory_page_pool();
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+PyObject* vm_get_all_memory(PyObject* self, PyObject* args)
+{
+	PyObject *o;
+	o = _vm_get_all_memory();
+	return o;
+}
+
+
+PyObject* reset_memory_page_pool_py(PyObject* self, PyObject* args)
+{
+    reset_memory_page_pool();
+    Py_INCREF(Py_None);
+    return Py_None;
+
+}
+
+PyObject* reset_code_bloc_pool_py(PyObject* self, PyObject* args)
+{
+    reset_code_bloc_pool();
+    Py_INCREF(Py_None);
+    return Py_None;
+
+}
+
+
+PyObject* call_pyfunc_from_globals(PyObject* self, PyObject* args)
+{
+	PyObject* p;
+	char* funcname;
+	if (!PyArg_ParseTuple(args, "s", &funcname))
+	    return NULL;
+
+	p = _call_pyfunc_from_globals(funcname);
+	return p;
+}
+
+
+PyObject* _vm_add_code_bloc(PyObject* self, PyObject* args)
+{
+	PyObject *item1;
+	PyObject *item2;
+    int ret = 0x1337beef;
+    unsigned int ad_start, ad_stop, ad_code = 0;
+
+    struct code_bloc_node * cbp;
+
+    if (!PyArg_ParseTuple(args, "OO", &item1, &item2))
+	    return NULL;
+
+
+    if (PyInt_Check(item1)){
+        ad_start = (unsigned int)PyInt_AsLong(item1);
+    }
+    else if (PyLong_Check(item1)){
+        ad_start = (unsigned int)PyInt_AsUnsignedLongLongMask(item1);
+    }
+    else{
+        RAISE(PyExc_TypeError,"arg1 must be int");
+    }
+
+
+
+    if (PyInt_Check(item2)){
+        ad_stop = (unsigned int)PyInt_AsLong(item2);
+    }
+    else if (PyLong_Check(item2)){
+        ad_stop = (unsigned int)PyInt_AsUnsignedLongLongMask(item2);
+    }
+    else{
+        RAISE(PyExc_TypeError,"arg2 must be int");
+    }
+    /*
+    if (PyInt_Check(item3)){
+        ad_code = (unsigned int)PyInt_AsLong(item3);
+    }
+    else if (PyLong_Check(item3)){
+        ad_code = (unsigned int)PyInt_AsUnsignedLongLongMask(item3);
+    }
+    else{
+        RAISE(PyExc_TypeError,"arg3 must be int");
+    }
+    */
+    
+    //printf("add code bloc %X %X\n", ad_start, ad_stop);
+
+
+    cbp = create_code_bloc_node(ad_start, ad_stop);
+    cbp->ad_start = ad_start;
+    cbp->ad_stop = ad_stop;
+    cbp->ad_code = ad_code;
+
+
+    add_code_bloc(cbp);
+
+    return PyInt_FromLong((long)ret);
+}
+
+
+PyObject* vm_add_code_bloc(PyObject *item1, PyObject *item2)//, PyObject *item3)
+{
+	PyObject* p;
+	p = _vm_add_code_bloc(item1, item2);//, item3);
+	return p;
+}
+
+PyObject* dump_code_bloc_pool_py(void)
+{
+	dump_code_bloc_pool();
+	Py_INCREF(Py_None);
+	return Py_None;
+
+}
+
+
+
+PyObject* vm_get_cpu_state(void)
+{
+	PyObject* o;
+	o = _vm_get_cpu_state();
+	return o;
+}
+
+PyObject*  vm_set_cpu_state(PyObject * s_cpustate)
+{
+	PyObject *o;
+	o = _vm_set_cpu_state(s_cpustate);
+	return o;
+		
+}
+
+
+
+unsigned int get_memory_page_max_address_py(void)
+{
+	unsigned int ret;
+	ret = _get_memory_page_max_address_py();
+	return ret;
+}
+
+PyObject * vm_get_memory_page_max_address(PyObject* self, PyObject* args)
+{
+	PyObject* v;
+	unsigned int tmp;
+
+	tmp = get_memory_page_max_address_py();
+	v = PyInt_FromLong((long)tmp);
+	return v;
+}
+
+unsigned int get_memory_page_max_user_address_py(void)
+{
+	unsigned int ret;
+	ret = _get_memory_page_max_user_address_py();
+	return ret;
+}
+
+
+unsigned int get_memory_page_from_min_ad_py(unsigned int size)
+{
+	unsigned int ret;
+	ret = _get_memory_page_from_min_ad_py(size);
+	return ret;
+
+}
+
+
+PyObject* _vm_exec_blocs(PyObject* self, PyObject* args)
+{
+	PyObject* b;
+	PyObject* module;
+	PyObject* func;
+	PyObject* meip;
+	unsigned int tmp;
+
+	PyObject* my_eip;
+	PyObject* known_blocs;
+	PyObject* e;
+
+	if (!PyArg_ParseTuple(args, "OO", &my_eip, &known_blocs))
+		return NULL;
+
+	if(!PyDict_Check(known_blocs))
+		RAISE(PyExc_TypeError, "arg must be dict");
+
+	if (PyInt_Check(my_eip)){
+		tmp = (unsigned int)PyInt_AsLong(my_eip);
+	}
+	else if (PyLong_Check(my_eip)){
+		tmp = (unsigned int)PyInt_AsUnsignedLongLongMask(my_eip);
+	}
+	else{
+		RAISE(PyExc_TypeError,"arg1 must be int");
+	}
+ 
+	meip = PyInt_FromLong((long)tmp);
+	while (1){
+		b = PyDict_GetItem(known_blocs, meip);
+		if (b == NULL)
+			return meip;
+		module = PyObject_GetAttrString(b, "module_c");
+		if (module == NULL)
+			return meip;
+		//Py_DECREF(b);
+		
+		func = PyObject_GetAttrString(module, "func");
+		if (func == NULL)
+			return meip;
+
+		Py_DECREF(module);
+
+		
+		if (!PyCallable_Check (func)) {
+			printf("function not callable\n");
+			exit(0);    
+		}
+		Py_DECREF(meip);
+		meip = PyObject_CallObject (func, NULL);
+
+		Py_DECREF(func);
+		e = PyErr_Occurred ();
+		if (e){
+			printf("exception\n");
+			return meip;
+		}
+
+		if (vmcpu.vm_exception_flags)
+			return meip;
+
+	}
+	
+}
+
+
+PyObject* vm_exec_blocs(PyObject* self, PyObject* args)
+{
+	PyObject* my_eip;
+	my_eip = _vm_exec_blocs(self, args);
+	return my_eip;
+}
+
+
+
+PyObject* vm_exec_bloc(PyObject* self, PyObject* args)
+{
+	PyObject* b;
+	PyObject* module;
+	PyObject* func;
+	PyObject* meip;
+	unsigned int tmp;
+
+	PyObject* my_eip;
+	PyObject* known_blocs;
+	PyObject* e;
+
+	if (!PyArg_ParseTuple(args, "OO", &my_eip, &known_blocs))
+		return NULL;
+
+
+	if (PyInt_Check(my_eip)){
+		tmp = (unsigned int)PyInt_AsLong(my_eip);
+	}
+	else if (PyLong_Check(my_eip)){
+		tmp = (unsigned int)PyInt_AsUnsignedLongLongMask(my_eip);
+	}
+	else{
+		RAISE(PyExc_TypeError,"arg1 must be int");
+	}
+
+
+
+	//printf("eip val: %x\n", tmp);
+	meip = PyInt_FromLong((long)tmp);
+	//printf("x %p\n", meip);
+	b = PyDict_GetItem(known_blocs, my_eip);
+	if (b == NULL)
+		return meip;
+	
+	module = PyObject_GetAttrString(b, "module_c");
+	if (module == NULL)
+		return meip;
+	//Py_DECREF(b);
+	
+	func = PyObject_GetAttrString(module, "func");
+	if (func == NULL)
+		return meip;
+	
+	Py_DECREF(module);
+	
+	
+	if (!PyCallable_Check (func)) {
+		printf("function not callable\n");
+		exit(0);    
+	}
+	Py_DECREF(meip);
+	meip = PyObject_CallObject (func, NULL);
+	
+	Py_DECREF(func);
+	e = PyErr_Occurred ();
+	if (e){
+		printf("exception\n");
+		return meip;
+	}
+
+	return meip;
+	
+}
+
+/*
+PyObject* vm_exec_bloc(PyObject* my_eip, PyObject* known_blocs)
+{
+	my_eip = _vm_exec_bloc(my_eip, known_blocs);
+	return my_eip;
+}
+*/
+
+
+static PyObject *CodenatError;
+
+
+static PyMethodDef CodenatMethods[] = {
+    {"vm_init_regs",  vm_init_regs, METH_VARARGS,
+     "init regs vm."},
+    {"vm_push_uint32_t", vm_push_uint32_t, METH_VARARGS,
+     "push on vm stack"},
+    {"dump_gpregs_py", dump_gpregs_py, METH_VARARGS,
+     "x"},
+
+
+    {"vm_push_uint32_t", vm_push_uint32_t, METH_VARARGS,
+     "x"},
+    {"vm_pop_uint32_t",vm_pop_uint32_t, METH_VARARGS,
+     "X"},
+    {"vm_get_gpreg", vm_get_gpreg, METH_VARARGS,
+     "X"},
+    {"vm_set_gpreg",vm_set_gpreg, METH_VARARGS,
+     "X"},
+    {"vm_init_regs",vm_init_regs, METH_VARARGS,
+     "X"},
+    {"dump_gpregs_py", dump_gpregs_py, METH_VARARGS,
+     "X"},
+
+    {"init_memory_page_pool_py", init_memory_page_pool_py, METH_VARARGS,
+     "X"},
+    {"init_code_bloc_pool_py",init_code_bloc_pool_py, METH_VARARGS,
+     "X"},
+    {"vm_set_mem_access", vm_set_mem_access, METH_VARARGS,
+     "X"},
+    {"vm_set_mem", vm_set_mem, METH_VARARGS,
+     "X"},
+    {"vm_add_code_bloc",vm_add_code_bloc, METH_VARARGS,
+     "X"},
+    {"vm_exec_bloc",vm_exec_bloc, METH_VARARGS,
+     "X"},
+    {"vm_exec_blocs",vm_exec_blocs, METH_VARARGS,
+     "X"},
+    {"vm_get_str", vm_get_str, METH_VARARGS,
+     "X"},
+    {"vm_add_memory_page",vm_add_memory_page, METH_VARARGS,
+     "X"},
+    {"vm_reset_exception", vm_reset_exception, METH_VARARGS,
+     "X"},
+    {"dump_memory_page_pool_py", dump_memory_page_pool_py, METH_VARARGS,
+     "X"},
+    {"vm_get_all_memory",vm_get_all_memory, METH_VARARGS,
+     "X"},
+    {"reset_memory_page_pool_py", reset_memory_page_pool_py, METH_VARARGS,
+     "X"},
+    {"reset_code_bloc_pool_py", reset_code_bloc_pool_py, METH_VARARGS,
+     "X"},
+    {"call_pyfunc_from_globals",call_pyfunc_from_globals, METH_VARARGS,
+     "X"},
+
+    {"vm_get_exception",vm_get_exception, METH_VARARGS,
+     "X"},
+    {"vm_get_exception",vm_get_exception, METH_VARARGS,
+     "X"},
+    {"vm_get_last_write_ad", vm_get_last_write_ad, METH_VARARGS,
+     "X"},
+    {"vm_get_last_write_size",vm_get_last_write_size, METH_VARARGS,
+     "X"},
+    {"vm_get_memory_page_max_address",vm_get_memory_page_max_address, METH_VARARGS,
+     "X"},
+
+    {NULL, NULL, 0, NULL}        /* Sentinel */
+
+};
+
+
+PyMODINIT_FUNC
+initlibcodenat_interface(void)
+{
+    PyObject *m;
+
+    m = Py_InitModule("libcodenat_interface", CodenatMethods);
+    if (m == NULL)
+        return;
+
+    CodenatError = PyErr_NewException("codenat.error", NULL, NULL);
+    Py_INCREF(CodenatError);
+    PyModule_AddObject(m, "error", CodenatError);
+}
+
diff --git a/miasm/tools/emul_lib/libcodenat_tcc.c b/miasm/tools/emul_lib/libcodenat_tcc.c
new file mode 100644
index 00000000..c9766388
--- /dev/null
+++ b/miasm/tools/emul_lib/libcodenat_tcc.c
@@ -0,0 +1,139 @@
+/*
+** Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License along
+** with this program; if not, write to the Free Software Foundation, Inc.,
+** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include <Python.h>
+
+#include <libtcc.h>
+
+
+
+/* tcc global state */
+TCCState *tcc_state = NULL;
+
+
+char *emul_lib_dir = NULL;
+char *emul_lib_path = NULL;
+char *emul_libpython_dir = NULL;
+
+PyObject* tcc_set_emul_lib_path(PyObject* self, PyObject* args)
+{
+	char* libdir;
+	char* libpath;
+	char* libpython_dir;
+	if (!PyArg_ParseTuple(args, "sss", &libdir, &libpath, &libpython_dir))
+		return NULL;
+	
+	emul_lib_dir = (char*)malloc(strlen(libdir)+1);
+	emul_lib_path = (char*)malloc(strlen(libpath)+1);
+	emul_libpython_dir = (char*)malloc(strlen(libpython_dir)+1);
+	strcpy(emul_lib_dir, libdir);
+	strcpy(emul_lib_path, libpath);
+	strcpy(emul_libpython_dir, libpython_dir);
+	return Py_None;
+}
+
+void tcc_init_state(void)
+{
+	
+	tcc_state = tcc_new();
+	if (!tcc_state) {
+		fprintf(stderr, "Impossible de creer un contexte TCC\n");
+		exit(1);
+        }
+        tcc_set_output_type(tcc_state, TCC_OUTPUT_MEMORY);
+
+	tcc_add_include_path(tcc_state, "/usr/include/python2.6");
+	tcc_add_include_path(tcc_state, emul_lib_dir);
+	tcc_add_library_path(tcc_state, emul_lib_dir);
+	tcc_add_library_path(tcc_state, emul_libpython_dir);
+	tcc_add_file(tcc_state, emul_lib_path);
+}
+
+
+
+
+PyObject*  tcc_exec_bloc(PyObject* self, PyObject* args)
+{
+	int (*func)(void);
+
+	unsigned long ret;
+	if (!PyArg_ParseTuple(args, "i", &func))
+		return NULL;
+	ret = func();
+	return PyInt_FromLong((long)ret);
+}
+
+PyObject* tcc_compil(PyObject* self, PyObject* args)
+{
+	char* func_name;
+	char* func_code;
+        int (*entry)(void);
+        void *mem;
+        int size;
+
+	if (!PyArg_ParseTuple(args, "ss", &func_name, &func_code))
+		return NULL;
+
+	tcc_init_state();
+        if (tcc_compile_string(tcc_state, func_code) != 0) {
+                printf("Erreur de compilation !\n");
+                exit(0);
+        }
+	
+        size = tcc_relocate(tcc_state, NULL);
+        if (size == -1)
+                exit(0);
+
+        mem = malloc(size);
+        tcc_relocate(tcc_state, mem);
+
+        entry = tcc_get_symbol(tcc_state, func_name);
+	
+	tcc_delete(tcc_state);
+
+	return PyInt_FromLong((long)entry);
+
+}
+
+
+static PyObject *TccError;
+
+
+static PyMethodDef TccMethods[] = {
+    {"tcc_set_emul_lib_path",  tcc_set_emul_lib_path, METH_VARARGS,
+     "init tcc path"},
+    {"tcc_exec_bloc",  tcc_exec_bloc, METH_VARARGS,
+     "tcc exec bloc"},
+    {"tcc_compil",  tcc_compil, METH_VARARGS,
+     "tcc compil"},
+    {NULL, NULL, 0, NULL}        /* Sentinel */
+};
+    
+PyMODINIT_FUNC
+initlibcodenat_tcc(void)
+{
+    PyObject *m;
+
+    m = Py_InitModule("libcodenat_tcc", TccMethods);
+    if (m == NULL)
+        return;
+
+    TccError = PyErr_NewException("tcc.error", NULL, NULL);
+    Py_INCREF(TccError);
+    PyModule_AddObject(m, "error", TccError);
+}
+
diff --git a/miasm/tools/emul_lib/main.c b/miasm/tools/emul_lib/main.c
new file mode 100644
index 00000000..e088191d
--- /dev/null
+++ b/miasm/tools/emul_lib/main.c
@@ -0,0 +1,43 @@
+/*
+** Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License along
+** with this program; if not, write to the Free Software Foundation, Inc.,
+** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include <Python.h>
+#include "queue.h"
+#include "libcodenat.h"
+int main()
+{
+	memory_page* mp;
+	struct memory_page_node * mpn;
+	
+	init_memory_page_pool();
+	dump_memory_page_pool();
+	
+	
+	mp = create_memory_page(0x1000, 0x10);	
+	mpn = create_memory_page_node(mp);
+	add_memory_page(mpn);
+
+	dump_memory_page_pool();
+
+
+	mp = create_memory_page(0x2000, 0x10);	
+	mpn = create_memory_page_node(mp);
+	add_memory_page(mpn);
+	dump_memory_page_pool();
+
+	return 0;
+}
diff --git a/miasm/tools/emul_lib/queue.h b/miasm/tools/emul_lib/queue.h
new file mode 100644
index 00000000..0caf72fb
--- /dev/null
+++ b/miasm/tools/emul_lib/queue.h
@@ -0,0 +1,553 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)queue.h	8.5 (Berkeley) 8/20/94
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define	_SYS_QUEUE_H_
+
+//#include <sys/cdefs.h>
+
+/*
+ * This file defines four types of data structures: singly-linked lists,
+ * singly-linked tail queues, lists and tail queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction.  Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ *				SLIST	LIST	STAILQ	TAILQ
+ * _HEAD			+	+	+	+
+ * _HEAD_INITIALIZER		+	+	+	+
+ * _ENTRY			+	+	+	+
+ * _INIT			+	+	+	+
+ * _EMPTY			+	+	+	+
+ * _FIRST			+	+	+	+
+ * _NEXT			+	+	+	+
+ * _PREV			-	-	-	+
+ * _LAST			-	-	+	+
+ * _FOREACH			+	+	+	+
+ * _FOREACH_SAFE		+	+	+	+
+ * _FOREACH_REVERSE		-	-	-	+
+ * _FOREACH_REVERSE_SAFE	-	-	-	+
+ * _INSERT_HEAD			+	+	+	+
+ * _INSERT_BEFORE		-	+	-	+
+ * _INSERT_AFTER		+	+	+	+
+ * _INSERT_TAIL			-	-	+	+
+ * _CONCAT			-	-	+	+
+ * _REMOVE_HEAD			+	-	+	-
+ * _REMOVE			+	+	+	+
+ *
+ */
+#define	QUEUE_MACRO_DEBUG 0
+#if QUEUE_MACRO_DEBUG
+/* Store the last 2 places the queue element or head was altered */
+struct qm_trace {
+	char * lastfile;
+	int lastline;
+	char * prevfile;
+	int prevline;
+};
+
+#define	TRACEBUF	struct qm_trace trace;
+#define	TRASHIT(x)	do {(x) = (void *)-1;} while (0)
+
+#define	QMD_TRACE_HEAD(head) do {					\
+	(head)->trace.prevline = (head)->trace.lastline;		\
+	(head)->trace.prevfile = (head)->trace.lastfile;		\
+	(head)->trace.lastline = __LINE__;				\
+	(head)->trace.lastfile = __FILE__;				\
+} while (0)
+
+#define	QMD_TRACE_ELEM(elem) do {					\
+	(elem)->trace.prevline = (elem)->trace.lastline;		\
+	(elem)->trace.prevfile = (elem)->trace.lastfile;		\
+	(elem)->trace.lastline = __LINE__;				\
+	(elem)->trace.lastfile = __FILE__;				\
+} while (0)
+
+#else
+#define	QMD_TRACE_ELEM(elem)
+#define	QMD_TRACE_HEAD(head)
+#define	TRACEBUF
+#define	TRASHIT(x)
+#endif	/* QUEUE_MACRO_DEBUG */
+
+/*
+ * Singly-linked List declarations.
+ */
+#define	SLIST_HEAD(name, type)						\
+struct name {								\
+	struct type *slh_first;	/* first element */			\
+}
+
+#define	SLIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define	SLIST_ENTRY(type)						\
+struct {								\
+	struct type *sle_next;	/* next element */			\
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define	SLIST_EMPTY(head)	((head)->slh_first == NULL)
+
+#define	SLIST_FIRST(head)	((head)->slh_first)
+
+#define	SLIST_FOREACH(var, head, field)					\
+	for ((var) = SLIST_FIRST((head));				\
+	    (var);							\
+	    (var) = SLIST_NEXT((var), field))
+
+#define	SLIST_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = SLIST_FIRST((head));				\
+	    (var) && ((tvar) = SLIST_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	SLIST_FOREACH_PREVPTR(var, varp, head, field)			\
+	for ((varp) = &SLIST_FIRST((head));				\
+	    ((var) = *(varp)) != NULL;					\
+	    (varp) = &SLIST_NEXT((var), field))
+
+#define	SLIST_INIT(head) do {						\
+	SLIST_FIRST((head)) = NULL;					\
+} while (0)
+
+#define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
+	SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);	\
+	SLIST_NEXT((slistelm), field) = (elm);				\
+} while (0)
+
+#define	SLIST_INSERT_HEAD(head, elm, field) do {			\
+	SLIST_NEXT((elm), field) = SLIST_FIRST((head));			\
+	SLIST_FIRST((head)) = (elm);					\
+} while (0)
+
+#define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
+
+#define	SLIST_REMOVE(head, elm, type, field) do {			\
+	if (SLIST_FIRST((head)) == (elm)) {				\
+		SLIST_REMOVE_HEAD((head), field);			\
+	}								\
+	else {								\
+		struct type *curelm = SLIST_FIRST((head));		\
+		while (SLIST_NEXT(curelm, field) != (elm))		\
+			curelm = SLIST_NEXT(curelm, field);		\
+		SLIST_NEXT(curelm, field) =				\
+		    SLIST_NEXT(SLIST_NEXT(curelm, field), field);	\
+	}								\
+} while (0)
+
+#define	SLIST_REMOVE_HEAD(head, field) do {				\
+	SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);	\
+} while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define	STAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *stqh_first;/* first element */			\
+	struct type **stqh_last;/* addr of last next element */		\
+}
+
+#define	STAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).stqh_first }
+
+#define	STAILQ_ENTRY(type)						\
+struct {								\
+	struct type *stqe_next;	/* next element */			\
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define	STAILQ_CONCAT(head1, head2) do {				\
+	if (!STAILQ_EMPTY((head2))) {					\
+		*(head1)->stqh_last = (head2)->stqh_first;		\
+		(head1)->stqh_last = (head2)->stqh_last;		\
+		STAILQ_INIT((head2));					\
+	}								\
+} while (0)
+
+#define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
+
+#define	STAILQ_FIRST(head)	((head)->stqh_first)
+
+#define	STAILQ_FOREACH(var, head, field)				\
+	for((var) = STAILQ_FIRST((head));				\
+	   (var);							\
+	   (var) = STAILQ_NEXT((var), field))
+
+
+#define	STAILQ_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = STAILQ_FIRST((head));				\
+	    (var) && ((tvar) = STAILQ_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	STAILQ_INIT(head) do {						\
+	STAILQ_FIRST((head)) = NULL;					\
+	(head)->stqh_last = &STAILQ_FIRST((head));			\
+} while (0)
+
+#define	STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\
+	if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
+		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
+	STAILQ_NEXT((tqelm), field) = (elm);				\
+} while (0)
+
+#define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL)	\
+		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
+	STAILQ_FIRST((head)) = (elm);					\
+} while (0)
+
+#define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
+	STAILQ_NEXT((elm), field) = NULL;				\
+	*(head)->stqh_last = (elm);					\
+	(head)->stqh_last = &STAILQ_NEXT((elm), field);			\
+} while (0)
+
+#define	STAILQ_LAST(head, type, field)					\
+	(STAILQ_EMPTY((head)) ?						\
+		NULL :							\
+	        ((struct type *)					\
+		((char *)((head)->stqh_last) - __offsetof(struct type, field))))
+
+#define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
+
+#define	STAILQ_REMOVE(head, elm, type, field) do {			\
+	if (STAILQ_FIRST((head)) == (elm)) {				\
+		STAILQ_REMOVE_HEAD((head), field);			\
+	}								\
+	else {								\
+		struct type *curelm = STAILQ_FIRST((head));		\
+		while (STAILQ_NEXT(curelm, field) != (elm))		\
+			curelm = STAILQ_NEXT(curelm, field);		\
+		if ((STAILQ_NEXT(curelm, field) =			\
+		     STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
+			(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
+	}								\
+} while (0)
+
+#define	STAILQ_REMOVE_HEAD(head, field) do {				\
+	if ((STAILQ_FIRST((head)) =					\
+	     STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)		\
+		(head)->stqh_last = &STAILQ_FIRST((head));		\
+} while (0)
+
+#define	STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do {			\
+	if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL)	\
+		(head)->stqh_last = &STAILQ_FIRST((head));		\
+} while (0)
+
+/*
+ * List declarations.
+ */
+#define	LIST_HEAD(name, type)						\
+struct name {								\
+	struct type *lh_first;	/* first element */			\
+}
+
+#define	LIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define	LIST_ENTRY(type)						\
+struct {								\
+	struct type *le_next;	/* next element */			\
+	struct type **le_prev;	/* address of previous next element */	\
+}
+
+/*
+ * List functions.
+ */
+
+#define	LIST_EMPTY(head)	((head)->lh_first == NULL)
+
+#define	LIST_FIRST(head)	((head)->lh_first)
+
+#define	LIST_FOREACH(var, head, field)					\
+	for ((var) = LIST_FIRST((head));				\
+	    (var);							\
+	    (var) = LIST_NEXT((var), field))
+
+#define	LIST_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = LIST_FIRST((head));				\
+	    (var) && ((tvar) = LIST_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	LIST_INIT(head) do {						\
+	LIST_FIRST((head)) = NULL;					\
+} while (0)
+
+#define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
+	if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
+		LIST_NEXT((listelm), field)->field.le_prev =		\
+		    &LIST_NEXT((elm), field);				\
+	LIST_NEXT((listelm), field) = (elm);				\
+	(elm)->field.le_prev = &LIST_NEXT((listelm), field);		\
+} while (0)
+
+#define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.le_prev = (listelm)->field.le_prev;		\
+	LIST_NEXT((elm), field) = (listelm);				\
+	*(listelm)->field.le_prev = (elm);				\
+	(listelm)->field.le_prev = &LIST_NEXT((elm), field);		\
+} while (0)
+
+#define	LIST_INSERT_HEAD(head, elm, field) do {				\
+	if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)	\
+		LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
+	LIST_FIRST((head)) = (elm);					\
+	(elm)->field.le_prev = &LIST_FIRST((head));			\
+} while (0)
+
+#define	LIST_NEXT(elm, field)	((elm)->field.le_next)
+
+#define	LIST_REMOVE(elm, field) do {					\
+	if (LIST_NEXT((elm), field) != NULL)				\
+		LIST_NEXT((elm), field)->field.le_prev = 		\
+		    (elm)->field.le_prev;				\
+	*(elm)->field.le_prev = LIST_NEXT((elm), field);		\
+} while (0)
+
+/*
+ * Tail queue declarations.
+ */
+#define	TAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *tqh_first;	/* first element */			\
+	struct type **tqh_last;	/* addr of last next element */		\
+	TRACEBUF							\
+}
+
+#define	TAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).tqh_first }
+
+#define	TAILQ_ENTRY(type)						\
+struct {								\
+	struct type *tqe_next;	/* next element */			\
+	struct type **tqe_prev;	/* address of previous next element */	\
+	TRACEBUF							\
+}
+
+/*
+ * Tail queue functions.
+ */
+#define	TAILQ_CONCAT(head1, head2, field) do {				\
+	if (!TAILQ_EMPTY(head2)) {					\
+		*(head1)->tqh_last = (head2)->tqh_first;		\
+		(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last;	\
+		(head1)->tqh_last = (head2)->tqh_last;			\
+		TAILQ_INIT((head2));					\
+		QMD_TRACE_HEAD(head);					\
+		QMD_TRACE_HEAD(head2);					\
+	}								\
+} while (0)
+
+#define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)
+
+#define	TAILQ_FIRST(head)	((head)->tqh_first)
+
+#define	TAILQ_FOREACH(var, head, field)					\
+	for ((var) = TAILQ_FIRST((head));				\
+	    (var);							\
+	    (var) = TAILQ_NEXT((var), field))
+
+#define	TAILQ_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = TAILQ_FIRST((head));				\
+	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+
+#define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
+	for ((var) = TAILQ_LAST((head), headname);			\
+	    (var);							\
+	    (var) = TAILQ_PREV((var), headname, field))
+
+#define	TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)	\
+	for ((var) = TAILQ_LAST((head), headname);			\
+	    (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1);	\
+	    (var) = (tvar))
+
+#define	TAILQ_INIT(head) do {						\
+	TAILQ_FIRST((head)) = NULL;					\
+	(head)->tqh_last = &TAILQ_FIRST((head));			\
+	QMD_TRACE_HEAD(head);						\
+} while (0)
+
+#define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
+		    &TAILQ_NEXT((elm), field);				\
+	else {								\
+		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
+		QMD_TRACE_HEAD(head);					\
+	}								\
+	TAILQ_NEXT((listelm), field) = (elm);				\
+	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);		\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+	QMD_TRACE_ELEM(&listelm->field);				\
+} while (0)
+
+#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
+	TAILQ_NEXT((elm), field) = (listelm);				\
+	*(listelm)->field.tqe_prev = (elm);				\
+	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);		\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+	QMD_TRACE_ELEM(&listelm->field);				\
+} while (0)
+
+#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
+		TAILQ_FIRST((head))->field.tqe_prev =			\
+		    &TAILQ_NEXT((elm), field);				\
+	else								\
+		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
+	TAILQ_FIRST((head)) = (elm);					\
+	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
+	QMD_TRACE_HEAD(head);						\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+} while (0)
+
+#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
+	TAILQ_NEXT((elm), field) = NULL;				\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
+	QMD_TRACE_HEAD(head);						\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+} while (0)
+
+#define	TAILQ_LAST(head, headname)					\
+	(*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define	TAILQ_PREV(elm, headname, field)				\
+	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#define	TAILQ_REMOVE(head, elm, field) do {				\
+	if ((TAILQ_NEXT((elm), field)) != NULL)				\
+		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
+		    (elm)->field.tqe_prev;				\
+	else {								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+		QMD_TRACE_HEAD(head);					\
+	}								\
+	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
+	TRASHIT((elm)->field.tqe_next);					\
+	TRASHIT((elm)->field.tqe_prev);					\
+	QMD_TRACE_ELEM(&(elm)->field);					\
+} while (0)
+
+
+#ifdef _KERNEL
+
+/*
+ * XXX insque() and remque() are an old way of handling certain queues.
+ * They bogusly assumes that all queue heads look alike.
+ */
+
+struct quehead {
+	struct quehead *qh_link;
+	struct quehead *qh_rlink;
+};
+
+#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+
+static __inline void
+insque(void *a, void *b)
+{
+	struct quehead *element = (struct quehead *)a,
+		 *head = (struct quehead *)b;
+
+	element->qh_link = head->qh_link;
+	element->qh_rlink = head;
+	head->qh_link = element;
+	element->qh_link->qh_rlink = element;
+}
+
+static __inline void
+remque(void *a)
+{
+	struct quehead *element = (struct quehead *)a;
+
+	element->qh_link->qh_rlink = element->qh_rlink;
+	element->qh_rlink->qh_link = element->qh_link;
+	element->qh_rlink = 0;
+}
+
+#else /* !(__GNUC__ || __INTEL_COMPILER) */
+
+void	insque(void *a, void *b);
+void	remque(void *a);
+
+#endif /* __GNUC__ || __INTEL_COMPILER */
+
+#endif /* _KERNEL */
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/miasm/tools/func_analyser.py b/miasm/tools/func_analyser.py
new file mode 100755
index 00000000..aa34964b
--- /dev/null
+++ b/miasm/tools/func_analyser.py
@@ -0,0 +1,485 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+from x86_escape import opcode_factory, bin_stream, instr_dis
+from asmbloc import *
+from parse_asm import *
+import shlex
+from ia32_sem import *
+from copy import copy
+import pefile
+import pprint
+
+
+class imp_func:
+    def __init__(self, address, name, name_dll, unstack=None):
+        self.address = address
+        self.name = name
+        self.dllname = name_dll
+        self.unstack = unstack
+    def __str__(self):
+        return hex(self.address)+' '+str(self.name)+' '+str(self.dllname)+' '+str(self.unstack)
+
+x86mnemo = opcode_factory()
+
+fname = "calc.exe"
+f = open(fname, 'rb')
+pe =  pefile.PE(fname)
+
+pool_import_func = {}
+print "read import"
+if hasattr(pe, "DIRECTORY_ENTRY_IMPORT"):
+  for entry in pe.DIRECTORY_ENTRY_IMPORT:
+    #print entry.dll
+    for imp in entry.imports:
+      #print '\t', hex(imp.address), imp.name
+      pool_import_func[imp.address] = imp_func(imp.address, imp.name, entry.dll)
+
+dll_pe_cache = {}
+dll_rep = "dlls/"
+def init_dll_cache(dllname):
+    global dll_pe_cache
+    print "read %s"%dllname
+    pe =  pefile.PE(dll_rep+dllname)
+    dll_pe_cache[dllname] = pe
+    print 'read ok'
+
+
+def read_dll_export(dll_name, func_name):
+    global dll_pe_cache
+    fname = dll_name.lower()
+    print "read export", fname
+
+    if not fname in dll_pe_cache:
+        print 'not loaded dll'
+        init_dll_cache(fname)
+        
+    pe = dll_pe_cache[fname]
+    """
+    pe =  pefile.PE(fname)
+    """
+    f_tmp = open(dll_rep+fname, 'rb')
+
+    if not hasattr(pe, "DIRECTORY_ENTRY_EXPORT"):
+        return None
+
+    dict_export = dict([(exp.name, exp) for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols])
+    if not func_name in dict_export:
+        return None
+
+    offset = pe.get_offset_from_rva(dict_export[func_name].address)
+    print "offset", hex(offset)
+    in_str_tmp = bin_stream(f_tmp, offset)
+    symbol_pool_tmp = asm_symbol_pool()
+    all_bloc_tmp = dis_bloc_all(x86mnemo, in_str_tmp, in_str_tmp.offset, [], symbol_pool_tmp, follow_call = False)
+    ret = quick_ret_analyse(offset, all_bloc_tmp)
+    
+    return ret
+
+
+
+print "disasm bin follow "
+#0x366
+#0x2F0
+#0x3B0
+
+#open file
+start_dis = 0x9F09#0xB50
+in_str = bin_stream(f, start_dis)
+
+#disasm binary
+job_done = []
+symbol_pool = asm_symbol_pool()
+all_bloc = dis_bloc_all(x86mnemo, in_str, in_str.offset, job_done, symbol_pool, follow_call = False)
+print "symbols:"
+print symbol_pool
+
+g = bloc2graph(all_bloc)
+open("graph.txt" , "w").write(g)
+
+jcc = ['jz', 'je', 'jnz', 'jp', 'jnp', 'jg', 'jge', 'ja', 'jae', 'jb', 'jbe', 'jl', 'jle', 'js', 'jns', 'loop']
+
+eax_i = ExprId('eax_i')
+ebx_i = ExprId('ebx_i')
+ecx_i = ExprId('ecx_i')
+edx_i = ExprId('edx_i')
+esi_i = ExprId('esi_i')
+edi_i = ExprId('edi_i')
+esp_i = ExprId('esp_i')
+ebp_i = ExprId('ebp_i')
+
+MEM_GLOB = ExprId('MEM_GLOB')
+
+def dump_pool(p):
+    print '/-------------\\'
+    for x in p:
+        print x, p[x]
+    print '\\_____________/'
+    
+
+def hook_mem_read(evaluator, src):
+    evaluator.log.warn('mem read %s'%str(src))
+    src_address = evaluator.eval_expr(src.arg, {})
+    src_address = evaluator.simp_full_exp(src_address)
+    src_address = evaluator.simp_expr_arith_final(src_address)
+    
+    print 'test read',src_address, evaluator.simp_expr_arith_final(src_address)
+    dump_pool(evaluator.pool[MEM_GLOB])
+    
+
+    if not str(src_address) in evaluator.pool[MEM_GLOB]:
+        evaluator.log.warning('unkown read address:%s'%src_address)
+        return ExprMem(src_address, size = src.size)
+    return evaluator.pool[MEM_GLOB][str(src_address)]
+    
+
+def hook_mem_write(evaluator, dst, src, pool_out):
+    evaluator.log.warn("mem write: %s %s"%(str(dst), str(src)))
+
+    dst_address = evaluator.eval_expr(dst.arg, {})
+    dst_address = evaluator.simp_full_exp(dst_address)
+    dst_address = evaluator.simp_expr_arith_final(dst_address)
+    print 'test write',dst_address, evaluator.simp_expr_arith_final(dst_address)
+
+    evaluator.pool[MEM_GLOB][str(dst_address)] = src
+    dump_pool(evaluator.pool[MEM_GLOB])
+
+
+    
+    
+#set unkown stack for all blocks
+for b in all_bloc:
+    b.eval_start,b.eval_stop = None, None
+    for l in b.lines:
+        l.arg_lookup = None
+        l.stack_h_after = None
+
+
+    
+#first bloc start at 0
+#esp_init_arg= 0x1000
+evaluator = eval_int({esp:esp_i, ebp:ebp_i, eax:eax_i, ebx:ebx_i, ecx:ecx_i, edx:edx_i, esi:esi_i, edi:edi_i,
+                      cs:9,
+                      zf : 0, 
+                      nf : 0, 
+                      pf : 0, 
+                      of : 0, 
+                      cf : 0, 
+                      tf : 0, 
+                      i_f: 0, 
+                      df : 0, 
+                      af : 0, 
+                      iopl: 3,
+                      nt : 0, 
+                      rf : 0, 
+                      vm : 0, 
+                      ac : 0, 
+                      vif: 0, 
+                      vip: 0, 
+                      i_d: 0,
+                      MEM_GLOB:{},
+                      },
+                     hook_mem_read,
+                     hook_mem_write
+                     )
+args_func = []
+#for i in xrange(3, 0, -1):
+    #args_func.append(ExprId('arg_%d'%i))
+
+    #evaluator.eval_instr(push(args_func[-1]))
+evaluator.eval_instr(push('ret_addr'))
+esp_init= evaluator.pool[esp]
+
+all_bloc[0].eval_start = evaluator
+
+def quick_ret_analyse(offset, all_bloc_arg):
+    #first, try to find ret and look for unstack arg.
+    for b in all_bloc_arg:
+        l = b.lines[-1]
+        if l.m.name == 'ret':
+            args = [dict_to_Expr(x, l.m.modifs) for x in l.arg]
+            if len(args) == 0:
+                return 0
+            else:
+                #exprint
+                return args[0].arg
+    #no ret found means special func
+    #try evaluation to ret and look at esp decal
+    #hack stack decal
+    return None
+
+def is_func_wrapper(ad, pool_import_func = {}):
+    x86mnemo = opcode_factory()
+    in_str_tmp = bin_stream(f, ad.offset)
+    instr = x86mnemo.dis(in_str_tmp)
+    print 'i'*80
+    print instr
+    if instr.m.name in ['jmp'] and is_address(instr.arg[0]):
+        return True
+    
+    return False
+
+#is simply import call?
+def is_import_call(offset, eval_arg, symbol_pool, pool_import_func = {}):
+    evaluator_tmp = eval_int(dict([(x,copy(eval_arg.pool[x])) for x in eval_arg.pool]), hook_mem_read, hook_mem_write)
+    in_str_tmp = bin_stream(f, offset)
+
+    #eval only jmp/call until eip load
+    ad_done = {}
+    while True:
+        if offset in ad_done:
+            return False, None
+        ad_done[offset] = True
+        l = x86mnemo.dis(in_str_tmp)
+        if not l.m.name in ['call', 'jmp']:
+            return False, None
+
+        args = [dict_to_Expr(x, l.m.modifs) for x in l.arg]
+        if l.m.name in ['call']:
+            if is_imm(l.arg[0]):
+                e = mnemo_func[l.m.name](ExprInt(in_str_tmp.offset), ExprOp('+', in_str.offset, args[0]) )
+            else:
+                e = mnemo_func[l.m.name](ExprInt(in_str_tmp.offset), args[0])
+        else:
+            e = mnemo_func[l.m.name](*args)
+
+        evaluator_tmp.eval_instr(e)
+        if eip in evaluator_tmp.pool:
+            n_eip = evaluator_tmp.pool[eip]                
+            if type(n_eip) in [int, long]:
+                offset = n_eip
+                continue
+            if not isinstance(n_eip, ExprMem):
+                return False, None
+            ad = evaluator_tmp.eval_expr(n_eip.arg, {})
+            
+            if not type(ad) in [int, long]:
+                return False, None
+            if not ad in pool_import_func:
+                return False, None
+
+            unstack = None
+            print "import func spotted:", str(pool_import_func[ad])
+            #if pool_import_func[ad].name in known_func:
+
+            print pool_import_func[ad].name
+            dll_name = pool_import_func[ad].dllname
+            func_name = pool_import_func[ad].name
+            unstack = read_dll_export(dll_name, func_name)
+            print "result:",unstack
+            #unstack = known_func[pool_import_func[ad].name].unstack
+                    
+            return True, unstack
+        iiiopop
+        #offset = in_str_tmp.offset
+        
+
+
+def stack_h(b, symbol_pool, pool_import_func = {}):
+    evaluator_tmp = eval_int(dict([(x,copy(b.eval_start.pool[x])) for x in b.eval_start.pool]), hook_mem_read, hook_mem_write)
+    #if b.lines[0].offset == 0x9FCE:
+    #    fds
+    for m in b.lines:
+        #m.stack_h = evaluator_tmp.pool[esp]
+        m.stack_h = evaluator.simp_expr_arith_final(evaluator_tmp.pool[esp])
+        print hex(m.offset), m.stack_h, str(m)
+        
+        
+        if m.m.name in ['call']:
+            
+            """
+            #hack call next code
+            if m.offset+m.l == s.offset:
+                evaluator_tmp.pool[esp]-=4
+                return evaluator_tmp
+            """
+            ret, unstack = is_import_call(m.offset, evaluator_tmp, symbol_pool, pool_import_func)
+            if unstack!=None:
+                evaluator_tmp.pool[esp]=evaluator_tmp.eval_expr(ExprOp('+', evaluator_tmp.pool[esp], unstack), {})
+                return evaluator_tmp
+            if ret:
+                return None
+
+            if not has_symb(m.arg[0]):
+                return None
+            dst = m.arg[0][x86_afs.symb].keys()
+            if len(dst)!=1:
+                return None
+            s = symbol_pool.getby_name(dst[0])
+            if not s:
+                return None
+
+            
+            if is_func_wrapper(s):
+                return evaluator_tmp
+            
+
+            in_str_tmp = bin_stream(f, s.offset)
+            
+            job_done_tmp = []
+            symbol_pool_tmp = asm_symbol_pool()
+            all_bloc_tmp = dis_bloc_all(x86mnemo, in_str_tmp, in_str_tmp.offset, job_done_tmp, symbol_pool_tmp, follow_call = False)
+            ret = quick_ret_analyse(s.offset, all_bloc_tmp)
+            #decal not found
+            if ret == None:
+                return ret
+            #decal is expr
+            if isinstance(ret, Expr):
+                #print ret
+                e = evaluator_tmp.eval_expr(ret, {})
+                if type(e) in [int, long]:
+                    print "eval esp oki!", e
+                    ret = e
+                else:
+                    return None
+                
+            #decal found int
+            if type(ret) in [int, long]:
+                evaluator_tmp.pool[esp]=evaluator_tmp.eval_expr(ExprOp('+', evaluator_tmp.pool[esp], ret), {})
+                return evaluator_tmp
+
+        
+        if m.m.name in jcc:
+            continue
+
+        args = [dict_to_Expr(x, m.m.modifs) for x in m.arg]
+            
+        e = mnemo_func[m.m.name](*args)
+        
+        print "exprs:"
+        for x in e:
+            print x
+        evaluator_tmp.eval_instr(e)
+        if eip in evaluator_tmp.pool:
+            print evaluator_tmp.pool[eip]
+            ret = evaluator_tmp.eval_expr(eip, {})
+            if ret == 'ret_addr':
+                m.stack_h_after = evaluator.simp_expr_arith_final(evaluator_tmp.pool[esp])
+            
+        
+    return evaluator_tmp
+
+
+def get_expr_diff(evaluator, a, b):
+    if evaluator == None:
+        return None
+    a_e = evaluator.simp_expr_arith_final(evaluator.eval_expr(a, {esp_i:0}))
+    b_e = evaluator.simp_expr_arith_final(evaluator.eval_expr(b, {esp_i:0}))
+    if not type(a_e) in [int, long] or not type(b_e) in [int, long]:
+        return None
+    return b_e-a_e
+    
+    
+    
+
+
+def resolve_func(all_bloc_arg, symbol_pool, pool_import_func):
+    all_bloc_dict = dict([(b.label,b) for b in all_bloc_arg])
+    while True:
+        fini = True
+        for b in all_bloc_arg:
+            force_stack_h = False
+            #if one son is known, inform his brothers
+            if b.eval_stop == None:
+                for next in b.bto:
+                    if next.label in all_bloc_dict and all_bloc_dict[next.label].eval_start!=None:
+                        b.eval_stop = all_bloc_dict[next.label].eval_start
+                        force_stack_h = True
+                        
+                        for x in b.bto:
+                            if x.label in all_bloc_dict and all_bloc_dict[x.label].eval_start==None:
+                                all_bloc_dict[x.label].eval_start = all_bloc_dict[next.label].eval_start
+                                fini = False
+            
+            if b.eval_start == None and b.eval_stop != None:
+                #try to find stack decal and inform start
+                print "tttt", hex(b.lines[0].offset)
+                
+                b.eval_start = b.eval_stop
+                tmp = stack_h(b, symbol_pool, pool_import_func)
+                print '_____',tmp
+
+                decal = get_expr_diff(tmp, tmp.eval_expr(esp, {}),b.eval_stop.eval_expr(esp, {}))
+
+                if decal == None:
+                    b.eval_start = None
+                    fdsfsd
+                    for l in b.lines:
+                        l.stack_h = None
+                    continue
+                tmp.pool[esp] = ExprOp('+', b.eval_stop.pool[esp] ,decal)
+                b.eval_start = tmp
+                print 'decal found ', b.label, decal
+                fini = False
+            
+            if b.eval_start == None:
+                continue
+            
+            if b.eval_stop != None and not force_stack_h:
+                continue
+
+
+            print '*****eval:', b.label, b.eval_start.eval_expr(esp, {})
+            b.eval_stop = stack_h(b, symbol_pool, pool_import_func)
+            if b.eval_stop == None:
+                continue
+            print 'propag:', b.label, b.eval_stop.eval_expr(esp, {})
+            for next in b.bto:
+                if next.label in all_bloc_dict:
+                    print next
+                    all_bloc_dict[next.label].eval_start = b.eval_stop
+            fini = False
+            
+        if fini:
+            break
+    
+    lines = reduce(lambda x,y:x+y.lines, all_bloc_arg, [])
+    return None
+
+
+
+print '_'*10
+print resolve_func(all_bloc, symbol_pool, pool_import_func)
+print 'result:'
+for b in all_bloc:
+    #print b
+    if not b.eval_stop or not b.eval_start:
+        print b.label, 'unresolved bloc'
+        continue
+        
+    #print b.label, esp_init-b.eval_start.pool[esp]
+    #if eip in b.eval_stop.pool:
+    #    print 'end at:', b.eval_stop.pool[eip], esp_init-b.eval_stop.pool[esp]
+
+lines = reduce(lambda x,y:x+y.lines, all_bloc, [])
+lines = [(l.offset, l) for l in lines]
+lines.sort()
+for o, l in lines:
+    if not 'stack_h' in l.__dict__:
+        l.stack_h = None
+    print "%-20s"%str(l.stack_h), "%-20s"%str(l.stack_h_after), l
+    #print "%-5s"%str(l.stack_h)
+    #print l.arg
+    
+"""
+for b in all_bloc:
+    for l in b.lines:
+        if not 'stack_h' in l.__dict__:
+            l.stack_h = None
+        print l.stack_h, l
+"""
diff --git a/miasm/tools/hook_helper.py b/miasm/tools/hook_helper.py
new file mode 100755
index 00000000..063d5444
--- /dev/null
+++ b/miasm/tools/hook_helper.py
@@ -0,0 +1,237 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+from miasm.tools.pe_helper import *
+from elfesteem import *
+from miasm.core import bin_stream
+from miasm.arch.ia32_sem import *
+from miasm.core import asmbloc
+from miasm.core import parse_asm
+import re
+import sys
+from Crypto.Hash import MD5
+
+
+class hooks():
+    def name2str(self, n):
+        return "str_%s"%n
+    
+    def __init__(self, in_str, symbol_pool, gen_data_log_code = True):
+        self.in_str = in_str
+        self.all_bloc = [[]]
+        self.symbol_pool = symbol_pool
+        if gen_data_log_code:
+            self.all_bloc, self.symbol_pool = parse_asm.parse_txt(x86mnemo,'''
+        
+        f_name:
+        .string "out.txt"
+        f_handle:
+        .long 0x0
+        my_critic_sec:
+        .long 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+        write_ret:
+        .long 0xDEADBEEF
+        mtick:
+        .long 0xdeadbeef
+        
+        
+        log_name_data_len:
+            push    ebp
+            mov     ebp, esp
+            pushad
+        
+        
+        
+            mov eax, [f_handle]
+            test eax, eax
+            jnz write_file_2
+            ;; create log file
+            push 0
+            push 0x80
+            push 4
+            push 0
+            push 1
+            push 4
+            lea ebx, [f_name]
+            push ebx
+            call [CreateFileA]
+            mov [f_handle], eax
+        
+            ;; create lock
+            push my_critic_sec
+            call [initializecriticalsection]
+            
+        write_file_2:
+            ;; lock
+            push my_critic_sec
+            call [entercriticalsection]
+        
+            
+            ;; write log name
+            push [ebp+8]
+            call [lstrlenA]
+            inc eax
+        
+            push 0
+            lea ebx, [write_ret]
+            push ebx
+            push eax
+            push [ebp+8]
+            push [f_handle]
+            call [WriteFile]
+        
+
+            ;; write tickcount
+            call [GetTickCount]
+            mov [mtick], eax
+            push 0
+            lea ebx, [write_ret]
+            push ebx
+            push 4
+            lea ebx, [mtick]
+            push ebx
+            push [f_handle]
+            call [WriteFile]
+            
+        
+            ;; write data size
+            push 0
+            lea ebx, [write_ret]
+            push ebx
+            push 4
+            lea ebx, [ebp+0x10]
+            push ebx
+            push [f_handle]
+            call [WriteFile]
+        
+        
+            ;;write data
+            push 0
+            lea ebx, [write_ret]
+            push ebx
+            push [ebp+0x10]
+            push [ebp+0xc]
+            push [f_handle]
+            call [WriteFile]
+        
+            ;; unlock
+            push my_critic_sec
+            call [leavecriticalsection]
+        
+        
+            popad
+            mov esp, ebp
+            pop ebp
+            ret 0xc
+        
+        ''', symbol_pool = symbol_pool)
+            
+    
+    def add_hook(self, hook_ad, args_to_hook = {}, vars_decl = [], func_code = "", post_hook = ""):
+        wrapper_name = "wrapper_%.8X"%hook_ad
+        wrapper_log_name = "wrapper_log_%.8X"%hook_ad
+        patch_name = "patch_%.8X"%hook_ad
+        patch_end_name = "patch_end_%.8X"%hook_ad
+        
+        log_name = "log_%.8X"%hook_ad
+
+        string_decl = []
+        to_hook = args_to_hook.keys()
+        to_hook.sort()
+
+        for s in to_hook:
+            if s.endswith('DONT_LOG'):
+                continue
+            string_decl.append('%s:\n.string "%s"'%(self.name2str(s), s))
+        string_decl = "\n".join(string_decl)
+        
+
+        lines, total_bytes = asmbloc.steal_bytes(self.in_str, x86_mn, hook_ad, 5)
+        erased_asm = "\n".join([str(l) for l in lines])
+        print 'stolen lines'
+        print erased_asm
+
+        self.symbol_pool.getby_name_create(patch_name).offset = hook_ad
+        self.symbol_pool.getby_name_create(patch_end_name).offset = hook_ad+total_bytes
+
+
+        asm_s = '''
+%s:
+    call %s
+'''%(wrapper_name, wrapper_log_name)+erased_asm+"\n"+post_hook+"\n"+'''
+    jmp %s'''%(patch_end_name)+'''
+%s:
+    ;;int 3
+    pushad
+    pushfd
+    '''%wrapper_log_name
+
+        for s in to_hook[::-1]:
+            asm_s += args_to_hook[s][1]
+        asm_s +='''
+    call    %s
+    popfd
+    popad
+    ret
+'''%(log_name)+string_decl+'\n'+'\n'.join(vars_decl)+'''
+%s:
+    push ebp
+    mov ebp, esp
+    
+'''%(log_name)
+        asm_s += func_code +'\n'
+
+        for i, c in enumerate(to_hook):
+            len_howto, arg_asm = args_to_hook[c]
+            if type(len_howto) in [int, long]:
+                asm_s += '''
+    push %d
+    '''%(len_howto)
+            elif isinstance(len_howto, str):
+                asm_s += len_howto
+
+            if not c.endswith('DONT_LOG'):
+                asm_s += '''
+    push [ebp+%d]
+    push %s
+    call log_name_data_len
+        '''%(8+4*i, self.name2str(c))
+
+
+        asm_s +="""
+    pop     ebp
+    ret     %d
+    
+    """%(len(to_hook)*4)
+
+        asm_s +="""
+        %s:
+        jmp %s
+        %s:
+        .split
+        """%(patch_name, wrapper_name, patch_end_name)
+    
+        #print asm_s
+
+        all_bloc, self.symbol_pool = parse_asm.parse_txt(x86mnemo,asm_s, symbol_pool = self.symbol_pool)
+        self.all_bloc[0] += all_bloc[0]
+        return log_name
+        
+    
+
+        
diff --git a/miasm/tools/nux_api.py b/miasm/tools/nux_api.py
new file mode 100644
index 00000000..98fd2ce0
--- /dev/null
+++ b/miasm/tools/nux_api.py
@@ -0,0 +1,917 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+from to_c_helper import *
+import struct
+import inspect
+import socket
+import time
+import random
+import os
+import sys
+ctime_str = None
+def fd_generator():
+    i = 0
+    while True:
+        yield i
+        i+=1
+
+fd_gen = fd_generator()
+fd_stdin = fd_gen.next()
+fd_stout = fd_gen.next()
+
+
+socket_pool = {}
+def get_str_ansi(ad_str, max_l = None):
+    l = 0
+    tmp = ad_str
+    while vm_get_str(tmp, 1) != "\x00":
+        tmp +=1
+        l+=1
+        if max_l and l > max_l:
+            break
+    return vm_get_str(ad_str, l)
+
+def get_dw_stack(offset):
+    esp = vm_get_gpreg()['esp']
+    return updw(vm_get_str(esp+offset, 4))
+
+
+def whoami():
+    return inspect.stack()[1][3]
+
+
+
+def xxx_memset():
+    ret_ad = vm_pop_uint32_t()
+    arg_addr = get_dw_stack(0)
+    arg_c = get_dw_stack(4)
+    arg_size = get_dw_stack(8)
+
+    print whoami(), hex(ret_ad), '(', hex(arg_addr), arg_c, arg_size, ')'
+    vm_set_mem(arg_addr, chr(arg_c)*arg_size)
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = arg_addr
+    vm_set_gpreg(regs)
+
+def xxx_printf():
+    ret_ad = vm_pop_uint32_t()
+    fmt_p = get_dw_stack(0)
+    fmt_s = get_str_ansi(fmt_p)
+
+    print whoami(), hex(ret_ad), '(', repr(fmt_s), ')'
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+def xxx_socket():
+    ret_ad = vm_pop_uint32_t()
+    arg_domain = get_dw_stack(0)
+    arg_type = get_dw_stack(4)
+    arg_proto = get_dw_stack(8)
+
+    print whoami(), hex(ret_ad), '(', arg_domain, arg_type, arg_proto,')'
+    fd = fd_gen.next()
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    #regs['eax'] = fd
+    # XXX DANGEROUS
+    s = socket.socket(arg_domain, arg_type, arg_proto)
+    socket_pool[s.fileno()] = s
+    regs['eax'] = s.fileno()
+    
+    
+    vm_set_gpreg(regs)
+
+
+def xxx_htonl():
+    ret_ad = vm_pop_uint32_t()
+    arg_dw = get_dw_stack(0)
+
+    print whoami(), hex(ret_ad), '(', arg_dw,')'
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = socket.htonl(arg_dw)
+    vm_set_gpreg(regs)
+
+def xxx_htons():
+    ret_ad = vm_pop_uint32_t()
+    arg_dw = get_dw_stack(0)
+
+    print whoami(), hex(ret_ad), '(', arg_dw,')'
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = socket.htons(arg_dw)
+    vm_set_gpreg(regs)
+
+def xxx_bind():
+    ret_ad = vm_pop_uint32_t()
+    arg_sockfd = get_dw_stack(0)
+    arg_addr = get_dw_stack(4)
+    arg_addrlen = get_dw_stack(8)
+
+    print whoami(), hex(ret_ad), '(', arg_sockfd, hex(arg_addr), arg_addrlen,')'
+
+    addr_s = vm_get_str(arg_addr, arg_addrlen)
+    print repr(addr_s)
+    sin_f, sin_port, sin_addr = struct.unpack('>HHL', addr_s[:8])
+    print repr(sin_f), repr(sin_port), repr(sin_addr)
+    # XXX
+    #sin_port = 2222
+    socket_pool[arg_sockfd].bind(('', sin_port))
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+def xxx_listen():
+    ret_ad = vm_pop_uint32_t()
+    arg_sockfd = get_dw_stack(0)
+    arg_backlog = get_dw_stack(4)
+
+    print whoami(), hex(ret_ad), '(', arg_sockfd, arg_backlog, ')'
+    socket_pool[arg_sockfd].listen(arg_backlog)
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+def xxx_accept():
+    ret_ad = vm_pop_uint32_t()
+    arg_sockfd = get_dw_stack(0)
+    arg_addr = get_dw_stack(4)
+    arg_addrlen = get_dw_stack(8)
+
+    print whoami(), hex(ret_ad), '(', arg_sockfd, hex(arg_addr), arg_addrlen, ')'
+    conn, addr = socket_pool[arg_sockfd].accept()
+    socket_pool[conn.fileno()] = conn
+
+    print 'ACCEPT', conn, addr
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = conn.fileno()
+    vm_set_gpreg(regs)
+
+
+def xxx_puts():
+    ret_ad = vm_pop_uint32_t()
+    arg_s = get_dw_stack(0)
+
+    print whoami(), hex(ret_ad), '(', arg_s, ')'
+    s = get_str_ansi(arg_s)
+    print 'PUTS', repr(s)
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+
+def xxx_recv():
+    ret_ad = vm_pop_uint32_t()
+    arg_sockfd = get_dw_stack(0)
+    arg_buf = get_dw_stack(4)
+    arg_len = get_dw_stack(8)
+    arg_flags = get_dw_stack(12)
+
+    print whoami(), hex(ret_ad), '(', arg_sockfd, arg_buf, arg_len, arg_sockfd, ')'
+    buf = socket_pool[arg_sockfd].recv(arg_len)
+    
+    print 'RECV', repr(buf)
+    vm_set_mem(arg_buf, buf)
+
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    if buf:
+        regs['eax'] = len(buf)
+    else:
+        regs['eax'] = -1
+    vm_set_gpreg(regs)
+
+
+def xxx_send():
+    ret_ad = vm_pop_uint32_t()
+    arg_sockfd = get_dw_stack(0)
+    arg_buf = get_dw_stack(4)
+    arg_len = get_dw_stack(8)
+    arg_flags = get_dw_stack(12)
+
+    print whoami(), hex(ret_ad), '(', arg_sockfd, arg_buf, arg_len, arg_sockfd, ')'
+    buf = vm_get_str(arg_buf, arg_len)
+    try:
+        socket_pool[arg_sockfd].send(buf)
+    except:
+        print 'send fail'
+        buf = ""
+    
+    print 'SEND', repr(buf)
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = len(buf)
+    vm_set_gpreg(regs)
+
+def xxx_close():
+    ret_ad = vm_pop_uint32_t()
+    arg_sockfd = get_dw_stack(0)
+
+    print whoami(), hex(ret_ad), '(', arg_sockfd, ')'
+    socket_pool[arg_sockfd].close()
+    
+    print 'close', repr(arg_sockfd)
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+
+def xxx_signal():
+    ret_ad = vm_pop_uint32_t()
+    arg_signum = get_dw_stack(0)
+    arg_sigh = get_dw_stack(4)
+
+    print whoami(), hex(ret_ad), '(', arg_signum, hex(arg_sigh), ')'
+    # XXX todo
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+def xxx_setsockopt():
+    ret_ad = vm_pop_uint32_t()
+    arg_sockfd = get_dw_stack(0)
+    arg_level = get_dw_stack(4)
+    arg_optname = get_dw_stack(8)
+    arg_optval = get_dw_stack(12)
+    arg_optlen = get_dw_stack(16)
+
+    print whoami(), hex(ret_ad), '(', arg_sockfd, hex(arg_level), arg_optname, hex(arg_optval), arg_optlen, ')'
+    opt_val = vm_get_str(arg_optval, arg_optlen)
+    print repr(opt_val)
+    
+    # Translation between C and python values
+    # #define SOL_SOCKET	0xffff
+    dct_level = {0xffff:1, 1:1}
+    dct_argname = {4:2, 2:2}
+    arg_level = dct_level[arg_level]
+    arg_optname = dct_argname[arg_optname]
+    
+    print repr(arg_level), repr(arg_optname), repr(opt_val)
+    socket_pool[arg_sockfd].setsockopt(arg_level, arg_optname, opt_val)
+    # XXX todo
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+
+def xxx_getpwnam():
+    ret_ad = vm_pop_uint32_t()
+    arg_name = get_dw_stack(0)
+
+    print whoami(), hex(ret_ad), '(', hex(arg_name), ')'
+    s = get_str_ansi(arg_name)
+    print repr(s)
+    # create fake struct
+
+    name = s
+    password = "pwd_"+name
+    rname = name
+    udir = "/home/"+name
+    ushell = "shell_"+name
+    
+    ad = vm_get_memory_page_max_address()
+
+    vm_add_memory_page(ad, PAGE_READ|PAGE_WRITE, 0x1000*"\x00")
+    ad = (ad+0xfff) & 0xfffff000
+    s = struct.pack('IIIIIII',
+                    ad+0x100,
+                    ad+0x200,
+                    1337,
+                    1337,
+                    ad+0x300,
+                    ad+0x400,
+                    ad+0x500)
+    
+    s = struct.pack('256s256s256s256s256s256s', s, name, password, rname, udir, ushell)
+    print repr(s)
+    vm_set_mem(ad, s)
+    
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = ad
+    vm_set_gpreg(regs)
+
+def xxx_getuid():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad), '(', ')'
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 1337
+    vm_set_gpreg(regs)
+
+def xxx_getgid():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad), '(', ')'
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 1337
+    vm_set_gpreg(regs)
+
+def xxx_initgroups():
+    ret_ad = vm_pop_uint32_t()
+    arg_name = get_dw_stack(0)
+    arg_group = get_dw_stack(4)
+    
+    print whoami(), hex(ret_ad), '(', hex(arg_name), arg_group, ')'
+    s = get_str_ansi(arg_name)
+    print repr(s)
+    # XXX todo
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+def xxx_setresgid():
+    ret_ad = vm_pop_uint32_t()
+    arg_ruid = get_dw_stack(0)
+    arg_euid = get_dw_stack(4)
+    arg_suid = get_dw_stack(8)
+    
+    print whoami(), hex(ret_ad), '(', arg_ruid, arg_euid, arg_suid, ')'
+    # XXX todo
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+    
+def xxx_setresuid():
+    ret_ad = vm_pop_uint32_t()
+    arg_ruid = get_dw_stack(0)
+    arg_euid = get_dw_stack(4)
+    arg_suid = get_dw_stack(8)
+    
+    print whoami(), hex(ret_ad), '(', arg_ruid, arg_euid, arg_suid, ')'
+    # XXX todo
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+    
+def xxx_getegid():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad), '(', ')'
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 1337
+    vm_set_gpreg(regs)
+
+def xxx_geteuid():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad), '(', ')'
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 1337
+    vm_set_gpreg(regs)
+
+def xxx_chdir():
+    ret_ad = vm_pop_uint32_t()
+    arg_path = get_dw_stack(0)
+    
+    print whoami(), hex(ret_ad), '(', hex(arg_path), ')'
+    if arg_path:
+        s = get_str_ansi(arg_path)
+    else:
+        s = "default_path"
+    print repr(s)
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+
+def xxx_time():
+    ret_ad = vm_pop_uint32_t()
+    arg_time = get_dw_stack(0)
+    print whoami(), hex(ret_ad), '(', hex(arg_time), ')'
+
+    t = int(time.time())
+    if arg_time:
+        vm_set_mem(arg_time, pdw(t))
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = t
+    vm_set_gpreg(regs)
+
+def xxx_ctime():
+    global ctime_str
+    ret_ad = vm_pop_uint32_t()
+    arg_time = get_dw_stack(0)
+    print whoami(), hex(ret_ad), '(', hex(arg_time), ')'
+
+    if not ctime_str:
+        ad = vm_get_memory_page_max_address()
+        vm_add_memory_page(ad, PAGE_READ|PAGE_WRITE, 0x1000*"\x00")
+        ctime_str = ad
+        
+    t = vm_get_str(arg_time, 4)
+    t = updw(t)
+    print hex(t)
+    s = time.ctime(t)
+    vm_set_mem(ctime_str, s)
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = ctime_str
+    vm_set_gpreg(regs)
+
+def xxx_srand():
+    ret_ad = vm_pop_uint32_t()
+    arg_seed = get_dw_stack(0)
+    print whoami(), hex(ret_ad), '(', hex(arg_seed), ')'
+
+    random.seed(arg_seed)
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+def xxx_rand():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad), '(',  ')'
+
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = random.randint(0, 0xffffffff)
+    vm_set_gpreg(regs)
+
+def xxx_fork():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad), '(',  ')'
+
+
+    ret = os.fork()
+    #ret= 0
+    print 'FORK', ret
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = ret
+    vm_set_gpreg(regs)
+
+
+
+def xxx_strncpy():
+    ret_ad = vm_pop_uint32_t()
+    arg_dst = get_dw_stack(0)
+    arg_src = get_dw_stack(4)
+    arg_n = get_dw_stack(8)
+    
+    print whoami(), hex(ret_ad), '(', hex(arg_dst), hex(arg_src), arg_n,   ')'
+    src = get_str_ansi(arg_src, arg_n)
+    src = (src+'\x00'*arg_n)[:arg_n]
+    
+    vm_set_mem(arg_dst, src)
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = arg_dst
+    vm_set_gpreg(regs)
+
+def xxx_strlen():
+    ret_ad = vm_pop_uint32_t()
+    arg_src = get_dw_stack(0)
+    
+    print whoami(), hex(ret_ad), '(', hex(arg_src),   ')'
+    src = get_str_ansi(arg_src)
+    print repr(src)
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = len(src)
+    vm_set_gpreg(regs)
+
+
+def xxx_read():
+    ret_ad = vm_pop_uint32_t()
+    arg_fd = get_dw_stack(0)
+    arg_buf = get_dw_stack(4)
+    arg_len = get_dw_stack(8)
+
+    print whoami(), hex(ret_ad), '(', arg_fd, arg_buf, arg_len, ')'
+    buf = os.read(arg_fd, arg_len)
+    
+    print 'RECV', repr(buf)
+    vm_set_mem(arg_buf, buf)
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = len(buf)
+    vm_set_gpreg(regs)
+
+def xxx_strcmp():
+    ret_ad = vm_pop_uint32_t()
+    arg_s1 = get_dw_stack(0)
+    arg_s2 = get_dw_stack(4)
+    
+    print whoami(), hex(ret_ad), '(', hex(arg_s1), hex(arg_s2),    ')'
+    s1 = get_str_ansi(arg_s1)
+    s2 = get_str_ansi(arg_s2)
+    print repr(s1), repr(s2)
+    if s1 == s2:
+        ret = 0
+    elif s1 > s2:
+        ret = 1
+    else:
+        ret = -1
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = ret
+    vm_set_gpreg(regs)
+
+def xxx_exit():
+    ret_ad = vm_pop_uint32_t()
+    arg_code = get_dw_stack(0)
+    
+    print whoami(), hex(ret_ad), '(', hex(arg_code),   ')'
+
+    sys.exit(arg_code)
+
+def xxx__exit():
+    xxx_exit()
+
+
+def xxx_fdopen():
+    ret_ad = vm_pop_uint32_t()
+    arg_fd = get_dw_stack(0)
+    arg_mode = get_dw_stack(4)
+    
+    print whoami(), hex(ret_ad), '(', arg_fd, hex(arg_mode),    ')'
+    m = get_str_ansi(arg_mode)
+    print repr(m)
+
+    s = os.fdopen(arg_fd, m, 0)
+    socket_pool[id(s)] = s
+
+
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = id(s)
+    vm_set_gpreg(regs)
+
+def xxx_fclose():
+    ret_ad = vm_pop_uint32_t()
+    arg_fd = get_dw_stack(0)
+    
+    print whoami(), hex(ret_ad), '(', arg_fd,     ')'
+    socket_pool[arg_fd].close()
+
+
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+def parse_fmt(s):
+    fmt = s[:]+"\x00"
+    out = []
+    i = 0
+    while i < len(fmt):
+        c = fmt[i]
+        if c != "%":
+            i+=1
+            continue
+        if fmt[i+1] == "%":
+            i+=2
+            continue
+        j = 0
+        i+=1
+        while fmt[i+j] in "0123456789$.":
+            j+=1
+        if fmt[i+j] == "h":
+            x = fmt[i+j:i+j+2]
+        else:
+            x = fmt[i+j]
+        i+=j
+        out.append(x)
+    return out
+            
+
+def xxx_fprintf():
+    ret_ad = vm_pop_uint32_t()
+    arg_stream = get_dw_stack(0)
+    arg_fmt = get_dw_stack(4)
+    
+    print whoami(), hex(ret_ad), '(', arg_stream, hex(arg_fmt),    ')'
+    s = get_str_ansi(arg_fmt)
+    print repr(s)
+    fmt_a = parse_fmt(s)
+    offset = 8
+    args = []
+    for i, x in enumerate(fmt_a):
+        a = get_dw_stack(offset+4*i)
+        if x == "s":
+            a = get_str_ansi(a)
+        args.append(a)
+    print repr(s), repr(args)
+    
+    oo = s%(tuple(args))
+    print repr(oo)
+    socket_pool[arg_stream].write(oo)
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = len(oo)
+    vm_set_gpreg(regs)
+
+def xxx_fgets():
+    ret_ad = vm_pop_uint32_t()
+    arg_buf = get_dw_stack(0)
+    arg_size = get_dw_stack(4)
+    arg_stream = get_dw_stack(8)
+    
+    print whoami(), hex(ret_ad), '(', hex(arg_buf), arg_size, arg_stream,   ')'
+    buf = ""
+    while len(buf) < arg_size-1:
+        buf += socket_pool[arg_stream].read(1)
+        if not buf:
+            break
+        if "\n" in buf:
+            break
+        if "\x00" in buf:
+            break
+    if buf:
+        buf += "\x00"
+    print repr(buf)
+    vm_set_mem(arg_buf, buf)
+
+    if not buf:
+        arg_buf = 0
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = arg_buf
+    vm_set_gpreg(regs)
+
+def xxx_fwrite():
+    ret_ad = vm_pop_uint32_t()
+    arg_buf = get_dw_stack(0)
+    arg_size = get_dw_stack(4)
+    arg_nmemb = get_dw_stack(8)
+    arg_stream = get_dw_stack(12)
+    
+    print whoami(), hex(ret_ad), '(', hex(arg_buf), arg_size, arg_nmemb, arg_stream,   ')'
+
+    buf = vm_get_str(arg_buf, arg_size*arg_nmemb)
+    print repr(buf)
+    socket_pool[arg_stream].write(buf)
+    """
+    except:
+        print "err in write"
+        buf = ""
+    """
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = len(buf)
+    vm_set_gpreg(regs)
+
+def xxx_fflush():
+    ret_ad = vm_pop_uint32_t()
+    arg_stream = get_dw_stack(0)
+    
+    print whoami(), hex(ret_ad), '(', arg_stream,   ')'
+
+    socket_pool[arg_stream].flush()
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+def xxx_malloc():
+    ret_ad = vm_pop_uint32_t()
+    arg_size = get_dw_stack(0)
+    
+    print whoami(), hex(ret_ad), '(', arg_size,   ')'
+
+
+    ad = vm_get_memory_page_max_address()
+    ad = (ad+0xfff) & 0xfffff000
+    vm_add_memory_page(ad, PAGE_READ|PAGE_WRITE, arg_size*"\x00")
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = ad
+    vm_set_gpreg(regs)
+
+def xxx_bzero():
+    ret_ad = vm_pop_uint32_t()
+    arg_addr = get_dw_stack(0)
+    arg_size = get_dw_stack(4)
+    
+    print whoami(), hex(ret_ad), '(', hex(arg_addr), arg_size,   ')'
+
+    vm_set_mem(arg_addr, "\x00"*arg_size)
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+
+def xxx_fopen():
+    ret_ad = vm_pop_uint32_t()
+    arg_path = get_dw_stack(0)
+    arg_mode = get_dw_stack(4)
+    
+    print whoami(), hex(ret_ad), '(', arg_path, hex(arg_mode),    ')'
+    path = get_str_ansi(arg_path)
+    m = get_str_ansi(arg_mode)
+    print repr(path), repr(m)
+    path = "/home/serpilliere/projet/pelogger/user.db"
+    try:
+        s = open(path, m, 0)
+        socket_pool[id(s)] = s
+        s= id(s)
+    except:
+        s = 0
+
+
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = s
+    vm_set_gpreg(regs)
+
+def xxx_fread():
+    ret_ad = vm_pop_uint32_t()
+    arg_buf = get_dw_stack(0)
+    arg_size = get_dw_stack(4)
+    arg_nmemb = get_dw_stack(8)
+    arg_stream = get_dw_stack(12)
+    
+    print whoami(), hex(ret_ad), '(', hex(arg_buf), arg_size, arg_nmemb, arg_stream,   ')'
+
+    buf = socket_pool[arg_stream].read(arg_size*arg_nmemb)
+    print repr(buf)
+    vm_set_mem(arg_buf, buf)
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = len(buf)
+    vm_set_gpreg(regs)
+
+
+def xxx_atoi():
+    ret_ad = vm_pop_uint32_t()
+    arg_nptr = get_dw_stack(0)
+    
+    print whoami(), hex(ret_ad), '(', arg_nptr,   ')'
+    buf = get_str_ansi(arg_nptr)
+    print repr(buf)
+    i = int(buf)
+    print i
+    
+
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = i
+    vm_set_gpreg(regs)
+
+
+def xxx_strcpy():
+    ret_ad = vm_pop_uint32_t()
+    arg_dst = get_dw_stack(0)
+    arg_src = get_dw_stack(4)
+    
+    print whoami(), hex(ret_ad), '(', hex(arg_dst), hex(arg_src),    ')'
+    src = get_str_ansi(arg_src)
+    vm_set_mem(arg_dst, src+"\x00")
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = arg_dst
+    vm_set_gpreg(regs)
+
+
+def xxx_vasprintf():
+    ret_ad = vm_pop_uint32_t()
+    arg_strp = get_dw_stack(0)
+    arg_fmt = get_dw_stack(4)
+    arg_ap = get_dw_stack(8)
+    
+    print whoami(), hex(ret_ad), '(', hex(arg_strp), hex(arg_fmt), hex(arg_ap),   ')'
+    fmt = get_str_ansi(arg_fmt)
+    print repr(fmt)
+
+    fmt_a = parse_fmt(fmt)
+    
+    args = []
+    for i, x in enumerate(fmt_a):
+        a = updw(vm_get_str(arg_ap+4*i, 4))
+        if x == "s":
+            a = get_str_ansi(a)
+        args.append(a)
+
+
+    s = fmt%(tuple(args))+"\x00"
+    print repr(s)
+    ad = vm_get_memory_page_max_address()
+    ad = (ad+0xfff) & 0xfffff000
+    vm_add_memory_page(ad, PAGE_READ|PAGE_WRITE, (len(s)+1)*"\x00")
+
+    vm_set_mem(arg_strp, pdw(ad))
+    vm_set_mem(ad, s)
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = len(fmt)
+    vm_set_gpreg(regs)
+
+
+def xxx_sprintf():
+    ret_ad = vm_pop_uint32_t()
+    arg_str = get_dw_stack(0)
+    arg_fmt = get_dw_stack(4)
+    
+    print whoami(), hex(ret_ad), '(', hex(arg_str), hex(arg_fmt),    ')'
+    s = get_str_ansi(arg_fmt)
+    print repr(s)
+    fmt_a = parse_fmt(s)
+    offset = 8
+    args = []
+    for i, x in enumerate(fmt_a):
+        a = get_dw_stack(offset+4*i)
+        if x == "s":
+            a = get_str_ansi(a)
+        args.append(a)
+    print repr(s), repr(args)
+    
+    oo = s%(tuple(args))
+    print repr(oo)
+    vm_set_mem(arg_str, oo+"\x00")
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = len(oo)
+    vm_set_gpreg(regs)
+
+
+def xxx_strcat():
+    ret_ad = vm_pop_uint32_t()
+    arg_dst = get_dw_stack(0)
+    arg_src = get_dw_stack(4)
+    
+    print whoami(), hex(ret_ad), '(', hex(arg_dst), hex(arg_src),    ')'
+    src = get_str_ansi(arg_src)
+    dst = get_str_ansi(arg_dst)
+    print repr(dst), repr(src)
+    vm_set_mem(arg_dst, dst+src+'\x00')
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = arg_dst
+    vm_set_gpreg(regs)
+
+def xxx_strncmp():
+    ret_ad = vm_pop_uint32_t()
+    arg_s1 = get_dw_stack(0)
+    arg_s2 = get_dw_stack(4)
+    arg_n = get_dw_stack(8)
+    
+    print whoami(), hex(ret_ad), '(', hex(arg_s1), hex(arg_s2), arg_n,   ')'
+
+    s1 = get_str_ansi(arg_s1, arg_n)
+    s2 = get_str_ansi(arg_s2, arg_n)
+    print repr(s1), repr(s2)
+    if s1 == s2:
+        ret = 0
+    elif s1 > s2:
+        ret = 1
+    else:
+        ret = -1
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = ret
+    vm_set_gpreg(regs)
diff --git a/miasm/tools/pe_helper.py b/miasm/tools/pe_helper.py
new file mode 100644
index 00000000..aba8d1b7
--- /dev/null
+++ b/miasm/tools/pe_helper.py
@@ -0,0 +1,593 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+from elfesteem import *
+
+from miasm.arch.ia32_arch import *
+from miasm.tools.emul_helper import *
+from miasm.arch.ia32_sem import *
+import struct
+import miasm.core.asmbloc
+import miasm.core.bin_stream
+import os
+import re
+from  miasm.tools import to_c_helper
+import miasm.core.bin_stream
+pe_cache = {}
+def pe_from_name(n):
+    global pe_cache
+    
+    my_path = 'win_dll/'
+    all_pe = os.listdir(my_path)
+    if not n in all_pe:
+        print 'cannot find PE', n
+        return None
+
+    pe_name = my_path+n
+    if pe_name in pe_cache:
+        return pe_cache[pe_name]
+    e = pe_init.PE(open(pe_name, 'rb').read())
+    pe_cache[pe_name] = e
+    return e
+
+
+def func_from_import(pe_name, func):
+    e = pe_from_name(pe_name)
+
+    if not e or not e.DirExport:
+        print 'no export dir found'
+        return None, None
+
+
+    found = None
+    if type(func) is str:
+        for i, n in enumerate(e.DirExport.f_names):
+            if n.name.name == func:
+                found = e.DirExport.f_address[e.DirExport.f_nameordinals[i].ordinal]
+                break
+
+    elif type(func) in [int, long]:
+        for i, n in enumerate(e.DirExport.f_names):
+            if e.DirExport.f_nameordinals[i].ordinal+e.DirExport.expdesc.base == func:
+                found = e.DirExport.f_address[e.DirExport.f_nameordinals[i].ordinal]
+                break
+    else:
+        raise ValueError('unknown fund type', func)
+
+    #XXX todo: test if redirected export
+    return e, found
+
+
+
+def is_rva_in_code_section(e, rva):
+    s = e.getsectionbyrva(rva)
+    return s.flags&0x20!=0
+
+def guess_func_destack_dis(e, ad):
+    job_done = set()
+    symbol_pool = asmbloc.asm_symbol_pool()
+    in_str = bin_stream.bin_stream(e.virt)
+    
+    all_bloc = asmbloc.dis_bloc_all(x86_mn, in_str, ad, job_done, symbol_pool, follow_call = False, patch_instr_symb = False)
+    return guess_func_destack(all_bloc)
+    
+
+def guess_imports_ret_unstack(e):
+    unresolved = set()
+    resolved = {}
+    redirected = {}
+    for i,s in enumerate(e.DirImport.impdesc):
+        l = "%2d %-25s %s"%(i, repr(s.dlldescname) ,repr(s))
+        libname = s.dlldescname.name
+    
+    
+        for ii, f in enumerate(s.impbynames):
+            print '_'*20
+            funcname = f.name
+            
+            
+            my_e, ret = func_from_import(libname.lower(), funcname)
+            if ret:
+                func_addr = my_e.rva2virt(ret.rva)
+                print funcname, hex(func_addr)
+            else:
+                print 'not found'
+                continue
+    
+            #XXX python int obj len zarb bug
+            imgb = my_e.NThdr.ImageBase
+            if imgb>0x80000000:
+                imgb-=0x40000000
+                func_addr-=0x40000000
+                my_e.NThdr.ImageBase = imgb
+            
+            if not is_rva_in_code_section(my_e, ret.rva):
+                print "not in code section"
+                continue
+
+
+            ok, r = guess_func_destack_dis(my_e, func_addr)
+            print funcname, 'ret', r
+            if ok == True:
+                resolved[(libname, funcname)] = r
+            elif ok == None:
+                unresolved.add((libname, funcname))
+            else:
+                resolved[(libname, funcname)] = r
+
+
+    return resolved, unresolved, redirected
+
+
+def get_import_address(e):
+    import2addr = {}
+    
+    for i,s in enumerate(e.DirImport.impdesc):
+        fthunk = e.rva2virt(s.firstthunk)
+        l = "%2d %-25s %s"%(i, repr(s.dlldescname) ,repr(s))
+        
+        libname = s.dlldescname.name.lower()
+        for ii, imp in enumerate(s.impbynames):
+            if isinstance(imp, pe_init.ImportByName):
+                funcname = imp.name
+            else:
+                funcname = imp
+            l = "    %2d %-16s"%(ii, repr(funcname))
+    
+    
+            import2addr[(libname, funcname)] = e.rva2virt(s.firstthunk+4*ii)
+    return import2addr
+
+
+def get_import_address_elf(e):
+    import2addr = {}
+    for k, v in e.sh.rel_plt.rel.items():
+        import2addr[('xxx', k)] = v.offset
+    return import2addr
+
+
+def get_symbols_elf(e):
+    sym2addr = {}
+    for k, v in e.sh.dynsym.symbols.items():
+        sym2addr[k] = v
+    return sym2addr
+
+def guess_redirected(e, resolved, unresolved, redirected, import2addr):
+
+    import2addr_inv = [(x[1], x[0]) for x in import2addr.items()]
+    
+
+    to_del = []
+    for imp in redirected:
+        ad = redirected[imp]
+        if ad in import2addr_inv:
+            my_imp = import2addr[ad]
+            if not my_imp in resolved:
+                continue
+            else:
+                resolved[my_imp] = resolved[imp]
+                to_del.append(my_imp)
+                
+
+    redirected = [x for x in redirected if not x in to_del]
+    
+    return resolved, unresolved, redirected
+            
+
+if __name__ == '__main__':
+    e, ret = func_from_import('hal.dll', 'KfAcquireSpinLock')
+    if ret:
+        print dir(ret)
+        print hex(e.rva2virt(ret.rva))
+
+def get_imp_to_dict(e):
+    imp2ad = get_import_address(e)
+    imp_d = {}
+    
+    for libf, ad in imp2ad.items():
+        libname, f = libf
+        imp_d[ad] = libf
+    return imp_d
+
+
+
+
+def get_imp_bloc(all_bloc, new_lib, imp_d, symbol_pool):
+    f_imps = []
+    symb_equiv = {}
+    for b in all_bloc:
+        for l in b.lines:
+            for a in l.arg:
+                if not x86_afs.ad in a or not a[x86_afs.ad]:
+                    continue
+                print a
+                if not x86_afs.imm in a:
+                    continue
+                ad = a[x86_afs.imm]
+                if not ad in imp_d:
+                    continue
+                print 'spot', ad, l
+                lab = symbol_pool.getby_offset_create(ad)
+                print lab
+
+
+                l = symbol_pool.getby_offset(ad)
+                print "ioioio", l
+                l.offset = None
+
+                a[x86_afs.symb] = {lab.name:1}
+                print a
+                del a[x86_afs.imm]
+
+                libname, func = imp_d[ad]
+                print func
+                new_lib.append(
+                    ({"name":libname,
+                      "firstthunk":None},
+                     [func]),
+                    )
+                f_imps.append(func)
+                symb_equiv[func] = l
+    return f_imps, symb_equiv
+
+
+def code_is_line(e, ad):
+    job_done = set()
+    in_str = bin_stream.bin_stream(e.virt)
+    symbol_pool = asmbloc.asm_symbol_pool()
+    all_bloc = asmbloc.dis_bloc_all(x86_mn, in_str, ad, job_done, symbol_pool, bloc_wd = 2)
+    if len(all_bloc) !=1:
+        return None
+    if len(all_bloc[0].lines)!=1:
+        return None
+    return all_bloc
+
+def is_jmp_imp(l, imp_d):
+    if not l.m.name == 'jmp':
+        return False
+    if not is_address(l.arg[0]):
+        return False
+    ad = dict(l.arg[0])
+    del ad[x86_afs.ad]
+    if not is_imm(ad):
+        return False
+    print ad
+    i = ad[x86_afs.imm]
+    if not i in imp_d:
+        return False
+    print imp_d[i]
+    return imp_d[i]
+
+
+def code_is_jmp_imp(e, ad, imp_d):
+    all_bloc = code_is_line(e, ad)
+    if not all_bloc:
+        return None
+    l = all_bloc[0].lines[0]
+    return is_jmp_imp(l, imp_d)
+
+
+#giving e and address in function guess function start
+def guess_func_start(e, middle_ad, max_offset = 0x200):
+    ad = middle_ad+1
+    ad_found = None
+    while ad > middle_ad - max_offset:
+        ad-=1
+
+        ####### heuristic CC pad #######
+        if e.virt[ad] == "\xCC":
+            if e.virt[((ad+3)&~3)-1] == "\xCC":
+                ad_found = ((ad+3)&~3)
+                break
+            else:
+                continue
+        
+        
+        l = x86_mn.dis(e.virt[ad:ad+15])
+        if not l:
+            continue
+        if l.m.name in ["ret"]:
+            ad_found = ad+l.l
+            break
+        
+    if not ad_found:
+        print 'cannot find func start'
+        return None
+
+    while e.virt[ad_found] == "\xCC":
+        ad_found+=1
+
+    if e.virt[ad_found:ad_found+3] == "\x8D\x40\x00":
+        ad_found += 3
+    
+
+    return ad_found
+
+def get_nul_term(e, ad):
+    out = ""
+    while True:
+        c = e.virt[ad]
+        if c == None:
+            return None
+        if c == "\x00":
+            break
+        out+=c
+        ad+=1
+    return out
+
+#return None if is not str
+def guess_is_string(out):
+    if out == None or len(out) == 0:
+        return None
+    cpt = 0
+    for c in out:
+        if c.isalnum():
+            cpt+=1
+    if cpt * 100 / len(out) > 40:
+        return out
+    
+    return None
+
+
+def get_guess_string(e, ad):
+    s = get_nul_term(e, ad)
+    return guess_is_string(s)
+    
+
+            
+    
+
+
+def canon_libname_libfunc(libname, libfunc):
+    dn = libname.split('.')[0]
+    fn = "%s"%libfunc
+    return "%s_%s"%(dn, fn)
+    
+
+class libimp:
+    def __init__(self, lib_base_ad = 0x77700000):
+        self.name2off = {}
+        self.libbase2lastad = {}
+        self.libbase_ad = lib_base_ad
+        self.lib_imp2ad = {}
+        self.lib_imp2dstad = {}
+        self.fad2cname = {}
+        
+    def lib_get_add_base(self, name):
+        name = name.lower()
+        if name in self.name2off:
+            ad = self.name2off[name]
+        else:
+            print 'new lib', name
+            ad = self.libbase_ad
+            self.name2off[name] = ad
+            self.libbase2lastad[ad] = ad+0x1
+            self.lib_imp2ad[ad] = {}
+            self.lib_imp2dstad[ad] = {}
+            self.libbase_ad += 0x1000
+        return ad
+    
+    def lib_get_add_func(self, libad, imp_ord_or_name, dst_ad = None):
+        if not libad in self.name2off.values():
+            raise ValueError('unknown lib base!', hex(libad))
+
+        #test if not ordinatl
+        #if imp_ord_or_name >0x10000:
+        #    imp_ord_or_name = vm_get_str(imp_ord_or_name, 0x100)
+        #    imp_ord_or_name = imp_ord_or_name[:imp_ord_or_name.find('\x00')]
+
+
+        #/!\ can have multiple dst ad
+        if not imp_ord_or_name in self.lib_imp2dstad[libad]:
+            self.lib_imp2dstad[libad][imp_ord_or_name] = set()
+        self.lib_imp2dstad[libad][imp_ord_or_name].add(dst_ad)
+
+
+        if imp_ord_or_name in self.lib_imp2ad[libad]:
+            return self.lib_imp2ad[libad][imp_ord_or_name]
+        print 'new imp', imp_ord_or_name, dst_ad
+        ad = self.libbase2lastad[libad]
+        self.libbase2lastad[libad] += 0x1
+        self.lib_imp2ad[libad][imp_ord_or_name] = ad
+
+        name_inv = dict([(x[1], x[0]) for x in self.name2off.items()])
+        c_name = canon_libname_libfunc(name_inv[libad], imp_ord_or_name)
+        self.fad2cname[ad] = c_name
+        return ad
+
+    def check_dst_ad(self):
+        for ad in self.lib_imp2dstad:
+            all_ads = self.lib_imp2dstad[ad].values()
+            all_ads.sort()
+            for i, x in enumerate(all_ads[:-1]):
+                if x == None or all_ads[i+1] == None:
+                    return False
+                if x+4 != all_ads[i+1]:
+                    return False
+        return True
+    
+    def gen_new_lib(self, e):
+        new_lib = []
+        for n, ad in self.name2off.items():
+            all_ads = self.lib_imp2dstad[ad].values()
+            all_ads = reduce(lambda x,y:x+list(y), all_ads, [])
+            all_ads.sort()
+            #first, drop None
+            for i,x in enumerate(all_ads):
+                if not x in [0,  None]:
+                    break
+            all_ads = all_ads[i:]
+            while all_ads:
+                othunk = all_ads[0]
+                i = 0
+                while i+1 < len(all_ads) and all_ads[i]+4 == all_ads[i+1]:
+                    i+=1
+                out_ads = dict()
+                for k, vs in self.lib_imp2dstad[ad].items():
+                    for v in vs:
+                        out_ads[v] = k
+                funcs = [out_ads[x] for x in all_ads[:i+1]]
+                new_lib.append(({"name":n,
+                                 "firstthunk":e.virt2rva(othunk)},
+                                funcs)
+                               )
+                all_ads = all_ads[i+1:]
+        return new_lib
+            
+                
+
+def vm_load_pe(e, align_s = True, load_hdr = True):
+    aligned = True
+    for s in e.SHList:
+        if s.addr & 0xFFF:
+            aligned = False
+            break
+
+    if aligned:
+        if load_hdr:
+            pe_hdr = e.content[:0x400]+"\x00"*0xc00
+            to_c_helper.vm_add_memory_page(e.NThdr.ImageBase, to_c_helper.PAGE_READ|to_c_helper.PAGE_WRITE, pe_hdr)
+    
+        if align_s:
+            for i, s in enumerate(e.SHList[:-1]):
+                s.size = e.SHList[i+1].addr - s.addr
+                s.rawsize = s.size
+                s.offset = s.addr
+            s = e.SHList[-1]
+            s.size = (s.size+0xfff)&0xfffff000
+        
+        for s in e.SHList:
+            data = str(s.data)
+            data += "\x00"*(s.size-len(data))
+            to_c_helper.vm_add_memory_page(e.rva2virt(s.addr), to_c_helper.PAGE_READ|to_c_helper.PAGE_WRITE, data)
+            s.offset = s.addr
+        return
+
+    #not aligned
+    print 'WARNING pe is not aligned, creating big section'
+    min_addr = None
+    max_addr = None
+    data = ""
+
+    if load_hdr:
+        data = e.content[:0x400]
+        data += (e.SHList[0].addr - len(data))*"\x00"
+        min_addr = 0
+
+
+    
+    for i, s in enumerate(e.SHList):
+        if i < len(e.SHList)-1:
+            s.size = e.SHList[i+1].addr - s.addr
+        s.rawsize = s.size
+        s.offset = s.addr
+
+        if min_addr == None or s.addr < min_addr:
+            min_addr = s.addr
+            
+        if max_addr == None or s.addr + s.size > max_addr:
+            max_addr = s.addr + s.size
+    min_addr = e.rva2virt(min_addr)
+    max_addr = e.rva2virt(max_addr)
+
+    print hex(min_addr) , hex(max_addr), hex(max_addr - min_addr)
+    for s in e.SHList:
+        data += str(s.data)
+        data += "\x00"*(s.size-len(str(s.data)))
+
+    vm_add_memory_page(min_addr, PAGE_READ|PAGE_WRITE, data)
+    
+    
+
+def vm_load_elf(e, align_s = True, load_hdr = True):
+    for p in e.ph.phlist:
+        if p.ph.type != 1:
+            continue
+        print hex(p.ph.vaddr), hex(p.ph.offset), hex(p.ph.filesz)
+        data = e._content[p.ph.offset:p.ph.offset + p.ph.filesz]
+        
+        r_vaddr = p.ph.vaddr & ~0xFFF
+        data = (p.ph.vaddr - r_vaddr) *"\x00" + data
+        data += (((len(data) +0xFFF) & ~0xFFF)-len(data)) * "\x00"
+        to_c_helper.vm_add_memory_page(r_vaddr, to_c_helper.PAGE_READ|to_c_helper.PAGE_WRITE, data)
+        
+def preload_lib(e, patch_vm_imp = True, lib_base_ad = 0x77700000):
+    runtime_lib = libimp(lib_base_ad)
+    fa = get_import_address(e)
+
+    dyn_funcs = {}
+    
+    print 'imported funcs:', fa
+    for (libname, libfunc), ad in fa.items():
+        ad_base_lib = runtime_lib.lib_get_add_base(libname)
+        ad_libfunc = runtime_lib.lib_get_add_func(ad_base_lib, libfunc, ad)
+
+        libname_s = canon_libname_libfunc(libname, libfunc)
+        dyn_funcs[libname_s] = ad_libfunc
+        if patch_vm_imp:
+            to_c_helper.vm_set_mem(ad, struct.pack('L', ad_libfunc))
+        
+    return runtime_lib, dyn_funcs
+
+def preload_elf(e, patch_vm_imp = True, lib_base_ad = 0x77700000):
+    # XXX quick hack
+    fa = get_import_address_elf(e)
+    runtime_lib = libimp(lib_base_ad)
+
+    dyn_funcs = {}
+    
+    print 'imported funcs:', fa
+    for (libname, libfunc), ad in fa.items():
+        ad_base_lib = runtime_lib.lib_get_add_base(libname)
+        ad_libfunc = runtime_lib.lib_get_add_func(ad_base_lib, libfunc, ad)
+
+        libname_s = canon_libname_libfunc(libname, libfunc)
+        dyn_funcs[libname_s] = ad_libfunc
+        if patch_vm_imp:
+            to_c_helper.vm_set_mem(ad, struct.pack('L', ad_libfunc))
+        
+    return runtime_lib, dyn_funcs
+
+
+def get_export_name_addr_list(e):
+    out = []
+    for i, n in enumerate(e.DirExport.f_names):
+        addr = e.DirExport.f_address[e.DirExport.f_nameordinals[i].ordinal]
+        f_name = n.name.name
+        out.append((f_name, e.rva2virt(addr.rva)))
+    return out
+
+
+
+class find_call_xref:
+    def __init__(self, e, off):
+        import re
+        self.e = e
+        self.off = off
+        #create itertor to find simple CALL offsets
+        p = re.escape("\xE8")
+        self.my_iter = re.finditer(p, e.content)
+    def next(self):
+        while True:
+            off_i = self.my_iter.next().start()
+            off = off_i + 5 + struct.unpack('l', self.e.content[off_i+1:off_i+5])[0]
+            if off == self.off:
+                return off_i
+        raise StopIteration
+    def __iter__(self):
+        return self
+        
diff --git a/miasm/tools/seh_helper.py b/miasm/tools/seh_helper.py
new file mode 100644
index 00000000..c5d8db44
--- /dev/null
+++ b/miasm/tools/seh_helper.py
@@ -0,0 +1,348 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+#from codenat import *
+from to_c_helper import *
+import to_c_helper
+
+FS_0_AD = 0x7ff70000
+PEB_AD = 0x11110000
+
+# fs:[0] Page (TIB)
+tib_address = FS_0_AD
+peb_address = PEB_AD
+peb_ldr_data_address = PEB_AD + 0x1000
+in_load_order_module_list_address = PEB_AD + 0x2000
+in_load_order_module_1 = PEB_AD + 0x3000
+default_seh = PEB_AD + 0x10000
+
+
+context_address = 0xdeada000
+exception_record_address = 0xdeadb000
+return_from_exception = 0x6eadbeef
+
+FAKE_SEH_B_AD = 0x11bb0000
+
+cur_seh_ad = FAKE_SEH_B_AD
+default_image_base = 0x400000
+
+
+def build_fake_teb():
+    """
+    +0x000 NtTib                     : _NT_TIB    
+    +0x01c EnvironmentPointer        : Ptr32 Void
+    +0x020 ClientId                  : _CLIENT_ID
+    +0x028 ActiveRpcHandle           : Ptr32 Void
+    +0x02c ThreadLocalStoragePointer : Ptr32 Void
+    +0x030 ProcessEnvironmentBlock   : Ptr32 _PEB 
+    ...
+    """
+    o = ""
+    o += pdw(default_seh)
+    o += (0x18 - len(o)) *"\x00"
+    o += pdw(tib_address)
+    
+    o += (0x30 - len(o)) *"\x00"
+    o += pdw(peb_address)
+    
+    return o
+
+
+def build_fake_peb():
+    """
+    +0x000 InheritedAddressSpace    : UChar
+    +0x001 ReadImageFileExecOptions : UChar
+    +0x002 BeingDebugged            : UChar
+    +0x003 SpareBool                : UChar
+    +0x004 Mutant                   : Ptr32 Void
+    +0x008 ImageBaseAddress         : Ptr32 Void
+    +0x00c Ldr                      : Ptr32 _PEB_LDR_DATA
+    """
+    o = ""
+    o += "\x00"*0x8
+    o += pdw(default_image_base)
+    o += pdw(peb_ldr_data_address)
+    return o
+
+
+def build_fake_ldr_data():
+    """
+    +0x000 Length                          : Uint4B
+    +0x004 Initialized                     : UChar
+    +0x008 SsHandle                        : Ptr32 Void
+    +0x00c InLoadOrderModuleList           : _LIST_ENTRY
+    +0x014 InMemoryOrderModuleList         : _LIST_ENTRY
+    """
+    o = ""
+    o += "\x00"*0xc
+    #text XXX
+    o += pdw(in_load_order_module_list_address) + pdw(0)
+    o += pdw(in_load_order_module_list_address+8) + pdw(0)
+    o += pdw(in_load_order_module_list_address+0x10) + pdw(0)
+    return o
+
+
+def build_fake_inordermodule(modules_name):
+    """
+    +0x000 Flink : Ptr32                                 -+ This distance
+    +0x004 Blink : Ptr32                                  | is eight bytes
+    +0x018 DllBase                        : Ptr32 Void   -+ DllBase -> _IMAGE_DOS_HEADER
+    +0x01c EntryPoint                     : Ptr32 Void
+    +0x020 SizeOfImage                    : Uint4B
+    +0x024 FullDllName                    : _UNICODE_STRING
+    +0x02c BaseDllName                    : _UNICODE_STRING
+    +0x034 Flags                          : Uint4B
+    +0x038 LoadCount                      : Uint2B
+    +0x03a TlsIndex                       : Uint2B
+    +0x03c HashLinks                      : _LIST_ENTRY
+    +0x03c SectionPointer                 : Ptr32 Void
+    +0x040 CheckSum                       : Uint4B
+    +0x044 TimeDateStamp                  : Uint4B
+    +0x044 LoadedImports                  : Ptr32 Void
+    +0x048 EntryPointActivationContext    : Ptr32 Void
+    +0x04c PatchInformation               : Ptr32 Void
+    """
+
+    o = ""
+    o += pdw(in_load_order_module_1  )
+    o += pdw(0)
+    o += pdw(in_load_order_module_1+8  )
+    o += pdw(0)
+    o += pdw(in_load_order_module_1+0x10)
+    o += pdw(0)
+    o += pdw(default_image_base)
+    o += (0x1000 - len(o))*"I"
+        
+    for i, m in enumerate(modules_name):
+        #fname = os.path.join('win_dll', m)
+        fname = m
+        e = pe_init.PE(open(fname, 'rb').read())
+        m_o = ""
+        m_o += pdw(in_load_order_module_1 + (i+1)*0x1000 )
+        m_o += pdw(in_load_order_module_1 + (i-1)*0x1000)
+        m_o += pdw(in_load_order_module_1 + (i+1)*0x1000 + 8 )
+        m_o += pdw(in_load_order_module_1 + (i-1)*0x1000 + 8)
+        m_o += pdw(in_load_order_module_1 + (i+1)*0x1000 + 0x10 )
+        m_o += pdw(in_load_order_module_1 + (i-1)*0x1000 + 0x10)
+        m_o += pdw(e.NThdr.ImageBase)
+        m_o += pdw(e.rva2virt(e.Opthdr.AddressOfEntryPoint))
+        m_o += pdw(e.NThdr.sizeofimage)
+        m_o += (0x1000 - len(m_o))*"J"
+
+        print "module", "%.8X"%e.NThdr.ImageBase, fname
+        
+        o += m_o
+    return o
+
+
+    
+all_seh_ad = dict([(x, None) for x in xrange(FAKE_SEH_B_AD, FAKE_SEH_B_AD+0x1000, 0x20)])
+#http://blog.fireeye.com/research/2010/08/download_exec_notes.html
+def init_seh():
+    global seh_count
+    seh_count = 0
+    
+    #vm_add_memory_page(tib_address, PAGE_READ | PAGE_WRITE, p(default_seh) + p(0) * 11 + p(peb_address))
+    vm_add_memory_page(FS_0_AD, PAGE_READ | PAGE_WRITE, build_fake_teb())
+    #vm_add_memory_page(peb_address, PAGE_READ | PAGE_WRITE, p(0) * 3 + p(peb_ldr_data_address))
+    vm_add_memory_page(peb_address, PAGE_READ | PAGE_WRITE, build_fake_peb())
+    #vm_add_memory_page(peb_ldr_data_address, PAGE_READ | PAGE_WRITE, p(0) * 3 + p(in_load_order_module_list_address) + p(0) * 0x20)
+    vm_add_memory_page(peb_ldr_data_address, PAGE_READ | PAGE_WRITE, build_fake_ldr_data())
+
+    #vm_add_memory_page(in_load_order_module_list_address, PAGE_READ | PAGE_WRITE, p(0) * 40)
+    vm_add_memory_page(in_load_order_module_list_address, PAGE_READ | PAGE_WRITE, build_fake_inordermodule(["win_dll/kernel32.dll", "win_dll/kernel32.dll"]))
+    vm_add_memory_page(default_seh, PAGE_READ | PAGE_WRITE, p(0xffffffff) + p(0x41414141) + p(0x42424242))
+
+    vm_add_memory_page(context_address, PAGE_READ | PAGE_WRITE, '\x00' * 0x2cc)
+    vm_add_memory_page(exception_record_address, PAGE_READ | PAGE_WRITE, '\x00' * 200)
+
+    vm_add_memory_page(FAKE_SEH_B_AD, PAGE_READ | PAGE_WRITE, 0x10000*"\x00")
+
+#http://www.codeproject.com/KB/system/inject2exe.aspx#RestorethefirstRegistersContext5_1
+def regs2ctxt(regs):
+    ctxt = ""
+    ctxt += '\x00\x00\x00\x00'  #ContextFlags
+    ctxt += '\x00\x00\x00\x00' * 6 #drX
+    ctxt += '\x00' * 112 #float context
+    ctxt += '\x00\x00\x00\x00' + '\x3b\x00\x00\x00' + '\x23\x00\x00\x00' + '\x23\x00\x00\x00' #segment selectors
+    ctxt += p(regs['edi']) + p(regs['esi']) + p(regs['ebx']) + p(regs['edx']) + p(regs['ecx']) + p(regs['eax']) + p(regs['ebp']) + p(regs['eip']) #gpregs
+    ctxt += '\x23\x00\x00\x00' #cs
+    ctxt += '\x00\x00\x00\x00' #eflags
+    ctxt += p(regs['esp'])  #esp
+    ctxt += '\x23\x00\x00\x00' #ss segment selector
+    return ctxt
+
+
+def ctxt2regs(ctxt):
+    ctxt = ctxt[:]
+    regs = {}
+    #regs['ctxtsflags'] = updw(ctxt[:4])
+    ctxt = ctxt[4:]
+    for i in xrange(8):
+        if i in [4, 5]:
+            continue
+        #regs['dr%d'%i] = updw(ctxt[:4])
+        ctxt = ctxt[4:]
+
+    ctxt = ctxt[112:] #skip float
+
+    #regs['seg_gs'] = updw(ctxt[:4])
+    ctxt = ctxt[4:]
+    #regs['seg_fs'] = updw(ctxt[:4])
+    ctxt = ctxt[4:]
+    #regs['seg_es'] = updw(ctxt[:4])
+    ctxt = ctxt[4:]
+    #regs['seg_ds'] = updw(ctxt[:4])
+    ctxt = ctxt[4:]
+    
+    regs['edi'], regs['esi'], regs['ebx'], regs['edx'], regs['ecx'], regs['eax'], regs['ebp'], regs['eip']  = struct.unpack('LLLLLLLL', ctxt[:4*8])
+    ctxt = ctxt[4*8:]
+
+    #regs['seg_cs'] = updw(ctxt[:4])
+    ctxt = ctxt[4:]
+    
+    #regs['eflag'] = updw(ctxt[:4])
+    ctxt = ctxt[4:]
+    
+    regs['esp'] = updw(ctxt[:4])
+    ctxt = ctxt[4:]
+
+    for a, b in regs.items():
+        print a, hex(b)
+    #skip extended
+    return regs
+
+
+def get_free_seh_place():
+    global all_seh_ad
+    ads = all_seh_ad.keys()
+    ads.sort()
+    for ad in ads:
+        v = all_seh_ad[ad]
+        if v == None:
+            print 'TAKING SEH', hex(ad)
+            all_seh_ad[ad] = True
+            return ad
+    raise ValueError('too many stacked seh ')
+
+def free_seh_place(ad):
+    print 'RELEASING SEH', hex(ad)
+
+    if not ad in all_seh_ad:
+        raise ValueError('zarb seh ad!', hex(ad))
+    if all_seh_ad[ad] != True:
+        raise ValueError('seh alreaedy remouvede?!!', hex(ad))
+    all_seh_ad[ad] = None
+
+def fake_seh_handler(except_code):
+    global seh_count
+    regs = vm_get_gpreg()
+    print '-> exception at', hex(regs['eip']), seh_count
+    seh_count += 1
+    
+    # Help lambda
+    p = lambda s: struct.pack('L', s)
+    
+    dump_gpregs_py()
+    # Forge a CONTEXT
+    ctxt =  '\x00\x00\x00\x00' + '\x00\x00\x00\x00' * 6 + '\x00' * 112 + '\x00\x00\x00\x00' + '\x3b\x00\x00\x00' + '\x23\x00\x00\x00' + '\x23\x00\x00\x00' + p(regs['edi']) + p(regs['esi']) + p(regs['ebx']) + p(regs['edx']) + p(regs['ecx']) + p(regs['eax']) + p(regs['ebp']) + p(regs['eip']) + '\x23\x00\x00\x00' + '\x00\x00\x00\x00' + p(regs['esp']) + '\x23\x00\x00\x00'
+    #ctxt = regs2ctxt(regs)
+    
+    # Find a room for seh
+    #seh = (get_memory_page_max_address_py()+0x1000)&0xfffff000
+
+    # Get current seh (fs:[0])
+    seh_ptr = vm_read_dword(tib_address)
+    
+    # Retrieve seh fields
+    old_seh, eh, safe_place = struct.unpack('LLL', vm_get_str(seh_ptr, 0xc))
+    
+    print '-> seh_ptr', hex(seh_ptr), '-> { old_seh', hex(old_seh), 'eh', hex(eh), 'safe_place', hex(safe_place), '}'
+    #print '-> write SEH at', hex(seh&0xffffffff)
+    
+    # Write current seh
+    #vm_add_memory_page(seh, PAGE_READ | PAGE_WRITE, p(old_seh) + p(eh) + p(safe_place) + p(0x99999999))
+    
+    # Write context
+    vm_set_mem(context_address, ctxt)
+
+    # Write exception_record
+
+    """
+    #http://msdn.microsoft.com/en-us/library/aa363082(v=vs.85).aspx
+    
+    typedef struct _EXCEPTION_RECORD {
+      DWORD                    ExceptionCode;
+      DWORD                    ExceptionFlags;
+      struct _EXCEPTION_RECORD *ExceptionRecord;
+      PVOID                    ExceptionAddress;
+      DWORD                    NumberParameters;
+      ULONG_PTR                ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
+    } EXCEPTION_RECORD, *PEXCEPTION_RECORD;
+    """
+    
+    vm_set_mem(exception_record_address, p(except_code) + p(0) + p(0)  + p(regs['eip']) + p(0) + p(0) )
+
+    # Prepare the stack
+    vm_push_uint32_t(context_address)               # Context
+    vm_push_uint32_t(seh_ptr)                       # SEH
+    vm_push_uint32_t(exception_record_address)      # ExceptRecords
+    vm_push_uint32_t(return_from_exception)         # Ret address
+    
+    
+    
+    # Set fake new current seh for exception
+
+    fake_seh_ad = get_free_seh_place()
+    print hex(fake_seh_ad)
+    vm_set_mem(fake_seh_ad, p(seh_ptr) + p(0xaaaaaaaa) + p(0xaaaaaabb) + p(0xaaaaaacc))
+    vm_set_mem(tib_address, p(fake_seh_ad))
+    
+    dump_seh()
+    
+    print '-> jumping at', hex(eh)
+    to_c_helper.vm_reset_exception()
+    
+    
+    regs = vm_get_gpreg()
+    #XXX set ebx to nul?
+    regs['ebx'] = 0
+    vm_set_gpreg(regs)
+    
+    return eh
+    
+fake_seh_handler.base = FAKE_SEH_B_AD
+
+
+def dump_seh():
+	print 'dump_seh:'
+	print '-> tib_address:', hex(tib_address)
+
+	cur_seh_ptr = vm_read_dword(tib_address)
+
+	indent = 1
+	loop = 0
+	while True:
+		#if loop > 3:
+                #		djawidj
+		prev_seh, eh = struct.unpack('LL', vm_get_str(cur_seh_ptr, 8))
+		print '\t' * indent + 'seh_ptr:', hex(cur_seh_ptr), ' -> { prev_seh:', hex(prev_seh), 'eh:', hex(eh), '}'
+		if prev_seh in [0xFFFFFFFF, 0]:
+			break
+		cur_seh_ptr = prev_seh
+		indent += 1
+		loop += 1
diff --git a/miasm/tools/to_c_helper.py b/miasm/tools/to_c_helper.py
new file mode 100644
index 00000000..28ed91e2
--- /dev/null
+++ b/miasm/tools/to_c_helper.py
@@ -0,0 +1,1024 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+from miasm.core import asmbloc
+from miasm.core.bin_stream import bin_stream
+from miasm.arch.ia32_arch import *
+from miasm.arch.ia32_sem import *
+import struct
+
+from elfesteem import *
+
+
+
+from miasm.tools.emul_helper import *
+from miasm.expression.expression_eval_abstract import eval_abs
+from miasm.expression.expression_helper import *
+
+from elfesteem.strpatchwork import StrPatchwork
+import ctypes
+
+def id2new(i):
+    return str(i)+'_new'
+
+
+
+
+my_C_id = [
+	eax,
+	ebx,
+	ecx,
+	edx,
+	esi,
+	edi,
+	esp,
+	ebp,
+	eip,
+	zf,
+	nf,
+	pf,
+	of,
+	cf,
+	af,
+	df,
+	#eax_new,
+	#ebx_new,
+	#ecx_new,
+	#edx_new,
+	#esi_new,
+	#edi_new,
+	#esp_new,
+	#ebp_new,
+	#eip_new,
+	#zf_new,
+	#nf_new,
+	#pf_new,
+	#of_new,
+	#cf_new,
+	#af_new,
+	#df_new,
+	tf,
+	i_f,
+	iopl,
+	nt,
+	rf,
+	vm,
+	ac,
+	vif,
+	vip,
+	i_d,
+	#tf_new,
+	#i_f_new,
+	#iopl_new,
+	#nt_new,
+	#rf_new,
+	#vm_new,
+	#ac_new,
+	#vif_new,
+	#vip_new,
+	#i_d_new,
+	#my_tick,
+	reg_float_control,
+	cond,
+	ds,
+	#vm_exception_flags,
+	#vm_exception_flags_new,
+	#vm_last_write_ad,
+	#vm_last_write_size,
+	tsc1,
+	tsc2,
+
+        float_st0,
+        float_st1,
+        float_st2,
+        float_st3,
+        float_st4,
+        float_st5,
+        float_st6,
+        float_st7,
+
+	float_c0,
+	float_c1,
+	float_c2,
+	float_c3,
+
+	cr0,
+	cr3,
+
+
+        float_stack_ptr,
+
+    ]    
+id2Cid = {}
+for x in my_C_id:
+    id2Cid[x] = ExprId('vmcpu.'+str(x))
+    
+def patch_c_id(e):
+    return e.reload_expr(id2Cid)
+
+
+code_deal_exception_at_instr = r"""
+if (vmcpu.vm_exception_flags > EXCEPT_NUM_UDPT_EIP) {
+    %s = 0x%X; 
+    return (unsigned int)vmcpu.eip; 
+}
+"""
+code_deal_exception_post_instr = r"""
+if (vmcpu.vm_exception_flags) {
+    %s = (vmcpu.vm_exception_flags > EXCEPT_NUM_UDPT_EIP) ?  0x%X : 0x%X; 
+    return (unsigned int)vmcpu.eip; 
+}
+"""
+
+    
+def Exp2C(exprs, l = None, addr2label = None, gen_exception_code = False):
+    if not addr2label:
+        addr2label = lambda x:x
+    id_to_update = []
+    out = []
+    out_eip = []
+    #print [str(x) for x in exprs]
+
+    dst_dict = {}
+
+    new_expr = []
+
+    eip_is_dst = False
+
+    for e in exprs:
+        if not isinstance(e, ExprAff):
+            raise ValueError('should be expr', str(e))
+
+        if isinstance(e.dst, ExprId):
+            if not e.dst in dst_dict:
+                dst_dict[e.dst] = []
+            dst_dict[e.dst].append(e)
+        else:
+            new_expr.append(e)
+            
+    for dst, exs in dst_dict.items():
+        if len(exs) ==1:
+            new_expr += exs
+            continue
+        print 'warning: detected multi dst to same id'
+        print l
+        new_expr+=exs
+        #test if multi slice (for example xchg al, ah)
+        if not False in [isinstance(e.src, ExprCompose) for e in exs]:
+            #spotted multi affectation to same id
+            e_colision = reduce(lambda x,y:x+y, [e.get_modified_slice() for e in exs])
+            #print [str(x) for x in e_colision]
+            known_intervals = [(x.start, x.stop) for x in e_colision]
+            #print known_intervals
+            missing_i = get_missing_interval(known_intervals)
+            #print missing_i
+    
+            rest = [ExprSliceTo(ExprSlice(dst, *r), *r) for r in missing_i]
+            final_dst = ExprCompose(e_colision+ rest)
+            
+            new_expr.append(ExprAff(dst, final_dst))
+        
+    out_mem = []
+    
+    for e in new_expr:
+            
+        if True:#e.dst != eip:
+            
+            src, dst = e.src, e.dst
+            str_src = patch_c_id(src).toC()
+            str_dst = patch_c_id(dst).toC()
+            if isinstance(dst, ExprId):
+                id_to_update.append(dst)
+                str_dst = id2new(patch_c_id(dst))
+                out.append('%s = %s;'%(str_dst, str_src))
+            elif isinstance(dst, ExprMem):
+                str_dst = str_dst.replace('MEM_LOOKUP', 'MEM_WRITE')
+                out_mem.append('%s, %s);'%(str_dst[:-1], str_src))
+                
+            
+        if e.dst == eip :
+            eip_is_dst = True
+            if isinstance(e.src, ExprCond):
+                #out_eip.append("cond = %s;"%e.src.cond.toC())
+                out.append("vmcpu.cond = %s;"%patch_c_id(e.src.cond).toC())
+                out_eip+=["if (vmcpu.cond)",
+                          "\tGOTO_STATIC(vmcpu.eip);//%s);"%(addr2label(e.src.src1.arg)),
+                          "else",
+                          "\tGOTO_STATIC(vmcpu.eip);//%s);"%(addr2label(e.src.src2.arg)),
+                          ]
+            else:
+                if isinstance(e.src, ExprInt):
+                    if l.is_subcall():
+                        out_eip.append("GOTO_STATIC_SUB(%s);"%(addr2label(e.src.arg)))
+                    else:
+                        out_eip.append("GOTO_STATIC(0x%.8X);"%(e.src.arg))
+                else:
+                    if l.is_subcall():
+                        out_eip.append("GOTO_DYN_SUB(%s);"%(patch_c_id(e.src).toC()))
+                    else:
+                        out_eip.append('GOTO_DYNAMIC; //(%s);'%patch_c_id(e.src).toC())
+
+
+    #if len(id_to_update) != len(set(id_to_update)):
+    #    raise ValueError('Not implemented: multi dst to same id!', str([str(x) for x in exprs]))
+
+    out+=out_mem
+
+    if gen_exception_code:
+        out.append(code_deal_exception_at_instr % (patch_c_id(eip), l.offset))
+
+    for i in id_to_update:
+        out.append('%s = %s;'%(patch_c_id(i), id2new(patch_c_id(i))))
+
+
+
+
+    post_instr = []
+    #### test stop exec ####
+    if gen_exception_code:
+        if eip_is_dst:
+            #post_instr.append("if (vmcpu.vm_exception_flags) { /*eip = 0x%X; */return (unsigned int)vm_get_exception(vmcpu.vm_exception_flags); }"%(l.offset))
+            post_instr.append("if (vmcpu.vm_exception_flags) { /*eip = 0x%X; */return (unsigned int)vmcpu.eip; }"%(l.offset))
+        else:
+            post_instr.append(code_deal_exception_post_instr % (patch_c_id(eip), l.offset, l.offset + l.l))
+    
+    """
+    print "1"
+    print out
+    print "2"
+    print out_eip
+    print "3"
+    print post_instr
+    """
+    
+        
+
+    #eip manip after all modifications
+    return out+out_eip, post_instr
+
+
+def bloc2C(all_bloc, addr2label = None, gen_exception_code = False, dbg_instr = False, dbg_reg = False, dbg_lbl = False, filtered_ad = None, tick_dbg = None):
+    all_instrs = digest_allbloc_instr(all_bloc)
+
+    if not addr2label:
+        addr2label = lambda x:"loc_%.8X"%x
+
+
+    out = []
+    label_done = set()
+    for b in all_bloc:
+        #out.append("%s:"%str(b.label.name))
+        if dbg_lbl or dbg_instr:
+            if (not filtered_ad) or b.label.offset in filtered_ad:
+                if tick_dbg!=None:
+                    out.append('if (my_tick > %d)'%tick_dbg)
+                out.append(r'printf("%s\n");'%str(b.label.name))
+        
+        
+        for l in b.lines:
+            if l.offset in label_done:
+                continue
+            label_done.add(l.offset)
+            l,ex = all_instrs[l.offset]
+            if addr2label:
+                out.append("%s:"%addr2label(l.offset))
+            else:
+                out.append("loc_%.8X:"%l.offset)
+                
+            o, post_instr = Exp2C(ex, l, addr2label, gen_exception_code)
+            
+
+            
+
+            #if add_return:
+            #    o.append('return;');
+            #if add_call:
+            #    o.append('%s();'%add_call);
+    
+            if (0xF2 in l.prefix or 0xF3 in l.prefix) and l.m.name in ["ins", "outs", "movsb", "movsw", "movsd", "lodsb", "lodsw", "lodsd", "stosb", "stosw", "stosd" ]+ [ "cmpsb", "cmpsw", "cmpsd", "scasb", "scasw", "scasd" ]:
+                zf_w = zf in reduce(lambda x,y:x+y, [list(x.get_w()) for x in ex], [])
+                my_o = ["while (1){"]
+                #my_o.append("if (vmcpu.vm_exception_flags) { %s = 0x%X; return (PyObject*)vm_get_exception(vm_exception_flags); }"%(patch_c_id(eip), l.offset))
+                #my_o.append(code_deal_exception_post_instr % (patch_c_id(eip), l.offset, l.offset + l.l))
+                my_o.append(code_deal_exception_post_instr % (patch_c_id(eip), l.offset, l.offset))
+
+
+                #my_o.append(r'printf("ecx %.8X\n", ecx );')            
+                my_o+= ['if (%s==0) break;'%patch_c_id(ecx)]
+                my_o+=o
+                my_o+= ['%s--;'%patch_c_id(ecx)]
+                if zf_w:
+                    if 0xF3 in l.prefix:
+                        my_o+= ['if (%s==0) break;'%patch_c_id(zf)]
+                    if 0xF2 in l.prefix:
+                        my_o+= ['if (%s==1) break;'%patch_c_id(zf)]
+
+
+                my_o += ["}"]
+    
+                o = my_o
+
+            o+= post_instr
+            #print "\t"+"\n\t".join(o)
+
+            if dbg_reg and ((not filtered_ad) or l.offset in filtered_ad):
+                if tick_dbg!=None:
+                    out.append(r'vmcpu.my_tick++;')
+                    out.append('if (vmcpu.my_tick > %d)'%tick_dbg)
+                out.append(r'printf("                                          eax %.8X ebx %.8X ecx %.8X edx %.8X esi %.8X edi %.8X esp %.8X ebp %.8X c%X p%X a%X z%X n%X d%X o%X\n", vmcpu.eax, vmcpu.ebx, vmcpu.ecx, vmcpu.edx, vmcpu.esi, vmcpu.edi, vmcpu.esp, vmcpu.ebp, vmcpu.cf, vmcpu.pf, vmcpu.af, vmcpu.zf, vmcpu.nf, vmcpu.df, vmcpu.of );')
+            if dbg_instr and ((not filtered_ad) or l.offset in filtered_ad):
+                if tick_dbg!=None:
+                    out.append('if (vmcpu.my_tick > %d)'%tick_dbg)
+                out.append(r'printf("%s\n");'%str(l))
+            else:
+                out.append(r'//%s'%str(l))
+
+            out+=o
+
+        
+        for c in b.bto:
+            if c.c_t == asmbloc.asm_constraint.c_next:
+                out.append("GOTO_STATIC(0x%.8X);"%(c.label.offset))
+        
+        """
+        #in case of bad disasm, no next, so default next instr
+        #XXX BUG if  no line!!!
+        
+        if b.lines:
+            l = b.lines[-1]
+            out.append("GOTO_STATIC(%s);"%(addr2label(l.offset + l.l)))
+        """
+
+
+    return out
+
+
+
+def bloc_gen_C_func(all_bloc, funcname, addr2label = None, gen_exception_code = False, dbg_instr = False, dbg_reg = False, dbg_lbl = False, filtered_ad = None, tick_dbg = None):
+    f_dec = 'unsigned int %s(void)'%funcname
+    out = []
+    out+=[f_dec,
+          '{',
+          ]
+    out += bloc2C(all_bloc, addr2label, gen_exception_code, dbg_instr, dbg_reg, dbg_lbl, filtered_ad, tick_dbg)
+    out+=['}',
+          ]
+    return f_dec, out
+
+    
+
+
+def gen_x86_core():
+    import os
+
+    lib_dir = os.path.dirname(os.path.realpath(__file__))
+    lib_dir = os.path.join(lib_dir, 'emul_lib')
+
+    txt = ""
+    txt += '#include "%s/queue.h"\n'%lib_dir
+    txt += '#include "%s/libcodenat.h"\n'%lib_dir
+
+    txt += r'''
+    
+//#define RAISE(errtype,msg) { PyErr_SetString(errtype,msg); RE_RAISE; }
+//#define RE_RAISE           { return NULL; }
+
+#define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;}
+
+
+
+'''
+    return txt
+        
+
+def gen_C_source(funcs_code, known_mems, dyn_dispatcher):
+    c_source = dyn_dispatcher
+    c_source+= "\n".join(funcs_code)
+    
+    kmems = gen_known_mems_code(known_mems)
+    c_source = gen_x86_core()+"\n".join(kmems)+c_source
+    return c_source
+
+
+def blocs_to_memory_ranges(all_blocs):
+    code_addr = []
+    for b in all_blocs:
+        # XXX no lines in bloc?
+        if not b.lines:
+            continue
+        code_addr.append((b.lines[0].offset, b.lines[-1].offset + b.lines[-1].l))
+    return code_addr
+
+def del_bloc_in_range(all_blocs, ad1, ad2):
+    bloc_out = []
+    for b in all_blocs:
+        # XXX no lines in bloc?
+        if not b.lines:
+            continue
+        
+        if b.lines[0].offset>=ad2 or b.lines[-1].offset + b.lines[-1].l <= ad1:
+            bloc_out.append(b)
+        else:
+            #print 'inv bloc', b.label
+            pass
+    return bloc_out
+    
+def merge_memory_ranges(t):
+    i = 0
+    while i < len(t)-1:
+        j = i+1
+        rA1, rA2 = t[i]
+        while j < len(t):
+            rB1, rB2 = t[j]
+            #print "uu", hex(rA1), hex(rA2)
+            #print "vv", hex(rB1), hex(rB2)
+
+            if rA1 >= rB1 and rA2 <= rB2:
+                #print '#rA included in rB'
+                rA1, rA2 = t[j]
+                del(t[j])
+                continue
+            elif rA1 <= rB1 and rA2 >= rB2:
+                #print '#rB included in rA'
+                del(t[j])
+                continue
+            elif rA1 <= rB1 and rA2 >= rB1:
+                #print '#rA ends in rB'
+                rA2 = rB2
+                del(t[j])
+                continue
+            elif rB1 <= rA1 and rB2 >= rA1:
+                #print '#rB ends in rA'
+                rA1 = rB1
+                del(t[j])
+                continue
+            j+=1
+        if t[i] != (rA1, rA2):
+            t[i] = rA1, rA2
+        else:
+            i+=1
+            
+
+def gen_code_addr_tab(t):
+    out = []
+
+    out += ["#define CODE_ADDR_SIZE (2*%d)"%len(t)]
+    out += ["unsigned int code_addr_tab[2*%d] = {"%len(t)]
+    for r in t:
+        out += ["\t0x%.8X, 0x%.8X,"%(r)]
+        
+    out += ['};']
+    return '\n'.join(out)+'\n'
+    
+def asm2C(f_name, known_mems, dyn_func, in_str, x86_mn, symbol_pool, func_to_dis, dont_dis = [], follow_call = False, dontdis_retcall = False, log_mn = False, log_reg = False, log_lbl = False, filtered_ad = [], tick_dbg = None, code_addr = [], all_bloc_funcs = []):
+
+    funcs_code = []
+    funcs_dec = []
+
+    all_bloc_funcs+=asmbloc.dis_multi_func(in_str, x86_mn, symbol_pool, func_to_dis, dont_dis, follow_call, dontdis_retcall)
+    """
+    for f in  all_bloc_funcs:
+        print hex(f)
+        print all_bloc_funcs[f]
+        g = asmbloc.bloc2graph(all_bloc_funcs[f])
+        open("tmp/graph_%.8X.txt"%f , "w").write(g)
+    """
+
+    #fds
+    
+        
+    for b in all_bloc_funcs:
+        if b.label.offset in dont_dis:
+            continue
+
+        #XXX no lines in bloc?
+        if not b.lines:
+            continue
+        l = b.lines[-1]
+        #if l.m.name.startswith('jmp') and not x86_afs.symb in l.arg[0]:
+        #    raise ValueError('unsupported dst', str(l))
+        '''
+        if (l.m.name.startswith('call') or l.m.name.startswith('jmp')) and not x86_afs.symb in l.arg[0]:
+
+            #print "TOTO", hex(l.offset), l, l.arg[0]
+            
+            #deal dyn call
+            instr = x86_mn.dis(x86_mn.asm('mov eax, eax')[0])
+            #XXX HACK to be unik address
+            instr.offset = l.offset+1
+
+            instr.arg = [{x86_afs.symb:{ExprId('dyn_dst'):1}}, dict(l.arg[0])]
+
+            #print instr, str(instr)
+            #instr.offset = 0x1337beef
+            
+            #b.lines[-1:-1] = [instr]
+            #l.arg[0] = {x86_afs.symb:func_deal_dyn}
+
+
+            #if dyn func is not in ref, add it (todo in gen C)
+        '''
+    
+        for l in b.lines:
+    
+            #test imm redirect mem ad
+            for a in l.arg:
+                if not x86_afs.imm in a: continue
+                i = a[x86_afs.imm]
+
+
+                l_name = None
+                for m_ad, m_val in known_mems.items():
+                    if m_ad <= i < m_ad+len(m_val):
+                        l_name = "(unsigned int)&tab_%.8X[0x%X]"%(m_ad, i-m_ad)
+                        break
+
+                for f in dyn_func:
+                    if i == f:
+                        if i == 0x00401EDB:
+                            fdsfdsf
+                        #l_name = "(unsigned int)&dyn_func_%.8X"%(f)
+                        l_name = "(unsigned int)0x%.8X"%(f)
+                for f in func_to_dis:
+                    if i == f:
+                        #l_name = "(unsigned int)&func_%.8X"%(f)
+                        l_name = "(unsigned int)0x%.8X"%(f)
+                        break
+
+                if not l_name:
+                    continue
+                
+                    
+                
+                
+                label = asmbloc.asm_label(l_name, i)
+                #symbol_pool.add(label)
+                a[x86_afs.symb] = {label:1}
+                del a[x86_afs.imm]
+                
+                
+    
+    
+    
+                        
+                        
+                        
+          
+    #print "_"*20
+
+    code_addr += blocs_to_memory_ranges(all_bloc_funcs)
+    merge_memory_ranges(code_addr)
+    
+    
+    
+        
+    #g = asmbloc.bloc2graph(all_bloc)
+    #open("graph_%.8X.txt"%ad , "w").write(g)
+    
+    allb = all_bloc_funcs#reduce(lambda x,y:x+y, all_bloc_funcs.values(), [])
+    f_dec, out = bloc_gen_C_func(allb, f_name, None, True, log_mn, log_reg, log_lbl, filtered_ad, tick_dbg)
+    funcs_dec.append(f_dec)
+    funcs_code+=out
+
+
+    for f, f_code in dyn_func.items():
+        l_name = "loc_%.8X"%f
+        funcs_code[-1:-1] = [l_name+":"]
+        funcs_code[-1:-1] = f_code.split('\n')
+        l = asmbloc.asm_label(l_name, f)
+        b = asmbloc.asm_bloc(l)
+        #all_bloc_funcs[f] = [b]
+        all_bloc_funcs += [b]
+
+    funcs_code[2:2] = ["FUNC_DYNAMIC;"]
+    funcs_code[3:3] = ["GOTO_DYNAMIC;"]
+
+    funcs_code[0:0] = [gen_code_addr_tab(code_addr)]
+    #funcs_dec = ["void func_%.8X(void)"%x for x in all_bloc_funcs]
+
+
+    #test return direct dyn dispatch
+    dispatch_table = dispatch_table_from_f_blocs(all_bloc_funcs)
+    dyn_dispatcher = gen_dynamic_dispatcher(dispatch_table)
+
+    return funcs_code, dyn_dispatcher
+
+
+def gen_C_from_asmbloc(in_str, offset, symbol_pool, dont_dis = [], job_done = None, log_mn = False, log_reg = False, log_lbl = False, filtered_ad = [], tick_dbg = None, code_addr = [], all_bloc_funcs = []):
+    if job_done == None:
+        job_done = set()
+
+    f_name = "bloc_%.8X"%offset
+    l = symbol_pool.getby_offset_create(offset)
+    cur_bloc = asmbloc.asm_bloc(l)
+        
+    asmbloc.dis_bloc(x86_mn, in_str, cur_bloc, offset, job_done, symbol_pool,[],
+                     follow_call = False, patch_instr_symb = True, dontdis_retcall = False,lines_wd = None, amode=x86_afs.u32, sex=0)
+
+    f_dec, out = bloc_gen_C_func([cur_bloc], f_name, None, True, log_mn, log_reg, log_lbl, filtered_ad, tick_dbg)
+    #print "\n".join(out)
+    return f_dec, out, cur_bloc
+
+    
+    
+
+
+def dispatch_table_from_f_blocs(all_f_b):
+    dispatch_table = {}
+    #for b in all_f_b:
+    #    dispatch_table[b.label.offset] = b.label.name
+    for b in all_f_b:
+        dispatch_table[b.label.offset] = b.label.name
+        for l in b.lines:
+            dispatch_table[l.offset] = "loc_%.8X"%l.offset
+
+    return dispatch_table
+
+
+def gen_dynamic_dispatcher(dispatch_table):
+    offsets = dispatch_table.keys()
+    offsets.sort()
+    
+    out1 = []
+    out1 += ["#define FUNC_DYNAMIC"]
+    out1 += ['void* tab_eip_label[(%d+1)*2] = '%len(dispatch_table)]
+    out1 += ['{']
+    for o in offsets:
+        out1+=['\t(void*)0x%.8X, (void*)&&%s,'%(o, dispatch_table[o])]
+    out1+=['\t(void*)0x%.8X, (void*)0x0,'%(0)]
+
+    out1 += ['};']
+
+    out2 = []
+    out2 += ["void * get_label_from_eip(void** tab_eip_label)"]
+    out2 += ['{']
+    
+    out2 += ['\tvoid *labelref = NULL;']
+    
+    out2 += ['\tunsigned int i = 0;']
+    out2 += ['\twhile (tab_eip_label[2*i]!= NULL && tab_eip_label[2*i+1]!=NULL){']
+    out2 += ['\t\tif (tab_eip_label[i*2] == (void*)vmcpu.eip){']
+    out2 += ['\t\t\tlabelref = tab_eip_label[i*2+1];']
+    out2 += ['\t\t\treturn labelref;']
+    out2 += ['\t\t}']
+    out2 += ['\ti++;']
+    out2 += ['\t}']
+    out2 += [r'printf("Unkown destination! 0x%.8X\n", vmcpu.eip);']
+    out2 += [r'vmcpu.vm_exception_flags |= EXCEPT_UNK_EIP;']
+    #out2 += [r'exit(0);']
+    out2 += ['return labelref;']
+    out2 += ['}']
+    
+
+    out = []
+
+    out += ["#define GOTO_DYNAMIC"]
+    out += ["labelref = get_label_from_eip();"]
+    out += ["if (labelref == NULL) {"]
+    out += [r'printf("Unkown destination! 0x%.8X\n", vmcpu.eip);']
+    out += [r'vmcpu.vm_exception_flags |= EXCEPT_UNK_EIP;']
+    out += ["return (PyObject*)vm_get_exception(vm_exception_flags);"]
+    out += ['}']
+    out += ['goto *labelref;']
+    
+    """
+    out += ['{']
+    #out += [r'printf("search dst: %X\n", eip);']
+    
+    out += ['switch(eip){']
+    for o in offsets:
+        out+=['case 0x%.8X:'%o]
+        out+=['goto %s;'%dispatch_table[o]]
+        out+=['break;']
+    
+    out += ['case 0x1337beef:']
+    out += [r'printf("return reached %X\n", eip);']
+    out += ['return NULL;']
+    out += ['default:']
+    out += [r'printf("Unkown destination! 0x%.8X\n", eip);']
+    out += [r'vm_exception_flags |= EXCEPT_UNK_EIP;']
+    out += ["return (PyObject*)vm_get_exception(vm_exception_flags);"]
+    out += ['break;']
+    out += ['}']
+    out += ['}']
+    """    
+    return out1, out2
+        
+def gen_dyn_func_manager(dyn_func, dis_func):
+    total_func_num = len(dyn_func)+len(dis_func)
+    out = "int (*tab_func[%d][2])(void) = {"%(total_func_num)
+    dec_f_ptr = ""
+    init_f_ptr = ""
+    for f_ad, f_name in dyn_func.items():
+        out+="{%s, %s},"%("0x%.8X"%f_ad, f_name)
+
+        dec_f_ptr += "unsigned int dyn_func_%.8X;\n"%(f_ad)
+        init_f_ptr+= "dyn_func_%.8X = (unsigned int)&%s;\n"%(f_ad, f_name)
+           
+    for f_ad in dis_func:
+        out+="{0x%.8X, func_%.8X},"%(f_ad, f_ad)
+    out+="};"
+        
+        
+    code = "\n"
+    code += "#define DYN_FUNC_NUM %d"%total_func_num
+    code += r"""
+/*
+void func_dyn_manager(void)
+{
+    unsigned int i;
+""" + out + r"""
+    
+    for (i=0;i<DYN_FUNC_NUM;i++){
+        if (dyn_dst == tab_func[i][0]){
+            printf("i %d v@%X r@%X\n", i, tab_func[i][0], tab_func[i][1]);
+            tab_func[i][1]();
+            return;
+        }
+    }
+    
+    printf("unknown dyn dst!\n");
+    exit(0);
+}
+*/
+    """
+    return dec_f_ptr, init_f_ptr, code
+
+
+
+def insert_printf(c_source, label):
+    for i, l in enumerate(c_source):
+        print l
+        if l.startswith(label):
+            c_source[i+1:i+1] = ['printf("reached %s\\n");'%label]
+        
+
+
+
+def gen_label_declaration(known_mems):
+    lab_dec = []
+    
+    for m_ad, m_val in known_mems.items():
+        dec_name = "char tab_%.8X[0x%X]"%(m_ad, len(m_val))
+        data = m_val
+        dec_name+=' = {'+', '.join(["0x%.2X"%ord(x) for x in data])+'};'
+        lab_dec.append(dec_name)
+
+    
+    return lab_dec
+
+
+def gen_call_func(funcname, args, precode = "", postcode = ""):
+    out = ""
+    
+def gen_known_mems_code(known_mems):
+    code = []
+    for m_ad, m_val in known_mems.items():
+        out = ""
+        out += "char *tab_%.8X;"%(m_ad)
+        out += "char tab_data_%.8X[0x%X] = "%(m_ad, len(m_val))
+        out += '{'+', '.join(["0x%.2X"%ord(x) for x in m_val])+'};'
+        out += 'unsigned int get_tab_%.8X() { return (unsigned int)tab_%.8X;}'%(m_ad, m_ad)
+        code.append(out)
+
+    #test transform tab_XX to dynamic allocated prod
+    """
+    code.append("void init_tab_mem(void)")
+    code.append("{")
+    code.append("unsigned int ret;")
+    
+    for m_ad, m_val in known_mems.items():
+        #code.append("tab_%.8X = malloc(0x%.8X);\n"%(m_ad, len(m_val)))
+        code.append("ret = posix_memalign(&tab_%.8X, 0x10000, 0x%.8X);"%(m_ad, len(m_val)))
+        code.append("if (ret){")
+        code.append(r'    printf("cannot alloc");')
+        code.append(r'    exit(-1);')
+        code.append(r'}')
+        
+
+        code.append("memcpy(tab_%.8X, tab_data_%.8X, 0x%.8X);"%(m_ad, m_ad, len(m_val)))
+    code.append("}\n")
+    """
+    
+    
+
+    return code
+
+if __name__ == '__main__':
+    e = dec(ExprMem(eax))
+    for x in e:
+        print x
+    print '_'*80
+    o = Exp2C(e)
+    for x in o:
+        print x
+    print '#'*80
+
+    new_e = [x.replace_expr({ExprMem(eax): ExprId('ioio')}) for x in e]
+    for x in new_e:
+        print x
+    print '-'*80
+    o = Exp2C(new_e)
+    for x in o:
+        print x
+    print '#'*80
+
+    
+
+
+def _compile(self):
+    import os
+    from distutils.core import setup, Extension
+    import os
+
+    lib_dir = os.path.dirname(os.path.realpath(__file__))
+    lib_dir = os.path.join(lib_dir, 'emul_lib')
+
+    os.chdir(self._buildDir)
+    ext = Extension(self._moduleName,
+                    [self._srcFileName],
+                    library_dirs=self._options.get('library_dirs'),
+                    libraries=self._options.get('libraries'),
+                    define_macros=self._options.get('define_macros'),
+                    undef_macros=self._options.get('undef_macros'),
+                    extra_link_args = ['-Wl,-rpath,'+lib_dir]
+                    )
+    try:
+        setup(name = self._moduleName,
+              version = self._moduleVersion,
+              ext_modules = [ext],
+              script_args = ["build"] + (self._options.get('distutils_args') or []),
+              script_name="C.py",
+              package_dir=self._buildDir,
+              )
+    except SystemExit, e:
+        raise BuildError(e)
+        
+    os.chdir(self._homeDir)
+    
+
+    
+
+
+from miasm.tools.codenat import *
+'''
+def updt_bloc_emul(known_blocs, in_str, my_eip, symbol_pool, code_blocs_mem_range, dont_dis = [], log_mn = False, log_regs = False):
+
+    f_dec, funcs_code, cur_bloc = gen_C_from_asmbloc(in_str, my_eip, symbol_pool, dont_dis, log_mn, log_regs)
+
+    dyn_dispatcher = """
+    #define GOTO_DYNAMIC do {return %s;} while(0)
+    #define GOTO_STATIC(a) do {vmcpu.eip = a;return %s;} while(0)
+    #define GOTO_STATIC_SUB(a) do {return %s;} while(0)
+    #define GOTO_DYN_SUB(a) do {return %s;} while(0)
+    #define vm_get_exception(a)  %s
+    """%(patch_c_id(eip), patch_c_id(eip), patch_c_id(eip), patch_c_id(eip), patch_c_id(eip))
+
+    c_source = gen_C_source(funcs_code, {}, dyn_dispatcher)
+    c_source = "#include <Python.h>\n"+c_source
+
+    a = gen_C_module(c_source)
+    bn = bloc_nat(my_eip, cur_bloc, a, log_mn, log_regs)
+    #f_dec = f_dec[10:-6]
+    f_dec = f_dec[13:-6]
+    a.func = a[f_dec]
+    known_blocs[my_eip] = bn
+
+    ###### update code ranges ###
+    
+    code_addr = blocs_to_memory_ranges([bn.b])
+    code_blocs_mem_range += code_addr
+    merge_memory_ranges(code_blocs_mem_range)
+    reset_code_bloc_pool_py()
+    for a, b in  code_blocs_mem_range:
+            vm_add_code_bloc(a, b)
+'''    
+
+ttt = 0
+def updt_bloc_emul(known_blocs, in_str, my_eip, symbol_pool, code_blocs_mem_range, dont_dis = [], job_done = None, log_mn = False, log_regs = False):
+    if job_done == None:
+        job_done = set()
+    f_dec, funcs_code, cur_bloc = gen_C_from_asmbloc(in_str, my_eip, symbol_pool, dont_dis, job_done, log_mn, log_regs)
+
+    dyn_dispatcher = """
+    #define GOTO_DYNAMIC do {return %s;} while(0)
+    #define GOTO_STATIC(a) do {vmcpu.eip = a; return %s;} while(0)
+    #define GOTO_STATIC_SUB(a) do {return %s;} while(0)
+    #define GOTO_DYN_SUB(a) do {return %s;} while(0)
+    #define vm_get_exception(a)  %s
+    """%(patch_c_id(eip), patch_c_id(eip), patch_c_id(eip), patch_c_id(eip), patch_c_id(eip))
+
+    c_source = gen_C_source(funcs_code, {}, dyn_dispatcher)
+    c_source = "#include <Python.h>\n"+c_source
+    #c_source = '#include "emul_lib/libcodenat.h"\n'+c_source
+    #print c_source
+
+    a = gen_C_module_tcc(f_dec[13:-6], c_source)
+    bn = bloc_nat(my_eip, cur_bloc, a, log_mn, log_regs)
+
+    bn.c_source = c_source
+    #f_dec = f_dec[10:-6]
+    f_dec = f_dec[13:-6]
+    #a.func = a[f_dec]
+    known_blocs[my_eip] = bn
+    ###### update code ranges ###
+    code_addr = blocs_to_memory_ranges([bn.b])
+    code_blocs_mem_range += code_addr
+    merge_memory_ranges(code_blocs_mem_range)
+    reset_code_bloc_pool_py()
+    for a, b in  code_blocs_mem_range:
+            vm_add_code_bloc(a, b)
+    
+#'''
+
+def updt_pe_from_emul(e):
+    for s in e.SHList:
+        sdata = vm_get_str(e.rva2virt(s.addr), s.rawsize)
+        e.virt[e.rva2virt(s.addr)] = sdata
+    return bin_stream(e.virt)
+    
+    return bin_stream_vm()
+
+
+
+def updt_automod_code(known_blocs):
+    w_ad, w_size = vm_get_last_write_ad(), vm_get_last_write_size()
+    print hex(w_ad), hex(w_size)
+    #all_bloc_funcs = del_bloc_in_range([bn.b for bn in known_blocs], w_ad, w_ad+w_size/8)
+    known_blocs = del_bloc_in_range(known_blocs, w_ad, w_ad+w_size/8)
+    
+    code_addr = blocs_to_memory_ranges([bn.b for bn in known_blocs.values()])
+    merge_memory_ranges(code_addr)
+    
+    reset_code_bloc_pool_py()
+    for a, b in  code_addr:
+        vm_add_code_bloc(a, b)
+        
+    #dump_code_bloc_pool_py()
+    
+    vm_reset_exception()
+
+
+    return known_blocs, code_addr
+
+import random
+
+    
+
+def c_emul_bloc(known_blocs, my_eip):
+    if not my_eip in known_blocs:
+        raise ValueError('unknown bloc (should have been disasm...', hex(my_eip))
+    return known_blocs[my_eip].module_c.func()
+
+
+class bin_stream_vm():
+    def __init__(self, offset = 0L):
+        self.offset = offset
+
+    def readbs(self, l=1):
+        s = vm_get_str(self.offset, l)
+        self.offset+=l
+        return s
+
+    def writebs(self, l=1):
+        raise 'writebs unsupported'
+
+    def __str__(self):
+        raise 'writebs unsupported'
+    def setoffset(self, val):
+        val = val & 0xFFFFFFFF
+        self.offset = val
+
+
+
+vm_read_dword = lambda a: struct.unpack('L', vm_get_str(a, 4))[0]
+p = lambda addr: struct.pack('L', addr)
+pdw = p
+updw = lambda bbbb: struct.unpack('L', bbbb)[0]
+pw = lambda x: struct.pack('H', x)
+upw = lambda x: struct.unpack('H', x)[0]
+
+#try:
+if True:
+    from emul_lib.libcodenat_interface import *
+    
+    #vm_init_regs = libcodenat.vm_init_regs
+#except:
+#    print "WARNING! unable to build libcodenat C interface!!"
+
+
+
diff --git a/miasm/tools/win_api.py b/miasm/tools/win_api.py
new file mode 100644
index 00000000..378d8cd1
--- /dev/null
+++ b/miasm/tools/win_api.py
@@ -0,0 +1,1509 @@
+#
+# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+from to_c_helper import *
+import struct
+from Crypto.Hash import MD5
+import inspect
+from zlib import crc32
+handle_toolhelpsnapshot = 0xaaaa00
+toolhelpsnapshot_info = {}
+handle_curprocess = 0xaaaa01
+dbg_present = 0
+
+tickcount =0
+
+dw_pid_dummy1 = 0x111
+dw_pid_explorer = 0x222
+dw_pid_dummy2 = 0x333
+dw_pid_cur = 0x444
+
+
+module_fname_nux = None
+module_name = "test.exe\x00"
+module_path = "c:\\mydir\\"+module_name
+module_filesize = None
+getversion = 0x0A280105
+
+getforegroundwindow =  0x333333
+
+
+cryptcontext_hwnd = 0x44400
+cryptcontext_bnum = 0x44000
+cryptcontext_num = 0
+
+cryptcontext = {}
+
+phhash_crypt_md5 = 0x55555
+
+file_hwnd_num = 0x66600
+files_hwnd = {}
+file_offsets = {}
+
+windowlong_dw = 0x77700
+
+
+module_cur_hwnd = 0x88800
+
+module_file_nul = 0x999000
+runtime_dll = None
+
+"""
+typedef struct tagPROCESSENTRY32 {
+  DWORD     dwSize;
+  DWORD     cntUsage;
+  DWORD     th32ProcessID;
+  ULONG_PTR th32DefaultHeapID;
+  DWORD     th32ModuleID;
+  DWORD     cntThreads;
+  DWORD     th32ParentProcessID;
+  LONG      pcPriClassBase;
+  DWORD     dwFlags;
+  TCHAR     szExeFile[MAX_PATH];
+} PROCESSENTRY32, *PPROCESSENTRY32;
+"""
+
+
+def whoami():
+    return inspect.stack()[1][3]
+
+
+class hobj:
+    pass
+
+
+class mdl:
+    def __init__(self, ad, l):
+        self.ad = ad
+        self.l = l
+    def __str__(self):
+        return struct.pack('LL', self.ad, self.l)
+
+def get_str_ansi(ad_str):
+    l = 0
+    tmp = ad_str
+    while vm_get_str(tmp, 1) != "\x00":
+        tmp +=1
+        l+=1
+    return vm_get_str(ad_str, l)
+    
+def get_str_unic(ad_str):
+    l = 0
+    tmp = ad_str
+    while vm_get_str(tmp, 2) != "\x00\x00":
+        tmp +=2
+        l+=2
+    return vm_get_str(ad_str, l)
+
+
+def kernel32_GlobalAlloc():
+    ret_ad = vm_pop_uint32_t()
+    uflags = vm_pop_uint32_t()
+    msize = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(uflags), hex(msize), ')'
+    max_ad = get_memory_page_from_min_ad_py(msize)
+
+    vm_add_memory_page(max_ad, PAGE_READ|PAGE_WRITE, "\x00"*msize)
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = max_ad
+    vm_set_gpreg(regs)
+
+
+def kernel32_GlobalFree():
+    ret_ad = vm_pop_uint32_t()
+    ad = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(ad), ')'
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    vm_set_gpreg(regs)
+
+def kernel32_IsDebuggerPresent():
+    ret_ad = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', ')'
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = dbg_present
+    vm_set_gpreg(regs)
+
+
+def kernel32_CreateToolhelp32Snapshot():
+    ret_ad = vm_pop_uint32_t()
+    dwflags = vm_pop_uint32_t()
+    th32processid = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(dwflags), hex(th32processid), ')'
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = handle_toolhelpsnapshot
+    vm_set_gpreg(regs)
+
+def kernel32_GetCurrentProcess():
+    ret_ad = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', ')'
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = handle_curprocess
+    vm_set_gpreg(regs)
+
+def kernel32_GetCurrentProcessId():
+    ret_ad = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', ')'
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = dw_pid_cur
+    vm_set_gpreg(regs)
+
+
+process_list = [
+    [
+        0x40,               #DWORD     dwSize;             
+        0,                  #DWORD     cntUsage;           
+        dw_pid_dummy1,       #DWORD     th32ProcessID;      
+        0x11111111,         #ULONG_PTR th32DefaultHeapID;  
+        0x11111112,         #DWORD     th32ModuleID;       
+        1,                  #DWORD     cntThreads;         
+        dw_pid_explorer,    #DWORD     th32ParentProcessID;
+        0xbeef,             #LONG      pcPriClassBase;     
+        0x0,                #DWORD     dwFlags;            
+        "dummy1.exe"          #TCHAR     szExeFile[MAX_PATH];
+        ],
+    [
+        0x40,               #DWORD     dwSize;             
+        0,                  #DWORD     cntUsage;           
+        dw_pid_explorer,    #DWORD     th32ProcessID;      
+        0x11111111,         #ULONG_PTR th32DefaultHeapID;  
+        0x11111112,         #DWORD     th32ModuleID;       
+        1,                  #DWORD     cntThreads;         
+        4,                  #DWORD     th32ParentProcessID;
+        0xbeef,             #LONG      pcPriClassBase;     
+        0x0,                #DWORD     dwFlags;            
+        "explorer.exe"      #TCHAR     szExeFile[MAX_PATH];
+        ],
+
+    [
+        0x40,               #DWORD     dwSize;             
+        0,                  #DWORD     cntUsage;           
+        dw_pid_dummy2,       #DWORD     th32ProcessID;      
+        0x11111111,         #ULONG_PTR th32DefaultHeapID;  
+        0x11111112,         #DWORD     th32ModuleID;       
+        1,                  #DWORD     cntThreads;         
+        dw_pid_explorer,    #DWORD     th32ParentProcessID;
+        0xbeef,             #LONG      pcPriClassBase;     
+        0x0,                #DWORD     dwFlags;            
+        "dummy2.exe"          #TCHAR     szExeFile[MAX_PATH];
+        ],
+
+    [
+        0x40,               #DWORD     dwSize;             
+        0,                  #DWORD     cntUsage;           
+        dw_pid_cur,         #DWORD     th32ProcessID;      
+        0x11111111,         #ULONG_PTR th32DefaultHeapID;  
+        0x11111112,         #DWORD     th32ModuleID;       
+        1,                  #DWORD     cntThreads;         
+        dw_pid_explorer,    #DWORD     th32ParentProcessID;
+        0xbeef,             #LONG      pcPriClassBase;     
+        0x0,                #DWORD     dwFlags;            
+        module_name          #TCHAR     szExeFile[MAX_PATH];
+        ],
+
+
+]
+
+def kernel32_Process32First():
+    ret_ad = vm_pop_uint32_t()
+    s_handle = vm_pop_uint32_t()
+    ad_pentry = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(s_handle), hex(ad_pentry), ')'
+
+    pentry = struct.pack('LLLLLLLLL', *process_list[0][:-1])+process_list[0][-1]
+    vm_set_mem(ad_pentry, pentry)
+    
+    toolhelpsnapshot_info[s_handle] = 0
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 1
+    vm_set_gpreg(regs)
+
+
+def kernel32_Process32Next():
+    ret_ad = vm_pop_uint32_t()
+    s_handle = vm_pop_uint32_t()
+    ad_pentry = vm_pop_uint32_t()
+
+    toolhelpsnapshot_info[s_handle] +=1
+    if toolhelpsnapshot_info[s_handle] >= len(process_list):
+        eax = 0
+    else:
+        eax = 1
+        n = toolhelpsnapshot_info[s_handle]
+        print whoami(), hex(ret_ad), '(', hex(s_handle), hex(ad_pentry), ')'
+        pentry = struct.pack('LLLLLLLLL', *process_list[n][:-1])+process_list[n][-1]
+        vm_set_mem(ad_pentry, pentry)
+        
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = eax
+    vm_set_gpreg(regs)
+
+
+    
+
+def kernel32_GetTickCount():
+    global tickcount
+    ret_ad = vm_pop_uint32_t()
+    
+    print whoami(), hex(ret_ad), '(', ')'
+    tickcount +=1
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = tickcount
+    vm_set_gpreg(regs)
+
+
+def kernel32_GetVersion():
+    ret_ad = vm_pop_uint32_t()
+    
+    print whoami(), hex(ret_ad), '(', ')'
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = getversion
+    vm_set_gpreg(regs)
+
+
+def kernel32_GetPriorityClass():
+    ret_ad = vm_pop_uint32_t()
+    hwnd = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(hwnd), ')'
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+def kernel32_SetPriorityClass():
+    ret_ad = vm_pop_uint32_t()
+    hwnd = vm_pop_uint32_t()
+    dwpclass = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(hwnd), hex(dwpclass),')'
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+    
+
+def kernel32_CloseHandle():
+    ret_ad = vm_pop_uint32_t()
+    hwnd = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(hwnd),')'
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 1
+    vm_set_gpreg(regs)
+    
+
+def user32_GetForegroundWindow():
+    ret_ad = vm_pop_uint32_t()
+    
+    print whoami(), hex(ret_ad), '(', ')'
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = getforegroundwindow
+    vm_set_gpreg(regs)
+
+
+
+def user32_FindWindowA():
+    ret_ad = vm_pop_uint32_t()
+    pclassname = vm_pop_uint32_t()
+    pwindowname = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(pclassname), hex(pwindowname), ')'
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+
+def user32_GetTopWindow():
+    ret_ad = vm_pop_uint32_t()
+    hwnd = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(hwnd), ')'
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+def user32_BlockInput():
+    ret_ad = vm_pop_uint32_t()
+    b = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(b), ')'
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 1
+    vm_set_gpreg(regs)
+    
+
+def advapi32_CryptAcquireContextA():
+    ret_ad = vm_pop_uint32_t()
+    phprov = vm_pop_uint32_t()
+    pszcontainer = vm_pop_uint32_t()
+    pszprovider = vm_pop_uint32_t()
+    dwprovtype = vm_pop_uint32_t()
+    dwflags = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(phprov), hex(pszcontainer), hex(pszprovider), hex(dwprovtype), hex(dwflags), ')'
+
+    prov = vm_get_str(pszprovider, 0x100)
+    prov = prov[:prov.find('\x00')]
+    print 'prov:', prov
+                
+
+    vm_set_mem(phprov, pdw(cryptcontext_hwnd))
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 1
+    vm_set_gpreg(regs)
+
+
+def advapi32_CryptCreateHash():
+    global cryptcontext_num
+    ret_ad = vm_pop_uint32_t()
+    hprov = vm_pop_uint32_t()
+    algid = vm_pop_uint32_t()
+    hkey = vm_pop_uint32_t()
+    dwflags = vm_pop_uint32_t()
+    phhash = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(hprov), hex(algid), hex(hkey), hex(dwflags), hex(phhash), ')'
+
+    cryptcontext_num +=1
+
+    if algid == 0x00008003:
+        print 'algo is MD5'
+        vm_set_mem(phhash, pdw(cryptcontext_bnum+cryptcontext_num))
+        cryptcontext[cryptcontext_bnum+cryptcontext_num] = hobj()
+        cryptcontext[cryptcontext_bnum+cryptcontext_num].h = MD5.new()
+    else:
+        raise ValueError('un impl algo1')
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 1
+    vm_set_gpreg(regs)
+    
+def advapi32_CryptHashData():
+    global cryptcontext
+    ret_ad = vm_pop_uint32_t()
+    hhash = vm_pop_uint32_t()
+    pbdata = vm_pop_uint32_t()
+    dwdatalen = vm_pop_uint32_t()
+    dwflags = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(hhash), hex(pbdata), hex(dwdatalen), hex(dwflags), ')'
+
+    if not hhash in cryptcontext:
+        raise ValueError("unknown crypt context")
+
+    data = vm_get_str(pbdata, dwdatalen)
+    print 'will hash'
+    print repr(data)
+    cryptcontext[hhash].h.update(data)
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 1
+    vm_set_gpreg(regs)
+
+
+def advapi32_CryptDeriveKey():
+    ret_ad = vm_pop_uint32_t()
+    hprov = vm_pop_uint32_t()
+    algid = vm_pop_uint32_t()
+    hbasedata = vm_pop_uint32_t()
+    dwflags = vm_pop_uint32_t()
+    phkey = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(hprov), hex(algid), hex(hbasedata), hex(dwflags), hex(phkey), ')'
+
+    if algid == 0x6801:
+        print 'using DES'
+    else:
+        raise ValueError('un impl algo2')        
+
+    h = cryptcontext[hbasedata].h.digest()
+    print 'hash', repr(h)
+    cryptcontext[hbasedata].h_result = h
+    vm_set_mem(phkey, pdw(hbasedata))    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 1
+    vm_set_gpreg(regs)
+    
+def advapi32_CryptDestroyHash():
+    ret_ad = vm_pop_uint32_t()
+    hhash = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(hhash), ')'
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 1
+    vm_set_gpreg(regs)
+
+def advapi32_CryptDecrypt():
+    ret_ad = vm_pop_uint32_t()
+    hkey = vm_pop_uint32_t()
+    hhash = vm_pop_uint32_t()
+    final = vm_pop_uint32_t()
+    dwflags = vm_pop_uint32_t()
+    pbdata = vm_pop_uint32_t()
+    pdwdatalen = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(hkey), hex(hhash), hex(final), hex(dwflags), hex(pbdata), hex(pdwdatalen), ')'
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 1
+    vm_set_gpreg(regs)
+
+    fdfsd
+    
+def kernel32_CreateFileA():
+    ret_ad = vm_pop_uint32_t()
+    lpfilename = vm_pop_uint32_t()
+    dwsharedmode = vm_pop_uint32_t()
+    lpsecurityattr = vm_pop_uint32_t()
+    dwcreationdisposition = vm_pop_uint32_t()
+    dwflagsandattr = vm_pop_uint32_t()
+    htemplatefile = vm_pop_uint32_t()
+
+
+    fname = vm_get_str(lpfilename, 0x100)
+    fname = fname[:fname.find('\x00')]
+
+    print whoami(), hex(ret_ad), '(', hex(lpfilename), hex(dwsharedmode), hex(lpsecurityattr), hex(dwcreationdisposition), hex(dwflagsandattr), hex(htemplatefile), ')'
+    my_CreateFile(ret_ad, fname, dwsharedmode, lpsecurityattr, dwcreationdisposition, dwflagsandattr, htemplatefile)
+
+
+
+
+def kernel32_CreateFileW():
+    ret_ad = vm_pop_uint32_t()
+    lpfilename = vm_pop_uint32_t()
+    dwsharedmode = vm_pop_uint32_t()
+    lpsecurityattr = vm_pop_uint32_t()
+    dwcreationdisposition = vm_pop_uint32_t()
+    dwflagsandattr = vm_pop_uint32_t()
+    htemplatefile = vm_pop_uint32_t()
+
+    fname = vm_get_str(lpfilename, 0x100)
+    fname = fname[:fname.find('\x00\x00')]
+    fname = fname[::2]
+
+    print whoami(), hex(ret_ad), '(', hex(lpfilename), hex(dwsharedmode), hex(lpsecurityattr), hex(dwcreationdisposition), hex(dwflagsandattr), hex(htemplatefile), ')'
+    my_CreateFile(ret_ad, fname, dwsharedmode, lpsecurityattr, dwcreationdisposition, dwflagsandattr, htemplatefile)
+
+
+def my_CreateFile(ret_ad, fname, dwsharedmode, lpsecurityattr, dwcreationdisposition, dwflagsandattr, htemplatefile):
+    print whoami(), hex(ret_ad), '(', fname, hex(dwsharedmode), hex(lpsecurityattr), hex(dwcreationdisposition), hex(dwflagsandattr), hex(htemplatefile), ')'
+
+    print 'fname:', fname
+
+    eax = 0xffffffff
+
+    if fname in [r"\\.\SICE", r"\\.\NTICE", r"\\.\Siwvid"]:
+        pass
+        #eax = files_hwnd[fname] = file_hwnd_num
+        #file_hwnd_num += 1
+    elif fname == module_path[:-1]:
+        eax = module_file_nul
+    elif fname in ['NUL']:
+        eax = module_cur_hwnd
+    else:
+        raise ValueError('unknown filename')
+    
+    
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = eax
+    vm_set_gpreg(regs)
+
+    
+
+def kernel32_ReadFile():
+    ret_ad = vm_pop_uint32_t()
+    hwnd = vm_pop_uint32_t()
+    lpbuffer = vm_pop_uint32_t()
+    nnumberofbytestoread = vm_pop_uint32_t()
+    lpnumberofbytesread = vm_pop_uint32_t()
+    lpoverlapped = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(hwnd), hex(lpbuffer), hex(nnumberofbytestoread), hex(lpnumberofbytesread), hex(lpoverlapped), ')'
+
+    if hwnd == module_cur_hwnd:
+        
+        pass
+    else:
+        raise ValueError('unknown hwnd!')
+
+    eax = 0xffffffff
+
+    if hwnd in files_hwnd:
+        data = files_hwnd[module_cur_hwnd].read(nnumberofbytestoread)
+
+        if (lpnumberofbytesread):
+            vm_set_mem(lpnumberofbytesread, pdw(len(data)))
+        vm_set_mem(lpbuffer, data)
+
+    else:
+        raise ValueError('unknown filename')
+
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 1
+    vm_set_gpreg(regs)
+
+def kernel32_GetFileSize():
+    ret_ad = vm_pop_uint32_t()
+    hwnd = vm_pop_uint32_t()
+    lpfilesizehight = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(hwnd), hex(lpfilesizehight), ')'
+
+    if hwnd == module_cur_hwnd:
+        eax = len(open(module_fname_nux).read())
+    else:
+        raise ValueError('unknown hwnd!')
+
+    if lpfilesizehight != 0:
+        vm_set_mem(lpfilesizehight, pdw(eax&0xffff0000))
+            
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = eax
+    vm_set_gpreg(regs)
+    
+
+def kernel32_VirtualProtect():
+    ret_ad = vm_pop_uint32_t()
+    lpvoid = vm_pop_uint32_t()
+    dwsize = vm_pop_uint32_t()
+    flnewprotect = vm_pop_uint32_t()
+    lpfloldprotect = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(lpvoid), hex(dwsize), hex(flnewprotect), hex(lpfloldprotect), ')'
+    
+
+    access_dict = {    0x0: 0,
+                       0x1: 0,
+                       0x2: PAGE_READ,
+                       0x4: PAGE_READ | PAGE_WRITE,
+                       0x10: PAGE_EXEC,
+                       0x20: PAGE_EXEC | PAGE_READ,
+                       0x40: PAGE_EXEC | PAGE_READ | PAGE_WRITE,
+                       0x100: 0
+                       }
+
+    access_dict_inv = dict([(x[1], x[0]) for x in access_dict.items()])
+
+
+    if not flnewprotect in access_dict:
+        raise ValueError( 'unknown access dw!')
+    
+    vm_set_mem_access(lpvoid, access_dict[flnewprotect])
+
+    #XXX todo real old protect
+    vm_set_mem(lpfloldprotect, pdw(0x40))
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 1
+    vm_set_gpreg(regs)
+    dump_memory_page_pool_py()
+
+
+
+def kernel32_VirtualAlloc():
+    ret_ad = vm_pop_uint32_t()
+    lpvoid = vm_pop_uint32_t()
+    dwsize = vm_pop_uint32_t()
+    alloc_type = vm_pop_uint32_t()
+    flprotect = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(lpvoid), hex(dwsize), hex(alloc_type), hex(flprotect), ')'
+    
+
+    access_dict = {    0x0: 0,
+                       0x1: 0,
+                       0x2: PAGE_READ,
+                       0x4: PAGE_READ | PAGE_WRITE,
+                       0x10: PAGE_EXEC,
+                       0x20: PAGE_EXEC | PAGE_READ,
+                       0x40: PAGE_EXEC | PAGE_READ | PAGE_WRITE,
+                       0x100: 0
+                       }
+
+    access_dict_inv = dict([(x[1], x[0]) for x in access_dict.items()])
+
+
+    if not flprotect in access_dict:
+        raise ValueError( 'unknown access dw!')
+
+    max_ad = vm_get_memory_page_max_address()
+    max_ad = (max_ad+0xfff) & 0xfffff000
+
+
+    vm_add_memory_page(max_ad, access_dict[flprotect], "\x00"*dwsize)
+
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = max_ad
+    vm_set_gpreg(regs)
+    dump_memory_page_pool_py()
+    print 'ret', hex(max_ad), hex(ret_ad)
+    #XXX for malware tests
+    #vm_set_mem(regs['esp']-0x2C, pdw(0xFFFFFFFF))
+
+
+def kernel32_VirtualFree():
+    ret_ad = vm_pop_uint32_t()
+    lpvoid = vm_pop_uint32_t()
+    dwsize = vm_pop_uint32_t()
+    alloc_type = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(lpvoid), hex(dwsize), hex(alloc_type), ')'
+    
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    vm_set_gpreg(regs)
+    
+
+def user32_GetWindowLongA():
+    ret_ad = vm_pop_uint32_t()
+    hwnd = vm_pop_uint32_t()
+    nindex = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(hwnd), hex(nindex), ')'
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = windowlong_dw
+    vm_set_gpreg(regs)
+    
+
+def user32_SetWindowLongA():
+    ret_ad = vm_pop_uint32_t()
+    hwnd = vm_pop_uint32_t()
+    nindex = vm_pop_uint32_t()
+    newlong = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(hwnd), hex(nindex), hex(newlong), ')'
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = windowlong_dw
+    vm_set_gpreg(regs)
+    
+
+
+def kernel32_GetModuleFileNameA():
+    ret_ad = vm_pop_uint32_t()
+    hmodule = vm_pop_uint32_t()
+    lpfilename = vm_pop_uint32_t()
+    nsize = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), '(', hex(hmodule), hex(lpfilename), hex(nsize), ')'
+
+    if hmodule in [0]:
+        p = module_path[:]
+    else:
+        raise ValueError('unknown module h')
+
+
+    if nsize < len(p):
+        eax = nsize
+        p = p[:nsize]
+    else:
+        eax = len(p)
+    print repr(p)
+    vm_set_mem(lpfilename, p)
+
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = nsize
+    vm_set_gpreg(regs)
+
+lastwin32error = 0
+def kernel32_GetLastError():
+    ret_ad = vm_pop_uint32_t()
+    global lastwin32error
+    
+    print whoami(), hex(ret_ad), '(',  ')'
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = lastwin32error
+    vm_set_gpreg(regs)
+
+
+def kernel32_LoadLibraryA():
+    ret_ad = vm_pop_uint32_t()
+    dllname = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), hex(dllname)
+
+    libname = vm_get_str(dllname, 0x100)
+    libname = libname[:libname.find('\x00')]
+    print repr(libname)
+
+    eax = runtime_dll.lib_get_add_base(libname)
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = eax
+    vm_set_gpreg(regs)
+
+def kernel32_GetProcAddress():
+    ret_ad = vm_pop_uint32_t()
+    libbase = vm_pop_uint32_t()
+    fname = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad), hex(fname), hex(libbase)
+    fname = fname & 0xFFFFFFFF
+    if fname < 0x10000:
+        fname = fname
+    else:
+        fname = vm_get_str(fname, 0x100)
+        fname = fname[:fname.find('\x00')]
+    print repr(fname)
+
+    
+    ad = runtime_dll.lib_get_add_func(libbase, fname)
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = ad
+    vm_set_gpreg(regs)
+
+
+
+def kernel32_LoadLibraryW():
+    ret_ad = vm_pop_uint32_t()
+    dllname = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), hex(dllname)
+
+    libname = vm_get_str(dllname, 0x100)
+    libname = libname[:libname.find('\x00\x00')]
+    libname = libname[::2]
+    print repr(libname)
+
+    eax = runtime_dll.lib_get_add_base(libname)
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = eax
+    vm_set_gpreg(regs)
+
+
+def kernel32_GetModuleHandleA():
+    ret_ad = vm_pop_uint32_t()
+    dllname = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad), hex(dllname)
+
+    if dllname:
+        libname = vm_get_str(dllname, 0x100)
+        libname = libname[:libname.find('\x00')]
+        print libname
+        eax = runtime_dll.lib_get_add_base(libname)
+    else:
+        eax = e.Opthdr.Opthdr.ImageBase
+        print "default img base" , hex(eax)
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = eax
+    vm_set_gpreg(regs)
+
+
+def kernel32_GetSystemInfo():
+    ret_ad = vm_pop_uint32_t()
+    sys_ptr = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), hex(sys_ptr)
+
+    vm_set_mem(sys_ptr, "\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x01\x00\xFF\xFF\xFE\x7F\x0F\x00\x00\x00\x04\x00\x00\x00\x4A\x02\x00\x00\x00\x00\x01\x00\x06\x00\x0B\x0F")
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    #regs['eax'] = 0
+    vm_set_gpreg(regs)
+    
+
+def kernel32_IsWow64Process():
+    ret_ad = vm_pop_uint32_t()
+    h = vm_pop_uint32_t()
+    bool_ptr = vm_pop_uint32_t()
+
+    print whoami(), hex(ret_ad), hex(h), hex(bool_ptr)
+
+    vm_set_mem(bool_ptr, pdw(0))
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 1
+    vm_set_gpreg(regs)
+    
+def kernel32_GetCommandLineA():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 1
+    vm_set_gpreg(regs)
+
+cryptdll_md5_h = {}
+def cryptdll_MD5Init():
+    global cryptdll_MD5Init
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    ad_ctx = vm_pop_uint32_t()
+    index = len(cryptdll_md5_h)
+    h = MD5.new()
+    cryptdll_md5_h[index] = h
+
+    vm_set_mem(ad_ctx, pdw(index))
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    vm_set_gpreg(regs)
+    
+
+
+def cryptdll_MD5Update():
+    global cryptdll_MD5Init
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    ad_ctx = vm_pop_uint32_t()
+    ad_input = vm_pop_uint32_t()
+    inlen = vm_pop_uint32_t()
+
+    index = vm_get_str(ad_ctx, 4)
+    index = updw(index)
+    if not index in cryptdll_md5_h:
+        raise ValueError('unknown h context', index)
+
+    data = vm_get_str(ad_input, inlen)
+    cryptdll_md5_h[index].update(data)
+    print hexdump(data)
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    vm_set_gpreg(regs)
+    
+def cryptdll_MD5Final():
+    global cryptdll_MD5Init
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+
+    ad_ctx = vm_pop_uint32_t()
+
+    index = vm_get_str(ad_ctx, 4)
+    index = updw(index)
+    if not index in cryptdll_md5_h:
+        raise ValueError('unknown h context', index)
+    
+    h = cryptdll_md5_h[index].digest()
+    vm_set_mem(ad_ctx + 88, h)
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    vm_set_gpreg(regs)
+    
+def ntdll_RtlInitAnsiString():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    ad_ctx = vm_pop_uint32_t()
+    ad_str = vm_pop_uint32_t()
+
+    s = get_str_ansi(ad_str)
+    l = len(s)
+    print "string", l, s
+    vm_set_mem(ad_ctx, pw(l)+pw(l+1)+pdw(ad_str))
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    vm_set_gpreg(regs)
+
+
+def ntdll_RtlAnsiStringToUnicodeString():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    ad_ctxu = vm_pop_uint32_t()
+    ad_ctxa = vm_pop_uint32_t()
+    alloc_dst = vm_pop_uint32_t()
+
+    
+    l1, l2, ptra = struct.unpack('HHL', vm_get_str(ad_ctxa, 8))
+    print hex(l1), hex(l2), hex(ptra)
+
+    s = vm_get_str(ptra, l1)
+    print s
+    s = '\x00'.join(s) + "\x00\x00"
+    if alloc_dst:
+        ad = get_memory_page_max_address_py()
+        ad = (ad + 0xFFF) & ~0xFFF
+        vm_add_memory_page(ad , PAGE_READ | PAGE_WRITE, s)
+
+    vm_set_mem(ad_ctxu, pw(len(s))+pw(len(s)+1)+pdw(ad))   
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+
+def ntdll_RtlHashUnicodeString():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    ad_ctxu = vm_pop_uint32_t()
+    case_i = vm_pop_uint32_t()
+    h_id = vm_pop_uint32_t()
+    phout = vm_pop_uint32_t()
+
+    print hex(h_id)
+    if h_id != 1:
+        raise ValueError('unk hash unicode', h_id)
+
+    l1, l2, ptra = struct.unpack('HHL', vm_get_str(ad_ctxu, 8))
+    print hex(l1), hex(l2), hex(ptra)
+    s = vm_get_str(ptra, l1)
+    print repr(s)
+    s = s[::2][:-1]
+    print repr(s)
+    hv = 0
+
+    if case_i:
+        s = s.lower()
+    for c in s:
+        hv = ((65599*hv)+ord(c) )&0xffffffff
+    print "unicode h", hex(hv)
+    
+    vm_set_mem(phout, pdw(hv))
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+    
+def ntdll_RtlFreeUnicodeString():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    ad_ctxu = vm_pop_uint32_t()
+    
+    l1, l2, ptra = struct.unpack('HHL', vm_get_str(ad_ctxu, 8))
+    print l1, l2, hex(ptra)
+    s = vm_get_str(ptra, l1)
+    print 'free', repr(s)
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    vm_set_gpreg(regs)
+
+
+
+def kernel32_RtlMoveMemory():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    ad_dst = vm_pop_uint32_t()
+    ad_src = vm_pop_uint32_t()
+    m_len = vm_pop_uint32_t()
+    
+    print hex(ad_dst), hex(ad_src), hex(m_len)
+    data = vm_get_str(ad_src, m_len)
+    vm_set_mem(ad_dst, data)
+    print hexdump(data)
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    vm_set_gpreg(regs)
+
+
+def ntdll_RtlAnsiCharToUnicodeChar():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    ad_ad_ch = vm_pop_uint32_t()
+    
+    print hex(ad_ad_ch)
+    ad_ch = updw(vm_get_str(ad_ad_ch, 4))
+    print hex(ad_ch)
+    
+    ch = ord(vm_get_str(ad_ch, 1))
+    vm_set_mem(ad_ad_ch, pdw(ad_ch+1))
+
+    print repr(ch), repr(chr(ch))
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = ch
+    vm_set_gpreg(regs)
+    
+def ntdll_RtlFindCharInUnicodeString():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    flags = vm_pop_uint32_t()
+    main_str_ad = vm_pop_uint32_t()
+    search_chars_ad = vm_pop_uint32_t()
+    pos_ad = vm_pop_uint32_t()
+
+    print flags
+    if flags != 0:
+        raise ValueError('unk flags')
+
+    ml1, ml2, mptra = struct.unpack('HHL', vm_get_str(main_str_ad, 8))
+    print ml1, ml2, hex(mptra)
+    sl1, sl2, sptra = struct.unpack('HHL', vm_get_str(search_chars_ad, 8))
+    print sl1, sl2, hex(sptra)
+    
+    main_data= vm_get_str(mptra, ml1)[:-1]
+    search_data= vm_get_str(sptra, sl1)[:-1]
+
+    print repr(main_data[::2])
+    print repr(search_data)
+
+    pos = None
+    for i, c in enumerate(main_data):
+        for s in search_data:
+            if s == c:
+                pos = i
+                break
+        if pos:
+            break
+            
+    print pos
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    if pos == None:
+        regs['eax'] = 0xC0000225
+        vm_set_mem(pos_ad, pdw(0))
+    else:
+        regs['eax'] = 0
+        vm_set_mem(pos_ad, pdw(pos))
+    
+    vm_set_gpreg(regs)
+    print 'ret', hex(regs['eax'])
+
+def ntdll_RtlComputeCrc32():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    dwinit = vm_pop_uint32_t()
+    pdata = vm_pop_uint32_t()
+    ilen = vm_pop_uint32_t()
+
+
+    data = vm_get_str(pdata, ilen)
+    print hex(dwinit)
+    print hexdump(data)
+    crc_r = crc32(data, dwinit)
+    print "crc32", hex(crc_r)
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = crc_r
+    vm_set_gpreg(regs)
+    
+    
+    
+def ntdll_RtlExtendedIntegerMultiply():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    b2 = vm_pop_uint32_t()
+    b1 = vm_pop_uint32_t()
+    bm = vm_pop_uint32_t()
+    
+    print hex(b1), hex(b2), hex(bm)
+    a = (b1<<32)+b2
+    a = a*bm
+    print hex(a)
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = (a&0xffffffff)
+    regs['edx'] = (a>>32)&0xffffffff
+
+    vm_set_gpreg(regs)
+    
+def ntdll_RtlLargeIntegerAdd():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    a2 = vm_pop_uint32_t()
+    a1 = vm_pop_uint32_t()    
+    b2 = vm_pop_uint32_t()
+    b1 = vm_pop_uint32_t()
+    
+    print hex(a1), hex(a2), hex(b1), hex(b2)
+    a = (a1<<32)+a2 + (b1<<32)+b2
+    print hex(a)
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = (a&0xffffffff)
+    regs['edx'] = (a>>32)&0xffffffff
+
+    vm_set_gpreg(regs)
+    
+def ntdll_RtlLargeIntegerShiftRight():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    a2 = vm_pop_uint32_t()
+    a1 = vm_pop_uint32_t()    
+    m = vm_pop_uint32_t()
+    
+    print hex(a1), hex(a2), hex(m)
+    a = ((a1<<32)+a2)>>m
+    print hex(a)
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = (a&0xffffffff)
+    regs['edx'] = (a>>32)&0xffffffff
+
+    vm_set_gpreg(regs)
+
+def ntdll_RtlEnlargedUnsignedMultiply():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    a = vm_pop_uint32_t()&0xFFFFFFFF
+    b = vm_pop_uint32_t()&0xFFFFFFFF
+    
+    print hex(a), hex(b)
+    a = a*b
+    print hex(a)
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = (a&0xffffffff)
+    regs['edx'] = (a>>32)&0xffffffff
+
+    vm_set_gpreg(regs)
+
+def ntdll_RtlLargeIntegerSubtract():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    a2 = vm_pop_uint32_t()
+    a1 = vm_pop_uint32_t()    
+    b2 = vm_pop_uint32_t()
+    b1 = vm_pop_uint32_t()
+    
+    print hex(a1), hex(a2), hex(b1), hex(b2)
+    a = (a1<<32)+a2 - (b1<<32)+b2
+    print hex(a)
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = (a&0xffffffff)
+    regs['edx'] = (a>>32)&0xffffffff
+
+    vm_set_gpreg(regs)
+
+
+def ntdll_RtlCompareMemory():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    ad1 = vm_pop_uint32_t()
+    ad2 = vm_pop_uint32_t()
+    m_len = vm_pop_uint32_t()
+    
+    print hex(ad1), hex(ad2), hex(m_len)
+    data1 = vm_get_str(ad1, m_len)
+    data2 = vm_get_str(ad2, m_len)
+
+    print hexdump(data1)
+    print hexdump(data2)
+    i = 0
+    while data1[i] == data2[i]:
+        i+=1
+        if i >=m_len:
+            break
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = i
+    vm_set_gpreg(regs)
+    print 'compare ret:', i
+
+
+def user32_GetMessagePos():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0x00110022
+    vm_set_gpreg(regs)
+    
+def kernel32_Sleep():
+    ret_ad = vm_pop_uint32_t()
+    t = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad), hex(t)
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    vm_set_gpreg(regs)
+
+    #XXX for malware tests
+    vm_set_mem(regs['esp']-0x20, pdw(0xFFFFFFFF))
+        
+def ntdll_ZwUnmapViewOfSection():
+    ret_ad = vm_pop_uint32_t()
+    h = vm_pop_uint32_t()
+    ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad), hex(h), hex(ad)
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+def kernel32_IsBadReadPtr():
+    ret_ad = vm_pop_uint32_t()
+    lp = vm_pop_uint32_t()
+    ucb = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad), hex(lp), hex(ucb)
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+    
+
+win_event_num = 0x13370
+def ntoskrnl_KeInitializeEvent():
+    global win_event_num
+    ret_ad = vm_pop_uint32_t()
+    my_event = vm_pop_uint32_t()
+    my_type = vm_pop_uint32_t()
+    my_state = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad), hex(my_event), hex(my_type), hex(my_state)
+    vm_set_mem(my_event, pdw(win_event_num))
+    win_event_num +=1
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+
+    
+    
+
+
+def ntoskrnl_RtlGetVersion():
+    ret_ad = vm_pop_uint32_t()
+    ptr_version = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad), hex(ptr_version)
+
+    s = struct.pack('LLLLL', 0x88000000,0x88000001,0x88000002,0x88000003,0x88000004 )
+    vm_set_mem(ptr_version, s)
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+    
+
+def hal_ExAcquireFastMutex():
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+    
+
+nt_mdl = {}
+nt_mdl_ad = None
+nt_mdl_cur = 0
+
+def mdl2ad(n):
+    return nt_mdl_ad+0x10*n
+
+def ad2mdl(ad):
+    return ((ad-nt_mdl_ad)&0xFFFFFFFFL)/0x10
+    
+def ntoskrnl_IoAllocateMdl():
+    global nt_mdl, nt_mdl_ad, nt_mdl_cur
+    ret_ad = vm_pop_uint32_t()
+    v_addr = vm_pop_uint32_t()
+    l = vm_pop_uint32_t()
+    second_buf = vm_pop_uint32_t()
+    chargequota = vm_pop_uint32_t()
+    pirp = vm_pop_uint32_t()
+    
+    print whoami(), hex(ret_ad), hex(v_addr), hex(l), hex(second_buf), hex(chargequota), hex(pirp)
+    m = mdl(v_addr, l)
+    nt_mdl[nt_mdl_cur] = m
+    vm_set_mem(mdl2ad(nt_mdl_cur), str(m))
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = mdl2ad(nt_mdl_cur)
+    vm_set_gpreg(regs)
+
+    nt_mdl_cur += 1
+
+def ntoskrnl_MmProbeAndLockPages():
+    global nt_mdl, nt_mdl_ad, nt_mdl_cur
+    ret_ad = vm_pop_uint32_t()
+    p_mdl = vm_pop_uint32_t()&0xffffffff
+    access_mode = vm_pop_uint32_t()
+    op = vm_pop_uint32_t()
+    
+    print whoami(), hex(ret_ad), hex(p_mdl), hex(access_mode), hex(op)
+
+    if not ad2mdl(p_mdl) in nt_mdl:
+        raise ValueError('unk mdl', hex(p_mdl))
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+    
+def ntoskrnl_MmMapLockedPagesSpecifyCache():
+    global nt_mdl, nt_mdl_ad, nt_mdl_cur
+    ret_ad = vm_pop_uint32_t()
+    p_mdl = vm_pop_uint32_t()&0xffffffff
+    access_mode = vm_pop_uint32_t()
+    cache_type = vm_pop_uint32_t()
+    base_ad = vm_pop_uint32_t()
+    bugcheckonfailure = vm_pop_uint32_t()
+    priority = vm_pop_uint32_t()
+    
+    print whoami(), hex(ret_ad), hex(p_mdl), hex(access_mode), hex(cache_type), hex(base_ad), hex(bugcheckonfailure), hex(priority)
+    if not ad2mdl(p_mdl) in nt_mdl:
+        raise ValueError('unk mdl', hex(p_mdl))
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = nt_mdl[ad2mdl(p_mdl)].ad
+    vm_set_gpreg(regs)
+    
+def ntoskrnl_MmProtectMdlSystemAddress():
+    global nt_mdl, nt_mdl_ad, nt_mdl_cur
+    ret_ad = vm_pop_uint32_t()
+    p_mdl = vm_pop_uint32_t()&0xffffffff
+    prot = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad), hex(p_mdl), hex(prot)
+    if not ad2mdl(p_mdl) in nt_mdl:
+        raise ValueError('unk mdl', hex(p_mdl))
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+    
+def ntoskrnl_MmUnlockPages():
+    global nt_mdl, nt_mdl_ad, nt_mdl_cur
+    ret_ad = vm_pop_uint32_t()
+    p_mdl = vm_pop_uint32_t()&0xffffffff
+    print whoami(), hex(ret_ad), hex(p_mdl)
+    if not ad2mdl(p_mdl) in nt_mdl:
+        raise ValueError('unk mdl', hex(p_mdl))
+
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+    
+
+def ntoskrnl_IoFreeMdl():
+    global nt_mdl, nt_mdl_ad, nt_mdl_cur
+    ret_ad = vm_pop_uint32_t()
+    p_mdl = vm_pop_uint32_t()&0xffffffff
+    print whoami(), hex(ret_ad), hex(p_mdl)
+    if not ad2mdl(p_mdl) in nt_mdl:
+        raise ValueError('unk mdl', hex(p_mdl))
+    del(nt_mdl[ad2mdl(p_mdl)])
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+    
+
+def hal_ExReleaseFastMutex():
+    global nt_mdl, nt_mdl_ad, nt_mdl_cur
+    ret_ad = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad)
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+    
+def ntoskrnl_RtlQueryRegistryValues():
+    global nt_mdl, nt_mdl_ad, nt_mdl_cur
+    ret_ad = vm_pop_uint32_t()
+    relativeto = vm_pop_uint32_t()
+    path = vm_pop_uint32_t()
+    querytable = vm_pop_uint32_t()
+    context = vm_pop_uint32_t()
+    environ = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad), hex(relativeto), hex(path), hex(querytable), hex(context), hex(environ)
+    p = get_str_unic(path)
+    print repr(p[::2])
+    
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = 0
+    vm_set_gpreg(regs)
+    
+
+def ntoskrnl_ExAllocatePoolWithTagPriority():
+    global nt_mdl, nt_mdl_ad, nt_mdl_cur
+    ret_ad = vm_pop_uint32_t()
+    pool_type = vm_pop_uint32_t()
+    nbr_of_bytes = vm_pop_uint32_t()
+    tag = vm_pop_uint32_t()
+    priority = vm_pop_uint32_t()
+    print whoami(), hex(ret_ad), hex(pool_type), hex(nbr_of_bytes), hex(tag), hex(priority)
+
+    max_ad = vm_get_memory_page_max_address()
+    max_ad = (max_ad+0xfff) & 0xfffff000
+
+
+    vm_add_memory_page(max_ad, PAGE_READ|PAGE_WRITE, "\x00"*nbr_of_bytes)
+    regs = vm_get_gpreg()
+    regs['eip'] = ret_ad
+    regs['eax'] = max_ad
+    vm_set_gpreg(regs)
+
+    print "ad", hex(max_ad)
diff --git a/setup.py b/setup.py
new file mode 100755
index 00000000..f3a2be16
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,29 @@
+#! /usr/bin/env python
+
+from distutils.core import setup,Extension
+
+setup(
+    name = 'Miasm',
+    version = '0.1',
+    packages=['miasm', 'miasm/tools', 
+              'miasm/expression', 'miasm/graph', 'miasm/arch',
+              'miasm/core', 'miasm/tools/emul_lib' ],
+    package_data = {'miasm':['tools/emul_lib/*.h']},
+#    data_files = [('toto', ['miasm/tools/emul_lib/queue.h'])],
+    ext_modules = [
+        Extension("miasm.tools.emul_lib.libcodenat_interface",
+                  ["miasm/tools/emul_lib/libcodenat_interface.c",
+                   "miasm/tools/emul_lib/libcodenat.c"]),
+        Extension("miasm.tools.emul_lib.libcodenat_tcc",
+                  ["miasm/tools/emul_lib/libcodenat_tcc.c"],
+                  libraries=["tcc"])
+        ],
+
+    # Metadata
+    author = 'Fabrice Desclaux',
+    author_email = 'serpilliere@droid-corp.org',
+    description = 'Machine code manipulation library',
+    license = 'GPLv2',
+    # keywords = '',
+    # url = '',
+)