diff options
Diffstat (limited to 'miasm2/jitter/vm_mngr.c')
| -rw-r--r-- | miasm2/jitter/vm_mngr.c | 1640 |
1 files changed, 1640 insertions, 0 deletions
diff --git a/miasm2/jitter/vm_mngr.c b/miasm2/jitter/vm_mngr.c new file mode 100644 index 00000000..7d47fadc --- /dev/null +++ b/miasm2/jitter/vm_mngr.c @@ -0,0 +1,1640 @@ +/* +** 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 <inttypes.h> +#include <math.h> + +#include "queue.h" +#include "vm_mngr.h" + + + + +/* +struct memory_page_list_head memory_page_pool; +struct code_bloc_list_head code_bloc_pool; + +struct memory_breakpoint_info_head memory_breakpoint_pool; +*/ + +/****************memory manager**************/ + + + + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + + +//#define DEBUG_MIASM_AUTOMOD_CODE + + + + + +void print_val(uint64_t base, uint64_t addr) +{ + uint64_t *ptr = (uint64_t *) addr; + fprintf(stderr, "addr 0x%"PRIX64" val 0x%"PRIX64"\n", addr-base, *ptr); +} + + +int is_mem_mapped(vm_mngr_t* vm_mngr, uint64_t ad) +{ + struct memory_page_node * mpn; + /* + mpn = memory_page_pool_tab[ad>>MEMORY_PAGE_POOL_MASK_BIT]; + if ( mpn && (mpn->ad <= ad) && (ad < mpn->ad + mpn->size)) + return 1; + */ + LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){ + if ((mpn->ad <= ad) && (ad <mpn->ad + mpn->size)) + return 1; + } + + return 0; +} + + +/* return the address base of the memory page + containing addr +*/ +uint64_t get_mem_base_addr(vm_mngr_t* vm_mngr, uint64_t ad, uint64_t *addr_base) +{ + struct memory_page_node * mpn; + /* + mpn = memory_page_pool_tab[ad>>MEMORY_PAGE_POOL_MASK_BIT]; + if ( mpn && (mpn->ad <= ad) && (ad < mpn->ad + mpn->size)){ + *addr_base = mpn->ad; + return 1; + } + */ + LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){ + if ((mpn->ad <= ad) && (ad <mpn->ad + mpn->size)) { + *addr_base = mpn->ad; + return 1; + } + } + return 0; +} + +struct memory_page_node * get_memory_page_from_address(vm_mngr_t* vm_mngr, uint64_t ad) +{ + struct memory_page_node * mpn; +#if 0 + mpn = memory_page_pool_tab[ad>>MEMORY_PAGE_POOL_MASK_BIT]; + if ( mpn && (mpn->ad <= ad) && (ad < mpn->ad + mpn->size)) + return mpn; + + fprintf(stderr, "WARNING: address 0x%"PRIX64" is not mapped in virtual memory:\n", ad); + //dump_memory_page_pool(); + //dump_gpregs(); + //exit(-1); + vm_mngr->exception_flags |= EXCEPT_ACCESS_VIOL; + + return NULL; +#else + + //printf("search for page ad: %X\n", ad); + LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){ + if ((mpn->ad <= ad) && (ad < mpn->ad + mpn->size)) + return mpn; + } + fprintf(stderr, "WARNING: address 0x%"PRIX64" is not mapped in virtual memory:\n", ad); + //dump_memory_page_pool(); + //dump_gpregs(); + //exit(-1); + vm_mngr->exception_flags |= EXCEPT_ACCESS_VIOL; + return NULL; +#endif +} + + + + +static inline uint64_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t ad) +{ + struct memory_page_node * mpn; + unsigned char * addr; + uint64_t ret = 0; + struct memory_breakpoint_info * b; + + + mpn = get_memory_page_from_address(vm_mngr, ad); + if (!mpn) + return 0; + + if ((mpn->access & PAGE_READ) == 0){ + fprintf(stderr, "access to non readable page!! %"PRIX64"\n", ad); + vm_mngr->exception_flags |= EXCEPT_ACCESS_VIOL; + return 0; + } + + /* check read breakpoint*/ + LIST_FOREACH(b, &vm_mngr->memory_breakpoint_pool, next){ + if ((b->access & BREAKPOINT_READ) == 0) + continue; + if ((b->ad <= ad) && (ad < b->ad + b->size)) + vm_mngr->exception_flags |= EXCEPT_BREAKPOINT_INTERN; + } + + + 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 = *((uint64_t*)addr)&0xFFFFFFFFFFFFFFFFULL; + ret = Endian64_Swap(ret); + break; + default: + exit(0); + break; + } + } + /* read is multiple page wide */ + else{ + unsigned int new_size = my_size; + int index = 0; + fprintf(stderr, "read multiple page! %"PRIX64" %d\n", ad, new_size); + dump_memory_page_pool(vm_mngr); + while (new_size){ + mpn = get_memory_page_from_address(vm_mngr, ad); + if (!mpn) + return 0; + addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad]; + ret |= (*((unsigned char*)addr)&0xFF)<<(index); + index +=8; + 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(vm_mngr_t* vm_mngr, unsigned int my_size, + uint64_t ad, uint64_t src) +{ + struct memory_page_node * mpn; + unsigned char * addr; + struct memory_breakpoint_info * b; + + mpn = get_memory_page_from_address(vm_mngr, ad); + if (!mpn) + return; + + if ((mpn->access & PAGE_WRITE) == 0){ + fprintf(stderr, "access to non writable page!! %"PRIX64"\n", ad); + vm_mngr->exception_flags |= EXCEPT_ACCESS_VIOL; + return ; + } + + /* check read breakpoint*/ + LIST_FOREACH(b, &vm_mngr->memory_breakpoint_pool, next){ + if ((b->access & BREAKPOINT_WRITE) == 0) + continue; + if ((b->ad <= ad) && (ad < b->ad + b->size)) + vm_mngr->exception_flags |= EXCEPT_BREAKPOINT_INTERN; + } + + 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); + *((uint64_t*)addr) = src&0xFFFFFFFFFFFFFFFFULL; + break; + default: + exit(0); + break; + } + } + /* write is multiple page wide */ + else{ + fprintf(stderr, "write multiple page! %"PRIX64" %d\n", ad, my_size); + dump_memory_page_pool(vm_mngr); + 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(vm_mngr, ad); + if (!mpn) + return; + + addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad]; + *((unsigned char*)addr) = src&0xFF; + my_size -= 8; + src >>=8; + ad ++; + } + } +} + +/* TODO: Those functions have to be moved to a common operations file, with + * parity, ... + */ + +inline uint16_t bcdadd_16(uint16_t a, uint16_t b) +{ + int carry = 0; + int i,j = 0; + uint16_t res = 0; + int nib_a, nib_b; + for (i = 0; i < 16; i += 4) { + nib_a = (a >> i) & (0xF); + nib_b = (b >> i) & (0xF); + + j = (carry + nib_a + nib_b); + if (j >= 10) { + carry = 1; + j -= 10; + j &=0xf; + } + else { + carry = 0; + } + res += j << i; + } + return res; +} + +inline uint16_t bcdadd_cf_16(uint16_t a, uint16_t b) +{ + int carry = 0; + int i,j = 0; + int nib_a, nib_b; + for (i = 0; i < 16; i += 4) { + nib_a = (a >> i) & (0xF); + nib_b = (b >> i) & (0xF); + + j = (carry + nib_a + nib_b); + if (j >= 10) { + carry = 1; + j -= 10; + j &=0xf; + } + else { + carry = 0; + } + } + return carry; +} +// ################## + +void dump_code_bloc(vm_mngr_t* vm_mngr) +{ + struct code_bloc_node * cbp; + LIST_FOREACH(cbp, &vm_mngr->code_bloc_pool, next){ + fprintf(stderr, "%"PRIX64"%"PRIX64"\n", cbp->ad_start, cbp->ad_stop); + } + +} + +inline void check_write_code_bloc(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t addr) +{ + struct code_bloc_node * cbp; + vm_mngr->last_write_ad = addr; + vm_mngr->last_write_size = my_size; + + + + //if(vmmngr.my_tick> my_tick) + // printf("M_WRITE %2d %.8X %.8X\n", my_size, addr, src); + if (!(addr + my_size/8 <= vm_mngr->code_bloc_pool_ad_min || + addr >=vm_mngr->code_bloc_pool_ad_max)){ + LIST_FOREACH(cbp, &vm_mngr->code_bloc_pool, next){ + if ((cbp->ad_start < addr + my_size/8) && + (addr < cbp->ad_stop)){ +#ifdef DEBUG_MIASM_AUTOMOD_CODE + fprintf(stderr, "**********************************\n"); + fprintf(stderr, "self modifying code %"PRIX64" %.8X\n", + addr, my_size); + fprintf(stderr, "**********************************\n"); + //dump_code_bloc(vm_mngr); +#endif + vm_mngr->exception_flags |= EXCEPT_CODE_AUTOMOD; + + break; + } + } + } +} + +PyObject* addr2BlocObj(vm_mngr_t* vm_mngr, uint64_t addr) +{ + PyObject* pyaddr; + PyObject* b; + + //printf("addr2blocobj %"PRIx64"\n", addr); + pyaddr = PyLong_FromUnsignedLongLong(addr); + /* + Py_INCREF(pyaddr); + return pyaddr; + */ + b = PyDict_GetItem(vm_mngr->addr2obj, pyaddr); + if (b == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + + //printf("addr2blocobj OBJ %p\n", b); + Py_INCREF(b); + return b; +} + +/* +PyObject* add_code_resolver(vm_mngr_t* vm_mngr, uint64_t addr) +{ + pyaddr = PyLong_FromUnsignedLongLong(addr); + + func_resolver* f = malloc(sizeof(func_resolver)); + f->func = addr2blocobj; + fsdfsd + return f; +} +*/ +/* +void MEM_WRITE(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t addr, unsigned int src) +{ + struct code_bloc_node * cbp; + + vm_mngr->last_write_ad = addr; + vm_mngr->last_write_size = my_size; + + //if(vmmngr.my_tick> my_tick) + // printf("M_WRITE %2d %.8X %.8X\n", my_size, addr, src); + if (!(addr + my_size/8 <= vm_mngr->code_bloc_pool_ad_min || + addr >= vm_mngr->code_bloc_pool_ad_max)){ + LIST_FOREACH(cbp, &vm_mngr->code_bloc_pool, next){ + if ((cbp->ad_start <= addr + my_size/8) && + (addr < cbp->ad_stop)){ +#ifdef DEBUG_MIASM_AUTOMOD_CODE + fprintf(stderr, "self modifying code %"PRIX64" %.8X\n", + addr, my_size); +#endif + vm_mngr->exception_flags |= EXCEPT_CODE_AUTOMOD; + break; + } + } + } + + memory_page_write(vm_mngr, my_size, addr, src); +} +*/ +void MEM_WRITE_08(vm_mngr_t* vm_mngr, uint64_t addr, unsigned char src) +{ + check_write_code_bloc(vm_mngr, 8, addr); + memory_page_write(vm_mngr, 8, addr, src); +} + +void MEM_WRITE_16(vm_mngr_t* vm_mngr, uint64_t addr, unsigned short src) +{ + check_write_code_bloc(vm_mngr, 16, addr); + memory_page_write(vm_mngr, 16, addr, src); +} +void MEM_WRITE_32(vm_mngr_t* vm_mngr, uint64_t addr, unsigned int src) +{ + check_write_code_bloc(vm_mngr, 32, addr); + memory_page_write(vm_mngr, 32, addr, src); +} +void MEM_WRITE_64(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t src) +{ + check_write_code_bloc(vm_mngr, 64, addr); + memory_page_write(vm_mngr, 64, addr, src); +} + +unsigned int MEM_LOOKUP(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t addr) +{ + unsigned int ret; + ret = memory_page_read(vm_mngr, my_size, addr); + return ret; +} + +unsigned char MEM_LOOKUP_08(vm_mngr_t* vm_mngr, uint64_t addr) +{ + unsigned char ret; + ret = memory_page_read(vm_mngr, 8, addr); + return ret; +} +unsigned short MEM_LOOKUP_16(vm_mngr_t* vm_mngr, uint64_t addr) +{ + unsigned short ret; + ret = memory_page_read(vm_mngr, 16, addr); + return ret; +} +unsigned int MEM_LOOKUP_32(vm_mngr_t* vm_mngr, uint64_t addr) +{ + unsigned int ret; + ret = memory_page_read(vm_mngr, 32, addr); + return ret; +} +uint64_t MEM_LOOKUP_64(vm_mngr_t* vm_mngr, uint64_t addr) +{ + uint64_t ret; + ret = memory_page_read(vm_mngr, 64, addr); + return ret; +} + +inline unsigned int parity(unsigned int a) +{ +#if defined(__builtin_parity) + return __builtin_parity(a); +#else + unsigned int tmp, cpt; + + tmp = a&0xFF; + cpt = 1; + while (tmp!=0){ + cpt^=tmp&1; + tmp>>=1; + } + return cpt; +#endif +} + + +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: + fprintf(stderr, "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: + fprintf(stderr, "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: + fprintf(stderr, "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: fprintf(stderr, "inv size in mul %d\n", size); exit(0); + } + + a &= mask; + b &= mask; + return ((int64_t)a * (int64_t) b) & mask; +} + +unsigned int mul_hi_op(unsigned int size, unsigned int a, unsigned int b) +{ + uint64_t res = 0; + unsigned int mask; + + switch (size) { + case 8: mask = 0xff; break; + case 16: mask = 0xffff; break; + case 32: mask = 0xffffffff; break; + default: fprintf(stderr, "inv size in mul %d\n", size); exit(0); + } + + a &= mask; + b &= mask; + res = ((uint64_t)a * (uint64_t)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) +{ + int64_t res = 0; + res = a*b; + return res>>8; +} + +int imul_hi_op_16(short a, short b) +{ + int64_t res = 0; + res = a*b; + return res>>16; +} + +int imul_hi_op_32(int a, int b) +{ + int64_t res = 0; + res = (int64_t)a*(int64_t)b; + //printf("%x %x dd %"PRIx64"\n", a, b, res); + return res>>32ULL; +} + +unsigned int umul16_lo(unsigned short a, unsigned short b) +{ + return (a*b) & 0xffff; +} + +unsigned int umul16_hi(unsigned short a, unsigned short b) +{ + uint32_t c; + c = a*b; + return (c>>16) & 0xffff; +} + + + + +unsigned int div_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c) +{ + int64_t num; + if (c == 0) + { + //vmmngr.exception_flags |= EXCEPT_INT_DIV_BY_ZERO; + return 0; + } + num = ((int64_t)a << size) + b; + num/=(int64_t)c; + return num; +} + + +unsigned int rem_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c) +{ + int64_t num; + + if (c == 0) + { + //vmmngr.exception_flags |= EXCEPT_INT_DIV_BY_ZERO; + return 0; + } + + num = ((int64_t)a << size) + b; + num = (int64_t)num-c*(num/c); + return num; +} + + +unsigned 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: + fprintf(stderr, "inv size in rotleft %d\n", size); + exit(0); + } +} + +unsigned 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: + fprintf(stderr, "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) +{ + uint64_t tmp; + + + size++; + b %= size; + + if (b == 0) { + switch(size){ + case 8+1: + return a&0xff; + case 16+1: + return a&0xffff; + case 32+1: + return a&0xffffffff; + default: + fprintf(stderr, "inv size in rclleft %d\n", size); + exit(0); + } + } + + tmp = (a<<1) | cf; + b -=1; + 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: + fprintf(stderr, "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) +{ + uint64_t tmp; + + tmp = (cf<< size) | a; + + size++; + 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: + fprintf(stderr, "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){ + fprintf(stderr, "not implemented 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; + return 0x00020652; + case 1: + //return 0x02040800; + return 0x00000800; + case 2: + //return 0x0004E3BD; + return 0x00000209; + case 3: + //return 0xBFEBFBFF; + return 0x078bf9ff; + } + } + else{ + fprintf(stderr, "WARNING not implemented cpuid index %X!\n", a); + //exit(-1); + } + return 0; +} + +#define DEBUG_MIASM_DOUBLE + +void dump_float(void) +{ + /* + printf("%e\n", vmmngr.float_st0); + printf("%e\n", vmmngr.float_st1); + printf("%e\n", vmmngr.float_st2); + printf("%e\n", vmmngr.float_st3); + printf("%e\n", vmmngr.float_st4); + printf("%e\n", vmmngr.float_st5); + printf("%e\n", vmmngr.float_st6); + printf("%e\n", vmmngr.float_st7); + */ +} + +double mem_32_to_double(unsigned int m) +{ + float f; + double d; + + f = *((float*)&m); + d = f; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%d float %e\n", m, d); +#endif + return d; +} + + +double mem_64_to_double(uint64_t m) +{ + double d; + d = *((double*)&m); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%"PRId64" double %e\n", m, d); +#endif + return d; +} + +double int_16_to_double(unsigned int m) +{ + double d; + + d = (double)(m&0xffff); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%d double %e\n", m, d); +#endif + return d; +} + +double int_32_to_double(unsigned int m) +{ + double d; + + d = (double)m; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%d double %e\n", m, d); +#endif + return d; +} + +double int_64_to_double(uint64_t m) +{ + double d; + + d = (double)m; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%"PRId64" double %e\n", m, d); +#endif + return d; +} + +int32_t double_to_int_32(double d) +{ + int32_t i; + + i = (int32_t)d; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e int %d\n", d, i); +#endif + return i; +} + +int64_t double_to_int_64(double d) +{ + int64_t i; + + i = (int64_t)d; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e int %"PRId64"\n", d, i); +#endif + return i; +} + + +double fadd(double a, double b) +{ + double c; + c = a + b; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e + %e -> %e\n", a, b, c); +#endif + return c; +} + +double fsub(double a, double b) +{ + double c; + c = a - b; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e - %e -> %e\n", a, b, c); +#endif + return c; +} + +double fmul(double a, double b) +{ + double c; + c = a * b; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e * %e -> %e\n", a, b, c); +#endif + return c; +} + +double fdiv(double a, double b) +{ + double c; + c = a / b; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e / %e -> %e\n", a, b, c); +#endif + return c; +} + +double ftan(double a) +{ + double b; + b = tan(a); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e tan %e\n", a, b); +#endif + return b; +} + +double frndint(double a) +{ + int64_t b; + double c; + b = (int64_t)a; + c = (double)b; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e double %e\n", a, c); +#endif + return c; +} + +double fsin(double a) +{ + double b; + b = sin(a); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e sin %e\n", a, b); +#endif + return b; +} + +double fcos(double a) +{ + double b; + b = cos(a); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e cos %e\n", a, b); +#endif + return b; +} + + +double fscale(double a, double b) +{ + double c; + c = a * exp2(trunc(b)); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e *exp2 %e -> %e\n", a, b, c); +#endif + return c; +} + +double f2xm1(double a) +{ + double b; + b = exp2(a)-1; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e exp2 -1 %e\n", a, b); +#endif + return b; +} + +double fsqrt(double a) +{ + double b; + b = sqrt(a); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e sqrt %e\n", a, b); +#endif + return b; +} + +double fabs(double a) +{ + double b; + b = abs(a); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e abs %e\n", a, b); +#endif + return b; +} + + + +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); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%d %e\n", m, d); +#endif + return m; +} + +uint64_t double_to_mem_64(double d) +{ + uint64_t m; + m = *((uint64_t*)&d); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%"PRId64" %e\n", m, d); +#endif + return m; +} + +struct memory_page_node * create_memory_page_node(uint64_t ad, unsigned int size, unsigned int access) +{ + struct memory_page_node * mpn; + void* p; + + mpn = malloc(sizeof(*mpn)); + if (!mpn){ + fprintf(stderr, "cannot alloc mpn\n"); + return NULL; + } + p = malloc(size); + if (!p){ + fprintf(stderr, "cannot alloc %d\n", size); + return NULL; + } + mpn->ad = ad; + mpn->size = size; + mpn->access = access; + mpn->ad_hp = p; + + return mpn; +} + + +struct code_bloc_node * create_code_bloc_node(uint64_t ad_start, uint64_t ad_stop) +{ + struct code_bloc_node * cbp; + + cbp = malloc(sizeof(*cbp)); + if (!cbp){ + fprintf(stderr, "cannot alloc cbp\n"); + exit(-1); + } + + cbp->ad_start = ad_start; + cbp->ad_stop = ad_stop; + + return cbp; +} + + +void add_code_bloc(vm_mngr_t* vm_mngr, struct code_bloc_node* cbp) +{ + LIST_INSERT_HEAD(&vm_mngr->code_bloc_pool, cbp, next); + if (vm_mngr->code_bloc_pool_ad_min> cbp->ad_start) + vm_mngr->code_bloc_pool_ad_min = cbp->ad_start; + if (vm_mngr->code_bloc_pool_ad_max< cbp->ad_stop) + vm_mngr->code_bloc_pool_ad_max = cbp->ad_stop; +} + +void dump_code_bloc_pool(vm_mngr_t* vm_mngr) +{ + struct code_bloc_node * cbp; + + LIST_FOREACH(cbp, &vm_mngr->code_bloc_pool, next){ + printf("ad start %"PRIX64" ad_stop %"PRIX64"\n", + cbp->ad_start, + cbp->ad_stop); + } +} + + +void init_memory_page_pool(vm_mngr_t* vm_mngr) +{ + unsigned int i; + LIST_INIT(&vm_mngr->memory_page_pool); + for (i=0;i<MAX_MEMORY_PAGE_POOL_TAB; i++) + vm_mngr->memory_page_pool_tab[i] = NULL; +} + +void init_code_bloc_pool(vm_mngr_t* vm_mngr) +{ + LIST_INIT(&vm_mngr->code_bloc_pool); + vm_mngr->code_bloc_pool_ad_min = 0xffffffff; + vm_mngr->code_bloc_pool_ad_max = 0; +} + +void init_memory_breakpoint(vm_mngr_t* vm_mngr) +{ + LIST_INIT(&vm_mngr->memory_breakpoint_pool); +} + + +void reset_memory_page_pool(vm_mngr_t* vm_mngr) +{ + struct memory_page_node * mpn; + unsigned int i; + + while (!LIST_EMPTY(&vm_mngr->memory_page_pool)) { + mpn = LIST_FIRST(&vm_mngr->memory_page_pool); + LIST_REMOVE(mpn, next); + free(mpn->ad_hp); + free(mpn); + } + for (i=0;i<MAX_MEMORY_PAGE_POOL_TAB; i++) + vm_mngr->memory_page_pool_tab[i] = NULL; + +} + + +void reset_code_bloc_pool(vm_mngr_t* vm_mngr) +{ + struct code_bloc_node * cbp; + + + while (!LIST_EMPTY(&vm_mngr->code_bloc_pool)) { + cbp = LIST_FIRST(&vm_mngr->code_bloc_pool); + LIST_REMOVE(cbp, next); + free(cbp); + } + vm_mngr->code_bloc_pool_ad_min = 0xffffffff; + vm_mngr->code_bloc_pool_ad_max = 0; +} + + +void reset_memory_breakpoint(vm_mngr_t* vm_mngr) +{ + struct memory_breakpoint_info * mpn; + + while (!LIST_EMPTY(&vm_mngr->memory_breakpoint_pool)) { + mpn = LIST_FIRST(&vm_mngr->memory_breakpoint_pool); + LIST_REMOVE(mpn, next); + free(mpn); + } + +} + + +int is_mpn_in_tab(vm_mngr_t* vm_mngr, struct memory_page_node* mpn_a) +{ + struct memory_page_node * mpn; + + /* + 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){ + return 1; + } + } + */ + LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){ + if (mpn->ad >= mpn_a->ad + mpn_a->size) + continue; + if (mpn->ad + mpn->size <= mpn_a->ad) + continue; + printf("is mpn in! %"PRIX64" %"PRIX64" \n", mpn_a->ad, mpn_a->size); + printf("known:! %"PRIX64" %"PRIX64" \n", mpn->ad, mpn->size); + + return 1; + } + + return 0; +} + +void insert_mpn_in_tab(struct memory_page_node* mpn_a) +{ + /* + 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){ + fprintf(stderr, "known page in tab\n"); + exit(1); + } + memory_page_pool_tab[i] = mpn_a; + } + */ + +} + +void add_memory_page(vm_mngr_t* vm_mngr, struct memory_page_node* mpn_a) +{ + struct memory_page_node * mpn; + struct memory_page_node * lmpn; + + if (LIST_EMPTY(&vm_mngr->memory_page_pool)){ + LIST_INSERT_HEAD(&vm_mngr->memory_page_pool, mpn_a, next); + insert_mpn_in_tab(mpn_a); + return; + } + LIST_FOREACH(mpn, &vm_mngr->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(vm_mngr_t* vm_mngr) +{ + struct memory_page_node * mpn; + + LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){ + printf("ad %"PRIX64" size %"PRIX64" %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 + ); + } +} + +void dump_memory_breakpoint_pool(vm_mngr_t* vm_mngr) +{ + struct memory_breakpoint_info * mpn; + + LIST_FOREACH(mpn, &vm_mngr->memory_breakpoint_pool, next){ + printf("ad %"PRIX64" size %"PRIX64" access %"PRIX64"\n", + mpn->ad, + mpn->size, + mpn->access + ); + } +} + + +void add_memory_breakpoint(vm_mngr_t* vm_mngr, uint64_t ad, uint64_t size, unsigned int access) +{ + struct memory_breakpoint_info * mpn_a; + mpn_a = malloc(sizeof(*mpn_a)); + if (!mpn_a) { + printf("cannot alloc\n"); + exit(0); + } + mpn_a->ad = ad; + mpn_a->size = size; + mpn_a->access = access; + + LIST_INSERT_HEAD(&vm_mngr->memory_breakpoint_pool, mpn_a, next); + +} + +void remove_memory_breakpoint(vm_mngr_t* vm_mngr, uint64_t ad, unsigned int access) +{ + struct memory_breakpoint_info * mpn; + + LIST_FOREACH(mpn, &vm_mngr->memory_breakpoint_pool, next){ + if (mpn->ad == ad && mpn->access == access) + LIST_REMOVE(mpn, next); + } + +} + + + + + + + +unsigned int get_memory_page_next(vm_mngr_t* vm_mngr, unsigned int n_ad) +{ + struct memory_page_node * mpn; + uint64_t ad = 0; + + LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){ + if (mpn->ad < n_ad) + continue; + + if (ad == 0 || mpn->ad <ad) + ad = mpn->ad; + } + return ad; +} + + +#if 0 +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; + } +#endif + + + +/********************************************/ + +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"); + +} + + + + +unsigned int access_segment(unsigned int d) +{ + // XXX TODO + printf("access segment %X\n", d); + return 0; +} +unsigned int access_segment_ok(unsigned int d) +{ + // XXX TODO + printf("access segment ok %X\n", d); + return 0; +} + +unsigned int load_segment_limit(unsigned int d) +{ + // XXX TODO + printf("load segment limit %X\n", d); + return 0; +} +unsigned int load_segment_limit_ok(unsigned int d) +{ + // XXX TODO + printf("load segment limit ok %X\n", d); + return 0; +} + +unsigned int load_tr_segment_selector(unsigned int d) +{ + // XXX TODO + return 0; +} + +// Return vm_mngr's exception flag value +uint64_t get_exception_flag(vm_mngr_t* vm_mngr) +{ + return vm_mngr->exception_flags; +} |