Example #1
0
void _interrupt(uc_engine *uc, uint32_t intno, void *user_data)
{
    if (intno == 6) {
        uc_emu_stop(uc);
        got_sigill = 1;
    }
}
Example #2
0
int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count)
{
    CPUState *mycpu = uc->cpu;
    int i;

    for (i = 0; i < count; i++) {
        unsigned int regid = regs[i];
        const void *value = vals[i];
        if (regid >= UC_M68K_REG_A0 && regid <= UC_M68K_REG_A7)
            M68K_CPU(uc, mycpu)->env.aregs[regid - UC_M68K_REG_A0] = *(uint32_t *)value;
        else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7)
            M68K_CPU(uc, mycpu)->env.dregs[regid - UC_M68K_REG_D0] = *(uint32_t *)value;
        else {
            switch(regid) {
                default: break;
                case UC_M68K_REG_PC:
                         M68K_CPU(uc, mycpu)->env.pc = *(uint32_t *)value;
                         // force to quit execution and flush TB
                         uc->quit_request = true;
                         uc_emu_stop(uc);
                         break;
            }
        }
    }

    return 0;
}
Example #3
0
int arm64_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
{
    CPUState *mycpu = first_cpu;

    if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28)
        ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_X0] = *(uint64_t *)value;
    else {
        switch(regid) {
            default: break;
            case UC_ARM64_REG_X29:
                     ARM_CPU(uc, mycpu)->env.xregs[29] = *(uint64_t *)value;
                     break;
            case UC_ARM64_REG_X30:
                     ARM_CPU(uc, mycpu)->env.xregs[30] = *(uint64_t *)value;
                     break;
            case UC_ARM64_REG_PC:
                     ARM_CPU(uc, mycpu)->env.pc = *(uint64_t *)value;
                     // force to quit execution and flush TB
                     uc->quit_request = true;
                     uc_emu_stop(uc);
                     break;
            case UC_ARM64_REG_SP:
                     ARM_CPU(uc, mycpu)->env.xregs[31] = *(uint64_t *)value;
                     break;
        }
    }

    return 0;
}
Example #4
0
int arm_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
{
    CPUState *mycpu = first_cpu;

    if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12)
        ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0] = *(uint32_t *)value;
    else {
        switch(regid) {
            //case UC_ARM_REG_SP:
            case UC_ARM_REG_R13:
                ARM_CPU(uc, mycpu)->env.regs[13] = *(uint32_t *)value;
                break;
            //case UC_ARM_REG_LR:
            case UC_ARM_REG_R14:
                ARM_CPU(uc, mycpu)->env.regs[14] = *(uint32_t *)value;
                break;
            //case UC_ARM_REG_PC:
            case UC_ARM_REG_R15:
                ARM_CPU(uc, mycpu)->env.pc = *(uint32_t *)value;
                ARM_CPU(uc, mycpu)->env.regs[15] = *(uint32_t *)value;
                // force to quit execution and flush TB
                uc->quit_request = true;
                uc_emu_stop(uc);

                break;
        }
    }

    return 0;
}
Example #5
0
int sparc_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
{
    CPUState *mycpu = first_cpu;

    if (regid >= UC_SPARC_REG_G0 && regid <= UC_SPARC_REG_G7)
        SPARC_CPU(uc, mycpu)->env.gregs[regid - UC_SPARC_REG_G0] = *(uint32_t *)value;
    else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7)
        SPARC_CPU(uc, mycpu)->env.regwptr[regid - UC_SPARC_REG_O0] = *(uint32_t *)value;
    else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7)
        SPARC_CPU(uc, mycpu)->env.regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint32_t *)value;
    else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7)
            SPARC_CPU(uc, mycpu)->env.regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint32_t *)value;
    else {
        switch(regid) {
            default: break;
            case UC_SPARC_REG_PC:
                SPARC_CPU(uc, mycpu)->env.pc = *(uint32_t *)value;
                SPARC_CPU(uc, mycpu)->env.npc = *(uint32_t *)value + 4;
                // force to quit execution and flush TB
                uc->quit_request = true;
                uc_emu_stop(uc);
                break;
        }
    }

    return 0;
}
Example #6
0
int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, int count)
{
    CPUState *mycpu = uc->cpu;
    int i;

    for (i = 0; i < count; i++) {
        unsigned int regid = regs[i];
        const void *value = vals[i];
        if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28)
            ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_X0] = *(uint64_t *)value;
        else {
            switch(regid) {
                default: break;
                case UC_ARM64_REG_X29:
                         ARM_CPU(uc, mycpu)->env.xregs[29] = *(uint64_t *)value;
                         break;
                case UC_ARM64_REG_X30:
                         ARM_CPU(uc, mycpu)->env.xregs[30] = *(uint64_t *)value;
                         break;
                case UC_ARM64_REG_PC:
                         ARM_CPU(uc, mycpu)->env.pc = *(uint64_t *)value;
                         // force to quit execution and flush TB
                         uc->quit_request = true;
                         uc_emu_stop(uc);
                         break;
                case UC_ARM64_REG_SP:
                         ARM_CPU(uc, mycpu)->env.xregs[31] = *(uint64_t *)value;
                         break;
            }
        }
    }

    return 0;
}
Example #7
0
int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count)
{
    CPUState *mycpu = first_cpu;
    int i;

    for (i = 0; i < count; i++) {
        unsigned int regid = regs[i];
        const void *value = vals[i];
        if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31)
            MIPS_CPU(uc, mycpu)->env.active_tc.gpr[regid - UC_MIPS_REG_0] = *(uint32_t *)value;
        else {
            switch(regid) {
                default: break;
                case UC_MIPS_REG_PC:
                         MIPS_CPU(uc, mycpu)->env.active_tc.PC = *(uint32_t *)value;
                         // force to quit execution and flush TB
                         uc->quit_request = true;
                         uc_emu_stop(uc);
                         break;
            }
        }
    }

    return 0;
}
Example #8
0
static void hook_count_cb(struct uc_struct *uc, uint64_t address, uint32_t size, void *user_data)
{
    // count this instruction. ah ah ah.
    uc->emu_counter++;

    if (uc->emu_counter > uc->emu_count)
        uc_emu_stop(uc);
}
// This hook is used to show that code is executing in the emulator.
static void mips_codehook(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
{
    printf("Executing: %llX\n", address);
    if( address == 0x100008 )
    {
        printf("Stopping at: %llX\n", address);
        uc_emu_stop(uc);
    }
}
Example #10
0
// callback for tracing instructions, detect HLT and terminate emulation
static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, void *user_data)
{
    uint8_t opcode;
    unsigned char buf[256];

    insts_executed++;

    if (uc_mem_read(uc, addr, buf, size) != UC_ERR_OK) {
        printf("not ok - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr);
        if (uc_emu_stop(uc) != UC_ERR_OK) {
            printf("not ok - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr);
            _exit(-1);
        }
    }

    opcode = buf[0];
    switch (opcode) {
        case 0x41:  // inc ecx
            if (uc_mem_protect(uc, 0x101000, 0x1000, UC_PROT_READ) != UC_ERR_OK) {
                printf("not ok - uc_mem_protect fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr);
                _exit(-1);
            }
            break;
        case 0x42:  // inc edx
            if (uc_mem_unmap(uc, 0x101000, 0x1000) != UC_ERR_OK) {
                printf("not ok - uc_mem_unmap fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr);
                _exit(-1);
            }
            break;
        case 0xf4:  // hlt
            if (uc_emu_stop(uc) != UC_ERR_OK) {
                printf("not ok - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr);
                _exit(-1);
            }
            break;
        default:  // all others
            break;
    }
}
Example #11
0
// callback for tracing instruction
static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, void *user_data)
{
    uint8_t opcode;
    uint32_t testval;
    if (uc_mem_read(uc, addr, &opcode, 1) != UC_ERR_OK) {
        printf("not ok %d - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
    }
    printf("ok %d - uc_mem_read for opcode at address 0x%" PRIx64 "\n", log_num++, addr);
    switch (opcode) {
        case 0x90:  //nop
            printf("# Handling NOP\n");
            if (uc_mem_read(uc, 0x200000 + test_num * 0x100000, &testval, sizeof(testval)) != UC_ERR_OK) {
                printf("not ok %d - uc_mem_read fail for address: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000);
            } else {
                printf("ok %d - good uc_mem_read for address: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000);
                printf("# uc_mem_read for test %d\n", test_num);

                if (testval == tests[test_num]) {
                    printf("ok %d - passed test %d\n", log_num++, test_num);
                } else {
                    printf("not ok %d - failed test %d\n", log_num++, test_num);
                    printf("# Expected: 0x%x\n",tests[test_num]);
                    printf("# Received: 0x%x\n", testval);
                }
            }
            if (uc_mem_unmap(uc, 0x200000 + test_num * 0x100000, 0x1000) != UC_ERR_OK) {
                printf("not ok %d - uc_mem_unmap fail during hook_code callback, addr: 0x%x\n", log_num++, 0x200000 + test_num * 0x100000);
            } else {
                printf("ok %d - uc_mem_unmap success\n", log_num++);
            }
            test_num++;
            break;
        case 0xf4:  //hlt
            printf("# Handling HLT\n");
            if (uc_emu_stop(uc) != UC_ERR_OK) {
                printf("not ok %d - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
                _exit(-1);
            } else {
                printf("ok %d - hlt encountered, uc_emu_stop called\n", log_num++);
            }
            break;
        default:  //all others
            printf("# Handling OTHER\n");
            break;
    }
}
Example #12
0
static void *_timeout_fn(void *arg)
{
    struct uc_struct *uc = arg;
    int64_t current_time = get_clock();

    do {
        usleep(TIMEOUT_STEP);
        // perhaps emulation is even done before timeout?
        if (uc->emulation_done)
            break;
    } while(get_clock() - current_time < uc->timeout);

    // timeout before emulation is done?
    if (!uc->emulation_done) {
        // force emulation to stop
        uc_emu_stop(uc);
    }

    return NULL;
}
Example #13
0
// callback for tracing instruction
static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, void *user_data)
{
    uint8_t opcode;

    if (uc_mem_read(uc, addr, &opcode, 1) != UC_ERR_OK) {
        printf("not ok %d - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
    }

    //   printf("ok %d - uc_mem_read for opcode at address 0x%" PRIx64 "\n", log_num++, addr);
    switch (opcode) {
        case 0xf4:  //hlt
            printf("# Handling HLT\n");
            if (uc_emu_stop(uc) != UC_ERR_OK) {
                printf("not ok %d - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", log_num++, addr);
                _exit(-1);
            } else {
                printf("ok %d - hlt encountered, uc_emu_stop called\n", log_num++);
            }
            break;
        default:  //all others
            //         printf("# Handling OTHER\n");
            break;
    }
}
Example #14
0
UNICORN_EXPORT
uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, uint32_t perms)
{
    MemoryRegion *mr;
    uint64_t addr = address;
    size_t count, len;
    bool remove_exec = false;

    if (size == 0)
        // trivial case, no change
        return UC_ERR_OK;

    // address must be aligned to uc->target_page_size
    if ((address & uc->target_page_align) != 0)
        return UC_ERR_ARG;

    // size must be multiple of uc->target_page_size
    if ((size & uc->target_page_align) != 0)
        return UC_ERR_ARG;

    // check for only valid permissions
    if ((perms & ~UC_PROT_ALL) != 0)
        return UC_ERR_ARG;

    if (uc->mem_redirect) {
        address = uc->mem_redirect(address);
    }

    // check that user's entire requested block is mapped
    if (!check_mem_area(uc, address, size))
        return UC_ERR_NOMEM;

    // Now we know entire region is mapped, so change permissions
    // We may need to split regions if this area spans adjacent regions
    addr = address;
    count = 0;
    while(count < size) {
        mr = memory_mapping(uc, addr);
        len = MIN(size - count, mr->end - addr);
        if (!split_region(uc, mr, addr, len, false))
            return UC_ERR_NOMEM;

        mr = memory_mapping(uc, addr);
        // will this remove EXEC permission?
        if (((mr->perms & UC_PROT_EXEC) != 0) && ((perms & UC_PROT_EXEC) == 0))
            remove_exec = true;
        mr->perms = perms;
        uc->readonly_mem(mr, (perms & UC_PROT_WRITE) == 0);

        count += len;
        addr += len;
    }

    // if EXEC permission is removed, then quit TB and continue at the same place
    if (remove_exec) {
        uc->quit_request = true;
        uc_emu_stop(uc);
    }

    return UC_ERR_OK;
}
Example #15
0
int main(int argc, char **argv, char **envp)
{
    uc_engine *uc;
    uc_err err;
	int ret;
	uc_hook hhc;
	uint32_t val;
	EmuStarterParam_t starter_params;
#ifdef _WIN32
	HANDLE th = (HANDLE)-1;
#else
	pthread_t th;
#endif

	// dynamically load shared library
#ifdef DYNLOAD
	uc_dyn_load(NULL, 0);
#endif

	// Initialize emulator in MIPS 32bit little endian mode
    printf("uc_open()\n");
	err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32, &uc);
    if (err)
	{
        printf("Failed on uc_open() with error returned: %u\n", err);
        return err;
    }

	// map in a page of mem
	printf("uc_mem_map()\n");
	err = uc_mem_map(uc, addr, 0x1000, UC_PROT_ALL);
    if (err)
	{
        printf("Failed on uc_mem_map() with error returned: %u\n", err);
        return err;
    }

	// write machine code to be emulated to memory
	printf("uc_mem_write()\n");
    err = uc_mem_write(uc, addr, loop_test_code, sizeof(loop_test_code));
	if( err )
	{
        printf("Failed on uc_mem_write() with error returned: %u\n", err);
        return err;
    }
	
    // hook all instructions by having @begin > @end
	printf("uc_hook_add()\n");
    uc_hook_add(uc, &hhc, UC_HOOK_CODE, mips_codehook, NULL, 1, 0);
	if( err )
	{
        printf("Failed on uc_hook_add(code) with error returned: %u\n", err);
        return err;
    }
	
	
	// start background thread
	printf("---- Thread Starting ----\n");
	starter_params.uc = uc;
	starter_params.startAddr = addr;
	starter_params.endAddr = addr + sizeof(loop_test_code);

#ifdef _WIN32
	// create thread
	th = (HANDLE)_beginthreadex(NULL, 0, win32_emu_starter, &starter_params, CREATE_SUSPENDED, NULL);
	if(th == (HANDLE)-1)
	{
		printf("Failed on _beginthreadex() with error returned: %u\n", _errno());
		return -1;
	}
	// start thread
	ret = ResumeThread(th);
	if( ret == -1 )
	{
		printf("Failed on ResumeThread() with error returned: %u\n", _errno());
		return -2;
	}
	// wait 3 seconds
	Sleep(3 * 1000);
#else
	// add posix code to start the emu_starter() thread
	ret = pthread_create(&th, NULL, posix_emu_starter, &starter_params);
	if( ret )
	{
		printf("Failed on pthread_create() with error returned: %u\n", err);
		return -2;
	}
	// wait 3 seconds
	sleep(3);
#endif


	// Stop the thread after it has been let to run in the background for a while
	printf("---- Thread Stopping ----\n");
	printf("uc_emu_stop()\n");
	err = uc_emu_stop(uc);
	if( err )
	{
        printf("Failed on uc_emu_stop() with error returned: %u\n", err);
        return err;
    }
	test_passed_ok = true;
	

	// done executing, print some reg values as a test
	uc_reg_read(uc, UC_MIPS_REG_PC, &val);	printf("pc is %X\n", val);
	uc_reg_read(uc, UC_MIPS_REG_A0, &val);	printf("a0 is %X\n", val);
	
	// free resources
	printf("uc_close()\n");
	uc_close(uc);
	
	if( test_passed_ok )
		printf("\n\nTEST PASSED!\n\n");
	else
		printf("\n\nTEST FAILED!\n\n");

	// dynamically free shared library
#ifdef DYNLOAD
    uc_dyn_free();
#endif

	return 0;
}
Example #16
0
int x86_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
{
    CPUState *mycpu = first_cpu;

    switch(uc->mode) {
        default:
            break;

        case UC_MODE_16:
            switch(regid) {
                default: break;
                case UC_X86_REG_ES:
                    X86_CPU(uc, mycpu)->env.segs[R_ES].selector = *(uint16_t *)value;
                    return 0;
                case UC_X86_REG_SS:
                    X86_CPU(uc, mycpu)->env.segs[R_SS].selector = *(uint16_t *)value;
                    return 0;
                case UC_X86_REG_DS:
                    X86_CPU(uc, mycpu)->env.segs[R_DS].selector = *(uint16_t *)value;
                    return 0;
                case UC_X86_REG_FS:
                    X86_CPU(uc, mycpu)->env.segs[R_FS].selector = *(uint16_t *)value;
                    return 0;
                case UC_X86_REG_GS:
                    X86_CPU(uc, mycpu)->env.segs[R_GS].selector = *(uint16_t *)value;
                    return 0;
            }
            // fall-thru
        case UC_MODE_32:
            switch(regid) {
                default:
                    break;
                case UC_X86_REG_CR0 ... UC_X86_REG_CR4:
                    X86_CPU(uc, mycpu)->env.cr[regid - UC_X86_REG_CR0] = *(uint32_t *)value;
                    break;
                case UC_X86_REG_DR0 ... UC_X86_REG_DR7:
                    X86_CPU(uc, mycpu)->env.dr[regid - UC_X86_REG_DR0] = *(uint32_t *)value;
                    break;
                case UC_X86_REG_EFLAGS:
                    X86_CPU(uc, mycpu)->env.eflags = *(uint32_t *)value;
                    X86_CPU(uc, mycpu)->env.eflags0 = *(uint32_t *)value;
                    break;
                case UC_X86_REG_EAX:
                    X86_CPU(uc, mycpu)->env.regs[R_EAX] = *(uint32_t *)value;
                    break;
                case UC_X86_REG_AX:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint16_t *)value);
                    break;
                case UC_X86_REG_AH:
                    WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint8_t *)value);
                    break;
                case UC_X86_REG_AL:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint8_t *)value);
                    break;
                case UC_X86_REG_EBX:
                    X86_CPU(uc, mycpu)->env.regs[R_EBX] = *(uint32_t *)value;
                    break;
                case UC_X86_REG_BX:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint16_t *)value);
                    break;
                case UC_X86_REG_BH:
                    WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint8_t *)value);
                    break;
                case UC_X86_REG_BL:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint8_t *)value);
                    break;
                case UC_X86_REG_ECX:
                    X86_CPU(uc, mycpu)->env.regs[R_ECX] = *(uint32_t *)value;
                    break;
                case UC_X86_REG_CX:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint16_t *)value);
                    break;
                case UC_X86_REG_CH:
                    WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint8_t *)value);
                    break;
                case UC_X86_REG_CL:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint8_t *)value);
                    break;
                case UC_X86_REG_EDX:
                    X86_CPU(uc, mycpu)->env.regs[R_EDX] = *(uint32_t *)value;
                    break;
                case UC_X86_REG_DX:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint16_t *)value);
                    break;
                case UC_X86_REG_DH:
                    WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint8_t *)value);
                    break;
                case UC_X86_REG_DL:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint8_t *)value);
                    break;
                case UC_X86_REG_ESP:
                    X86_CPU(uc, mycpu)->env.regs[R_ESP] = *(uint32_t *)value;
                    break;
                case UC_X86_REG_SP:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESP], *(uint16_t *)value);
                    break;
                case UC_X86_REG_EBP:
                    X86_CPU(uc, mycpu)->env.regs[R_EBP] = *(uint32_t *)value;
                    break;
                case UC_X86_REG_BP:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBP], *(uint16_t *)value);
                    break;
                case UC_X86_REG_ESI:
                    X86_CPU(uc, mycpu)->env.regs[R_ESI] = *(uint32_t *)value;
                    break;
                case UC_X86_REG_SI:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESI], *(uint16_t *)value);
                    break;
                case UC_X86_REG_EDI:
                    X86_CPU(uc, mycpu)->env.regs[R_EDI] = *(uint32_t *)value;
                    break;
                case UC_X86_REG_DI:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDI], *(uint16_t *)value);
                    break;
                case UC_X86_REG_EIP:
                    X86_CPU(uc, mycpu)->env.eip = *(uint32_t *)value;
                    // force to quit execution and flush TB
                    uc->quit_request = true;
                    uc_emu_stop(uc);
                    break;
                case UC_X86_REG_IP:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.eip, *(uint16_t *)value);
                    // force to quit execution and flush TB
                    uc->quit_request = true;
                    uc_emu_stop(uc);
                    break;
                case UC_X86_REG_CS:
                    X86_CPU(uc, mycpu)->env.segs[R_CS].selector = *(uint16_t *)value;
                    break;
                case UC_X86_REG_DS:
                    X86_CPU(uc, mycpu)->env.segs[R_DS].selector = *(uint16_t *)value;
                    break;
                case UC_X86_REG_SS:
                    X86_CPU(uc, mycpu)->env.segs[R_SS].selector = *(uint16_t *)value;
                    break;
                case UC_X86_REG_ES:
                    X86_CPU(uc, mycpu)->env.segs[R_ES].selector = *(uint16_t *)value;
                    break;
                case UC_X86_REG_FS:
                    X86_CPU(uc, mycpu)->env.segs[R_FS].selector = *(uint16_t *)value;
                    break;
                case UC_X86_REG_GS:
                    X86_CPU(uc, mycpu)->env.segs[R_GS].selector = *(uint16_t *)value;
                    break;
                case UC_X86_REG_IDTR:
                    X86_CPU(uc, mycpu)->env.idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit;
                    X86_CPU(uc, mycpu)->env.idt.base = (uint32_t)((uc_x86_mmr *)value)->base;
                    break;
                case UC_X86_REG_GDTR:
                    X86_CPU(uc, mycpu)->env.gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit;
                    X86_CPU(uc, mycpu)->env.gdt.base = (uint32_t)((uc_x86_mmr *)value)->base;
                    break;
                case UC_X86_REG_LDTR:
                    X86_CPU(uc, mycpu)->env.ldt.limit = ((uc_x86_mmr *)value)->limit;
                    X86_CPU(uc, mycpu)->env.ldt.base = (uint32_t)((uc_x86_mmr *)value)->base;
                    X86_CPU(uc, mycpu)->env.ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector;
                    X86_CPU(uc, mycpu)->env.ldt.flags = ((uc_x86_mmr *)value)->flags;
                    break;
                case UC_X86_REG_TR:
                    X86_CPU(uc, mycpu)->env.tr.limit = ((uc_x86_mmr *)value)->limit;
                    X86_CPU(uc, mycpu)->env.tr.base = (uint32_t)((uc_x86_mmr *)value)->base;
                    X86_CPU(uc, mycpu)->env.tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector;
                    X86_CPU(uc, mycpu)->env.tr.flags = ((uc_x86_mmr *)value)->flags;
                    break;
            }
            break;

