diff options
| author | Theofilos Augoustis <theofilos.augoustis@gmail.com> | 2025-10-14 09:09:29 +0000 |
|---|---|---|
| committer | Theofilos Augoustis <theofilos.augoustis@gmail.com> | 2025-10-14 09:09:29 +0000 |
| commit | 579cf1d03fb932083e6317967d1613d5c2587fb6 (patch) | |
| tree | 629f039935382a2a7391bce9253f6c9968159049 /src/miasm/jitter/op_semantics.c | |
| parent | 51c15d3ea2e16d4fc5f0f01a3b9befc66b1f982e (diff) | |
| download | focaccia-miasm-579cf1d03fb932083e6317967d1613d5c2587fb6.tar.gz focaccia-miasm-579cf1d03fb932083e6317967d1613d5c2587fb6.zip | |
Convert to src-layout ta/nix
Diffstat (limited to 'src/miasm/jitter/op_semantics.c')
| -rw-r--r-- | src/miasm/jitter/op_semantics.c | 853 |
1 files changed, 853 insertions, 0 deletions
diff --git a/src/miasm/jitter/op_semantics.c b/src/miasm/jitter/op_semantics.c new file mode 100644 index 00000000..6725ae64 --- /dev/null +++ b/src/miasm/jitter/op_semantics.c @@ -0,0 +1,853 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <inttypes.h> +#include <math.h> +#include "op_semantics.h" + +const uint8_t parity_table[256] = { + CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, + 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, + 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, + CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, + 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, + CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, + CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, + 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, + 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, + CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, + CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, + 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, + CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, + 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, + 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, + CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, + 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, + CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, + CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, + 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, + CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, + 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, + 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, + CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, + CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, + 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, + 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, + CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, + 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, + CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, + CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, + 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, +}; + +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; +} + +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; +} + +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(EXIT_FAILURE); + } + + 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(EXIT_FAILURE); + } + + 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 (int)(res>>8); +} + +int imul_hi_op_16(short a, short b) +{ + int64_t res = 0; + res = a*b; + return (int)(res>>16); +} + +int imul_hi_op_32(int a, int b) +{ + int64_t res = 0; + res = (int64_t)a*(int64_t)b; + return (int)(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; +} + +uint64_t rot_left(uint64_t size, uint64_t a, uint64_t b) +{ + uint64_t tmp; + + b = b & 0x3F; + 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; + case 64: + tmp = (a << b) | ((a&0xFFFFFFFFFFFFFFFF) >> (size - b)); + return tmp & 0xFFFFFFFFFFFFFFFF; + + /* Support cases for rcl */ + case 9: + tmp = (a << b) | ((a & 0x1FF) >> (size - b)); + return tmp & 0x1FF; + case 17: + tmp = (a << b) | ((a & 0x1FFFF) >> (size - b)); + return tmp & 0x1FFFF; + case 33: + tmp = (a << b) | ((a & 0x1FFFFFFFF) >> (size - b)); + return tmp & 0x1FFFFFFFF; + /* TODO XXX: support rcl in 64 bit mode */ + + default: + fprintf(stderr, "inv size in rotleft %"PRIX64"\n", size); + exit(EXIT_FAILURE); + } +} + +uint64_t rot_right(uint64_t size, uint64_t a, uint64_t b) +{ + uint64_t tmp; + + b = b & 0x3F; + 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; + case 64: + tmp = ((a & 0xFFFFFFFFFFFFFFFF) >> b) | (a << (size - b)); + return tmp & 0xFFFFFFFFFFFFFFFF; + + /* Support cases for rcr */ + case 9: + tmp = ((a & 0x1FF) >> b) | (a << (size - b)); + return tmp & 0x1FF; + case 17: + tmp = ((a & 0x1FFFF) >> b) | (a << (size - b)); + return tmp & 0x1FFFF; + case 33: + tmp = ((a & 0x1FFFFFFFF) >> b) | (a << (size - b)); + return tmp & 0x1FFFFFFFF; + /* TODO XXX: support rcr in 64 bit mode */ + + default: + fprintf(stderr, "inv size in rotright %"PRIX64"\n", size); + exit(EXIT_FAILURE); + } +} + +/* + * Count leading zeros - count the number of zero starting at the most + * significant bit + * + * Example: + * - cntleadzeros(size=32, src=2): 30 + * - cntleadzeros(size=32, src=0): 32 + */ +uint64_t cntleadzeros(uint64_t size, uint64_t src) +{ + int64_t i; + + for (i=(int64_t)size-1; i>=0; i--){ + if (src & (1ull << i)) + return (uint64_t)(size - (i + 1)); + } + return (uint64_t)size; +} + +/* + * Count trailing zeros - count the number of zero starting at the least + * significant bit + * + * Example: + * - cnttrailzeros(size=32, src=2): 1 + * - cnttrailzeros(size=32, src=0): 32 + */ +unsigned int cnttrailzeros(uint64_t size, uint64_t src) +{ + uint64_t i; + for (i=0; i<size; i++){ + if (src & (1ull << i)) + return (unsigned int)i; + } + return (unsigned int)size; +} + + +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 x86_cpuid(unsigned int a, unsigned int reg_num) +{ + if (reg_num >3){ + fprintf(stderr, "not implemented x86_cpuid reg %x\n", reg_num); + exit(EXIT_FAILURE); + } + // cases are output: EAX: 0; EBX: 1; ECX: 2; EDX: 3 + if (a == 0){ + switch(reg_num){ + case 0: + return 0xa; + // "GenuineIntel" + case 1: + return 0x756E6547; + case 2: + return 0x6C65746E; + case 3: + return 0x49656E69; + } + } + + else if (a == 1){ + switch(reg_num){ + case 0: + // Using a version too high will enable recent + // instruction set + return 0x000006FB; + //return 0x00020652; + case 1: + //return 0x02040800; + return 0x00000800; + case 2: + //return 0x0004E3BD; + return 0x00000209; + case 3: + return (/* fpu */ 1 << 0) | + (/* tsc */ 1 << 4) | + (/* cx8 */ 1 << 8) | + (/* cmov */ 1 << 15) | + (/* mmx */ 1 << 23) | + (/* sse */ 1 << 25) | + (/* sse2 */ 1 << 26) | + (/* ia64 */ 1 << 30); + } + } + // Cache and TLB + else if (a == 2){ + switch(reg_num){ + case 0: + return 0x00000000; + case 1: + return 0x00000000; + case 2: + return 0x00000000; + case 3: + return 0x00000000; + } + } + // Intel thread/core and cache topology + else if (a == 4){ + switch(reg_num){ + case 0: + return 0x00000000; + case 1: + return 0x00000000; + case 2: + return 0x00000000; + case 3: + return 0x00000000; + } + } + // Extended features + else if (a == 7){ + switch(reg_num){ + case 0: + return 0x00000000; + case 1: + return (/* fsgsbase */ 1 << 0) | (/* bmi1 */ 1 << 3); + case 2: + return 0x00000000; + case 3: + return 0x00000000; + } + } + // Extended Function CPUID Information + else if (a == 0x80000000){ + switch(reg_num){ + case 0: + // Pentium 4 Processor supporting Hyper-Threading + // Technology to Intel Xeon Processor 5100 Series + return 0x80000008; + case 1: + return 0x00000000; + case 2: + return 0x00000000; + case 3: + return 0x00000000; + } + } + else if (a == 0x80000001){ + switch(reg_num){ + case 0: + // Extended Processor Signature and Extended Feature + // Bits + return 0x00000000; + case 1: + return 0x00000000; + case 2: + return (/* LAHF-SAHF */ 1 << 0) + | (/* LZCNT */ 0 << 5) + | (/* PREFETCHW */ 1 << 8); + case 3: + return (/* SYSCALL/SYSRET */ 1 << 11) + | (/* Execute Disable Bit available */ 0 << 20) + | (/* 1-GByte pages available */ 0 << 26) + | (/* RDTSCP and IA32_TSC_AUX available */ 0 << 27) + | (/* Intel ® 64 Architecture available */ 1 << 29); + } + } + else{ + fprintf(stderr, "WARNING not implemented x86_cpuid index %X!\n", a); + exit(EXIT_FAILURE); + } + 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); + */ +} + +typedef union { + uint32_t u32; + float flt; +} float_uint32_t; + + +typedef union { + uint64_t u64; + double dbl; +} double_uint64_t; + + +uint32_t fpu_fadd32(uint32_t a, uint32_t b) +{ + float_uint32_t a_cast, b_cast, c_cast; + + a_cast.u32 = a; + b_cast.u32 = b; + + c_cast.flt = a_cast.flt + b_cast.flt; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e + %e -> %e\n", a, b, c_cast.flt); +#endif + return c_cast.u32; +} + +uint64_t fpu_fadd64(uint64_t a, uint64_t b) +{ + double_uint64_t a_cast, b_cast, c_cast; + + a_cast.u64 = a; + b_cast.u64 = b; + + c_cast.dbl = a_cast.dbl + b_cast.dbl; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e + %e -> %e\n", a, b, c_cast.dbl); +#endif + return c_cast.u64; +} + +uint32_t fpu_fsub32(uint32_t a, uint32_t b) +{ + float_uint32_t a_cast, b_cast, c_cast; + + a_cast.u32 = a; + b_cast.u32 = b; + + c_cast.flt = a_cast.flt - b_cast.flt; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e + %e -> %e\n", a, b, c_cast.flt); +#endif + return c_cast.u32; +} + +uint64_t fpu_fsub64(uint64_t a, uint64_t b) +{ + double_uint64_t a_cast, b_cast, c_cast; + + a_cast.u64 = a; + b_cast.u64 = b; + + c_cast.dbl = a_cast.dbl - b_cast.dbl; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e + %e -> %e\n", a, b, c_cast.dbl); +#endif + return c_cast.u64; +} + +uint32_t fpu_fmul32(uint32_t a, uint32_t b) +{ + float_uint32_t a_cast, b_cast, c_cast; + + a_cast.u32 = a; + b_cast.u32 = b; + + c_cast.flt = a_cast.flt * b_cast.flt; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e * %e -> %e\n", a, b, c_cast.flt); +#endif + return c_cast.u32; +} + +uint64_t fpu_fmul64(uint64_t a, uint64_t b) +{ + double_uint64_t a_cast, b_cast, c_cast; + + a_cast.u64 = a; + b_cast.u64 = b; + + c_cast.dbl = a_cast.dbl * b_cast.dbl; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e * %e -> %e\n", a, b, c_cast.dbl); +#endif + return c_cast.u64; +} + +uint32_t fpu_fdiv32(uint32_t a, uint32_t b) +{ + float_uint32_t a_cast, b_cast, c_cast; + + a_cast.u32 = a; + b_cast.u32 = b; + + c_cast.flt = a_cast.flt / b_cast.flt; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e * %e -> %e\n", a, b, c_cast.flt); +#endif + return c_cast.u32; +} + +uint64_t fpu_fdiv64(uint64_t a, uint64_t b) +{ + double_uint64_t a_cast, b_cast, c_cast; + + a_cast.u64 = a; + b_cast.u64 = b; + + c_cast.dbl = a_cast.dbl / b_cast.dbl; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e * %e -> %e\n", a, b, c_cast.dbl); +#endif + return c_cast.u64; +} + +double fpu_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 fpu_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 fpu_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 fpu_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 fpu_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 fpu_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; +} + +uint32_t fpu_fsqrt32(uint32_t a) +{ + float_uint32_t a_cast; + a_cast.u32 = a; + a_cast.flt = sqrtf(a_cast.flt); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e sqrt %e\n", a, a_cast.flt); +#endif + return a_cast.u32; +} + +uint64_t fpu_fsqrt64(uint64_t a) +{ + double_uint64_t a_cast; + + a_cast.u64 = a; + a_cast.dbl = sqrt(a_cast.dbl); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e sqrt %e\n", a, a_cast.dbl); +#endif + return a_cast.u64; +} + +uint64_t fpu_fabs64(uint64_t a) +{ + double_uint64_t a_cast; + + a_cast.u64 = a; + a_cast.dbl = fabs(a_cast.dbl); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e abs %e\n", a, a_cast.dbl); +#endif + return a_cast.u64; +} + +uint64_t fpu_fprem64(uint64_t a, uint64_t b) +{ + double_uint64_t a_cast, b_cast, c_cast; + + a_cast.u64 = a; + b_cast.u64 = b; + + c_cast.dbl = fmod(a_cast.dbl, b_cast.dbl); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e %% %e -> %e\n", a, b, c); +#endif + return c_cast.u64; +} + +double fpu_fchs(double a) +{ + double b; + b = -a; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf(" - %e -> %e\n", a, b); +#endif + return b; +} + +double fpu_fyl2x(double a, double b) +{ + double c; + c = b * (log(a) / log(2)); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e * log(%e) -> %e\n", b, a, c); +#endif + return c; +} + +double fpu_fpatan(double a, double b) +{ + double c; + c = atan2(b, a); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("arctan(%e / %e) -> %e\n", b, a, c); +#endif + return c; +} + +unsigned int fpu_fcom_c0(double a, double b) +{ + if (isnan(a) || isnan(b)) + return 1; + if (a>=b) + return 0; + return 1; +} +unsigned int fpu_fcom_c1(double a, double b) +{ + //XXX + return 0; +} +unsigned int fpu_fcom_c2(double a, double b) +{ + if (isnan(a) || isnan(b)) + return 1; + return 0; +} +unsigned int fpu_fcom_c3(double a, double b) +{ + if (isnan(a) || isnan(b)) + return 1; + if (a==b) + return 1; + return 0; +} + +uint64_t sint_to_fp_64(int64_t a) +{ + double_uint64_t a_cast; + a_cast.dbl = (double) a; + return a_cast.u64; +} + +uint32_t sint_to_fp_32(int32_t a) +{ + float_uint32_t a_cast; + a_cast.flt = (float) a; + return a_cast.u32; +} + +int32_t fp32_to_sint32(uint32_t a) +{ + // Enforce nearbyint (IEEE-754 behavior) + float rounded; + float_uint32_t a_cast; + a_cast.u32 = a; + rounded = nearbyintf(a_cast.flt); + return (int32_t) rounded; +} + +int64_t fp64_to_sint64(uint64_t a) +{ + // Enforce nearbyint (IEEE-754 behavior) + double rounded; + double_uint64_t a_cast; + a_cast.u64 = a; + rounded = nearbyint(a_cast.dbl); + return (int64_t) rounded; +} + +int32_t fp64_to_sint32(uint64_t a) +{ + // Enforce nearbyint (IEEE-754 behavior) + double rounded; + double_uint64_t a_cast; + a_cast.u64 = a; + rounded = nearbyint(a_cast.dbl); + return (int32_t) rounded; +} + +uint32_t fp64_to_fp32(uint64_t a) +{ + float_uint32_t a_cast32; + double_uint64_t a_cast64; + a_cast64.u64 = a; + a_cast32.flt = (float)a_cast64.dbl; + return a_cast32.u32; +} + +uint64_t fp32_to_fp64(uint32_t a) +{ + float_uint32_t a_cast32; + double_uint64_t a_cast64; + a_cast32.u32 = a; + a_cast64.dbl = (double)a_cast32.flt; + return a_cast64.u64; +} + +uint32_t fpround_towardszero_fp32(uint32_t a) +{ + float_uint32_t a_cast; + a_cast.u32 = a; + a_cast.flt = truncf(a_cast.flt); + return a_cast.u32; +} + +uint64_t fpround_towardszero_fp64(uint64_t a) +{ + double_uint64_t a_cast; + a_cast.u64 = a; + a_cast.dbl = trunc(a_cast.dbl); + return a_cast.u64; +} + + +UDIV(8) +UDIV(16) +UDIV(32) +UDIV(64) + +UMOD(8) +UMOD(16) +UMOD(32) +UMOD(64) + +SDIV(8) +SDIV(16) +SDIV(32) +SDIV(64) + +SMOD(8) +SMOD(16) +SMOD(32) +SMOD(64) |