diff --git a/librz/arch/isa/tms320/c55x_plus/c55plus_arch.c b/librz/arch/isa/tms320/c55x_plus/c55plus_arch.c index 1108f06fc2..f902ff4c41 100644 --- a/librz/arch/isa/tms320/c55x_plus/c55plus_arch.c +++ b/librz/arch/isa/tms320/c55x_plus/c55plus_arch.c @@ -1129,11 +1129,13 @@ static void c55plus_x_abs_word(const C55ArchDesc *a, ut64 bits, const C55OpDesc out->access = 16; } -// ar source ARn in byte1[3:0] of the 0xd0 ar word store. +// 16-bit register source in byte1[5:0] of the 0xd0 word store. The byte1[7:5]==001 +// row covers AR0-15 (0x20-0x2F) and T0-3 (0x30-0x33) (plus SP/DP); decode the full +// 6-bit field through gr1 instead of forcing AR, so e.g. 0x30 is T0 not AR0. static void c55plus_x_ar_src(const C55ArchDesc *a, ut64 bits, const C55OpDesc *d, C55Operand *out) { (void)d; out->kind = C55_OP_REG; - c55plus_gr1((ut8)(32 + ((bits >> 24) & 0x0f)), &out->reg); // ar0-15 + c55plus_gr1((ut8)((bits >> 24) & 0x3f), &out->reg); // byte1[5:0] out->width = c55plus_reg_width(a, &out->reg); } @@ -1404,23 +1406,18 @@ static void c55plus_x_macr_acdst(const C55ArchDesc *a, ut64 bits, const C55OpDes // shared register-modify / *sp(#k) / @#k addressing (byte1:byte2) and is wrapped // in dual(...) when byte3[5] is set; ACx is byte2[4:0]. Left unlifted, as in the // legacy decoder. -// btstclr / btstset / btst / btstnot #k5, [dbl(]*Smem[)], TCx (opcode 0x91, -// byte2[4:2] selecting op+access, 4 bytes): the extended memory bit-test family. -// Per the C55x+ encoding the addressing is byte1:byte2[7:6], TCx is byte2[5], the -// operation+access selector is byte2[4:2] (byte2[4:3]: 00 btstclr / 01 btstset / -// 10 btst / 11 btstnot; byte2[2]: 0 word / 1 dbl), and the 5-bit bit number is -// byte3[4:0]. The pre-existing word btstset (byte3[7:5]==000) keeps its own row; -// these extended rows reject byte3[7:5]==000 so that form still falls through to -// it. Left unlifted, as in the legacy decoder. +// btstclr / btstset / btst / btstnot #k, [dbl(]*Smem[)], TCx (opcode 0x91, 4 +// bytes): the memory bit-test family. Per the C55x+ encoding (verified against TI +// dis55 and SWPU104) the addressing is byte1:byte2[7:6], TCx is byte2[5], and +// byte2[4:2] selects operation and access width (byte2[4:3]: 00 btstclr / 01 +// btstset / 10 btst / 11 btstnot; byte2[2]: 0 word / 1 dbl). The immediate bit +// number is byte3[4:0] in the register / indirect forms but byte3[3:0] in the +// long-absolute *(#k24) form. Left unlifted, as in the +// legacy decoder. static void c55plus_x_btx_mem(const C55ArchDesc *a, ut64 bits, const C55OpDesc *d, C55Operand *out) { (void)d; - if ((((bits >> 5) & 0x7)) == 0) { - // byte3[7:5]==000 is the word btstset form: abandon so it falls through. - out->kind = C55_OP_INVALID; - return; - } ut8 b_ar = (ut8)((bits >> 16) & 0xff); // byte1 - ut8 b_mode = (ut8)((bits >> 8) & 0xff); // byte2 (smem_amode reads only [7:6]) + ut8 b_mode = (ut8)(((bits >> 8) & 0xff) & ~0x20); // byte2, TC bit (byte2[5]) cleared if (!c55plus_smem_amode(b_ar, b_mode, out)) { out->kind = C55_OP_INVALID; return; @@ -1432,8 +1429,18 @@ static void c55plus_x_btx_mem(const C55ArchDesc *a, ut64 bits, const C55OpDesc * static void c55plus_x_btx_bit(const C55ArchDesc *a, ut64 bits, const C55OpDesc *d, C55Operand *out) { (void)a; (void)d; + // The bit-number field width depends on the addressing mode (verified against + // TI dis55): the long-absolute *(#k24) form uses 4 bits (byte3[3:0]); the + // register / indirect forms use 5 bits (byte3[4:0]). + C55Operand mem = { 0 }; + ut8 b_ar = (ut8)((bits >> 16) & 0xff); // byte1 + ut8 b_mode = (ut8)(((bits >> 8) & 0xff) & ~0x20); // byte2, TC bit (byte2[5]) cleared + ut64 mask = 0x1f; + if (c55plus_smem_amode(b_ar, b_mode, &mem) && mem.amode == C55_AM_ABSOLUTE) { + mask = 0xf; + } out->kind = C55_OP_IMM; - out->imm = bits & 0x1f; // byte3[4:0] + out->imm = bits & mask; out->width = 16; } static void c55plus_x_btx_tc(const C55ArchDesc *a, ut64 bits, const C55OpDesc *d, C55Operand *out) { @@ -2016,34 +2023,6 @@ static void c55plus_x_b1_imm(const C55ArchDesc *a, ut64 bits, const C55OpDesc *d out->width = 16; } -// btstset #k, *Smem, TCx (opcode 0x91, base 4 bytes): test-and-set a memory bit. -// The bit number is byte3[4:0]; the Smem operand is byte1:byte2 but byte2[5] -// carries the TC selector (TC1/TC2) rather than addressing, so it is masked out -// before the shared Smem decode. Left unlifted, as in the legacy decoder. -static void c55plus_x_btstset_mem(const C55ArchDesc *a, ut64 bits, const C55OpDesc *d, C55Operand *out) { - (void)a; - (void)d; - ut8 b_ar = (ut8)((bits >> 16) & 0xff); // byte1 - ut8 b_mode = (ut8)(((bits >> 8) & 0xff) & ~0x20); // byte2 with the TC bit cleared - if (!c55plus_smem_amode(b_ar, b_mode, out)) { - out->kind = C55_OP_INVALID; - } -} -static void c55plus_x_btstset_bit(const C55ArchDesc *a, ut64 bits, const C55OpDesc *d, C55Operand *out) { - (void)a; - (void)d; - out->kind = C55_OP_IMM; - out->imm = bits & 0xf; // byte3[3:0] - out->width = 16; -} -static void c55plus_x_btstset_tc(const C55ArchDesc *a, ut64 bits, const C55OpDesc *d, C55Operand *out) { - (void)a; - (void)d; - out->kind = C55_OP_COND; - out->cond_is_flag = true; - out->cond_flag = (ut8)(4 + ((bits >> 13) & 1)); // byte2[5] -} - // Whole-accumulator destination ACx in byte2[4:0] (0x5c dbl load). static void c55plus_x_acc(const C55ArchDesc *a, ut64 bits, const C55OpDesc *d, C55Operand *out) { (void)d; @@ -2124,58 +2103,34 @@ static void c55plus_x_gr6(const C55ArchDesc *a, ut64 bits, const C55OpDesc *d, C out->width = c55plus_reg_width(a, &out->reg); } -// Double-word memory source of "copy dbl(*Smem), xar" (opcode 0x56, 3 bytes). -// The addressing differs from the standard Smem byte layout: byte1[3:0] is the -// base ARn and byte1[7:4] is a short index k4 (0 -> plain indirect, non-zero -> -// short(#k4)). byte2[7:6] selects the addressing group (10 = the indirect / -// indexed dbl form decoded here); byte2[5] = 0 marks the double-word (dbl) -// access and byte2[3:0] is the xar destination. The register-modify (00), -// direct (11), and byte/half (byte2[5]=1) forms fall back to the legacy decoder. -static void c55plus_x_copy_dbl_mem(const C55ArchDesc *a, ut64 bits, const C55OpDesc *d, C55Operand *out) { - (void)a; +// Memory source of the copy(ALLa = Smem) (opcode 0x54-0x57 LD_R, 3+ bytes) form. +// The Smem addressing is the standard byte1:byte2[7:6] matrix (so the const-index +// *ARn(#K16) and absolute forms extend the instruction); the access is dbl iff the +// destination register is a long (>16-bit) register, matching TI dis55. +static void c55plus_x_copy_smem(const C55ArchDesc *a, ut64 bits, const C55OpDesc *d, C55Operand *out) { (void)d; - ut8 b1 = (ut8)((bits >> 8) & 0xff); - ut8 b2 = (ut8)(bits & 0xff); - ut8 grp = (ut8)((b2 >> 6) & 3); - if ((b2 >> 5) & 1) { - out->kind = C55_OP_INVALID; // byte/half access, not the dbl form + ut8 b_ar = (ut8)((bits >> 8) & 0xff); // byte1 + ut8 b_mode = (ut8)(bits & 0xff); // byte2 + if (!c55plus_smem_amode(b_ar, b_mode, out)) { + out->kind = C55_OP_INVALID; return; } - if (grp == 2) { - // indirect / indexed-short: byte1 holds the base ARn (low nibble) and a - // short index k4 (high nibble). - out->kind = C55_OP_MEM; + C55Reg reg = { 0 }; + ut8 alla = (ut8)((((bits >> 16) & 0x3) << 6) | (bits & 0x3f)); // byte0[1:0]:byte2[5:0] + c55plus_gr1(alla, ®); + if (c55plus_reg_width(a, ®) > 16) { out->access = 32; out->dbl = true; - c55plus_gr1((ut8)(32 + (b1 & 0x0f)), &out->reg); // base ARn (low half of XARn) - ut8 k4 = (ut8)((b1 >> 4) & 0x0f); - if (k4) { - out->amode = C55_AM_INDEXED; - out->disp = k4; - } else { - out->amode = C55_AM_INDIRECT; - } - return; } - if (grp == 3 && ((b1 >> 7) & 1)) { - // SP-relative *sp(#k): the data address is (sp + k) << 1 (a byte - // address), 7-bit offset k = byte1[6:0]. - out->kind = C55_OP_MEM; - out->access = 32; - out->dbl = true; - out->amode = C55_AM_INDEXED; - c55plus_gr1(53, &out->reg); // sp - out->disp = (ut8)(b1 & 0x7f); - return; - } - out->kind = C55_OP_INVALID; // register-modify / DP-direct -> legacy } -// xar destination of "copy dbl(*Smem), xar" (opcode 0x56): byte2[3:0]. -static void c55plus_x_copy_xar(const C55ArchDesc *a, ut64 bits, const C55OpDesc *d, C55Operand *out) { +// Destination register ALLa of copy(ALLa = Smem): the 8-bit register id is +// byte0[1:0] (high 2 bits) joined with byte2[5:0]. +static void c55plus_x_copy_alla(const C55ArchDesc *a, ut64 bits, const C55OpDesc *d, C55Operand *out) { (void)d; + ut8 alla = (ut8)((((bits >> 16) & 0x3) << 6) | (bits & 0x3f)); // byte0[1:0]:byte2[5:0] out->kind = C55_OP_REG; - c55plus_gr1((ut8)(128 + (bits & 0x0f)), &out->reg); // xar0-15 (gr1 slots 128-143) + c55plus_gr1(alla, &out->reg); out->width = c55plus_reg_width(a, &out->reg); } @@ -2887,6 +2842,17 @@ static void c55plus_x_80_mem(const C55ArchDesc *a, ut64 bits, const C55OpDesc *d } } +// Destination Ra of the 0x80 "Ra = Rb + Smem" (ADD_RM) form: a 7-bit register +// field, low 6 bits in byte2[5:0] and the high bit in byte3[7] (so e.g. 0x30 -> +// T0, 0x40 -> AC0.H). The source Rb shares byte3 (its 7-bit field is byte3[6:0]). +static void c55plus_x_add_rm_ra(const C55ArchDesc *a, ut64 bits, const C55OpDesc *d, C55Operand *out) { + (void)d; + ut8 idx = (ut8)((((bits >> 7) & 1) << 6) | ((bits >> 8) & 0x3f)); // byte3[7]:byte2[5:0] + out->kind = C55_OP_REG; + c55plus_gr1(idx, &out->reg); + out->width = c55plus_reg_width(a, &out->reg); +} + // memory move. Operand A is byte1 + byte2[7:6] decoded by the shared Smem // helper; operand B is byte3, whose [6:4] field selects a register-modify mode // (0 postdec, 1 postinc, 2 *arN(t0), 3 indirect, 4 *(arN-t0), 5 *(arN-t1), @@ -3266,18 +3232,12 @@ static const C55InsnDef c55plus_table[] = { // accumulator half is byte2[5]; the Smem destination uses the same // addressing matrix as the load, with the same legacy fallback. { .mask = 0xff000000, .match = 0x51000000, .id = TMS320C55_INS_MOV, .ops = { { .fn = c55plus_x_ac_part }, { .fn = c55plus_x_smem_dest } } }, - // copy Smem, reg (opcode 0x54, 3 bytes): byte2[5:0] is the destination - // register; the Smem source reuses the store addressing decode. Accumulator - // destinations (dbl() source) and reserved slots fall back to the legacy - // decoder. - { .mask = 0xff000000, .match = 0x54000000, .id = TMS320C55_INS_COPY, .ops = { { .fn = c55plus_x_smem_dest }, { .fn = c55plus_x_gr6 } } }, - // copy dbl(*Smem), xar (opcode 0x56, 3 bytes): a double-word load of a memory - // operand into an extended AR register. byte1 holds the base ARn (low nibble) - // and a short index k4 (high nibble); byte2[3:0] is the xar destination. - // Only the indirect / indexed dbl form is decoded here (see - // c55plus_x_copy_dbl_mem); the register-modify, direct, and byte/half forms - // fall back to the legacy decoder (the absolute-address form is opcode 0xd1). - { .mask = 0xff000000, .match = 0x56000000, .id = TMS320C55_INS_COPY, .ops = { { .fn = c55plus_x_copy_dbl_mem }, { .fn = c55plus_x_copy_xar } } }, + // copy(ALLa = Smem) (opcode 0x54-0x57 LD_R, 3+ bytes): load a memory operand + // into any register. The 8-bit register id is byte0[1:0]:byte2[5:0]; the Smem + // source uses the standard byte1:byte2[7:6] addressing matrix, and the access + // is dbl iff the destination is a long (>16-bit) register. Verified against TI + // dis55 and SWPU104. + { .mask = 0xfc000000, .match = 0x54000000, .id = TMS320C55_INS_COPY, .ops = { { .fn = c55plus_x_copy_smem }, { .fn = c55plus_x_copy_alla } } }, // copy dbl(*(#addr)), xar (opcode 0xd1, 5 bytes): the absolute-address form of // the double-word load. byte1[7:6]==10 selects the dbl xar destination // (byte1[3:0]); the 24-bit byte address is bytes 2:4. Accumulator and @@ -3547,9 +3507,10 @@ static const C55InsnDef c55plus_table[] = { // mov #k16 << #sh, ACx (opcode 0xc2, byte1[7]==1). Lifted by the shared // shifted-immediate load path. { .mask = 0xff800000, .match = 0xc2800000, .id = TMS320C55_INS_MOV, .lop = C55_LOP_MOVSHL, .len = 5, .ops = { { .fn = c55plus_x_c2_imm }, { .fn = c55plus_x_c2_acy } } }, - // add *Smem, ACx, ACy (opcode 0x80, 4 bytes). Same operand shape as 0x85. - // Left unlifted. - { .mask = 0xff000000, .match = 0x80000000, .id = TMS320C55_INS_ADD, .len = 4, .ops = { { .fn = c55plus_x_80_mem }, { .fn = c55plus_x_85_acx }, { .fn = c55plus_x_85_acy } } }, + // Ra = Rb + Smem (opcode 0x80, ADD_RM, 4 bytes): the destination Ra is the + // 6-bit byte2[5:0] register, the source Rb is byte3 (gr1_sub7), and Smem is + // byte1:byte2[7:6]. Verified against TI dis55. Left unlifted. + { .mask = 0xff000000, .match = 0x80000000, .id = TMS320C55_INS_ADD, .len = 4, .ops = { { .fn = c55plus_x_80_mem }, { .fn = c55plus_x_85_acx }, { .fn = c55plus_x_add_rm_ra } } }, // or *Smem, ACx, ACy (opcode 0x85, 4 bytes). Left unlifted. { .mask = 0xff000000, .match = 0x85000000, .id = TMS320C55_INS_OR, .len = 4, .ops = { { .fn = c55plus_x_85_mem }, { .fn = c55plus_x_85_acx }, { .fn = c55plus_x_85_acy } } }, // sub ACx., *Smem, ACy. (opcode 0x82, 4 bytes). Left unlifted. @@ -3571,18 +3532,19 @@ static const C55InsnDef c55plus_table[] = { { .mask = 0xff0000c0, .match = 0xb7000000, .id = TMS320C55_INS_ADD, .len = 5, .ops = { { .fn = c55plus_x_b7_mem }, { .fn = c55plus_x_b7_acx }, { .fn = c55plus_x_b7_acy } } }, { .mask = 0xff0000c0, .match = 0xb7000040, .id = TMS320C55_INS_SUB, .len = 5, .ops = { { .fn = c55plus_x_b7_mem }, { .fn = c55plus_x_b7_acx }, { .fn = c55plus_x_b7_acy } } }, { .mask = 0xff0000c0, .match = 0xb70000c0, .id = TMS320C55_INS_MOV, .len = 5, .ops = { { .fn = c55plus_x_b7_mem }, { .fn = c55plus_x_b7_acy } } }, - // btstclr / btstset / btst / btstnot #k5, [dbl(]*Smem[)], TCx (opcode 0x91, - // byte2[4:2] selecting op+access): the extended memory bit-test family. Each row - // pins byte2[4:2]; the shared mem extractor rejects byte3[7:5]==000 so the word - // btstset below still matches that form. Left unlifted, as in the legacy decoder. + // btstclr / btstset / btst / btstnot #k, [dbl(]*Smem[)], TCx (opcode 0x91, 4 + // bytes): the memory bit-test family. byte2[4:3] selects the operation (00 + // btstclr / 01 btstset / 10 btst / 11 btstnot) and byte2[2] the access width (0 + // word / 1 dbl); the two rows per operation cover both widths. Verified against + // TI dis55 and SWPU104. Left unlifted, as in the legacy decoder. + { .mask = 0xff001c00, .match = 0x91000000, .id = TMS320C55_INS_BTSTCLR, .len = 4, .ops = { { .fn = c55plus_x_btx_bit }, { .fn = c55plus_x_btx_mem }, { .fn = c55plus_x_btx_tc } } }, { .mask = 0xff001c00, .match = 0x91000400, .id = TMS320C55_INS_BTSTCLR, .len = 4, .ops = { { .fn = c55plus_x_btx_bit }, { .fn = c55plus_x_btx_mem }, { .fn = c55plus_x_btx_tc } } }, + { .mask = 0xff001c00, .match = 0x91000800, .id = TMS320C55_INS_BTSTSET, .len = 4, .ops = { { .fn = c55plus_x_btx_bit }, { .fn = c55plus_x_btx_mem }, { .fn = c55plus_x_btx_tc } } }, { .mask = 0xff001c00, .match = 0x91000c00, .id = TMS320C55_INS_BTSTSET, .len = 4, .ops = { { .fn = c55plus_x_btx_bit }, { .fn = c55plus_x_btx_mem }, { .fn = c55plus_x_btx_tc } } }, + { .mask = 0xff001c00, .match = 0x91001000, .id = TMS320C55_INS_BTST, .len = 4, .ops = { { .fn = c55plus_x_btx_bit }, { .fn = c55plus_x_btx_mem }, { .fn = c55plus_x_btx_tc } } }, { .mask = 0xff001c00, .match = 0x91001400, .id = TMS320C55_INS_BTST, .len = 4, .ops = { { .fn = c55plus_x_btx_bit }, { .fn = c55plus_x_btx_mem }, { .fn = c55plus_x_btx_tc } } }, + { .mask = 0xff001c00, .match = 0x91001800, .id = TMS320C55_INS_BTSTNOT, .len = 4, .ops = { { .fn = c55plus_x_btx_bit }, { .fn = c55plus_x_btx_mem }, { .fn = c55plus_x_btx_tc } } }, { .mask = 0xff001c00, .match = 0x91001c00, .id = TMS320C55_INS_BTSTNOT, .len = 4, .ops = { { .fn = c55plus_x_btx_bit }, { .fn = c55plus_x_btx_mem }, { .fn = c55plus_x_btx_tc } } }, - // btstset #k, *Smem, TCx (opcode 0x91, byte3[7:5]==000): test-and-set a memory - // bit. The other 0x91 byte3[7:5] sub-codes (btstclr and the dbl-operand forms) - // are left to the legacy decoder. - { .mask = 0xff0000e0, .match = 0x91000000, .id = TMS320C55_INS_BTSTSET, .len = 4, .ops = { { .fn = c55plus_x_btstset_bit }, { .fn = c55plus_x_btstset_mem }, { .fn = c55plus_x_btstset_tc } } }, // bfxtr #k16, ACsrc, ACdst (opcode 0xc6, 5 bytes): bit-field extract, left // unlifted as in the legacy decoder. byte2[7:5]==011 is fixed (in the mask): // byte2[7] distinguishes bfxtr from the bfxpa expand form. diff --git a/test/db/asm/tms320_c55x+_32 b/test/db/asm/tms320_c55x+_32 index 82b8f3139b..d1d42b6da8 100644 --- a/test/db/asm/tms320_c55x+_32 +++ b/test/db/asm/tms320_c55x+_32 @@ -509,4 +509,17 @@ d "add *ar0(short(#0xc)), ac28.h, ac29" 80c09d5c 0x0 (set ac29 (+ (cast 40 (msb d "or *ar5(short(#0x2)), ac0.l, ac0.h" 8525a0e0 0x0 (set ac0 (| (& (var ac0) (bv 40 0xff0000ffff)) (<< (cast 40 false (| (cast 16 false (var ac0)) (loadw 0 16 (* (+ (cast 24 false (var xar5)) (bv 24 0x2)) (bv 24 0x2))))) (bv 8 0x10) false))) d "or *ar5(short(#0x6)), ac0.h, ac0.h" 856580c0 0x0 (set ac0 (| (& (var ac0) (bv 40 0xff0000ffff)) (<< (cast 40 false (| (cast 16 false (>> (var ac0) (bv 8 0x10) false)) (loadw 0 16 (* (+ (cast 24 false (var xar5)) (bv 24 0x6)) (bv 24 0x2))))) (bv 8 0x10) false))) d "sub ac0.l, *ar6(short(#0x4)), ac1.l" 8246a1e0 0x0 (set ac1 (| (& (var ac1) (bv 40 0xffffff0000)) (cast 40 false (- (loadw 0 16 (* (+ (cast 24 false (var xar6)) (bv 24 0x4)) (bv 24 0x2))) (cast 16 false (var ac0)))))) -d "sub ac0.l, *ar5(short(#0x4)), ac0.l" 8245a0e0 0x0 (set ac0 (| (& (var ac0) (bv 40 0xffffff0000)) (cast 40 false (- (loadw 0 16 (* (+ (cast 24 false (var xar5)) (bv 24 0x4)) (bv 24 0x2))) (cast 16 false (var ac0)))))) \ No newline at end of file +d "sub ac0.l, *ar5(short(#0x4)), ac0.l" 8245a0e0 0x0 (set ac0 (| (& (var ac0) (bv 40 0xffffff0000)) (cast 40 false (- (loadw 0 16 (* (+ (cast 24 false (var xar5)) (bv 24 0x4)) (bv 24 0x2))) (cast 16 false (var ac0)))))) +d "btst #0x0, *(#0xa009de), tc1" 91e05000a009de +d "btstclr #0x5, *(#0xa009de), tc1" 91e04005a009de +d "btstset #0x5, *(#0xa009de), tc1" 91e04805a009de +d "btstnot #0x5, *(#0xa009de), tc1" 91e05805a009de +d "btst #0xf, *(#0xa009de), tc1" 91e0501fa009de +d "btstnot #0x10, dbl(*ar5+), tc1" 91151c10 +d "mov t0, *(#0xa6e94e)" d030a6e94e 0x0 (storew 0 (bv 24 0xa6e94e) (var t0)) +d "mov t3, *(#0xa6e94e)" d033a6e94e 0x0 (storew 0 (bv 24 0xa6e94e) (var t3)) +d "add *(#0xa6e94e), ac5.l, t0" 80e07065a6e94e +d "add *(#0x9bbcc8), ac0, ac0.h" 80e040809bbcc8 +d "copy dbl(*ar5(#41)), xar6" 5685460029 0x0 (set xar6 (cast 24 false (loadw 0 32 (* (+ (cast 24 false (var xar5)) (bv 24 0x29)) (bv 24 0x2))))) +d "copy dbl(*ar5(#41)), ac0" 5485400029 0x0 (set ac0 (cast 40 (msb (loadw 0 32 (* (+ (cast 24 false (var xar5)) (bv 24 0x29)) (bv 24 0x2)))) (loadw 0 32 (* (+ (cast 24 false (var xar5)) (bv 24 0x29)) (bv 24 0x2))))) +d "copy *ar5(#41), ar5" 5485650029 0x0 (set ar5 (loadw 0 16 (* (+ (cast 24 false (var xar5)) (bv 24 0x29)) (bv 24 0x2))))