summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ir3emu.c67
1 files changed, 37 insertions, 30 deletions
diff --git a/ir3emu.c b/ir3emu.c
index 3850e82..c10e480 100644
--- a/ir3emu.c
+++ b/ir3emu.c
@@ -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;