On 5 December 2013 22:26, Richard Henderson <rth@xxxxxxxxxxx> wrote: > On 12/06/2013 10:51 AM, Peter Maydell wrote: >> + if (cond >= 0x0e) { /* condition "always" */ >> + tcg_src = read_cpu_reg(s, rn, sf); >> + tcg_gen_mov_i64(tcg_rd, tcg_src); > > I wonder if it's worth adding that 0x0[ef] case to the generic condition > processing rather than keep replicating it everywhere. I think "always true" is a special case anyway because you don't want to emit any kind of branching/label logic at all. >> + } else { >> + /* OPTME: we could use movcond here, at the cost of duplicating >> + * a lot of the arm_gen_test_cc() logic. >> + */ > > Honestly, arm_gen_test_cc should get refactored to a real test (as opposed to > branch) sooner rather than later. I had a think about this and I couldn't really come up with a particularly nice looking API for it, given the way that movcondi/setcondi/brcondi work. The best I could come up with was something like: enum ARMCondType { CondSimple; CondAnd; CondOr; }; typedef struct ARMCondState { int type; TCGv_i32 cmpop; TCGCond cond; bool cmpop_is_temp; } ARMCondState; /** * arm_cond_gen_test_cc: * @condstate: filled in with information about condition to check * @armcc: ARM condition value * @round: which of the (max 2) tests to deal with * * Decode the ARM condition value and identify which TCG condition * and operation to use. May emit code to set up the condition arguments. * The general idea is that you call with: * arm_test_gen_cc(&condstate, armcc, 1); * and then emit a brcondi/movcondi/setcondi against zero with the * filled in condstate.cmpop and condstate.cond. If condstate.cmpop_is_temp * is true you then have to free cmpop with tcg_temp_free_i32(). * If the condstate.type is CondAnd or CondOr then this is a condition * which is in two parts (eg gt: which is !Z && N == V). In this case then * (a) you are expected to set up multiple labels, feed movcond output * into a second movcond, etc to achieve the AND/OR effect and (b) * you should call the function a second time with round == 2 to get the * information for the second branch/comparison/test. */ void arm_gen_test_cc(ARMCondState *condstate, int armcc, int round); But that seems pretty ugly to me. The other awkwardness is that there's no easy way to do a "conditional move of 64 bit values based on 32 bit comparison", which means you need to sign extend the condstate.cmpop for 64 bit versions. So I definitely think I'd rather postpone this for now, unless you have a neat idea that I've missed for making it look nice. >> + arm_gen_test_cc(cond, label_match); >> + /* nomatch: */ >> + tcg_src = read_cpu_reg(s, rm, sf); >> + tcg_gen_mov_i64(tcg_rd, tcg_src); >> + if (else_inv) { >> + tcg_gen_not_i64(tcg_rd, tcg_rd); >> + } >> + if (else_inc) { >> + tcg_gen_addi_i64(tcg_rd, tcg_rd, 1); >> + } > > I think better as > > if (else_inv && else_inc) { > tcg_gen_neg_i64(tcg_rd, tcg_src); > } else if (else_inv) { > tcg_gen_not_i64(tcg_rd, tcg_src); > } else if (else_inc) { > tcg_gen_addi_i64(tcg_rd, tcg_src, 1); > } else { > tcg_gen_mov_i64(tcg_rd, tcg_src); > } Agreed, will fix. >> + if (!sf) { >> + tcg_gen_ext32u_i64(tcg_rd, tcg_rd); >> + } > > I do wonder about the usefulness of passing SF (as opposed to hardcoding 1) to > read_cpu_reg to begin, since the ext32u that it generates is redundant with the > one here at the end, and likely cannot be optimized away. Will fix. thanks -- PMM _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm