[libre-riscv-dev] spike-sv non-default element widths

Jacob Lifshay programmerjake at gmail.com
Wed Oct 10 21:34:42 BST 2018


On Wed, Oct 10, 2018 at 7:45 AM Luke Kenneth Casson Leighton <lkcl at lkcl.net>
wrote:

> .... actually.. ah.... for signed and unsigned integers, is it
> _actually_ the case that the size of the type will affect the answer,
> if typecast down to e.g. int16_t/uint16_t or int8_t/uint8_t?
>
>  by that i mean:
>
>  uint64_t x = 0..255;
>  uint64_t y = 0..255;
>  uint8_t x1 = (uint8_t)x;
>  uint8_t y1 = (uint8_t)y;
>
>  assert (x / y) == (x1 / y1)
>
> or any other operator.  will that hold for all possible values of x
> and y?  i mean, i _could_ write a for-loop to check... :)
>
Assuming the compare only operates on the lower 8 bits, it holds for
mul/add/sub/bitwise-logic/left-shift. It doesn't hold for div/mod or
right-shift. That's why there are only 1 of add/sub/and/or/xor/mul in RV
instead of a signed/unsigned version of each of them.

It works similarly for any wider bitwidth simulating a narrower bitwidth as
long as the upper bits of the results are ignored.

Note that it doesn't hold for the high-bits of a double-wide mul.

Also note that it doesn't work for signed integers in C/C++ as that depends
on wrapping around being allowed, which it isn't unless you use the -fwrapv
compiler flag. You can get around that by casting to unsigned before
running the alu op then casting to signed again (only for
mul/add/sub/and/or/xor/left-shift).

Neg/Not can be treated as (0 - x) and (~0 ^ x).

Jacob


More information about the libre-riscv-dev mailing list