diff options
author | Rob Clark <robdclark@gmail.com> | 2015-04-04 09:20:55 -0400 |
---|---|---|
committer | Rob Clark <robdclark@gmail.com> | 2015-04-04 09:20:55 -0400 |
commit | 01f3dd2168fc9161cc59af8a2d04076639274b65 (patch) | |
tree | 4613d2799d34401762bf5777840619c66b7ccb99 | |
parent | 954092869f4c4224c999193ea1a37c2817063d97 (diff) |
ir3emu: some fixes
-rw-r--r-- | ir3emu.c | 87 |
1 files changed, 55 insertions, 32 deletions
@@ -365,26 +365,22 @@ emu_run_cat1(struct ir3_emu_ctx *ctx, instr_cat1_t *cat1) }); } - if (type_float(cat1->src_type) && - type_uint(cat1->dst_type)) { + if (type_float(cat1->src_type) && type_uint(cat1->dst_type)) { dst.u = src.f; - } else if (type_float(cat1->src_type) && - type_sint(cat1->dst_type)) { + } else if (type_float(cat1->src_type) && type_sint(cat1->dst_type)) { dst.i = src.f; - } else if (type_uint(cat1->src_type) && - type_sint(cat1->dst_type)) { + } else if (type_uint(cat1->src_type) && type_sint(cat1->dst_type)) { dst.i = src.u; - } else if (type_uint(cat1->src_type) && - type_float(cat1->dst_type)) { - dst.i = src.f; - } else if (type_sint(cat1->src_type) && - type_float(cat1->dst_type)) { - dst.f = src.i; - } else if (type_sint(cat1->src_type) && - type_uint(cat1->dst_type)) { + } else if (type_uint(cat1->src_type) && type_float(cat1->dst_type)) { dst.f = src.u; + } else if (type_sint(cat1->src_type) && type_float(cat1->dst_type)) { + dst.f = src.i; + } else if (type_sint(cat1->src_type) && type_uint(cat1->dst_type)) { + dst.u = src.i; + } else if (cat1->src_type == cat1->dst_type) { + dst.u = src.u; } else { - dst.f = src.f; + assert(0); } write_dst(ctx, dst, (struct ir3_regdst){ @@ -399,6 +395,19 @@ emu_run_cat2(struct ir3_emu_ctx *ctx, instr_cat2_t *cat2) { struct ir3_regsrc src2rs; regval_t dst, src1, src2; + bool absnegf; + + switch (cat2->opc) { + /* TODO the .b instructions do bitwise negate, rather than + * float abs/neg, so they also need special handling.. + */ + case OPC_ABSNEG_S: + absnegf = false; + break; + default: + absnegf = true; + break; + } if (cat2->c1.src1_c) { src1 = read_src(ctx, 0, (struct ir3_regsrc){ @@ -407,8 +416,8 @@ emu_run_cat2(struct ir3_emu_ctx *ctx, instr_cat2_t *cat2) .r = cat2->src1_r, .c = cat2->c1.src1_c, .im = cat2->src1_im, - .neg = cat2->src1_neg, - .abs = cat2->src1_abs, + .neg = cat2->src1_neg && absnegf, + .abs = cat2->src1_abs && absnegf, }); } else if (cat2->rel1.src1_rel) { src1 = read_src(ctx, 0, (struct ir3_regsrc){ @@ -417,8 +426,8 @@ emu_run_cat2(struct ir3_emu_ctx *ctx, instr_cat2_t *cat2) .r = cat2->src1_r, .c = cat2->rel1.src1_c, .im = cat2->src1_im, - .neg = cat2->src1_neg, - .abs = cat2->src1_abs, + .neg = cat2->src1_neg && absnegf, + .abs = cat2->src1_abs && absnegf, .rel = cat2->rel1.src1_rel, }); } else { @@ -427,8 +436,8 @@ emu_run_cat2(struct ir3_emu_ctx *ctx, instr_cat2_t *cat2) .full = cat2->full, .r = cat2->src1_r, .im = cat2->src1_im, - .neg = cat2->src1_neg, - .abs = cat2->src1_abs, + .neg = cat2->src1_neg && absnegf, + .abs = cat2->src1_abs && absnegf, }); } @@ -439,8 +448,8 @@ emu_run_cat2(struct ir3_emu_ctx *ctx, instr_cat2_t *cat2) .r = cat2->src2_r, .c = cat2->c2.src2_c, .im = cat2->src2_im, - .neg = cat2->src2_neg, - .abs = cat2->src2_abs, + .neg = cat2->src2_neg && absnegf, + .abs = cat2->src2_abs && absnegf, }; } else if (cat2->rel2.src2_rel) { src2rs = (struct ir3_regsrc){ @@ -449,8 +458,8 @@ emu_run_cat2(struct ir3_emu_ctx *ctx, instr_cat2_t *cat2) .r = cat2->src2_r, .c = cat2->rel2.src2_c, .im = cat2->src2_im, - .neg = cat2->src2_neg, - .abs = cat2->src2_abs, + .neg = cat2->src2_neg && absnegf, + .abs = cat2->src2_abs && absnegf, .rel = cat2->rel2.src2_rel, }; } else { @@ -459,8 +468,8 @@ emu_run_cat2(struct ir3_emu_ctx *ctx, instr_cat2_t *cat2) .full = cat2->full, .r = cat2->src2_r, .im = cat2->src2_im, - .neg = cat2->src2_neg, - .abs = cat2->src2_abs, + .neg = cat2->src2_neg && absnegf, + .abs = cat2->src2_abs && absnegf, }; } @@ -473,6 +482,22 @@ emu_run_cat2(struct ir3_emu_ctx *ctx, instr_cat2_t *cat2) src2 = read_src(ctx, 1, src2rs); } + if (!absnegf) { + switch (cat2->opc) { + /* TODO the .b instructions do bitwise negate, rather than + * float abs/neg, so they also need special handling.. + */ + case OPC_ABSNEG_S: + if (cat2->src1_neg) + src1.i = -src1.i; + if (cat2->src1_abs) + src1.i = abs(src1.i); + break; + default: + break; + } + } + switch (cat2->opc) { case OPC_ADD_F: dst.f = src1.f + src2.f; @@ -490,8 +515,7 @@ emu_run_cat2(struct ir3_emu_ctx *ctx, instr_cat2_t *cat2) dst.i = src1.i * src2.i; break; case OPC_MULL_U: - /* technically, I think, this should multiply just the low bits.. */ - dst.u = src1.u * src2.u; + dst.u = (src1.u & 0xffff) * (src2.u & 0xffff); break; case OPC_CMPS_F: switch (cat2->cond) { @@ -660,14 +684,13 @@ emu_run_cat3(struct ir3_emu_ctx *ctx, instr_cat3_t *cat3) dst.f = (src1.f * src2.f) + src3.f; break; case OPC_MADSH_M16: - /* technically this should mul-add shift high, ie. ah * bl << 16 */ - dst.u = (src1.u * src2.u) + src3.u; + dst.u = (((src1.u >> 16) * (src2.u & 0xffff)) << 16) + src3.u; break; case OPC_SEL_F32: dst.f = (src2.i >= 0) ? src3.f : src1.f; break; case OPC_SEL_B32: - dst.f = src2.u ? src3.f : src1.f; + dst.f = src2.u ? src1.f : src3.f; break; default: emu_fatal(ctx, "unhandled cat3 opc: %u", cat3->opc); |