aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2026-04-12 01:00:46 +0000
committeriximeow <me@iximeow.net>2026-04-12 01:00:46 +0000
commit25eabe56e7f567565e6738273fecee4b87204a32 (patch)
tree60618ce630dfd7d1f1314ac5557b4925fe24cfe5 /src
parente6de43ec858d3d4e1219bb4b7426ff344d99dd33 (diff)
test table management instructions ({l,s}{g,i,l}dt)
these instructions, it turns out, have fixed operand size based on CPU execution mode and regardless of prefixes. good to know!
Diffstat (limited to 'src')
-rw-r--r--src/long_mode/behavior.rs24
-rw-r--r--src/long_mode/mod.rs11
2 files changed, 25 insertions, 10 deletions
diff --git a/src/long_mode/behavior.rs b/src/long_mode/behavior.rs
index a8d639d..051129d 100644
--- a/src/long_mode/behavior.rs
+++ b/src/long_mode/behavior.rs
@@ -2209,10 +2209,18 @@ fn opcode2behavior(opc: &Opcode) -> Option<BehaviorDigest> {
SYSCALL => { panic!("todo: syscall"); },
LSL => { panic!("todo: lsl"); },
LAR => { panic!("todo: lar"); },
- SGDT => { panic!("todo: sgdt"); },
- SIDT => { panic!("todo: sidt"); },
- LGDT => { panic!("todo: lgdt"); },
- LIDT => { panic!("todo: lidt"); },
+ SGDT => BehaviorDigest::empty()
+ .set_pl_special()
+ .set_operand(0, Access::Write),
+ SIDT => BehaviorDigest::empty()
+ .set_pl_special()
+ .set_operand(0, Access::Write),
+ LGDT => BehaviorDigest::empty()
+ .set_pl0()
+ .set_operand(0, Access::Read),
+ LIDT => BehaviorDigest::empty()
+ .set_pl0()
+ .set_operand(0, Access::Read),
SMSW => { panic!("todo: smsw"); },
LMSW => { panic!("todo: lmsw"); },
SWAPGS => { panic!("todo: swapgs"); },
@@ -2247,9 +2255,13 @@ fn opcode2behavior(opc: &Opcode) -> Option<BehaviorDigest> {
RDPMC => BehaviorDigest::empty()
.set_implicit_ops(RDPMC_IDX)
.set_pl_special(),
- SLDT => { panic!("todo: sldt"); },
+ SLDT => BehaviorDigest::empty()
+ .set_pl_special()
+ .set_operand(0, Access::Write),
STR => { panic!("todo: str"); },
- LLDT => { panic!("todo: lldt"); },
+ LLDT => BehaviorDigest::empty()
+ .set_pl0()
+ .set_operand(0, Access::Read),
LTR => { panic!("todo: ltr"); },
VERR => { panic!("todo: verr"); },
VERW => { panic!("todo: verw"); },
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index 117643a..7915dc0 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -8246,7 +8246,7 @@ fn read_operands<
} else {
instruction.opcode = Opcode::SGDT;
instruction.operand_count = 1;
- instruction.mem_size = 63;
+ instruction.mem_size = 10;
instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?;
}
} else if r == 1 {
@@ -8301,7 +8301,7 @@ fn read_operands<
} else {
instruction.opcode = Opcode::SIDT;
instruction.operand_count = 1;
- instruction.mem_size = 63;
+ instruction.mem_size = 10;
instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?;
}
} else if r == 2 {
@@ -8340,7 +8340,10 @@ fn read_operands<
} else {
instruction.opcode = Opcode::LGDT;
instruction.operand_count = 1;
- instruction.mem_size = 63;
+ // quoth SDM:
+ // > In 64-bit mode, the operand size is fixed at 8+2 bytes. The instruction
+ // > stores an 8-byte base and a 2-byte limit.
+ instruction.mem_size = 10;
instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?;
}
} else if r == 3 {
@@ -8404,7 +8407,7 @@ fn read_operands<
} else {
instruction.opcode = Opcode::LIDT;
instruction.operand_count = 1;
- instruction.mem_size = 63;
+ instruction.mem_size = 10;
instruction.operands[0] = read_E(words, instruction, modrm, bank, sink)?;
}
} else if r == 4 {