diff --git a/src/codegen_timing_p6.c b/src/codegen_timing_p6.c index 1b4d53d..a608164 100644 --- a/src/codegen_timing_p6.c +++ b/src/codegen_timing_p6.c @@ -19,7 +19,8 @@ typedef enum uop_type_t UOP_LOAD, /*Executes in port 2 Load unit*/ UOP_STOREADDR, /*Executes in port 3 Store Address unit*/ UOP_STOREDATA, /*Executes in port 4 Store Data unit*/ - UOP_FLOAT /*Executes in port 0 Floating Point unit*/ + UOP_FLOAT, /*Executes in port 0 Floating Point unit*/ + UOP_ALU0_SEG /*Executes in port 0 ALU, loads segment, causing pipeline flush on PPro*/ } uop_type_t; #define MAX_UOPS 300 @@ -512,7 +513,7 @@ static const p6_instruction_t call_far_op = .uop[2] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, .uop[3] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, .uop[4] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[5] = {.type = UOP_ALU0, .throughput = 28, .latency = 28} + .uop[5] = {.type = UOP_ALU0_SEG, .throughput = 28, .latency = 28} }; static const p6_instruction_t load_call_far_op = { @@ -523,7 +524,7 @@ static const p6_instruction_t load_call_far_op = .uop[3] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, .uop[4] = {.type = UOP_STOREADDR, .throughput = 1, .latency = 1}, .uop[5] = {.type = UOP_STOREDATA, .throughput = 1, .latency = 1}, - .uop[6] = {.type = UOP_ALU0, .throughput = 28, .latency = 28} + .uop[6] = {.type = UOP_ALU0_SEG, .throughput = 28, .latency = 28} }; static const p6_instruction_t cli_op = { @@ -676,15 +677,15 @@ static const p6_instruction_t invd_op = static const p6_instruction_t jmp_far_op = { .nr_uops = 2, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU0, .throughput = 21, .latency = 21} + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_ALU0_SEG, .throughput = 21, .latency = 21} }; static const p6_instruction_t load_jmp_far_op = { .nr_uops = 3, - .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[2] = {.type = UOP_ALU0, .throughput = 21, .latency = 21} + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[2] = {.type = UOP_ALU0_SEG, .throughput = 21, .latency = 21} }; static const p6_instruction_t lss_op = { @@ -692,7 +693,7 @@ static const p6_instruction_t lss_op = .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, .uop[1] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, .uop[2] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[3] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, + .uop[3] = {.type = UOP_ALU0_SEG,.throughput = 1, .latency = 1}, .uop[4] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, .uop[5] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, .uop[6] = {.type = UOP_ALU01, .throughput = 1, .latency = 1}, @@ -712,7 +713,7 @@ static const p6_instruction_t mov_seg_mem_op = { .nr_uops = 9, .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_ALU0_SEG,.throughput = 1, .latency = 1}, .uop[2] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, .uop[3] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, .uop[4] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, @@ -725,7 +726,7 @@ static const p6_instruction_t mov_seg_reg_op = { .nr_uops = 8, .uop[0] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, - .uop[1] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, + .uop[1] = {.type = UOP_ALU0_SEG,.throughput = 1, .latency = 1}, .uop[2] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, .uop[3] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, .uop[4] = {.type = UOP_ALU0, .throughput = 1, .latency = 1}, @@ -1593,11 +1594,11 @@ static const p6_port_t ports[] = {UNIT_STORE_ADDR}, {UNIT_STORE_DATA} }; - +const int nr_ports = (sizeof(ports) / sizeof(p6_port_t)); static p6_unit_t units[] = { - [UNIT_INT0] = {.uop_mask = (1 << UOP_ALU0) | (1 << UOP_ALU01), .port = 0}, /*Integer 0*/ + [UNIT_INT0] = {.uop_mask = (1 << UOP_ALU0) | (1 << UOP_ALU0_SEG) | (1 << UOP_ALU01), .port = 0}, /*Integer 0*/ [UNIT_INT1] = {.uop_mask = (1 << UOP_ALU1) | (1 << UOP_ALU01), .port = 1}, /*Integer 1*/ [UNIT_FPU] = {.uop_mask = 1 << UOP_FLOAT, .port = 0}, [UNIT_MMX_ADD] = {.uop_mask = 0, .port = 1}, @@ -1654,6 +1655,24 @@ static int uop_run(const p6_uop_t *uop, int decode_time) if (!best_unit) fatal("uop_run: can not find execution unit %x\n", uop->type); + if (cpu_s->cpu_type == CPU_PENTIUMPRO && uop->type == UOP_ALU0_SEG) + { + /*Pentium Pro will flush pipeline on a segment load. Find last + execution unit to complete, then set earliest start times on + _all_ execution units to after this point*/ + int last_start_cycle = 0; + + for (c = 0; c < nr_units; c++) + { + p6_unit_t *unit = &units[c]; + int start_cycle = unit->first_available_cycle; + + if (start_cycle > last_start_cycle) + last_start_cycle = start_cycle; + } + for (c = 0; c < nr_units; c++) + units[c].first_available_cycle = last_start_cycle+1; + } if (best_start_cycle < decode_time) best_start_cycle = decode_time; best_unit->first_available_cycle = best_start_cycle + uop->throughput; diff --git a/src/cpu.c b/src/cpu.c index 0c4487d..ce1dbc0 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -177,10 +177,10 @@ int fpu_get_type_from_index(int model, int manu, int cpu, int c) return fpus[c].type; } +CPU *cpu_s; + void cpu_set() { - CPU *cpu_s; - if (!models[model].cpu[cpu_manufacturer].cpus) { /*CPU is invalid, set to default*/ diff --git a/src/cpu.h b/src/cpu.h index ca8f4da..ee54925 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -102,6 +102,8 @@ typedef struct int atclk_div; } CPU; +extern CPU *cpu_s; + extern CPU cpus_8088[]; extern CPU cpus_8086[]; extern CPU cpus_286[];