diff --git a/src/codegen_timing_common.c b/src/codegen_timing_common.c index 33ac5cf..c29f24f 100644 --- a/src/codegen_timing_common.c +++ b/src/codegen_timing_common.c @@ -823,21 +823,21 @@ uint64_t opcode_deps_df_mod3[8] = uint64_t opcode_deps_81[8] = { - MODRM, MODRM, MODRM, MODRM, - MODRM, MODRM, MODRM, MODRM + MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, + MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632, MODRM | HAS_IMM1632 }; uint64_t opcode_deps_81_mod3[8] = { - SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, - SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | MODRM + SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, + SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM1632, SRCDEP_RM | MODRM | HAS_IMM1632 }; uint64_t opcode_deps_8x[8] = { - MODRM, MODRM, MODRM, MODRM, - MODRM, MODRM, MODRM, MODRM + MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8, + MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8, MODRM | HAS_IMM8 }; uint64_t opcode_deps_8x_mod3[8] = { - SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, - SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | DSTDEP_RM | MODRM, SRCDEP_RM | MODRM + SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, + SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | DSTDEP_RM | MODRM | HAS_IMM8, SRCDEP_RM | MODRM | HAS_IMM8 }; diff --git a/src/codegen_timing_common.h b/src/codegen_timing_common.h index b185270..533a135 100644 --- a/src/codegen_timing_common.h +++ b/src/codegen_timing_common.h @@ -72,6 +72,9 @@ #define FPU_FXCH (1ull << 33) +#define HAS_IMM8 (1ull << 34) +#define HAS_IMM1632 (1ull << 35) + #define REGMASK_IMPL_ESP (1 << 8) #define REGMASK_SHIFTPACK (1 << 9) diff --git a/src/codegen_timing_k6.c b/src/codegen_timing_k6.c index 78d9678..590e605 100644 --- a/src/codegen_timing_k6.c +++ b/src/codegen_timing_k6.c @@ -1723,6 +1723,7 @@ static const risc86_instruction_t *opcode_timings_df_mod3[8] = static uint8_t last_prefix; +static int prefixes; static int decode_timestamp; static int last_complete_timestamp; @@ -1899,12 +1900,64 @@ void decode_flush() decode_buffer.nr_uops = 0; } +/*The instruction is only of interest here if it's longer than 7 bytes, as that's the + limit on K6 short decoding*/ +static int codegen_timing_instr_length(uint64_t deps, uint32_t fetchdat, int op_32) +{ + int len = prefixes + 1; /*Opcode*/ + if (deps & MODRM) + { + len++; /*ModR/M*/ + if (deps & HAS_IMM8) + len++; + if (deps & HAS_IMM1632) + len += (op_32 & 0x100) ? 4 : 2; + + if (op_32 & 0x200) + { + if ((fetchdat & 7) == 4 && (fetchdat & 0xc0) != 0xc0) + { + /* Has SIB*/ + len++; + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 4; + else if ((fetchdat & 0x700) == 0x500) + len += 4; + } + else + { + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 4; + else if ((fetchdat & 0xc7) == 0x05) + len += 4; + } + } + else + { + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 2; + else if ((fetchdat & 0xc7) == 0x06) + len += 2; + } + } + + return len; +} + static void decode_instruction(const risc86_instruction_t *ins, uint64_t deps, uint32_t fetchdat, int op_32, int bit8) { uint32_t regmask_required; uint32_t regmask_modified; int c, d; int earliest_start = 0; + decode_type_t decode_type = ins->decode_type; + int instr_length = codegen_timing_instr_length(deps, fetchdat, op_32); /*Generate input register mask, and determine the earliest time this instruction can start. This is not accurate, as this is calculated per @@ -1931,7 +1984,14 @@ static void decode_instruction(const risc86_instruction_t *ins, uint64_t deps, u earliest_start = fpu_st_timestamp[reg]; } - switch (ins->decode_type) + /*Short decoders are limited to 7 bytes*/ + if (decode_type == DECODE_SHORT && instr_length > 7) + decode_type = DECODE_LONG; + /*Long decoder is limited to 11 bytes*/ + else if (instr_length > 11) + decode_type = DECODE_VECTOR; + + switch (decode_type) { case DECODE_SHORT: if (decode_buffer.nr_uops) @@ -2051,7 +2111,7 @@ static void decode_instruction(const risc86_instruction_t *ins, uint64_t deps, u void codegen_timing_k6_block_start() { int c; - + for (c = 0; c < nr_units; c++) units[c].first_available_cycle = 0; @@ -2085,6 +2145,7 @@ void codegen_timing_k6_start() nr_units = NR_K6_2_UNITS; } last_prefix = 0; + prefixes = 0; } void codegen_timing_k6_prefix(uint8_t prefix, uint32_t fetchdat) @@ -2093,6 +2154,7 @@ void codegen_timing_k6_prefix(uint8_t prefix, uint32_t fetchdat) decode_timestamp++; last_prefix = prefix; + prefixes++; } void codegen_timing_k6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc)