about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--example/disasm/callback.py2
-rw-r--r--miasm2/arch/aarch64/disasm.py4
-rw-r--r--miasm2/arch/aarch64/sem.py19
-rw-r--r--miasm2/arch/arm/disasm.py4
-rw-r--r--miasm2/arch/x86/disasm.py2
-rw-r--r--miasm2/arch/x86/sem.py35
-rw-r--r--miasm2/core/asmblock.py25
-rw-r--r--miasm2/jitter/arch/JitCore_x86.c23
-rw-r--r--miasm2/jitter/jitcore.py4
-rw-r--r--miasm2/jitter/jitload.py2
-rw-r--r--test/arch/x86/unit/mn_cdq.py445
-rwxr-xr-xtest/test_all.py1
12 files changed, 533 insertions, 33 deletions
diff --git a/example/disasm/callback.py b/example/disasm/callback.py
index 63987e85..a9bef20b 100644
--- a/example/disasm/callback.py
+++ b/example/disasm/callback.py
@@ -52,7 +52,7 @@ print "\n".join(str(block) for block in blocks)
 # Enable callback
 cb_x86_funcs.append(cb_x86_callpop)
 ## Other method:
-## mdis.dis_bloc_callback = cb_x86_callpop
+## mdis.dis_block_callback = cb_x86_callpop
 
 print "=" * 40
 print "With callback:\n"
diff --git a/miasm2/arch/aarch64/disasm.py b/miasm2/arch/aarch64/disasm.py
index a8604fe5..17eec414 100644
--- a/miasm2/arch/aarch64/disasm.py
+++ b/miasm2/arch/aarch64/disasm.py
@@ -14,7 +14,7 @@ class dis_aarch64b(disasmEngine):
     def __init__(self, bs=None, **kwargs):
         super(dis_aarch64b, self).__init__(
             mn_aarch64, self.attrib, bs,
-            dis_bloc_callback = cb_aarch64_disasm,
+            dis_block_callback = cb_aarch64_disasm,
             **kwargs)
 
 
@@ -23,5 +23,5 @@ class dis_aarch64l(disasmEngine):
     def __init__(self, bs=None, **kwargs):
         super(dis_aarch64l, self).__init__(
             mn_aarch64, self.attrib, bs,
-            dis_bloc_callback = cb_aarch64_disasm,
+            dis_block_callback = cb_aarch64_disasm,
             **kwargs)
diff --git a/miasm2/arch/aarch64/sem.py b/miasm2/arch/aarch64/sem.py
index 63f6a32d..d8dc1efa 100644
--- a/miasm2/arch/aarch64/sem.py
+++ b/miasm2/arch/aarch64/sem.py
@@ -73,6 +73,13 @@ def update_flag_sub_of(op1, op2, res):
     "Compote OF in @res = @op1 - @op2"
     return m2_expr.ExprAff(of, (((op1 ^ res) & (op1 ^ op2))).msb())
 
+
+# clearing cv flags for bics (see C5.6.25)
+
+def update_flag_bics ():
+    "Clear CF and OF"
+    return [ExprAff(cf, ExprInt (0,1)), ExprAff(of, ExprInt (0,1))]
+
 # z = x+y (+cf?)
 
 
@@ -189,6 +196,14 @@ def orn(arg1, arg2, arg3):
 @sbuild.parse
 def bic(arg1, arg2, arg3):
     arg1 = arg2 & (~extend_arg(arg2, arg3))
+    
+
+def bics(ir, instr, arg1, arg2, arg3):
+    e = []
+    arg1 = arg2 & (~extend_arg(arg2, arg3))
+    e += update_flag_logic (arg1)
+    e += update_flag_bics ()
+    return e, []
 
 
 @sbuild.parse
