[TriCore] Replace one- and sign-extend with MathExtra.h functions. (#2212)

* Replace one- and sign-extend with MathExtra.h functions.

This fixes incorrect sign extensions and reachable
aborts().

* Wrap around PC relative values instead of abort in case of overflow.

---------

Co-authored-by: billow <billow.fun@gmail.com>
This commit is contained in:
Rot127 2023-12-03 11:15:17 +00:00 committed by GitHub
parent d54934201c
commit 2fa9f60dcc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 53 deletions

View File

@ -416,16 +416,32 @@ static inline int64_t abs64(int64_t x) {
/// \brief Sign extend number in the bottom B bits of X to a 32-bit int.
/// Requires 0 < B <= 32.
/// Note that this implementation relies on right shift of signed
/// integers being an arithmetic shift.
static inline int32_t SignExtend32(uint32_t X, unsigned B) {
return (int32_t)(X << (32 - B)) >> (32 - B);
}
/// \brief Sign extend number in the bottom B bits of X to a 64-bit int.
/// Requires 0 < B <= 64.
/// Note that this implementation relies on right shift of signed
/// integers being an arithmetic shift.
static inline int64_t SignExtend64(uint64_t X, unsigned B) {
return (int64_t)(X << (64 - B)) >> (64 - B);
}
/// \brief One extend number X starting at bit B and returns it as int32_t.
/// Requires 0 < B <= 32.
static inline int32_t OneExtend32(uint32_t X, unsigned B) {
return (~0U << B) | X;
}
/// \brief One extend number X starting at bit B and returns it as int64_t.
/// Requires 0 < B <= 64.
static inline int64_t OneExtend64(uint64_t X, unsigned B) {
return (~0ULL << B) | X;
}
/// \brief Count number of 0's from the most significant bit to the least
/// stopping at the first 1.
///

View File

@ -39,38 +39,12 @@ static void printOperand(MCInst *MI, int OpNum, SStream *O);
#include "TriCoreGenRegisterInfo.inc"
static uint32_t to_u32(int64_t x)
static uint32_t wrapping_u32(int64_t x)
{
if (x > UINT32_MAX || x < -(int64_t)(UINT32_MAX)) {
abort();
}
x %= (int64_t)(UINT32_MAX);
return (uint32_t)x;
}
static inline unsigned int get_msb(uint64_t value)
{
unsigned int msb = 0;
while (value > 0) {
value >>= 1; // Shift bits to the right
msb++; // Increment the position of the MSB
}
return msb;
}
static inline int64_t sign_ext64(int64_t imm, unsigned n)
{
n = get_msb(imm) > n ? get_msb(imm) : n;
int64_t mask = 1 << (n - 1);
return (imm ^ mask) - mask;
}
static inline int32_t sign_ext32(int32_t imm, unsigned n)
{
n = get_msb(imm) > n ? get_msb(imm) : n;
int32_t mask = 1 << (n - 1);
return (imm ^ mask) - mask;
}
static bool fill_mem(MCInst *MI, unsigned int reg, int64_t disp);
static inline void set_mem(cs_tricore_op *op, uint8_t base, int64_t disp)
@ -193,7 +167,7 @@ static void printOperand(MCInst *MI, int OpNum, SStream *O)
fill_reg(MI, reg);
} else if (MCOperand_isImm(Op)) {
int64_t Imm = MCOperand_getImm(Op);
printUInt32Bang(O, to_u32(Imm));
printUInt32Bang(O, wrapping_u32(Imm));
fill_imm(MI, Imm);
}
}
@ -203,7 +177,7 @@ static void print_sign_ext(MCInst *MI, int OpNum, SStream *O, unsigned n)
MCOperand *MO = MCInst_getOperand(MI, OpNum);
if (MCOperand_isImm(MO)) {
int64_t imm = MCOperand_getImm(MO);
int32_t res = sign_ext32(to_u32(imm), n);
int32_t res = SignExtend32(wrapping_u32(imm), n);
printInt32Bang(O, res);
fill_imm(MI, res);
} else
@ -262,7 +236,7 @@ static void print_zero_ext(MCInst *MI, int OpNum, SStream *O, unsigned n)
const8_fixup(MI, &imm);
}
printUInt32Bang(O, to_u32(imm));
printUInt32Bang(O, wrapping_u32(imm));
fill_imm(MI, imm);
} else
printOperand(MI, OpNum, O);
@ -273,17 +247,18 @@ static void printOff18Imm(MCInst *MI, int OpNum, SStream *O)
MCOperand *MO = MCInst_getOperand(MI, OpNum);
if (MCOperand_isImm(MO)) {
int64_t imm = MCOperand_getImm(MO);
imm = ((to_u32(imm) & 0x3C000) << 14) | (to_u32(imm) & 0x3fff);
printUInt32Bang(O, to_u32(imm));
imm = ((wrapping_u32(imm) & 0x3C000) << 14) |
(wrapping_u32(imm) & 0x3fff);
printUInt32Bang(O, wrapping_u32(imm));
fill_imm(MI, imm);
} else
printOperand(MI, OpNum, O);
}
// PC + sext(2 * disp)
#define DISP1(N) ((int64_t)(MI->address) + sign_ext64(disp * 2, N))
#define DISP1(N) ((int64_t)(MI->address) + SignExtend64(disp * 2, N))
// PC + sext(disp) * 2
#define DISP2(N) ((int64_t)(MI->address) + sign_ext64(disp, N) * 2)
#define DISP2(N) ((int64_t)(MI->address) + SignExtend64(disp, N) * 2)
static void printDisp24Imm(MCInst *MI, int OpNum, SStream *O)
{
@ -302,8 +277,8 @@ static void printDisp24Imm(MCInst *MI, int OpNum, SStream *O)
case TRICORE_JA_b:
case TRICORE_JLA_b:
// = {disp24[23:20], 7b0000000, disp24[19:0], 1b0};
res = ((to_u32(disp) & 0xf00000) << 28) |
((to_u32(disp) & 0xfffff) << 1);
res = ((wrapping_u32(disp) & 0xf00000) << 28) |
((wrapping_u32(disp) & 0xfffff) << 1);
break;
case TRICORE_J_b:
case TRICORE_JL_b:
@ -311,7 +286,7 @@ static void printDisp24Imm(MCInst *MI, int OpNum, SStream *O)
break;
}
printUInt32Bang(O, to_u32(res));
printUInt32Bang(O, wrapping_u32(res));
fill_imm(MI, res);
} else
printOperand(MI, OpNum, O);
@ -357,7 +332,7 @@ static void printDisp15Imm(MCInst *MI, int OpNum, SStream *O)
break;
}
printUInt32Bang(O, to_u32(res));
printUInt32Bang(O, wrapping_u32(res));
fill_imm(MI, res);
} else
printOperand(MI, OpNum, O);
@ -383,7 +358,7 @@ static void printDisp8Imm(MCInst *MI, int OpNum, SStream *O)
break;
}
printUInt32Bang(O, to_u32(res));
printUInt32Bang(O, wrapping_u32(res));
fill_imm(MI, res);
} else
printOperand(MI, OpNum, O);
@ -422,16 +397,15 @@ static void printDisp4Imm(MCInst *MI, int OpNum, SStream *O)
break;
case TRICORE_LOOP_sbr:
// PC + {27b111111111111111111111111111, disp4, 0};
res = (int64_t)(MI->address) +
((0b111111111111111111111111111LL << 5) |
(to_u32(disp) << 1));
res = (int64_t)MI->address +
OneExtend32(wrapping_u32(disp) << 1, 5);
break;
default:
// handle other cases, if any
break;
}
printUInt32Bang(O, to_u32(res));
printUInt32Bang(O, wrapping_u32(res));
fill_imm(MI, res);
} else
printOperand(MI, OpNum, O);
@ -476,10 +450,9 @@ static void printOExtImm_4(MCInst *MI, int OpNum, SStream *O)
MCOperand *MO = MCInst_getOperand(MI, OpNum);
if (MCOperand_isImm(MO)) {
int64_t disp = MCOperand_getImm(MO);
int64_t res = (int64_t)(MI->address) +
((0b111111111111111111111111111 << 5) |
(to_u32(disp) << 1));
printUInt32Bang(O, to_u32(res));
int64_t res = (int64_t)MI->address +
(int64_t)OneExtend64(disp << 1, 5);
printUInt32Bang(O, wrapping_u32(res));
fill_imm(MI, res);
} else
printOperand(MI, OpNum, O);

