8000 UImm encoding for mov operations (#147) · kddnewton/ruby@79c083e · GitHub
[go: up one dir, main page]

Skip to content

Commit 79c083e

Browse files
authored
UImm encoding for mov operations (ruby#147)
1 parent 6af33b7 commit 79c083e

File tree

3 files changed

+71
-8
lines changed

3 files changed

+71
-8
lines changed

yjit/src/asm/x86_64/mod.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,6 +1201,33 @@ pub fn mov(cb: &mut CodeBlock, dst: X86Opnd, src: X86Opnd) {
12011201
cb.write_int(imm.value as u64, reg.num_bits.into());
12021202
}
12031203
},
1204+
// R + UImm
1205+
(X86Opnd::Reg(reg), X86Opnd::UImm(uimm)) => {
1206+
assert!(uimm.num_bits <= reg.num_bits);
1207+
1208+
// In case the source immediate could be zero extended to be 64
1209+
// bit, we can use the 32-bit operands version of the instruction.
1210+
// For example, we can turn mov(rax, 0x34) into the equivalent
1211+
// mov(eax, 0x34).
1212+
if (reg.num_bits == 64) && (uimm.value <= u32::MAX.into()) {
1213+
if dst.rex_needed() {
1214+
write_rex(cb, false, 0, 0, reg.reg_no);
1215+
}
1216+
write_opcode(cb, 0xB8, reg);
1217+
cb.write_int(uimm.value, 32);
1218+
} else {
1219+
if reg.num_bits == 16 {
1220+
cb.write_byte(0x66);
1221+
}
1222+
1223+
if dst.rex_needed() || reg.num_bits == 64 {
1224+
write_rex(cb, reg.num_bits == 64, 0, 0, reg.reg_no);
1225+
}
1226+
1227+
write_opcode(cb, if reg.num_bits == 8 { 0xb0 } else { 0xb8 }, reg);
1228+
cb.write_int(uimm.value, reg.num_bits.into());
1229+
}
1230+
},
12041231
// M + Imm
12051232
(X86Opnd::Mem(mem), X86Opnd::Imm(imm)) => {
12061233
assert!(imm.num_bits <= mem.num_bits);

yjit/src/asm/x86_64/tests.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,47 @@ fn test_mov() {
162162
check_bytes("48c742f8f4ffffff", |cb| mov(cb, mem_opnd(64, RDX, -8), imm_opnd(-12)));
163163
}
164164

165+
#[test]
166+
fn test_mov_unsigned() {
167+
// MOV AL, moffs8
168+
check_bytes("b001", |cb| mov(cb, AL, uimm_opnd(1)));
169+
check_bytes("b0ff", |cb| mov(cb, AL, uimm_opnd(u8::MAX.into())));
170+
171+
// MOV AX, moffs16
172+
check_bytes("66b80100", |cb| mov(cb, AX, uimm_opnd(1)));
173+
check_bytes("66b8ffff", |cb| mov(cb, AX, uimm_opnd(u16::MAX.into())));
174+
175+
// MOV EAX, moffs32
176+
check_bytes("b801000000", |cb| mov(cb, EAX, uimm_opnd(1)));
177+
check_bytes("b8ffffffff", |cb| mov(cb, EAX, uimm_opnd(u32::MAX.into())));
178+
179+
// MOV RAX, moffs64, will move down into EAX since it fits into 32 bits
180+
check_bytes("b801000000", |cb| mov(cb, RAX, uimm_opnd(1)));
181+
check_bytes("b8ffffffff", |cb| mov(cb, RAX, uimm_opnd(u32::MAX.into())));
182+
183+
// MOV RAX, moffs64, will not move down into EAX since it does not fit into 32 bits
184+
check_bytes("48b80000000001000000", |cb| mov(cb, RAX, uimm_opnd(u32::MAX as u64 + 1)));
185+
check_bytes("48b8ffffffffffffffff", |cb| mov(cb, RAX, uimm_opnd(u64::MAX.into())));
186+
187+
// MOV r8, imm8
188+
check_bytes("41b001", |cb| mov(cb, R8B, uimm_opnd(1)));
189+
check_bytes("41b0ff", |cb| mov(cb, R8B, uimm_opnd(u8::MAX.into())));
190+
191+
// MOV r16, imm16
192+
check_bytes("6641b80100", |cb| mov(cb, R8W, uimm_opnd(1)));
193+
check_bytes("6641b8ffff", |cb| mov(cb, R8W, uimm_opnd(u16::MAX.into())));
194+
195+
// MOV r32, imm32
196+
check_bytes("41b801000000", |cb| mov(cb, R8D, uimm_opnd(1)));
197+
check_bytes("41b8ffffffff", |cb| mov(cb, R8D, uimm_opnd(u32::MAX.into())));
198+
199+
// MOV r64, imm64, will move down into 32 bit since it fits into 32 bits
200+
check_bytes("41b801000000", |cb| mov(cb, R8, uimm_opnd(1)));
201+
202+
// MOV r64, imm64, will not move down into 32 bit since it does not fit into 32 bits
203+
check_bytes("49b8ffffffffffffffff", |cb| mov(cb, R8, uimm_opnd(u64::MAX)));
204+
}
205+
165206
#[test]
166207
fn test_movsx() {
167208
check_bytes("660fbec0", |cb| movsx(cb, AX, AL));

yjit/src/codegen.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -437,13 +437,9 @@ fn gen_exit(exit_pc: *mut VALUE, ctx: &Context, cb: &mut CodeBlock) -> CodePtr
437437
pop(cb, REG_EC);
438438
pop(cb, REG_CFP);
439439

440-
//mov(cb, RAX, uimm_opnd(Qundef.into()));
440+
mov(cb, RAX, uimm_opnd(Qundef.into()));
441441
ret(cb);
442442

443-
444-
todo!("missing uimm");
445-
446-
447443
return code_ptr;
448444
}
449445

@@ -1137,9 +1133,8 @@ mod tests {
11371133
fn test_gen_exit() {
11381134
let (_, ctx, mut cb, _) = setup_codegen();
11391135

1140-
// TODO: missing encoding of uimm operands
1141-
//gen_exit(0 as *mut VALUE, &ctx, &mut cb);
1142-
//assert!(cb.get_write_pos() > 0);
1136+
gen_exit(0 as *mut VALUE, &ctx, &mut cb);
1137+
assert!(cb.get_write_pos() > 0);
11431138
}
11441139

11451140
#[test]

0 commit comments

Comments
 (0)
0