X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=deps%2Flightrec%2Foptimizer.c;h=8ee66ad07e20a810150aa80c798be13739b852b6;hb=0b8caa417c2bef660d6a0c70cbab71f1e997023b;hp=7304abca4f3f312da469feb2dd55faecfeaf8db7;hpb=065ff7f4ff24dbad02bce5ba407c0dad66bf5acb;p=pcsx_rearmed.git diff --git a/deps/lightrec/optimizer.c b/deps/lightrec/optimizer.c index 7304abca..8ee66ad0 100644 --- a/deps/lightrec/optimizer.c +++ b/deps/lightrec/optimizer.c @@ -817,6 +817,66 @@ static void lightrec_optimize_sll_sra(struct opcode *list, unsigned int offset) to_nop->opcode = 0; } +static void lightrec_remove_useless_lui(struct block *block, unsigned int offset, + u32 known, u32 *values) +{ + struct opcode *list = block->opcode_list, + *op = &block->opcode_list[offset]; + int reader; + + if (!(op->flags & LIGHTREC_SYNC) && (known & BIT(op->i.rt)) && + values[op->i.rt] == op->i.imm << 16) { + pr_debug("Converting duplicated LUI to NOP\n"); + op->opcode = 0x0; + return; + } + + if (op->i.imm != 0 || op->i.rt == 0) + return; + + reader = find_next_reader(list, offset + 1, op->i.rt); + if (reader <= 0) + return; + + if (opcode_writes_register(list[reader].c, op->i.rt) || + reg_is_dead(list, reader, op->i.rt)) { + pr_debug("Removing useless LUI 0x0\n"); + + if (list[reader].i.rs == op->i.rt) + list[reader].i.rs = 0; + if (list[reader].i.op == OP_SPECIAL && + list[reader].i.rt == op->i.rt) + list[reader].i.rt = 0; + op->opcode = 0x0; + } +} + +static void lightrec_modify_lui(struct block *block, unsigned int offset) +{ + union code c, *lui = &block->opcode_list[offset].c; + bool stop = false, stop_next = false; + unsigned int i; + + for (i = offset + 1; !stop && i < block->nb_ops; i++) { + c = block->opcode_list[i].c; + stop = stop_next; + + if ((opcode_is_store(c) && c.i.rt == lui->i.rt) + || (!opcode_is_load(c) && opcode_reads_register(c, lui->i.rt))) + break; + + if (opcode_writes_register(c, lui->i.rt)) { + pr_debug("Convert LUI at offset 0x%x to kuseg\n", + i - 1 << 2); + lui->i.imm = kunseg(lui->i.imm << 16) >> 16; + break; + } + + if (has_delay_slot(c)) + stop_next = true; + } +} + static int lightrec_transform_ops(struct lightrec_state *state, struct block *block) { struct opcode *list = block->opcode_list; @@ -824,7 +884,6 @@ static int lightrec_transform_ops(struct lightrec_state *state, struct block *bl u32 known = BIT(0); u32 values[32] = { 0 }; unsigned int i; - int reader; for (i = 0; i < block->nb_ops; i++) { prev = op; @@ -863,30 +922,9 @@ static int lightrec_transform_ops(struct lightrec_state *state, struct block *bl break; case OP_LUI: - if (!(op->flags & LIGHTREC_SYNC) && - (known & BIT(op->i.rt)) && - values[op->i.rt] == op->i.imm << 16) { - pr_debug("Converting duplicated LUI to NOP\n"); - op->opcode = 0x0; - } - - if (op->i.imm != 0 || op->i.rt == 0) - break; - - reader = find_next_reader(list, i + 1, op->i.rt); - if (reader > 0 && - (opcode_writes_register(list[reader].c, op->i.rt) || - reg_is_dead(list, reader, op->i.rt))) { - - pr_debug("Removing useless LUI 0x0\n"); - - if (list[reader].i.rs == op->i.rt) - list[reader].i.rs = 0; - if (list[reader].i.op == OP_SPECIAL && - list[reader].i.rt == op->i.rt) - list[reader].i.rt = 0; - op->opcode = 0x0; - } + if (!prev || !has_delay_slot(prev->c)) + lightrec_modify_lui(block, i); + lightrec_remove_useless_lui(block, i, known, values); break; /* Transform ORI/ADDI/ADDIU with imm #0 or ORR/ADD/ADDU/SUB/SUBU @@ -928,16 +966,19 @@ static int lightrec_transform_ops(struct lightrec_state *state, struct block *bl op->i.op = OP_META_MOV; op->r.rs = op->r.rt; } - case OP_SPECIAL_SUB: /* fall-through */ + fallthrough; + case OP_SPECIAL_SUB: case OP_SPECIAL_SUBU: if (op->r.rt == 0) { pr_debug("Convert OR/ADD/SUB $zero to MOV\n"); op->i.op = OP_META_MOV; } - default: /* fall-through */ + fallthrough; + default: break; } - default: /* fall-through */ + fallthrough; + default: break; } } @@ -978,13 +1019,16 @@ static int lightrec_switch_delay_slots(struct lightrec_state *state, struct bloc if (opcode_reads_register(next_op, op.r.rd) || opcode_writes_register(next_op, op.r.rd)) continue; - case OP_SPECIAL_JR: /* fall-through */ + fallthrough; + case OP_SPECIAL_JR: if (opcode_writes_register(next_op, op.r.rs)) continue; - default: /* fall-through */ + fallthrough; + default: break; } - case OP_J: /* fall-through */ + fallthrough; + case OP_J: break; case OP_JAL: if (opcode_reads_register(next_op, 31) || @@ -996,7 +1040,8 @@ static int lightrec_switch_delay_slots(struct lightrec_state *state, struct bloc case OP_BNE: if (op.i.rt && opcode_writes_register(next_op, op.i.rt)) continue; - case OP_BLEZ: /* fall-through */ + fallthrough; + case OP_BLEZ: case OP_BGTZ: if (op.i.rs && opcode_writes_register(next_op, op.i.rs)) continue; @@ -1008,14 +1053,16 @@ static int lightrec_switch_delay_slots(struct lightrec_state *state, struct bloc if (opcode_reads_register(next_op, 31) || opcode_writes_register(next_op, 31)) continue; - case OP_REGIMM_BLTZ: /* fall-through */ + fallthrough; + case OP_REGIMM_BLTZ: case OP_REGIMM_BGEZ: if (op.i.rs && opcode_writes_register(next_op, op.i.rs)) continue; break; } - default: /* fall-through */ + fallthrough; + default: break; } @@ -1126,7 +1173,8 @@ static int lightrec_local_branches(struct lightrec_state *state, struct block *b offset = i + 1 + (s16)list->i.imm; if (offset >= 0 && offset < block->nb_ops) break; - default: /* fall-through */ + fallthrough; + default: continue; } @@ -1233,15 +1281,14 @@ static int lightrec_early_unload(struct lightrec_state *state, struct block *blo static int lightrec_flag_io(struct lightrec_state *state, struct block *block) { - const struct lightrec_mem_map *map; - struct opcode *prev2, *prev = NULL, *list = NULL; + struct opcode *prev = NULL, *list = NULL; + enum psx_map psx_map; u32 known = BIT(0); u32 values[32] = { 0 }; unsigned int i; - u32 val; + u32 val, kunseg_val; for (i = 0; i < block->nb_ops; i++) { - prev2 = prev; prev = list; list = &block->opcode_list[i]; @@ -1277,7 +1324,8 @@ static int lightrec_flag_io(struct lightrec_state *state, struct block *block) list->flags |= LIGHTREC_SMC; } } - case OP_SWL: /* fall-through */ + fallthrough; + case OP_SWL: case OP_SWR: case OP_SWC2: case OP_LB: @@ -1289,45 +1337,42 @@ static int lightrec_flag_io(struct lightrec_state *state, struct block *block) case OP_LWR: case OP_LWC2: if (OPT_FLAG_IO && (known & BIT(list->i.rs))) { - if (prev && prev->i.op == OP_LUI && - !(prev2 && has_delay_slot(prev2->c)) && - prev->i.rt == list->i.rs && - list->i.rt == list->i.rs && - prev->i.imm & 0x8000) { - pr_debug("Convert LUI at offset 0x%x to kuseg\n", - i - 1 << 2); - - val = kunseg(prev->i.imm << 16); - prev->i.imm = val >> 16; - values[list->i.rs] = val; - } - val = values[list->i.rs] + (s16) list->i.imm; - map = lightrec_get_map(state, NULL, kunseg(val)); - - if (!map || map->ops || - map == &state->maps[PSX_MAP_PARALLEL_PORT]) { - pr_debug("Flagging opcode %u as I/O access\n", - i); - list->flags |= LIGHTREC_IO_MODE(LIGHTREC_IO_HW); - break; - } - - if (val - map->pc < map->length) - list->flags |= LIGHTREC_NO_MASK; - - if (map == &state->maps[PSX_MAP_KERNEL_USER_RAM]) { + kunseg_val = kunseg(val); + psx_map = lightrec_get_map_idx(state, kunseg_val); + + switch (psx_map) { + case PSX_MAP_KERNEL_USER_RAM: + if (val == kunseg_val) + list->flags |= LIGHTREC_NO_MASK; + fallthrough; + case PSX_MAP_MIRROR1: + case PSX_MAP_MIRROR2: + case PSX_MAP_MIRROR3: pr_debug("Flaging opcode %u as RAM access\n", i); list->flags |= LIGHTREC_IO_MODE(LIGHTREC_IO_RAM); - } else if (map == &state->maps[PSX_MAP_BIOS]) { + break; + case PSX_MAP_BIOS: pr_debug("Flaging opcode %u as BIOS access\n", i); list->flags |= LIGHTREC_IO_MODE(LIGHTREC_IO_BIOS); - } else if (map == &state->maps[PSX_MAP_SCRATCH_PAD]) { + break; + case PSX_MAP_SCRATCH_PAD: pr_debug("Flaging opcode %u as scratchpad access\n", i); list->flags |= LIGHTREC_IO_MODE(LIGHTREC_IO_SCRATCH); + + /* Consider that we're never going to run code from + * the scratchpad. */ + list->flags |= LIGHTREC_NO_INVALIDATE; + break; + default: + pr_debug("Flagging opcode %u as I/O access\n", + i); + list->flags |= LIGHTREC_IO_MODE(LIGHTREC_IO_HW); + break; } } - default: /* fall-through */ + fallthrough; + default: break; } } @@ -1447,7 +1492,7 @@ static u8 get_mfhi_mflo_reg(const struct block *block, u16 offset, break; } - /* fall-through */ + fallthrough; default: continue; } @@ -1498,7 +1543,7 @@ static void lightrec_replace_lo_hi(struct block *block, u16 offset, return; } - /* fall-through */ + fallthrough; default: break; } @@ -1540,7 +1585,8 @@ static int lightrec_flag_mults_divs(struct lightrec_state *state, struct block * if (lightrec_always_skip_div_check() || (known & BIT(list->c.r.rt) && values[list->c.r.rt])) list->flags |= LIGHTREC_NO_DIV_CHECK; - case OP_SPECIAL_MULT: /* fall-through */ + fallthrough; + case OP_SPECIAL_MULT: case OP_SPECIAL_MULTU: break; default: