aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2023-02-11 13:17:03 -0800
committeriximeow <me@iximeow.net>2023-07-04 19:01:38 -0700
commit0a26c53950d3a9cae83242c281d695729e6362da (patch)
treed715dc9ae987e89e9662592f25e607fe3dd1d456
parenta5aa1cab2c050428839afcd4ed6057ec66a6c9cb (diff)
new perf record: 51.88cpi (2363ms)
-rw-r--r--src/long_mode/mod.rs155
1 files changed, 106 insertions, 49 deletions
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index 73f658a..61c6f10 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -5014,19 +5014,13 @@ impl OperandCodeBuilder {
// SIZE IS DECIDED BY THE FOLLOWING TABLE:
// 0: 1 BYTE
// 1: 4 BYTES
- const fn with_imm(mut self, only_imm: bool, size: u8) -> Self {
+ const fn only_imm(mut self) -> Self {
self.bits |= 0x100;
- self.bits |= (size as u16) << 6;
- self.bits |= (only_imm as u16) << 7;
self
}
- fn has_imm(&self) -> Option<(bool, u8)> {
- if self.bits & 0x100 != 0 {
- Some(((self.bits & 0x80) != 0, (self.bits as u8 >> 6) & 1))
- } else {
- None
- }
+ fn has_imm(&self) -> bool {
+ self.bits & 0x100 != 0
}
}
@@ -5041,13 +5035,15 @@ pub struct OperandCodeWrapper { code: OperandCode }
enum OperandCase {
Internal = 0, // handled internally and completely by embedded rules.
Gv_M = 1, // "internal", but must be distinguished from Gv_Ev
- Nothing = 2, // no operands. this is distinct from `Internal`: `Internal` may specify one or two operands depending on embedded rules.
- SingleMMMOper = 3, // one operand, disregard rrr bits of modrm.
- BaseOpWithI8 = 4,
- BaseOpWithIv = 5,
- MovI8 = 6,
- MovIv = 7,
- BitwiseWithI8 = 8,
+ Ibs = 2,
+ Jvds = 3,
+ Nothing = 4, // no operands. this is distinct from `Internal`: `Internal` may specify one or two operands depending on embedded rules.
+ SingleMMMOper = 5, // one operand, disregard rrr bits of modrm.
+ BaseOpWithI8 = 6,
+ BaseOpWithIv = 7,
+ MovI8 = 8,
+ MovIv = 9,
+ BitwiseWithI8 = 10,
// BitwiseWithIv = 9,
ShiftBy1_b,
ShiftBy1_v,
@@ -5245,9 +5241,9 @@ enum OperandCode {
Ivs = OperandCodeBuilder::new().operand_case(OperandCase::Ivs).bits(),
I_3 = OperandCodeBuilder::new().operand_case(OperandCase::I_3).bits(),
Nothing = OperandCodeBuilder::new().operand_case(OperandCase::Nothing).bits(),
- Ib = OperandCodeBuilder::new().with_imm(false, 0).operand_case(OperandCase::Ib).bits(),
- Ibs = OperandCodeBuilder::new().with_imm(true, 0).operand_case(OperandCase::Internal).bits(),
- Jvds = OperandCodeBuilder::new().with_imm(true, 1).operand_case(OperandCase::Internal).bits(),
+ Ib = OperandCodeBuilder::new().operand_case(OperandCase::Ib).bits(),
+ Ibs = OperandCodeBuilder::new().only_imm().operand_case(OperandCase::Ibs).bits(),
+ Jvds = OperandCodeBuilder::new().only_imm().operand_case(OperandCase::Jvds).bits(),
Yv_Xv = OperandCodeBuilder::new().operand_case(OperandCase::Yv_Xv).bits(),
x87_d8 = OperandCodeBuilder::new().operand_case(OperandCase::x87_d8).bits(),
@@ -5265,10 +5261,10 @@ enum OperandCode {
.byte_operands()
.operand_case(OperandCase::SingleMMMOper)
.bits(),
- AL_Ib = OperandCodeBuilder::new().operand_case(OperandCase::AL_Ib).with_imm(false, 0).bits(),
- AX_Ib = OperandCodeBuilder::new().operand_case(OperandCase::AX_Ib).with_imm(false, 0).bits(),
- Ib_AL = OperandCodeBuilder::new().operand_case(OperandCase::Ib_AL).with_imm(false, 0).bits(),
- Ib_AX = OperandCodeBuilder::new().operand_case(OperandCase::Ib_AX).with_imm(false, 0).bits(),
+ AL_Ib = OperandCodeBuilder::new().operand_case(OperandCase::AL_Ib).bits(),
+ AX_Ib = OperandCodeBuilder::new().operand_case(OperandCase::AX_Ib).bits(),
+ Ib_AL = OperandCodeBuilder::new().operand_case(OperandCase::Ib_AL).bits(),
+ Ib_AX = OperandCodeBuilder::new().operand_case(OperandCase::Ib_AX).bits(),
AX_DX = OperandCodeBuilder::new().operand_case(OperandCase::AX_DX).bits(),
AL_DX = OperandCodeBuilder::new().operand_case(OperandCase::AL_DX).bits(),
DX_AX = OperandCodeBuilder::new().operand_case(OperandCase::DX_AX).bits(),
@@ -5363,14 +5359,12 @@ enum OperandCode {
ModRM_0x80_Eb_Ib = OperandCodeBuilder::new()
.read_modrm()
.read_E()
- .with_imm(false, 0)
.byte_operands()
.operand_case(OperandCase::BaseOpWithI8)
.bits(),
ModRM_0x83_Ev_Ibs = OperandCodeBuilder::new()
.read_modrm()
.read_E()
- .with_imm(false, 0)
.operand_case(OperandCase::ModRM_0x83)
.bits(),
// this would be Eb_Ivs, 0x8e
@@ -5475,7 +5469,7 @@ enum OperandCode {
AL_Ob = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::AL_Ob).bits(),
AL_Xb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::AL_Xb).bits(),
AX_Ov = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::AX_Ov).bits(),
- AL_Ibs = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().with_imm(false, 0).byte_operands().operand_case(OperandCase::AL_Ibs).bits(),
+ AL_Ibs = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().byte_operands().operand_case(OperandCase::AL_Ibs).bits(),
AX_Ivd = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(OperandCase::AX_Ivd).bits(),
Eb_Gb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().byte_operands().only_modrm_operands().mem_reg().operand_case(OperandCase::Internal).bits(),
@@ -5485,7 +5479,7 @@ enum OperandCode {
Gv_M = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().only_modrm_operands().reg_mem().operand_case(OperandCase::Gv_M).bits(),
MOVDIR64B = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::MOVDIR64B).bits(),
M_Gv = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::M_Gv).bits(),
- Gv_Ev_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().with_imm(false, 0).reg_mem().operand_case(OperandCase::Gv_Ev_Ib).bits(),
+ Gv_Ev_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::Gv_Ev_Ib).bits(),
Gv_Ev_Iv = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(OperandCase::Gv_Ev_Iv).bits(),
Rv_Gmm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_modrm().read_E().reg_mem().operand_case(OperandCase::Rv_Gmm_Ib).bits(),
// gap, 0x9a
@@ -7178,10 +7172,10 @@ fn read_operands<
instruction.operands[1] = mem_oper;
}
- if let Some((only_imm, immsz)) = operand_code.has_imm() {
- instruction.imm =
- read_imm_signed(words, 1 << (immsz * 2))? as u64;
- if immsz == 0 {
+ if operand_code.has_imm() {
+ if operand_code.operand_case_handler_index() == OperandCase::Ibs {
+ instruction.imm =
+ read_imm_signed(words, 1)? as u64;
sink.record(
words.offset() as u32 * 8 - 8,
words.offset() as u32 * 8 - 1,
@@ -7189,31 +7183,21 @@ fn read_operands<
.with_id(words.offset() as u32 * 8),
);
} else {
+ instruction.imm =
+ read_imm_signed(words, 4)? as u64;
sink.record(
words.offset() as u32 * 8 - 32,
words.offset() as u32 * 8 - 1,
InnerDescription::Number("4-byte immediate", instruction.imm as i64)
.with_id(words.offset() as u32 * 8),
);
- }
- if only_imm {
- if immsz == 0 {
- instruction.operands[0] = OperandSpec::ImmI8;
- } else {
- sink.record(
- words.offset() as u32 * 8 - 32,
- words.offset() as u32 * 8 - 1,
- InnerDescription::Number("4-byte immediate", instruction.imm as i64)
- .with_id(words.offset() as u32 * 8),
- );
- if instruction.opcode == Opcode::CALL {
- instruction.mem_size = 8;
- }
- instruction.operands[0] = OperandSpec::ImmI32;
+ if instruction.opcode == Opcode::CALL {
+ instruction.mem_size = 8;
}
- instruction.operand_count = 1;
- return Ok(());
+ instruction.operands[0] = OperandSpec::ImmI32;
}
+ instruction.operand_count = 1;
+ return Ok(());
}
if let Some(z_operand_code) = operand_code.get_embedded_instructions() {
@@ -7366,7 +7350,8 @@ fn read_operands<
// match operand_code {
match operand_code.operand_case_handler_index() {
- OperandCase::Internal | OperandCase::Gv_M => {
+ OperandCase::Internal | OperandCase::Gv_M |
+ OperandCase::Ibs | OperandCase::Jvds => {
}
OperandCase::SingleMMMOper => {
instruction.operands[0] = mem_oper;
@@ -7374,6 +7359,14 @@ fn read_operands<
},
OperandCase::BaseOpWithI8 => {
instruction.opcode = base_opcode_map((modrm >> 3) & 7);
+ instruction.imm =
+ read_imm_signed(words, 1)? as u64;
+ sink.record(
+ words.offset() as u32 * 8 - 8,
+ words.offset() as u32 * 8 - 1,
+ InnerDescription::Number("1-byte immediate", instruction.imm as i64)
+ .with_id(words.offset() as u32 * 8),
+ );
instruction.operands[0] = mem_oper;
instruction.operands[1] = OperandSpec::ImmI8;
@@ -7817,6 +7810,14 @@ fn read_operands<
OperandCase::AL_Ibs => {
instruction.regs[0] =
RegSpec::al();
+ instruction.imm =
+ read_imm_signed(words, 1)? as u64;
+ sink.record(
+ words.offset() as u32 * 8 - 8,
+ words.offset() as u32 * 8 - 1,
+ InnerDescription::Number("1-byte immediate", instruction.imm as i64)
+ .with_id(words.offset() as u32 * 8),
+ );
sink.record(
modrm_start as u32 - 8,
modrm_start as u32 - 1,
@@ -7872,6 +7873,14 @@ fn read_operands<
OperandCase::ModRM_0x83 => {
instruction.operands[0] = mem_oper;
instruction.opcode = base_opcode_map((modrm >> 3) & 7);
+ instruction.imm =
+ read_imm_signed(words, 1)? as u64;
+ sink.record(
+ words.offset() as u32 * 8 - 8,
+ words.offset() as u32 * 8 - 1,
+ InnerDescription::Number("1-byte immediate", instruction.imm as i64)
+ .with_id(words.offset() as u32 * 8),
+ );
sink.record(
modrm_start + 3,
modrm_start + 5,
@@ -8212,6 +8221,14 @@ fn read_operands<
instruction.regs[1].bank = RegisterBank::X;
},
OperandCase::Gv_Ev_Ib => {
+ instruction.imm =
+ read_imm_signed(words, 1)? as u64;
+ sink.record(
+ words.offset() as u32 * 8 - 8,
+ words.offset() as u32 * 8 - 1,
+ InnerDescription::Number("1-byte immediate", instruction.imm as i64)
+ .with_id(words.offset() as u32 * 8),
+ );
instruction.operands[2] = OperandSpec::ImmI8;
instruction.operand_count = 3;
}
@@ -9451,6 +9468,14 @@ fn read_operands<
}
}
OperandCase::Ib => {
+ instruction.imm =
+ read_imm_signed(words, 1)? as u64;
+ sink.record(
+ words.offset() as u32 * 8 - 8,
+ words.offset() as u32 * 8 - 1,
+ InnerDescription::Number("1-byte immediate", instruction.imm as i64)
+ .with_id(words.offset() as u32 * 8),
+ );
instruction.operands[0] = OperandSpec::ImmU8;
instruction.operand_count = 1;
}
@@ -10226,6 +10251,14 @@ fn read_operands<
OperandCase::AL_Ib => {
instruction.regs[0] =
RegSpec::al();
+ instruction.imm =
+ read_imm_signed(words, 1)? as u64;
+ sink.record(
+ words.offset() as u32 * 8 - 8,
+ words.offset() as u32 * 8 - 1,
+ InnerDescription::Number("1-byte immediate", instruction.imm as i64)
+ .with_id(words.offset() as u32 * 8),
+ );
instruction.operands[0] = OperandSpec::RegRRR;
instruction.operands[1] = OperandSpec::ImmU8;
instruction.operand_count = 2;
@@ -10233,6 +10266,14 @@ fn read_operands<
OperandCase::AX_Ib => {
instruction.regs[0].num = 0;
instruction.regs[0].bank = bank_from_prefixes_64(SizeCode::vd, instruction.prefixes);
+ instruction.imm =
+ read_imm_signed(words, 1)? as u64;
+ sink.record(
+ words.offset() as u32 * 8 - 8,
+ words.offset() as u32 * 8 - 1,
+ InnerDescription::Number("1-byte immediate", instruction.imm as i64)
+ .with_id(words.offset() as u32 * 8),
+ );
instruction.operands[0] = OperandSpec::RegRRR;
instruction.operands[1] = OperandSpec::ImmU8;
instruction.operand_count = 2;
@@ -10240,6 +10281,14 @@ fn read_operands<
OperandCase::Ib_AL => {
instruction.regs[0] =
RegSpec::al();
+ instruction.imm =
+ read_imm_signed(words, 1)? as u64;
+ sink.record(
+ words.offset() as u32 * 8 - 8,
+ words.offset() as u32 * 8 - 1,
+ InnerDescription::Number("1-byte immediate", instruction.imm as i64)
+ .with_id(words.offset() as u32 * 8),
+ );
instruction.operands[0] = OperandSpec::ImmU8;
instruction.operands[1] = OperandSpec::RegRRR;
instruction.operand_count = 2;
@@ -10247,6 +10296,14 @@ fn read_operands<
OperandCase::Ib_AX => {
instruction.regs[0].num = 0;
instruction.regs[0].bank = bank_from_prefixes_64(SizeCode::vd, instruction.prefixes);
+ instruction.imm =
+ read_imm_signed(words, 1)? as u64;
+ sink.record(
+ words.offset() as u32 * 8 - 8,
+ words.offset() as u32 * 8 - 1,
+ InnerDescription::Number("1-byte immediate", instruction.imm as i64)
+ .with_id(words.offset() as u32 * 8),
+ );
instruction.operands[0] = OperandSpec::ImmU8;
instruction.operands[1] = OperandSpec::RegRRR;
instruction.operand_count = 2;