-
Notifications
You must be signed in to change notification settings - Fork 63
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
spectool: add 64-bit test programs (GP-0.5.3) #238
base: master
Are you sure you want to change the base?
spectool: add 64-bit test programs (GP-0.5.3) #238
Conversation
subotic
commented
Dec 6, 2024
•
edited
Loading
edited
- added test programs for 64-bit instructions as per GP-0.5.3
- extended "polkavm-common/assembler" to support 64-bit instructions
- fixed some unit tests. Need pointers on how to fix them correctly.
@koute Could you maybe take a look if I'm on the right track? |
Yes, you're on the right track. (: |
@koute Also, is it possible to authorise me to run the workflows? I don't want to bother you all the time. |
@koute Is it correct, that |
@koute how to discern between |
Not entirely sure how to do that; I've added you as a read-only contributor - hopefully that will make the tests auto run.
If it's a negative number (i.e. the most significant bit is set) then yes, it should be sign extended (but the VM takes care of that automatically).
If a value can be encoded with a (And we could also have an override to force |
Great pointers thank you very much. This clears and answers a lot. |
@koute could you maybe take a look again? I had to change some unit tests, which should probably be done differently, but for this I would need your input. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR!
if let Some(index) = rhs.find("i64 ") { | ||
let rhs = rhs[index + 4..].trim(); | ||
if let Some(imm) = parse_imm(rhs) { | ||
let imm = cast(imm).to_i64_sign_extend(); | ||
emit_and_continue!(Instruction::load_imm64(dst.into(), imm as u64)); | ||
} | ||
if let Some(imm64) = parse_imm64(rhs) { | ||
emit_and_continue!(Instruction::load_imm64(dst.into(), imm64 as u64)); | ||
} | ||
} | ||
|
||
if let Some(imm) = parse_imm(rhs) { | ||
emit_and_continue!(Instruction::load_imm(dst.into(), imm as u32)); | ||
} | ||
|
||
if let Some(imm64) = parse_imm64(rhs) { | ||
emit_and_continue!(Instruction::load_imm64(dst.into(), imm64 as u64)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is partially my fault because of how the load_imm instructions are currently printed out (I need to change it, or you could change it if you want), but here's how it should work:
a0 = $value
in the assembly/disassembly code should always result it exactly the $value being loaded into the register (what you see is what you get)- by default if the immediate can be represented with
load_imm
then it always should useload_imm
, and only should fall back toload_imm64
when it cannot i64
prefix should always forceload_imm64
load_imm
can be used to load immediates between0
and0x7fffffff
(inclusive), and also any immediates where all upper 33 bits are set (because it sign extends)
So, for example:
a0 = 0xffffffff
should result in0xffffffff
being assigned, so this must useload_imm64
(becauseload_imm
will sign extend the value from 32-bits to 64-bits)a0 = 0xffffffff87654321
should result in0xffffffff87654321
being assigned and should useload_imm
by default (because all of the upper bits are1
s soload_imm
with argument0x87654321
can be used)a0 = -2
should result in0xfffffffffffffffe
being assigned and should useload_imm
by default (because all of the upper bits are1
s soload_imm
with argument0xfffffffe
can be used)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@koute Ok, I think I got it now. Can you take a look at the new parse_immediate
function and see if it correctly captures the described behaviour?
tools/spectool/src/main.rs
Outdated
let rhs = polkavm_common::utils::parse_imm(rhs) | ||
.map(|i| { | ||
if i < 0 { | ||
cast(cast(i).to_i64_sign_extend()).to_unsigned() | ||
} else { | ||
cast(cast(i).to_unsigned()).to_u64() | ||
} | ||
}) | ||
.or_else(|| polkavm_common::utils::parse_imm64(rhs).map(|i| cast(i).to_unsigned())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should work similar to how I described load_imm
should work (so what value you see is what you get if it's in hex, and if it's like e.g. -4
then it should be immediately parsed as i64)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now using the new parse_immediate
function.
pre: a0 = 1 | ||
pre: a1 = 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For these 32-bit addition tests it would be nice to have:
- Both input value are larger than 32-bit, to show that the 32-bit version effectively truncates them
- Have two versions of the test - one which results in sign extension (the 31th bit of the result is one) and one which results in no sign extension (the 31th bit of the result is zero), to show the sign extension mechanic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added two more programs. Can you please take a look and see if this is what you where thinking?
fdd41f4
to
b631909
Compare