-
-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sign-extending signed integer types? #236
Comments
Essentially, we're reading from a byte. Do you have an example on how to get the result you're looking for in rust/bitvec? It may be possible! https://github.com/sharksforarms/deku/blob/master/src/impls/primitive.rs#L88 |
You can use Rust's arithmetic right shifts for sign-extension: fn sign_extend(num: i16, bits: u32) -> i16 {
let shift = i16::BITS - bits;
(num << shift) >> shift
} This can be combined with the I can also open a PR for this. Just let me know if this is something you want to support and whether this should be the default for signed integers. |
This is now the second time I have been asked for signed-integer support in The behavior as written is valid as long as Implementation notes: my experimental solution was to compute a sign mask, then conditionally apply it. Almost all calls into This comparison code: pub fn shifty_sext(val: i32, bits: u32) -> i32 {
check(bits);
let shamt = 32 - bits;
(val << shamt) >> shamt
}
pub fn masky_sext(mut val: i32, bits: u32) -> i32 {
check(bits);
let mask = !0 << bits;
if val & (1 << (bits - 1)) != 0 {
val |= mask;
}
val
}
pub fn shifty_sext_12(val: i32) -> i32 {
shifty_sext(val, 12)
}
pub fn masky_sext_12(val: i32) -> i32 {
masky_sext(val, 12)
}
fn check(bits: u32) {
if bits == 0 || bits > 32 {
panic!("invalid shamt");
}
} when compiled under example::shifty_sext:
mov ecx, esi
lea eax, [rcx - 1]
cmp eax, 32
jae .LBB7_1
neg cl
shl edi, cl
sar edi, cl
mov eax, edi
ret
.LBB7_1:
push rax
call std::panicking::begin_panic
ud2
example::masky_sext:
lea eax, [rsi - 1]
cmp eax, 32
jae .LBB8_1
lea eax, [rsi - 1]
movzx r8d, al
mov edx, -1
mov ecx, esi
shl edx, cl
xor eax, eax
bt edi, r8d
cmovb eax, edx
or eax, edi
ret
.LBB8_1:
push rax
call std::panicking::begin_panic
ud2
example::shifty_sext_12:
mov eax, edi
shl eax, 20
sar eax, 20
ret
example::masky_sext_12:
mov eax, edi
shl eax, 20
sar eax, 31
and eax, -4096
or eax, edi
ret While the unpropagated mask signer does not have a data dependency, the version with const-propagated length information does; this metric is now a tie and the shift signer has a shorter instruction stream (and no large immediates), so it wins. It is a bug in I believe that changing the Thanks korrat for the ping, and for tipping me over the edge into providing this support directly! |
Currently,
deku
deserializes signed integers with limited bit width like unsigned integers, as evidenced by the following (passing) test:I would expect
num
to be-1
instead, similar to how bit fields in C behave (Compiler Explorer example).Is this something that could be supported? Perhaps using another context argument?
The text was updated successfully, but these errors were encountered: