saa: make saa_wleb128[us]() take appropriate types; recode

Make saa_wleb128[us]() take uint64_t and int64_t, respectively, rather
than int.

Notably, if saa_wleb128u() were to receive negative int, it would have
looped forever.

Recode these functions in a style more consistent with NASM code in
general, and possibly a bit simpler.

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin (Intel) 2026-04-06 15:55:02 -07:00
parent 9fdc7eab6e
commit 8d4733962e
2 changed files with 51 additions and 48 deletions

View file

@ -57,8 +57,8 @@ void saa_write8(struct SAA *s, uint8_t v);
void saa_write16(struct SAA *s, uint16_t v);
void saa_write32(struct SAA *s, uint32_t v);
void saa_write64(struct SAA *s, uint64_t v);
void saa_wleb128u(struct SAA *, int); /* write unsigned LEB128 value */
void saa_wleb128s(struct SAA *, int); /* write signed LEB128 value */
void saa_writeaddr(struct SAA *, uint64_t, size_t);
void saa_wleb128u(struct SAA *, uint64_t v); /* unsigned LEB128 value */
void saa_wleb128s(struct SAA *, int64_t v); /* signed LEB128 value */
void saa_writeaddr(struct SAA *, uint64_t, size_t); /* specific size integer */
#endif /* NASM_SAA_H */

View file

@ -3,6 +3,7 @@
#include "compiler.h"
#include "nasmlib.h"
#include "ilog2.h"
#include "saa.h"
/* Aggregate SAA components smaller than this */
@ -299,55 +300,57 @@ void saa_writeaddr(struct SAA *s, uint64_t v, size_t len)
saa_wbytes(s, &v, len);
}
/* write unsigned LEB128 value to SAA */
void saa_wleb128u(struct SAA *psaa, int value)
/*
* Write an LEB128 value to an SAA. Each byte contains 7 bits of
* payload in littleendian order, with the topmost bit indicating
* continuation.
*
* For the signed format, the sign bit needs to be included, even if
* it zero, so may generate an encoding that would be invalid for
* the unsigned format, e.g 127:
*
* unsigned: 7F
* signed: FF 00
*
* Thus, the >> 6 instead of >> 7 in the exit test for the signed
* version.
*/
void saa_wleb128u(struct SAA *s, uint64_t value)
{
char temp[64], *ptemp;
uint8_t buf[sizeof(value)*2]; /* Very conservative allocation :) */
uint8_t *p = buf;
uint8_t byte;
int len;
ptemp = temp;
len = 0;
do {
while (1) {
byte = value & 127;
value >>= 7;
if (value != 0) /* more bytes to come */
byte |= 0x80;
*ptemp = byte;
ptemp++;
len++;
} while (value != 0);
saa_wbytes(psaa, temp, len);
}
/* write signed LEB128 value to SAA */
void saa_wleb128s(struct SAA *psaa, int value)
{
char temp[64], *ptemp;
uint8_t byte;
bool more, negative;
int size, len;
ptemp = temp;
more = 1;
negative = (value < 0);
size = sizeof(int) * 8;
len = 0;
while (more) {
byte = value & 0x7f;
value >>= 7;
if (negative)
/* sign extend */
value |= -(1 << (size - 7));
/* sign bit of byte is second high order bit (0x40) */
if ((value == 0 && !(byte & 0x40)) ||
((value == -1) && (byte & 0x40)))
more = 0;
else
byte |= 0x80;
*ptemp = byte;
ptemp++;
len++;
if (!value) {
*p++ = byte;
break;
}
byte |= 0x80;
*p++ = byte;
}
saa_wbytes(psaa, temp, len);
saa_wbytes(s, buf, p-buf);
}
/* write a signed LEB128 value to SAA */
void saa_wleb128s(struct SAA *s, int64_t value)
{
uint8_t buf[sizeof(value)*2]; /* Very conservative allocation :) */
uint8_t *p = buf;
uint8_t byte;
int64_t sign = value >> 63;
while (1) {
byte = value & 127;
if ((value >> 6) == sign) {
*p++ = byte;
break;
}
value >>= 7;
byte |= 0x80;
*p++ = byte;
}
saa_wbytes(s, buf, p-buf);
}