@@ -728,7 +743,9 @@ mnemo_func.update({
     'b.le': b_le,
     'b.ls': b_ls,
     'b.lt': b_lt,
-
+    
+    'bics': bics,
+    
     'ret': ret,
     'stp': stp,
     'ldp': ldp,
diff --git a/miasm2/arch/arm/disasm.py b/miasm2/arch/arm/disasm.py
index 3f6ea4d5..586fa903 100644
--- a/miasm2/arch/arm/disasm.py
+++ b/miasm2/arch/arm/disasm.py
@@ -39,13 +39,13 @@ class dis_armb(disasmEngine):
     attrib = 'b'
     def __init__(self, bs=None, **kwargs):
         super(dis_armb, self).__init__(mn_arm, self.attrib, bs, **kwargs)
-        self.dis_bloc_callback = cb_arm_disasm
+        self.dis_block_callback = cb_arm_disasm
 
 class dis_arml(disasmEngine):
     attrib = 'l'
     def __init__(self, bs=None, **kwargs):
         super(dis_arml, self).__init__(mn_arm, self.attrib, bs, **kwargs)
-        self.dis_bloc_callback = cb_arm_disasm
+        self.dis_block_callback = cb_arm_disasm
 
 class dis_armtb(disasmEngine):
     attrib = 'b'
diff --git a/miasm2/arch/x86/disasm.py b/miasm2/arch/x86/disasm.py
index fc981c09..ecb1b8da 100644
--- a/miasm2/arch/x86/disasm.py
+++ b/miasm2/arch/x86/disasm.py
@@ -15,7 +15,7 @@ class dis_x86(disasmEngine):
 
     def __init__(self, bs=None, **kwargs):
         super(dis_x86, self).__init__(mn_x86, self.attrib, bs, **kwargs)
-        self.dis_bloc_callback = cb_x86_disasm
+        self.dis_block_callback = cb_x86_disasm
 
 
 class dis_x86_16(dis_x86):
diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py
index 56aca1c2..deebba8c 100644
--- a/miasm2/arch/x86/sem.py
+++ b/miasm2/arch/x86/sem.py
@@ -1614,22 +1614,25 @@ def imul(_, instr, src1, src2=None, src3=None):
 
 
 def cbw(_, instr):
+    # Only in 16 bit
     e = []
-    tempAL = mRAX[instr.mode][:8]
-    tempAX = mRAX[instr.mode][:16]
+    tempAL = mRAX[instr.v_opmode()][:8]
+    tempAX = mRAX[instr.v_opmode()][:16]
     e.append(m2_expr.ExprAff(tempAX, tempAL.signExtend(16)))
     return e, []
 
 
 def cwde(_, instr):
+    # Only in 32/64 bit
     e = []
-    tempAX = mRAX[instr.mode][:16]
-    tempEAX = mRAX[instr.mode][:32]
+    tempAX = mRAX[instr.v_opmode()][:16]
+    tempEAX = mRAX[instr.v_opmode()][:32]
     e.append(m2_expr.ExprAff(tempEAX, tempAX.signExtend(32)))
     return e, []
 
 
 def cdqe(_, instr):
+    # Only in 64 bit
     e = []
     tempEAX = mRAX[instr.mode][:32]
     tempRAX = mRAX[instr.mode][:64]
@@ -1638,32 +1641,34 @@ def cdqe(_, instr):
 
 
 def cwd(_, instr):
+    # Only in 16 bit
     e = []
     tempAX = mRAX[instr.mode][:16]
     tempDX = mRDX[instr.mode][:16]
-    c = tempAX.signExtend(32)
-    e.append(m2_expr.ExprAff(tempAX, c[:16]))
-    e.append(m2_expr.ExprAff(tempDX, c[16:32]))
+    result = tempAX.signExtend(32)
+    e.append(m2_expr.ExprAff(tempAX, result[:16]))
+    e.append(m2_expr.ExprAff(tempDX, result[16:32]))
     return e, []
 
 
 def cdq(_, instr):
+    # Only in 32/64 bit
     e = []
-    tempEAX = mRAX[instr.mode][:32]
-    tempEDX = mRDX[instr.mode][:32]
-    c = tempEAX.signExtend(64)
-    e.append(m2_expr.ExprAff(tempEAX, c[:32]))
-    e.append(m2_expr.ExprAff(tempEDX, c[32:64]))
+    tempEAX = mRAX[instr.v_opmode()]
+    tempEDX = mRDX[instr.v_opmode()]
+    result = tempEAX.signExtend(64)
+    e.append(m2_expr.ExprAff(tempEDX, result[32:64]))
     return e, []
 
 
 def cqo(_, instr):
+    # Only in 64 bit
     e = []
     tempRAX = mRAX[instr.mode][:64]
     tempRDX = mRDX[instr.mode][:64]
-    c = tempRAX.signExtend(128)
-    e.append(m2_expr.ExprAff(tempRAX, c[:64]))
-    e.append(m2_expr.ExprAff(tempRDX, c[64:128]))
+    result = tempRAX.signExtend(128)
+    e.append(m2_expr.ExprAff(tempRAX, result[:64]))
+    e.append(m2_expr.ExprAff(tempRDX, result[64:128]))
     return e, []
 
 
diff --git a/miasm2/core/asmblock.py b/miasm2/core/asmblock.py
index 5b95976f..7d18c4f5 100644
--- a/miasm2/core/asmblock.py
+++ b/miasm2/core/asmblock.py
@@ -1350,7 +1350,7 @@ class disasmEngine(object):
 
     + callback(arch, attrib, pool_bin, cur_bloc, offsets_to_dis,
                symbol_pool)
-     - dis_bloc_callback: callback after each new disassembled block
+     - dis_block_callback: callback after each new disassembled block
     """
 
     def __init__(self, arch, attrib, bin_stream, **kwargs):
@@ -1372,7 +1372,7 @@ class disasmEngine(object):
         self.dontdis_retcall = False
         self.lines_wd = None
         self.blocs_wd = None
-        self.dis_bloc_callback = None
+        self.dis_block_callback = None
         self.dont_dis_nulstart_bloc = False
         self.dont_dis_retcall_funcs = set()
 
@@ -1387,9 +1387,18 @@ class disasmEngine(object):
         warnings.warn("""DEPRECATION WARNING: "job_done" is not needed anymore, support is dropped.""")
         return
 
+    def get_dis_bloc_callback(self):
+        warnings.warn("""DEPRECATION WARNING: "dis_bloc_callback" use dis_block_callback.""")
+        return self.dis_block_callback
+
+    def set_dis_bloc_callback(self, function):
+        warnings.warn("""DEPRECATION WARNING: "dis_bloc_callback" use dis_block_callback.""")
+        self.dis_block_callback = function
+
 
     # Deprecated
     job_done = property(get_job_done, set_job_done)
+    dis_bloc_callback = property(get_dis_bloc_callback, set_dis_bloc_callback)
 
     def _dis_block(self, offset, job_done=None):
         """Disassemble the block at offset @offset
@@ -1520,11 +1529,11 @@ class disasmEngine(object):
         # Fix multiple constraints
         cur_block.fix_constraints()
 
-        if self.dis_bloc_callback is not None:
-            self.dis_bloc_callback(mn=self.arch, attrib=self.attrib,
-                                   pool_bin=self.bin_stream, cur_bloc=cur_block,
-                                   offsets_to_dis=offsets_to_dis,
-                                   symbol_pool=self.symbol_pool)
+        if self.dis_block_callback is not None:
+            self.dis_block_callback(mn=self.arch, attrib=self.attrib,
+                                    pool_bin=self.bin_stream, cur_bloc=cur_block,
+                                    offsets_to_dis=offsets_to_dis,
+                                    symbol_pool=self.symbol_pool)
         return cur_block, offsets_to_dis
 
     def dis_block(self, offset):
@@ -1573,7 +1582,7 @@ class disasmEngine(object):
             blocks.add_node(cur_block)
 
         blocks.apply_splitting(self.symbol_pool,
-                               dis_block_callback=self.dis_bloc_callback,
+                               dis_block_callback=self.dis_block_callback,
                                mn=self.arch, attrib=self.attrib,
                                pool_bin=self.bin_stream)
         return blocks
diff --git a/miasm2/jitter/arch/JitCore_x86.c b/miasm2/jitter/arch/JitCore_x86.c
index 3198eff3..407a01c7 100644
--- a/miasm2/jitter/arch/JitCore_x86.c
+++ b/miasm2/jitter/arch/JitCore_x86.c
@@ -178,6 +178,29 @@ PyObject * cpu_init_regs(JitCpu* self)
 
 }
 
+void dump_gpregs_16(vm_cpu_t* vmcpu)
+{
+
+	printf("EAX %.8"PRIX32" EBX %.8"PRIX32" ECX %.8"PRIX32" EDX %.8"PRIX32" ",
+	       (uint32_t)(vmcpu->RAX & 0xFFFFFFFF),
+	       (uint32_t)(vmcpu->RBX & 0xFFFFFFFF),
+	       (uint32_t)(vmcpu->RCX & 0xFFFFFFFF),
+	       (uint32_t)(vmcpu->RDX & 0xFFFFFFFF));
+	printf("ESI %.8"PRIX32" EDI %.8"PRIX32" ESP %.8"PRIX32" EBP %.8"PRIX32" ",
+	       (uint32_t)(vmcpu->RSI & 0xFFFFFFFF),
+	       (uint32_t)(vmcpu->RDI & 0xFFFFFFFF),
+	       (uint32_t)(vmcpu->RSP & 0xFFFFFFFF),
+	       (uint32_t)(vmcpu->RBP & 0xFFFFFFFF));
+	printf("EIP %.8"PRIX32" ",
+	       (uint32_t)(vmcpu->RIP & 0xFFFFFFFF));
+	printf("zf %.1"PRIX32" nf %.1"PRIX32" of %.1"PRIX32" cf %.1"PRIX32"\n",
+	       (uint32_t)(vmcpu->zf & 0x1),
+	       (uint32_t)(vmcpu->nf & 0x1),
+	       (uint32_t)(vmcpu->of & 0x1),
+	       (uint32_t)(vmcpu->cf & 0x1));
+
+}
+
 void dump_gpregs_32(vm_cpu_t* vmcpu)
 {
 
diff --git a/miasm2/jitter/jitcore.py b/miasm2/jitter/jitcore.py
index 9c35f829..f2b1375d 100644
--- a/miasm2/jitter/jitcore.py
+++ b/miasm2/jitter/jitcore.py
@@ -63,7 +63,7 @@ class JitCore(object):
                                           follow_call=False,
                                           dontdis_retcall=False,
                                           split_dis=self.split_dis,
-                                          dis_bloc_callback=self.disasm_cb)
+                                          dis_block_callback=self.disasm_cb)
 
 
     def set_options(self, **kwargs):
