@samitouri / QOSamiQemu / commits / 006d624b94

target/mips: add Octeon LA* atomic instructions

Implement the Octeon LA* read-modify-write atomic instruction family: LAI/LAID, LAD/LADD, LAA/LAAD, LAS/LASD, LAC/LACD, and LAW/LAWD. These operations are architecturally distinct from SAA/SAAD and are used by existing Octeon user-mode code for atomic counters, bit operations, and exchange-style updates. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: James Hilliard <james.hilliard1@gmail.com> Co-developed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <bd591571-121c-4eac-8ce6-e1e2234dcf3f@linaro.org>

James Hilliard committed Apr 9, 2026 at 05:54 UTC 006d624b948bf91fd0f491fb44fdef082ff0f3e6
2 files changed +62
target/mips/tcg/octeon.decode
+17
@@ -68,6 +68,23 @@ V3MULU 011100 ..... ..... ..... 00000 010001 @r3
68 SAA 011100 ..... ..... 00000 00000 011000 @saa
69 SAAD 011100 ..... ..... 00000 00000 011001 @saa
70
71 +&la base rd
72 +&laa base add rd
73 +@la ...... base:5 ..... rd:5 ........... &la
74 +@laa ...... base:5 add:5 rd:5 ........... &laa
75 +LAI 011100 ..... 00000 ..... 00010 011111 @la
76 +LAID 011100 ..... 00000 ..... 00011 011111 @la
77 +LAD 011100 ..... 00000 ..... 00110 011111 @la
78 +LADD 011100 ..... 00000 ..... 00111 011111 @la
79 +LAA 011100 ..... ..... ..... 10010 011111 @laa
80 +LAAD 011100 ..... ..... ..... 10011 011111 @laa
81 +LAS 011100 ..... 00000 ..... 01010 011111 @la
82 +LASD 011100 ..... 00000 ..... 01011 011111 @la
83 +LAC 011100 ..... 00000 ..... 01110 011111 @la
84 +LACD 011100 ..... 00000 ..... 01111 011111 @la
85 +LAW 011100 ..... ..... ..... 10110 011111 @laa
86 +LAWD 011100 ..... ..... ..... 10111 011111 @laa
87 +
88 &zcb base
89 ZCB 011100 base:5 00000 00000 1110- 011111 &zcb
90
target/mips/tcg/octeon_translate.c
+45
@@ -185,6 +185,51 @@ static bool trans_saa(DisasContext *ctx, arg_saa *a, MemOp mop)
185 TRANS(SAA, trans_saa, MO_32);
186 TRANS(SAAD, trans_saa, MO_64);
187
188 +typedef void AtomicThreeOpFn(TCGv_i64, TCGv_va, TCGv_i64, TCGArg, MemOp);
189 +
190 +static bool do_atomic_la(DisasContext *ctx, arg_la *a,
191 + AtomicThreeOpFn *atomic_fn, int64_t imm, MemOp mop)
192 +{
193 + TCGv_i64 addr = tcg_temp_new_i64();
194 + TCGv_i64 old = tcg_temp_new_i64();
195 + MemOp amo = mo_endian(ctx) | mop | MO_ALIGN;
196 +
197 + gen_base_offset_addr(ctx, addr, a->base, 0);
198 +
199 + atomic_fn(old, addr, tcg_constant_i64(imm), ctx->mem_idx, amo);
200 + gen_store_gpr(old, a->rd);
201 + return true;
202 +}
203 +
204 +static bool do_atomic_laa(DisasContext *ctx, arg_laa *a,
205 + AtomicThreeOpFn *atomic_fn, MemOp mop)
206 +{
207 + TCGv_i64 addr = tcg_temp_new_i64();
208 + TCGv_i64 old = tcg_temp_new_i64();
209 + TCGv_i64 value = tcg_temp_new_i64();
210 + MemOp amo = mo_endian(ctx) | mop | MO_ALIGN;
211 +
212 + gen_base_offset_addr(ctx, addr, a->base, 0);
213 + gen_load_gpr(value, a->add);
214 +
215 + atomic_fn(old, addr, value, ctx->mem_idx, amo);
216 + gen_store_gpr(old, a->rd);
217 + return true;
218 +}
219 +
220 +TRANS(LAI, do_atomic_la, tcg_gen_atomic_fetch_add_i64, 1, MO_SL);
221 +TRANS(LAID, do_atomic_la, tcg_gen_atomic_fetch_add_i64, 1, MO_UQ);
222 +TRANS(LAD, do_atomic_la, tcg_gen_atomic_fetch_add_i64, -1, MO_SL);
223 +TRANS(LADD, do_atomic_la, tcg_gen_atomic_fetch_add_i64, -1, MO_UQ);
224 +TRANS(LAA, do_atomic_laa, tcg_gen_atomic_fetch_add_i64, MO_SL);
225 +TRANS(LAAD, do_atomic_laa, tcg_gen_atomic_fetch_add_i64, MO_UQ);
226 +TRANS(LAS, do_atomic_la, tcg_gen_atomic_xchg_i64, -1, MO_SL);
227 +TRANS(LASD, do_atomic_la, tcg_gen_atomic_xchg_i64, -1, MO_UQ);
228 +TRANS(LAC, do_atomic_la, tcg_gen_atomic_xchg_i64, 0, MO_SL);
229 +TRANS(LACD, do_atomic_la, tcg_gen_atomic_xchg_i64, 0, MO_UQ);
230 +TRANS(LAW, do_atomic_laa, tcg_gen_atomic_xchg_i64, MO_SL);
231 +TRANS(LAWD, do_atomic_laa, tcg_gen_atomic_xchg_i64, MO_UQ);
232 +
233 static bool trans_ZCB(DisasContext *ctx, arg_ZCB *a)
234 {
235 TCGv_i64 addr = tcg_temp_new_i64();