View File

@ -62,7 +62,7 @@
0xf6,0x24 = jnz d2, #0x8
0xfc,0xf6 = loop a15, #-0x14
0x37,0x00,0x62,0xfe = extr.u d15, d0, #0x1c, #0x2
0x6d,0xb8,0xf4,0x11 = call #-0x8fdc18
0x6d,0xb8,0xf4,0x11 = call #0x7023e8
0x91,0x00,0x03,0xfa = movh.a a15, #0xa030
0x3b,0x20,0xfe,0x0f = mov d0, #-0x1e
0x37,0x00,0x61,0x03 = extr.u d0, d0, #0x6, #0x1
@ -122,7 +122,7 @@
0x91,0x10,0x00,0xa4 = movh.a sp, #0x4001
0x37,0xf0,0x02,0x0e = insert d0, d0, d15, #0x1c, #0x2
0xd9,0xff,0xc8,0x22 = lea a15, [a15]#0x2c88
0x6d,0xb8,0x80,0x11 = call #-0x8fdd00
0x6d,0xb8,0x80,0x11 = call #0x702300
0x15,0xd0,0xc0,0xeb = ldlcx #0xd0003f80
0x4b,0x00,0x41,0x01 = itof d0, d0
0xb4,0xc2 = st.h [a12], d2
@ -156,7 +156,7 @@
0x60,0xc2 = mov.a a2, d12
0xd9,0xff,0x30,0x96 = lea a15, [a15]#0x6270
0x37,0xf0,0x02,0xf0 = insert d15, d0, d15, #0, #0x2
0x6d,0xa0,0x80,0x11 = call #-0xbfdd00
0x6d,0xa0,0x80,0x11 = call #0x402300
0x3b,0x00,0x00,0xf3 = mov d15, #0x3000
0x6d,0x00,0x26,0x05 = call #0xa4c
0xb7,0x0f,0x01,0xf1 = insert d15, d15, #0, #0x2, #0x1
@ -559,7 +559,7 @@
0x91,0x00,0x00,0xf8 = movh.a a15, #0x8000
0x37,0x0f,0x83,0xf1 = insert d15, d15, d0, #0x3, #0x3
0x7e,0x05 = jne d15, d0, #0xa
0x6d,0xa0,0xf4,0x11 = call #-0xbfdc18
0x6d,0xa0,0xf4,0x11 = call #0x4023e8
0x49,0xff,0x0c,0x0a = lea a15, [a15]#0xc
0xb7,0x6f,0x08,0xf0 = insert d15, d15, #0x6, #0, #0x8
0x10,0xe4 = addsc.a a4, a14, d15, #0
@ -884,7 +884,7 @@
0x6d,0xff,0x78,0xfb = call #-0x910
0x3b,0x00,0xd0,0x02 = mov d0, #0x2d00
0xd9,0x11,0x00,0x00 = lea a1, [a1]#0
0x6d,0x88,0x80,0x11 = call #-0xefdd00
0x6d,0x88,0x80,0x11 = call #0x102300
0xda,0x05 = mov d15, #0x5
0x3c,0x0d = j #0x1a
0xe2,0x1f = mul d15, d1