#ifdef TARGET_X86_64
        case UC_MODE_64:
            switch(regid) {
                default:
                    break;
                case UC_X86_REG_CR0 ... UC_X86_REG_CR4:
                    X86_CPU(uc, mycpu)->env.cr[regid - UC_X86_REG_CR0] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_DR0 ... UC_X86_REG_DR7:
                    X86_CPU(uc, mycpu)->env.dr[regid - UC_X86_REG_DR0] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_EFLAGS:
                    X86_CPU(uc, mycpu)->env.eflags = *(uint64_t *)value;
                    X86_CPU(uc, mycpu)->env.eflags0 = *(uint64_t *)value;
                    break;
                case UC_X86_REG_RAX:
                    X86_CPU(uc, mycpu)->env.regs[R_EAX] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_EAX:
                    WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint32_t *)value);
                    break;
                case UC_X86_REG_AX:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint16_t *)value);
                    break;
                case UC_X86_REG_AH:
                    WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint8_t *)value);
                    break;
                case UC_X86_REG_AL:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EAX], *(uint8_t *)value);
                    break;
                case UC_X86_REG_RBX:
                    X86_CPU(uc, mycpu)->env.regs[R_EBX] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_EBX:
                    WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint32_t *)value);
                    break;
                case UC_X86_REG_BX:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint16_t *)value);
                    break;
                case UC_X86_REG_BH:
                    WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint8_t *)value);
                    break;
                case UC_X86_REG_BL:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EBX], *(uint8_t *)value);
                    break;
                case UC_X86_REG_RCX:
                    X86_CPU(uc, mycpu)->env.regs[R_ECX] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_ECX:
                    WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint32_t *)value);
                    break;
                case UC_X86_REG_CX:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint16_t *)value);
                    break;
                case UC_X86_REG_CH:
                    WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint8_t *)value);
                    break;
                case UC_X86_REG_CL:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ECX], *(uint8_t *)value);
                    break;
                case UC_X86_REG_RDX:
                    X86_CPU(uc, mycpu)->env.regs[R_EDX] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_EDX:
                    WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint32_t *)value);
                    break;
                case UC_X86_REG_DX:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint16_t *)value);
                    break;
                case UC_X86_REG_DH:
                    WRITE_BYTE_H(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint8_t *)value);
                    break;
                case UC_X86_REG_DL:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EDX], *(uint8_t *)value);
                    break;
                case UC_X86_REG_RSP:
                    X86_CPU(uc, mycpu)->env.regs[R_ESP] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_ESP:
                    WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_ESP], *(uint32_t *)value);
                    break;
                case UC_X86_REG_SP:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESP], *(uint16_t *)value);
                    break;
                case UC_X86_REG_SPL:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ESP], *(uint8_t *)value);
                    break;
                case UC_X86_REG_RBP:
                    X86_CPU(uc, mycpu)->env.regs[R_EBP] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_EBP:
                    WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EBP], *(uint32_t *)value);
                    break;
                case UC_X86_REG_BP:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EBP], *(uint16_t *)value);
                    break;
                case UC_X86_REG_BPL:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EBP], *(uint8_t *)value);
                    break;
                case UC_X86_REG_RSI:
                    X86_CPU(uc, mycpu)->env.regs[R_ESI] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_ESI:
                    WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_ESI], *(uint32_t *)value);
                    break;
                case UC_X86_REG_SI:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_ESI], *(uint16_t *)value);
                    break;
                case UC_X86_REG_SIL:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_ESI], *(uint8_t *)value);
                    break;
                case UC_X86_REG_RDI:
                    X86_CPU(uc, mycpu)->env.regs[R_EDI] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_EDI:
                    WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[R_EDI], *(uint32_t *)value);
                    break;
                case UC_X86_REG_DI:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[R_EDI], *(uint16_t *)value);
                    break;
                case UC_X86_REG_DIL:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[R_EDI], *(uint8_t *)value);
                    break;
                case UC_X86_REG_RIP:
                    X86_CPU(uc, mycpu)->env.eip = *(uint64_t *)value;
                    // force to quit execution and flush TB
                    uc->quit_request = true;
                    uc_emu_stop(uc);
                    break;
                case UC_X86_REG_EIP:
                    WRITE_DWORD(X86_CPU(uc, mycpu)->env.eip, *(uint32_t *)value);
                    // force to quit execution and flush TB
                    uc->quit_request = true;
                    uc_emu_stop(uc);
                    break;
                case UC_X86_REG_IP:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.eip, *(uint16_t *)value);
                    // force to quit execution and flush TB
                    uc->quit_request = true;
                    uc_emu_stop(uc);
                    break;
                case UC_X86_REG_CS:
                    X86_CPU(uc, mycpu)->env.segs[R_CS].selector = *(uint16_t *)value;
                    break;
                case UC_X86_REG_DS:
                    X86_CPU(uc, mycpu)->env.segs[R_DS].selector = *(uint16_t *)value;
                    break;
                case UC_X86_REG_SS:
                    X86_CPU(uc, mycpu)->env.segs[R_SS].selector = *(uint16_t *)value;
                    break;
                case UC_X86_REG_ES:
                    X86_CPU(uc, mycpu)->env.segs[R_ES].selector = *(uint16_t *)value;
                    break;
                case UC_X86_REG_FS:
                    X86_CPU(uc, mycpu)->env.segs[R_FS].selector = *(uint16_t *)value;
                    break;
                case UC_X86_REG_GS:
                    X86_CPU(uc, mycpu)->env.segs[R_GS].selector = *(uint16_t *)value;
                    break;
                case UC_X86_REG_R8:
                    X86_CPU(uc, mycpu)->env.regs[8] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_R8D:
                    WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[8], *(uint32_t *)value);
                    break;
                case UC_X86_REG_R8W:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[8], *(uint16_t *)value);
                    break;
                case UC_X86_REG_R8B:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[8], *(uint8_t *)value);
                    break;
                case UC_X86_REG_R9:
                    X86_CPU(uc, mycpu)->env.regs[9] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_R9D:
                    WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[9], *(uint32_t *)value);
                    break;
                case UC_X86_REG_R9W:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[9], *(uint16_t *)value);
                    break;
                case UC_X86_REG_R9B:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[9], *(uint8_t *)value);
                    break;
                case UC_X86_REG_R10:
                    X86_CPU(uc, mycpu)->env.regs[10] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_R10D:
                    WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[10], *(uint32_t *)value);
                    break;
                case UC_X86_REG_R10W:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[10], *(uint16_t *)value);
                    break;
                case UC_X86_REG_R10B:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[10], *(uint8_t *)value);
                    break;
                case UC_X86_REG_R11:
                    X86_CPU(uc, mycpu)->env.regs[11] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_R11D:
                    WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[11], *(uint32_t *)value);
                    break;
                case UC_X86_REG_R11W:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[11], *(uint16_t *)value);
                    break;
                case UC_X86_REG_R11B:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[11], *(uint8_t *)value);
                    break;
                case UC_X86_REG_R12:
                    X86_CPU(uc, mycpu)->env.regs[12] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_R12D:
                    WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[12], *(uint32_t *)value);
                    break;
                case UC_X86_REG_R12W:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[12], *(uint16_t *)value);
                    break;
                case UC_X86_REG_R12B:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[12], *(uint8_t *)value);
                    break;
                case UC_X86_REG_R13:
                    X86_CPU(uc, mycpu)->env.regs[13] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_R13D:
                    WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[13], *(uint32_t *)value);
                    break;
                case UC_X86_REG_R13W:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[13], *(uint16_t *)value);
                    break;
                case UC_X86_REG_R13B:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[13], *(uint8_t *)value);
                    break;
                case UC_X86_REG_R14:
                    X86_CPU(uc, mycpu)->env.regs[14] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_R14D:
                    WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[14], *(uint32_t *)value);
                    break;
                case UC_X86_REG_R14W:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[14], *(uint16_t *)value);
                    break;
                case UC_X86_REG_R14B:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[14], *(uint8_t *)value);
                    break;
                case UC_X86_REG_R15:
                    X86_CPU(uc, mycpu)->env.regs[15] = *(uint64_t *)value;
                    break;
                case UC_X86_REG_R15D:
                    WRITE_DWORD(X86_CPU(uc, mycpu)->env.regs[15], *(uint32_t *)value);
                    break;
                case UC_X86_REG_R15W:
                    WRITE_WORD(X86_CPU(uc, mycpu)->env.regs[15], *(uint16_t *)value);
                    break;
                case UC_X86_REG_R15B:
                    WRITE_BYTE_L(X86_CPU(uc, mycpu)->env.regs[15], *(uint8_t *)value);
                    break;
                case UC_X86_REG_IDTR:
                    X86_CPU(uc, mycpu)->env.idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit;
                    X86_CPU(uc, mycpu)->env.idt.base = ((uc_x86_mmr *)value)->base;
                    break;
                case UC_X86_REG_GDTR:
                    X86_CPU(uc, mycpu)->env.gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit;
                    X86_CPU(uc, mycpu)->env.gdt.base = ((uc_x86_mmr *)value)->base;
                    break;
                case UC_X86_REG_LDTR:
                    X86_CPU(uc, mycpu)->env.ldt.limit = ((uc_x86_mmr *)value)->limit;
                    X86_CPU(uc, mycpu)->env.ldt.base = ((uc_x86_mmr *)value)->base;
                    X86_CPU(uc, mycpu)->env.ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector;
                    X86_CPU(uc, mycpu)->env.ldt.flags = ((uc_x86_mmr *)value)->flags;
                    break;
                case UC_X86_REG_TR:
                    X86_CPU(uc, mycpu)->env.tr.limit = ((uc_x86_mmr *)value)->limit;
                    X86_CPU(uc, mycpu)->env.tr.base = ((uc_x86_mmr *)value)->base;
                    X86_CPU(uc, mycpu)->env.tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector;
                    X86_CPU(uc, mycpu)->env.tr.flags = ((uc_x86_mmr *)value)->flags;
                    break;
            }
            break;
#endif
    }

    return 0;
}