@samitouri / QOSamiQemu / commits / 8bbb1a1807

tcg: Introduce tcg_gen_addN_i64

Add a helper for multi-limb 64-bit addition. The helper emits native carry-chain TCG ops when they are available and falls back to explicit carry propagation otherwise. This lets target translators build wider integer accumulators inline without open-coding the same add-with-carry sequence at each use site. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: James Hilliard <james.hilliard1@gmail.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20260520172313.23777-17-philmd@linaro.org>

Richard Henderson committed May 17, 2026 at 18:07 UTC 8bbb1a18075e8f557d1098bf0515e66b20feaafc
2 files changed +43
include/tcg/tcg-op-common.h
+1
@@ -253,6 +253,7 @@ void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
253 TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh);
254 void tcg_gen_addcio_i64(TCGv_i64 r, TCGv_i64 co,
255 TCGv_i64 a, TCGv_i64 b, TCGv_i64 ci);
256 +void tcg_gen_addN_i64(int n, TCGv_i64 *r, TCGv_i64 *a, TCGv_i64 *b);
257 void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2);
258 void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2);
259 void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2);
tcg/tcg-op.c
+42
@@ -2275,6 +2275,48 @@ void tcg_gen_addcio_i64(TCGv_i64 r, TCGv_i64 co,
2275 }
2276 }
2277
2278 +void tcg_gen_addN_i64(int n, TCGv_i64 *r, TCGv_i64 *a, TCGv_i64 *b)
2279 +{
2280 + tcg_debug_assert(n > 2);
2281 +
2282 + /* ??? Don't allow overlap for now. */
2283 + for (int i = 0; i < n - 1; ++i) {
2284 + for (int j = i + 1; j < n; ++j) {
2285 + tcg_debug_assert(r[i] != a[j]);
2286 + tcg_debug_assert(r[i] != b[j]);
2287 + }
2288 + }
2289 +
2290 + if (tcg_op_supported(INDEX_op_addci, TCG_TYPE_I64, 0)) {
2291 + tcg_gen_op3_i64(INDEX_op_addco, r[0], a[0], b[0]);
2292 + for (int i = 1; i < n - 1; ++i) {
2293 + tcg_gen_op3_i64(INDEX_op_addcio, r[i], a[i], b[i]);
2294 + }
2295 + tcg_gen_op3_i64(INDEX_op_addci, r[n - 1], a[n - 1], b[n - 1]);
2296 + } else {
2297 + TCGv_i64 t = tcg_temp_ebb_new_i64();
2298 + TCGv_i64 c = tcg_temp_ebb_new_i64();
2299 +
2300 + tcg_gen_add_i64(t, a[0], b[0]);
2301 + tcg_gen_setcond_i64(TCG_COND_LTU, c, t, a[0]);
2302 + tcg_gen_mov_i64(r[0], t);
2303 +
2304 + for (int i = 1; i < n - 1; ++i) {
2305 + tcg_gen_add_i64(t, a[i], c);
2306 + tcg_gen_setcond_i64(TCG_COND_LTU, c, t, c);
2307 + tcg_gen_add_i64(r[i], b[i], t);
2308 + tcg_gen_setcond_i64(TCG_COND_LTU, t, r[i], t);
2309 + tcg_gen_or_i64(c, c, t);
2310 + }
2311 +
2312 + tcg_gen_add_i64(r[n - 1], a[n - 1], b[n - 1]);
2313 + tcg_gen_add_i64(r[n - 1], r[n - 1], c);
2314 +
2315 + tcg_temp_free_i64(t);
2316 + tcg_temp_free_i64(c);
2317 + }
2318 +}
2319 +
2320 void tcg_gen_sub2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 al,
2321 TCGv_i64 ah, TCGv_i64 bl, TCGv_i64 bh)
2322 {