qemu/target/mips/tcg/tx79_translate.c
Philippe Mathieu-Daudé 34fe9fa368 target/mips: Rename 'rtype' as 'r'
We'll soon have more opcode and decoded arguments, and 'rtype'
is not very helpful. Naming it simply 'r' ease reviewing the
.decode files when we have many opcodes.

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20210801234202.3167676-5-f4bug@amsat.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
2021-08-25 13:02:14 +02:00

686 lines
19 KiB
C

/*
* Toshiba TX79-specific instructions translation routines
*
* Copyright (c) 2018 Fredrik Noring
* Copyright (c) 2021 Philippe Mathieu-Daudé
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-op-gvec.h"
#include "exec/helper-gen.h"
#include "translate.h"
/* Include the auto-generated decoder. */
#include "decode-tx79.c.inc"
/*
* Overview of the TX79-specific instruction set
* =============================================
*
* The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
* are only used by the specific quadword (128-bit) LQ/SQ load/store
* instructions and certain multimedia instructions (MMIs). These MMIs
* configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
* or sixteen 8-bit paths.
*
* Reference:
*
* The Toshiba TX System RISC TX79 Core Architecture manual,
* https://wiki.qemu.org/File:C790.pdf
*/
bool decode_ext_tx79(DisasContext *ctx, uint32_t insn)
{
if (TARGET_LONG_BITS == 64 && decode_tx79(ctx, insn)) {
return true;
}
return false;
}
/*
* Three-Operand Multiply and Multiply-Add (4 instructions)
* --------------------------------------------------------
* MADD [rd,] rs, rt Multiply/Add
* MADDU [rd,] rs, rt Multiply/Add Unsigned
* MULT [rd,] rs, rt Multiply (3-operand)
* MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
*/
/*
* Multiply Instructions for Pipeline 1 (10 instructions)
* ------------------------------------------------------
* MULT1 [rd,] rs, rt Multiply Pipeline 1
* MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
* DIV1 rs, rt Divide Pipeline 1
* DIVU1 rs, rt Divide Unsigned Pipeline 1
* MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
* MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
* MFHI1 rd Move From HI1 Register
* MFLO1 rd Move From LO1 Register
* MTHI1 rs Move To HI1 Register
* MTLO1 rs Move To LO1 Register
*/
static bool trans_MFHI1(DisasContext *ctx, arg_r *a)
{
gen_store_gpr(cpu_HI[1], a->rd);
return true;
}
static bool trans_MFLO1(DisasContext *ctx, arg_r *a)
{
gen_store_gpr(cpu_LO[1], a->rd);
return true;
}
static bool trans_MTHI1(DisasContext *ctx, arg_r *a)
{
gen_load_gpr(cpu_HI[1], a->rs);
return true;
}
static bool trans_MTLO1(DisasContext *ctx, arg_r *a)
{
gen_load_gpr(cpu_LO[1], a->rs);
return true;
}
/*
* Arithmetic (19 instructions)
* ----------------------------
* PADDB rd, rs, rt Parallel Add Byte
* PSUBB rd, rs, rt Parallel Subtract Byte
* PADDH rd, rs, rt Parallel Add Halfword
* PSUBH rd, rs, rt Parallel Subtract Halfword
* PADDW rd, rs, rt Parallel Add Word
* PSUBW rd, rs, rt Parallel Subtract Word
* PADSBH rd, rs, rt Parallel Add/Subtract Halfword
* PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
* PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
* PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
* PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
* PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
* PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
* PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
* PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
* PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
* PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
* PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
* PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
*/
static bool trans_parallel_arith(DisasContext *ctx, arg_r *a,
void (*gen_logic_i64)(TCGv_i64, TCGv_i64, TCGv_i64))
{
TCGv_i64 ax, bx;
if (a->rd == 0) {
/* nop */
return true;
}
ax = tcg_temp_new_i64();
bx = tcg_temp_new_i64();
/* Lower half */
gen_load_gpr(ax, a->rs);
gen_load_gpr(bx, a->rt);
gen_logic_i64(cpu_gpr[a->rd], ax, bx);
/* Upper half */
gen_load_gpr_hi(ax, a->rs);
gen_load_gpr_hi(bx, a->rt);
gen_logic_i64(cpu_gpr_hi[a->rd], ax, bx);
tcg_temp_free(bx);
tcg_temp_free(ax);
return true;
}
/* Parallel Subtract Byte */
static bool trans_PSUBB(DisasContext *ctx, arg_r *a)
{
return trans_parallel_arith(ctx, a, tcg_gen_vec_sub8_i64);
}
/* Parallel Subtract Halfword */
static bool trans_PSUBH(DisasContext *ctx, arg_r *a)
{
return trans_parallel_arith(ctx, a, tcg_gen_vec_sub16_i64);
}
/* Parallel Subtract Word */
static bool trans_PSUBW(DisasContext *ctx, arg_r *a)
{
return trans_parallel_arith(ctx, a, tcg_gen_vec_sub32_i64);
}
/*
* Min/Max (4 instructions)
* ------------------------
* PMAXH rd, rs, rt Parallel Maximum Halfword
* PMINH rd, rs, rt Parallel Minimum Halfword
* PMAXW rd, rs, rt Parallel Maximum Word
* PMINW rd, rs, rt Parallel Minimum Word
*/
/*
* Absolute (2 instructions)
* -------------------------
* PABSH rd, rt Parallel Absolute Halfword
* PABSW rd, rt Parallel Absolute Word
*/
/*
* Logical (4 instructions)
* ------------------------
* PAND rd, rs, rt Parallel AND
* POR rd, rs, rt Parallel OR
* PXOR rd, rs, rt Parallel XOR
* PNOR rd, rs, rt Parallel NOR
*/
/* Parallel And */
static bool trans_PAND(DisasContext *ctx, arg_r *a)
{
return trans_parallel_arith(ctx, a, tcg_gen_and_i64);
}
/* Parallel Or */
static bool trans_POR(DisasContext *ctx, arg_r *a)
{
return trans_parallel_arith(ctx, a, tcg_gen_or_i64);
}
/* Parallel Exclusive Or */
static bool trans_PXOR(DisasContext *ctx, arg_r *a)
{
return trans_parallel_arith(ctx, a, tcg_gen_xor_i64);
}
/* Parallel Not Or */
static bool trans_PNOR(DisasContext *ctx, arg_r *a)
{
return trans_parallel_arith(ctx, a, tcg_gen_nor_i64);
}
/*
* Shift (9 instructions)
* ----------------------
* PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
* PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
* PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
* PSLLW rd, rt, sa Parallel Shift Left Logical Word
* PSRLW rd, rt, sa Parallel Shift Right Logical Word
* PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
* PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
* PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
* PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
*/
/*
* Compare (6 instructions)
* ------------------------
* PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
* PCEQB rd, rs, rt Parallel Compare for Equal Byte
* PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
* PCEQH rd, rs, rt Parallel Compare for Equal Halfword
* PCGTW rd, rs, rt Parallel Compare for Greater Than Word
* PCEQW rd, rs, rt Parallel Compare for Equal Word
*/
static bool trans_parallel_compare(DisasContext *ctx, arg_r *a,
TCGCond cond, unsigned wlen)
{
TCGv_i64 c0, c1, ax, bx, t0, t1, t2;
if (a->rd == 0) {
/* nop */
return true;
}
c0 = tcg_const_tl(0);
c1 = tcg_const_tl(0xffffffff);
ax = tcg_temp_new_i64();
bx = tcg_temp_new_i64();
t0 = tcg_temp_new_i64();
t1 = tcg_temp_new_i64();
t2 = tcg_temp_new_i64();
/* Lower half */
gen_load_gpr(ax, a->rs);
gen_load_gpr(bx, a->rt);
for (int i = 0; i < (64 / wlen); i++) {
tcg_gen_sextract_i64(t0, ax, wlen * i, wlen);
tcg_gen_sextract_i64(t1, bx, wlen * i, wlen);
tcg_gen_movcond_i64(cond, t2, t1, t0, c1, c0);
tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], t2, wlen * i, wlen);
}
/* Upper half */
gen_load_gpr_hi(ax, a->rs);
gen_load_gpr_hi(bx, a->rt);
for (int i = 0; i < (64 / wlen); i++) {
tcg_gen_sextract_i64(t0, ax, wlen * i, wlen);
tcg_gen_sextract_i64(t1, bx, wlen * i, wlen);
tcg_gen_movcond_i64(cond, t2, t1, t0, c1, c0);
tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], t2, wlen * i, wlen);
}
tcg_temp_free(t2);
tcg_temp_free(t1);
tcg_temp_free(t0);
tcg_temp_free(bx);
tcg_temp_free(ax);
tcg_temp_free(c1);
tcg_temp_free(c0);
return true;
}
/* Parallel Compare for Greater Than Byte */
static bool trans_PCGTB(DisasContext *ctx, arg_r *a)
{
return trans_parallel_compare(ctx, a, TCG_COND_GE, 8);
}
/* Parallel Compare for Equal Byte */
static bool trans_PCEQB(DisasContext *ctx, arg_r *a)
{
return trans_parallel_compare(ctx, a, TCG_COND_EQ, 8);
}
/* Parallel Compare for Greater Than Halfword */
static bool trans_PCGTH(DisasContext *ctx, arg_r *a)
{
return trans_parallel_compare(ctx, a, TCG_COND_GE, 16);
}
/* Parallel Compare for Equal Halfword */
static bool trans_PCEQH(DisasContext *ctx, arg_r *a)
{
return trans_parallel_compare(ctx, a, TCG_COND_EQ, 16);
}
/* Parallel Compare for Greater Than Word */
static bool trans_PCGTW(DisasContext *ctx, arg_r *a)
{
return trans_parallel_compare(ctx, a, TCG_COND_GE, 32);
}
/* Parallel Compare for Equal Word */
static bool trans_PCEQW(DisasContext *ctx, arg_r *a)
{
return trans_parallel_compare(ctx, a, TCG_COND_EQ, 32);
}
/*
* LZC (1 instruction)
* -------------------
* PLZCW rd, rs Parallel Leading Zero or One Count Word
*/
/*
* Quadword Load and Store (2 instructions)
* ----------------------------------------
* LQ rt, offset(base) Load Quadword
* SQ rt, offset(base) Store Quadword
*/
static bool trans_LQ(DisasContext *ctx, arg_i *a)
{
TCGv_i64 t0;
TCGv addr;
if (a->rt == 0) {
/* nop */
return true;
}
t0 = tcg_temp_new_i64();
addr = tcg_temp_new();
gen_base_offset_addr(ctx, addr, a->base, a->offset);
/*
* Clear least-significant four bits of the effective
* address, effectively creating an aligned address.
*/
tcg_gen_andi_tl(addr, addr, ~0xf);
/* Lower half */
tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEQ);
gen_store_gpr(t0, a->rt);
/* Upper half */
tcg_gen_addi_i64(addr, addr, 8);
tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEQ);
gen_store_gpr_hi(t0, a->rt);
tcg_temp_free(t0);
tcg_temp_free(addr);
return true;
}
static bool trans_SQ(DisasContext *ctx, arg_i *a)
{
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv addr = tcg_temp_new();
gen_base_offset_addr(ctx, addr, a->base, a->offset);
/*
* Clear least-significant four bits of the effective
* address, effectively creating an aligned address.
*/
tcg_gen_andi_tl(addr, addr, ~0xf);
/* Lower half */
gen_load_gpr(t0, a->rt);
tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEQ);
/* Upper half */
tcg_gen_addi_i64(addr, addr, 8);
gen_load_gpr_hi(t0, a->rt);
tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEQ);
tcg_temp_free(addr);
tcg_temp_free(t0);
return true;
}
/*
* Multiply and Divide (19 instructions)
* -------------------------------------
* PMULTW rd, rs, rt Parallel Multiply Word
* PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
* PDIVW rs, rt Parallel Divide Word
* PDIVUW rs, rt Parallel Divide Unsigned Word
* PMADDW rd, rs, rt Parallel Multiply-Add Word
* PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
* PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
* PMULTH rd, rs, rt Parallel Multiply Halfword
* PMADDH rd, rs, rt Parallel Multiply-Add Halfword
* PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
* PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
* PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
* PDIVBW rs, rt Parallel Divide Broadcast Word
* PMFHI rd Parallel Move From HI Register
* PMFLO rd Parallel Move From LO Register
* PMTHI rs Parallel Move To HI Register
* PMTLO rs Parallel Move To LO Register
* PMFHL rd Parallel Move From HI/LO Register
* PMTHL rs Parallel Move To HI/LO Register
*/
/*
* Pack/Extend (11 instructions)
* -----------------------------
* PPAC5 rd, rt Parallel Pack to 5 bits
* PPACB rd, rs, rt Parallel Pack to Byte
* PPACH rd, rs, rt Parallel Pack to Halfword
* PPACW rd, rs, rt Parallel Pack to Word
* PEXT5 rd, rt Parallel Extend Upper from 5 bits
* PEXTUB rd, rs, rt Parallel Extend Upper from Byte
* PEXTLB rd, rs, rt Parallel Extend Lower from Byte
* PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
* PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
* PEXTUW rd, rs, rt Parallel Extend Upper from Word
* PEXTLW rd, rs, rt Parallel Extend Lower from Word
*/
/* Parallel Pack to Word */
static bool trans_PPACW(DisasContext *ctx, arg_r *a)
{
TCGv_i64 a0, b0, t0;
if (a->rd == 0) {
/* nop */
return true;
}
a0 = tcg_temp_new_i64();
b0 = tcg_temp_new_i64();
t0 = tcg_temp_new_i64();
gen_load_gpr(a0, a->rs);
gen_load_gpr(b0, a->rt);
gen_load_gpr_hi(t0, a->rt); /* b1 */
tcg_gen_deposit_i64(cpu_gpr[a->rd], b0, t0, 32, 32);
gen_load_gpr_hi(t0, a->rs); /* a1 */
tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], a0, t0, 32, 32);
tcg_temp_free(t0);
tcg_temp_free(b0);
tcg_temp_free(a0);
return true;
}
static void gen_pextw(TCGv_i64 dl, TCGv_i64 dh, TCGv_i64 a, TCGv_i64 b)
{
tcg_gen_deposit_i64(dl, b, a, 32, 32);
tcg_gen_shri_i64(b, b, 32);
tcg_gen_deposit_i64(dh, a, b, 0, 32);
}
static bool trans_PEXTLx(DisasContext *ctx, arg_r *a, unsigned wlen)
{
TCGv_i64 ax, bx;
if (a->rd == 0) {
/* nop */
return true;
}
ax = tcg_temp_new_i64();
bx = tcg_temp_new_i64();
gen_load_gpr(ax, a->rs);
gen_load_gpr(bx, a->rt);
/* Lower half */
for (int i = 0; i < 64 / (2 * wlen); i++) {
tcg_gen_deposit_i64(cpu_gpr[a->rd],
cpu_gpr[a->rd], bx, 2 * wlen * i, wlen);
tcg_gen_deposit_i64(cpu_gpr[a->rd],
cpu_gpr[a->rd], ax, 2 * wlen * i + wlen, wlen);
tcg_gen_shri_i64(bx, bx, wlen);
tcg_gen_shri_i64(ax, ax, wlen);
}
/* Upper half */
for (int i = 0; i < 64 / (2 * wlen); i++) {
tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
cpu_gpr_hi[a->rd], bx, 2 * wlen * i, wlen);
tcg_gen_deposit_i64(cpu_gpr_hi[a->rd],
cpu_gpr_hi[a->rd], ax, 2 * wlen * i + wlen, wlen);
tcg_gen_shri_i64(bx, bx, wlen);
tcg_gen_shri_i64(ax, ax, wlen);
}
tcg_temp_free(bx);
tcg_temp_free(ax);
return true;
}
/* Parallel Extend Lower from Byte */
static bool trans_PEXTLB(DisasContext *ctx, arg_r *a)
{
return trans_PEXTLx(ctx, a, 8);
}
/* Parallel Extend Lower from Halfword */
static bool trans_PEXTLH(DisasContext *ctx, arg_r *a)
{
return trans_PEXTLx(ctx, a, 16);
}
/* Parallel Extend Lower from Word */
static bool trans_PEXTLW(DisasContext *ctx, arg_r *a)
{
TCGv_i64 ax, bx;
if (a->rd == 0) {
/* nop */
return true;
}
ax = tcg_temp_new_i64();
bx = tcg_temp_new_i64();
gen_load_gpr(ax, a->rs);
gen_load_gpr(bx, a->rt);
gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
tcg_temp_free(bx);
tcg_temp_free(ax);
return true;
}
/* Parallel Extend Upper from Word */
static bool trans_PEXTUW(DisasContext *ctx, arg_r *a)
{
TCGv_i64 ax, bx;
if (a->rd == 0) {
/* nop */
return true;
}
ax = tcg_temp_new_i64();
bx = tcg_temp_new_i64();
gen_load_gpr_hi(ax, a->rs);
gen_load_gpr_hi(bx, a->rt);
gen_pextw(cpu_gpr[a->rd], cpu_gpr_hi[a->rd], ax, bx);
tcg_temp_free(bx);
tcg_temp_free(ax);
return true;
}
/*
* Others (16 instructions)
* ------------------------
* PCPYH rd, rt Parallel Copy Halfword
* PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
* PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
* PREVH rd, rt Parallel Reverse Halfword
* PINTH rd, rs, rt Parallel Interleave Halfword
* PINTEH rd, rs, rt Parallel Interleave Even Halfword
* PEXEH rd, rt Parallel Exchange Even Halfword
* PEXCH rd, rt Parallel Exchange Center Halfword
* PEXEW rd, rt Parallel Exchange Even Word
* PEXCW rd, rt Parallel Exchange Center Word
* QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
* MFSA rd Move from Shift Amount Register
* MTSA rs Move to Shift Amount Register
* MTSAB rs, immediate Move Byte Count to Shift Amount Register
* MTSAH rs, immediate Move Halfword Count to Shift Amount Register
* PROT3W rd, rt Parallel Rotate 3 Words
*/
/* Parallel Copy Halfword */
static bool trans_PCPYH(DisasContext *s, arg_r *a)
{
if (a->rd == 0) {
/* nop */
return true;
}
if (a->rt == 0) {
tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
return true;
}
tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], cpu_gpr[a->rt], 16, 16);
tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], cpu_gpr[a->rd], 32, 32);
tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt], cpu_gpr_hi[a->rt], 16, 16);
tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], 32, 32);
return true;
}
/* Parallel Copy Lower Doubleword */
static bool trans_PCPYLD(DisasContext *s, arg_r *a)
{
if (a->rd == 0) {
/* nop */
return true;
}
if (a->rs == 0) {
tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
} else {
tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr[a->rs]);
}
if (a->rt == 0) {
tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
} else if (a->rd != a->rt) {
tcg_gen_mov_i64(cpu_gpr[a->rd], cpu_gpr[a->rt]);
}
return true;
}
/* Parallel Copy Upper Doubleword */
static bool trans_PCPYUD(DisasContext *s, arg_r *a)
{
if (a->rd == 0) {
/* nop */
return true;
}
gen_load_gpr_hi(cpu_gpr[a->rd], a->rs);
if (a->rt == 0) {
tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
} else if (a->rd != a->rt) {
tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt]);
}
return true;
}
/* Parallel Rotate 3 Words Left */
static bool trans_PROT3W(DisasContext *ctx, arg_r *a)
{
TCGv_i64 ax;
if (a->rd == 0) {
/* nop */
return true;
}
if (a->rt == 0) {
tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
return true;
}
ax = tcg_temp_new_i64();
tcg_gen_mov_i64(ax, cpu_gpr_hi[a->rt]);
tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], ax, cpu_gpr[a->rt], 0, 32);
tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], ax, 0, 32);
tcg_gen_rotri_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], 32);
tcg_temp_free(ax);
return true;
}