arch-riscv: Fix (c.)addiw sign-extension behaviour
Previously calling a function with an INT_MAX argument would result in the following (incorrectly extended) trace: ``` lui a1, 524288 : IntAlu : D=0xffffffff80000000 c_addiw a1, -1 : IntAlu : D=0xffffffff7fffffff ``` I noticed this due to a kernel assertion that checked the second argument was bigger than the first. Since INT_MAX was incorrectly being extended to 0xffffffff7fffffff, the generated slt comparison instruction was returning 1 instead of the expected zero (which would have happened with 0x7fffffff). The problem in the current addiw logic is that the immediate value is an int64_t, so the 32-bit Rs1/Rc1 values are promoted to 64-bit for the aritmetic operation, thereby making the current cast redundant. Fix this by placing parens around the whole expression and truncating that to 32 bits. Change-Id: I7b18a8101b1c2614b9f056004e6a7f87b66b64c9 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/56103 Reviewed-by: Jason Lowe-Power <power.jg@gmail.com> Maintainer: Jason Lowe-Power <power.jg@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -135,7 +135,7 @@ decode QUADRANT default Unknown::unknown() {
|
||||
return std::make_shared<IllegalInstFault>(
|
||||
"source reg x0", machInst);
|
||||
}
|
||||
Rc1_sd = (int32_t)Rc1_sd + imm;
|
||||
Rc1_sw = (int32_t)(Rc1_sw + imm);
|
||||
}});
|
||||
0x2: c_li({{
|
||||
imm = CIMM5;
|
||||
@@ -471,7 +471,7 @@ decode QUADRANT default Unknown::unknown() {
|
||||
0x06: decode FUNCT3 {
|
||||
format IOp {
|
||||
0x0: addiw({{
|
||||
Rd_sd = Rs1_sw + imm;
|
||||
Rd_sw = (int32_t)(Rs1_sw + imm);
|
||||
}}, int32_t);
|
||||
0x1: slliw({{
|
||||
Rd_sd = Rs1_sw << imm;
|
||||
|
||||
Reference in New Issue
Block a user