@@ -140,7 +140,7 @@ class JitCore(object):
 
         # Prepare disassembler
         self.mdis.lines_wd = self.options["jit_maxline"]
-        self.mdis.dis_bloc_callback = self.disasm_cb
+        self.mdis.dis_block_callback = self.disasm_cb
 
         # Disassemble it
         try:
diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py
index 4760c8dd..ff7ba215 100644
--- a/miasm2/jitter/jitload.py
+++ b/miasm2/jitter/jitload.py
@@ -448,7 +448,7 @@ class jitter:
             return ret
 
     def handle_function(self, f_addr):
-        """Add a brakpoint which will trigger the function handler"""
+        """Add a breakpoint which will trigger the function handler"""
         self.add_breakpoint(f_addr, self.handle_lib)
 
     def add_lib_handler(self, libs, user_globals=None):
diff --git a/test/arch/x86/unit/mn_cdq.py b/test/arch/x86/unit/mn_cdq.py
new file mode 100644
index 00000000..f4e4d6e7
--- /dev/null
+++ b/test/arch/x86/unit/mn_cdq.py
@@ -0,0 +1,445 @@
+#! /usr/bin/env python2
+
+import sys
+
+from asm_test import Asm_Test_16, Asm_Test_32, Asm_Test_64
+from miasm2.core.utils import pck16, pck32
+
+
+class Test_CBW_16(Asm_Test_16):
+    MYSTRING = "test CBW 16"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.EAX = 0x87654321
+        self.myjit.cpu.EDX = 0x11223344
+
+    TXT = '''
+    main:
+       CBW
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.EAX == 0x87650021
+        assert self.myjit.cpu.EDX == 0x11223344
+
+
+class Test_CBW_16_signed(Asm_Test_16):
+    MYSTRING = "test CBW 16 signed"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.EAX = 0x87654381
+        self.myjit.cpu.EDX = 0x11223344
+
+    TXT = '''
+    main:
+       CBW
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.EAX == 0x8765FF81
+        assert self.myjit.cpu.EDX == 0x11223344
+
+
+class Test_CBW_32(Asm_Test_32):
+    MYSTRING = "test CBW 32"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.EAX = 0x87654321
+        self.myjit.cpu.EDX = 0x11223344
+
+    TXT = '''
+    main:
+       CBW
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.EAX == 0x87650021
+        assert self.myjit.cpu.EDX == 0x11223344
+
+
+class Test_CBW_32_signed(Asm_Test_32):
+    MYSTRING = "test CBW 32 signed"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.EAX = 0x87654381
+        self.myjit.cpu.EDX = 0x11223344
+
+    TXT = '''
+    main:
+       CBW
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.EAX == 0x8765FF81
+        assert self.myjit.cpu.EDX == 0x11223344
+
+
+class Test_CDQ_32(Asm_Test_32):
+    MYSTRING = "test cdq 32"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.EAX = 0x77654321
+        self.myjit.cpu.EDX = 0x11223344
+
+    TXT = '''
+    main:
+       CDQ
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.EAX == 0x77654321
+        assert self.myjit.cpu.EDX == 0x0
+
+
+class Test_CDQ_32_signed(Asm_Test_32):
+    MYSTRING = "test cdq 32 signed"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.EAX = 0x87654321
+        self.myjit.cpu.EDX = 0x11223344
+
+    TXT = '''
+    main:
+       CDQ
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.EAX == 0x87654321
+        assert self.myjit.cpu.EDX == 0xFFFFFFFF
+
+
+class Test_CDQ_64(Asm_Test_64):
+    MYSTRING = "test cdq 64"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.RAX = 0x1234567877654321
+        self.myjit.cpu.RDX = 0x1122334455667788
+
+    TXT = '''
+    main:
+       CDQ
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.RAX == 0x1234567877654321
+        assert self.myjit.cpu.RDX == 0x0
+
+
+class Test_CDQ_64_signed(Asm_Test_64):
+    MYSTRING = "test cdq 64 signed"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.RAX = 0x1234567887654321
+        self.myjit.cpu.RDX = 0x1122334455667788
+
+    TXT = '''
+    main:
+       CDQ
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.RAX == 0x1234567887654321
+        assert self.myjit.cpu.RDX == 0x00000000FFFFFFFF
+
+
+class Test_CDQE_64(Asm_Test_64):
+    MYSTRING = "test cdq 64"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.RAX = 0x1234567877654321
+        self.myjit.cpu.RDX = 0x1122334455667788
+
+    TXT = '''
+    main:
+       CDQE
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.RAX == 0x77654321
+        assert self.myjit.cpu.RDX == 0x1122334455667788
+
+
+class Test_CDQE_64_signed(Asm_Test_64):
+    MYSTRING = "test cdq 64 signed"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.RAX = 0x1234567887654321
+        self.myjit.cpu.RDX = 0x1122334455667788
+
+    TXT = '''
+    main:
+       CDQE
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.RAX == 0xFFFFFFFF87654321
+        assert self.myjit.cpu.RDX == 0x1122334455667788
+
+
+class Test_CWD_32(Asm_Test_32):
+    MYSTRING = "test cdq 32"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.EAX = 0x87654321
+        self.myjit.cpu.EDX = 0x12345678
+
+    TXT = '''
+    main:
+       CWD
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.RAX == 0x87654321
+        assert self.myjit.cpu.RDX == 0x12340000
+
+
+class Test_CWD_32_signed(Asm_Test_32):
+    MYSTRING = "test cdq 32"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.EAX = 0x87658321
+        self.myjit.cpu.EDX = 0x12345678
+
+    TXT = '''
+    main:
+       CWD
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.RAX == 0x87658321
+        assert self.myjit.cpu.RDX == 0x1234FFFF
+
+
+class Test_CWD_32(Asm_Test_32):
+    MYSTRING = "test cdq 32"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.EAX = 0x87654321
+        self.myjit.cpu.EDX = 0x12345678
+
+    TXT = '''
+    main:
+       CWD
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.RAX == 0x87654321
+        assert self.myjit.cpu.RDX == 0x12340000
+
+
+class Test_CWDE_32(Asm_Test_32):
+    MYSTRING = "test cwde 32"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.EAX = 0x87654321
+        self.myjit.cpu.EDX = 0x11223344
+
+    TXT = '''
+    main:
+       CWDE
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.RAX == 0x4321
+        assert self.myjit.cpu.RDX == 0x11223344
+
+
+class Test_CWDE_32_signed(Asm_Test_32):
+    MYSTRING = "test cwde 32 signed"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.RAX = 0x87658321
+        self.myjit.cpu.RDX = 0x11223344
+
+    TXT = '''
+    main:
+       CWDE
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.EAX == 0xFFFF8321
+        assert self.myjit.cpu.RDX == 0x11223344
+
+
+class Test_CWDE_64(Asm_Test_64):
+    MYSTRING = "test cwde 64"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.RAX = 0x1234567887654321
+        self.myjit.cpu.RDX = 0x1122334455667788
+
+    TXT = '''
+    main:
+       CWDE
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.RAX == 0x4321
+        assert self.myjit.cpu.RDX == 0x1122334455667788
+
+
+class Test_CWDE_64_signed(Asm_Test_64):
+    MYSTRING = "test cwde 64 signed"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.RAX = 0x1234567887658321
+        self.myjit.cpu.RDX = 0x1122334455667788
+
+    TXT = '''
+    main:
+       CWDE
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.RAX == 0xFFFF8321
+        assert self.myjit.cpu.RDX == 0x1122334455667788
+
+
+class Test_CQO_64(Asm_Test_64):
+    MYSTRING = "test cwde 64"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.RAX = 0x1234567887654321
+        self.myjit.cpu.RDX = 0x1122334455667788
+
+    TXT = '''
+    main:
+       CQO
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.RAX == 0x1234567887654321
+        assert self.myjit.cpu.RDX == 0x0
+
+
+class Test_CQO_64_signed(Asm_Test_64):
+    MYSTRING = "test cwde 64 signed"
+
+    def prepare(self):
+        self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr)
+
+    def test_init(self):
+        self.myjit.cpu.RAX = 0x8234567887658321
+        self.myjit.cpu.RDX = 0x1122334455667788
+
+    TXT = '''
+    main:
+       CQO
+       JMP lbl_ret
+    '''
+
+    def check(self):
+        assert self.myjit.cpu.RAX == 0x8234567887658321
+        assert self.myjit.cpu.RDX == 0xFFFFFFFFFFFFFFFF
+
+
+
+
+if __name__ == "__main__":
+    tests = [
+        Test_CBW_16,
+        Test_CBW_16_signed,
+
+        Test_CBW_32,
+        Test_CBW_32_signed,
+
+        Test_CWD_32,
+        Test_CWD_32_signed,
+
+        Test_CWDE_32,
+        Test_CWDE_32_signed,
+
+        Test_CWDE_64,
+        Test_CWDE_64_signed,
+
+        Test_CDQ_32,
+        Test_CDQ_32_signed,
+
+        Test_CDQ_64,
+        Test_CDQ_64_signed,
+
+        Test_CDQE_64,
+        Test_CDQE_64_signed,
+    ]
+    if sys.argv[1] not in ["gcc", "tcc"]:
+        # TODO XXX CQO use 128 bit not supported in gcc yet!
+        tests += [
+            Test_CQO_64,
+            Test_CQO_64_signed,
+        ]
+
+    [
+        test(*sys.argv[1:])() for test in tests
+    ]
diff --git a/test/test_all.py b/test/test_all.py
index 23937366..04aca62e 100755
--- a/test/test_all.py
+++ b/test/test_all.py
@@ -79,6 +79,7 @@ for script in ["x86/sem.py",
                "x86/unit/mn_pextr.py",
                "x86/unit/mn_pmovmskb.py",
                "x86/unit/mn_pushpop.py",
+               "x86/unit/mn_cdq.py",
                "x86/unit/mn_seh.py",
                "x86/unit/mn_cpuid.py",
                "x86/unit/mn_div.py",