diff options
-rw-r--r-- | ir3emu.c | 67 |
1 files changed, 37 insertions, 30 deletions
@@ -767,6 +767,10 @@ emu_run(struct ir3_emu_ctx *ctx) while ((ctx->pc < ctx->instrs_count) && !ctx->error) { instr_t *instr = &ctx->instrs[ctx->pc++]; + unsigned i, repeat = 0; + + if (instr->opc_cat <= 4) + repeat = instr->repeat; if (last_instr) { emu_check(ctx, !(is_sfu(last_instr) && is_sfu(instr)), @@ -776,41 +780,44 @@ emu_run(struct ir3_emu_ctx *ctx) emu_check(ctx, instr->sync, "needs (sy) on first instruction"); } - // XXX not sure if we need to keep different cycle counters for - // XXX tex/alu/sfu, or just tex vs alu/sfu?? - if (!is_tex(instr)) + // XXX this isn't completely right, since it ignores + // incrementing dst register and src registers w/ (r) + // flag.. but right now compiler only emit's repeated + // nops.. + for (i = 0; i <= repeat; i++) { ctx->cycle++; - ctx->cur = instr; + ctx->cur = instr; - if (is_input(instr)) { - if (ctx->last_input) { - emu_check(ctx, !ctx->last_input->cat2.ei, - "(ei) set before last input"); + if (is_input(instr)) { + if (ctx->last_input) { + emu_check(ctx, !ctx->last_input->cat2.ei, + "(ei) set before last input"); + } + ctx->last_input = instr; } - ctx->last_input = instr; - } - if ((1 <= instr->opc_cat) && (instr->opc_cat <= 4)) - if (instr->ss) - ctx->last_ss = ctx->cycle; - if (instr->sync) - ctx->last_sy = ctx->cycle; - - /* special handling for 'end' instruction: */ - if ((instr->opc_cat == 0) && (instr->cat0.opc == OPC_END)) - return; - - switch (instr->opc_cat) { - case 0: emu_run_cat0(ctx, &instr->cat0); break; - case 1: emu_run_cat1(ctx, &instr->cat1); break; - case 2: emu_run_cat2(ctx, &instr->cat2); break; - case 3: emu_run_cat3(ctx, &instr->cat3); break; - case 4: emu_run_cat4(ctx, &instr->cat4); break; - case 5: emu_run_cat5(ctx, &instr->cat5); break; - default: - emu_fatal(ctx, "unhandled instruction category: %d", instr->opc_cat); - break; + if ((1 <= instr->opc_cat) && (instr->opc_cat <= 4)) + if (instr->ss) + ctx->last_ss = ctx->cycle; + if (instr->sync) + ctx->last_sy = ctx->cycle; + + /* special handling for 'end' instruction: */ + if ((instr->opc_cat == 0) && (instr->cat0.opc == OPC_END)) + return; + + switch (instr->opc_cat) { + case 0: emu_run_cat0(ctx, &instr->cat0); break; + case 1: emu_run_cat1(ctx, &instr->cat1); break; + case 2: emu_run_cat2(ctx, &instr->cat2); break; + case 3: emu_run_cat3(ctx, &instr->cat3); break; + case 4: emu_run_cat4(ctx, &instr->cat4); break; + case 5: emu_run_cat5(ctx, &instr->cat5); break; + default: + emu_fatal(ctx, "unhandled instruction category: %d", instr->opc_cat); + break; + } } last_instr = instr; |