Skip to content

Commit 25befd4

Browse files
committed
Add an expression decoder cache to speed up move expression decoding when the same expression is encountered more than once.
1 parent a460bce commit 25befd4

File tree

2 files changed

+37
-28
lines changed

2 files changed

+37
-28
lines changed

redox-core/src/cpu.rs

+35-26
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use core::fmt;
22
use std::{arch::asm, panic, slice::Iter};
33

4+
use hashbrown::HashMap;
5+
46
use crate::{
57
com_bus::communication_bus::CommunicationBus,
68
ins::{
@@ -89,6 +91,8 @@ pub struct Cpu {
8991
pub is_in_interrupt_handler: bool,
9092
/// The last interrupt handler that was "active" (i.e. was not terminated with intret).
9193
pub last_interrupt_code: Option<u8>,
94+
/// The decoded expressions cache.
95+
decode_expression_cache: HashMap<u32, Expression>,
9296
}
9397

9498
impl Cpu {
@@ -99,6 +103,7 @@ impl Cpu {
99103
is_machine_mode: true,
100104
is_in_interrupt_handler: false,
101105
last_interrupt_code: None,
106+
decode_expression_cache: HashMap::new(),
102107
}
103108
}
104109

@@ -127,13 +132,17 @@ impl Cpu {
127132
///
128133
/// A u32 that is the calculated result of the expression.
129134
#[inline]
130-
fn decode_evaluate_u32_move_expression(
131-
&mut self,
132-
expr: &u32,
133-
privilege: &PrivilegeLevel,
134-
) -> u32 {
135-
let mut decoder = Expression::new();
136-
decoder.unpack(*expr);
135+
fn decode_evaluate_u32_expression(&mut self, expr: &u32, privilege: &PrivilegeLevel) -> u32 {
136+
// Cache the decoded expression so we don't need to do this multiple times
137+
// for the same expression.
138+
let decoder = self
139+
.decode_expression_cache
140+
.entry(*expr)
141+
.or_insert_with(|| {
142+
let mut expression = Expression::new();
143+
expression.unpack(*expr);
144+
expression
145+
});
137146

138147
// Determine the first and second operands.
139148
let value_1 = match decoder.operand_1 {
@@ -911,54 +920,54 @@ impl Cpu {
911920

912921
/******** [Bit Operation Instructions] ********/
913922
I::LeftShiftU8ImmU32Reg(imm, reg) => {
914-
let old_value = self.registers.read_reg_u32(reg, privilege);
915-
let shifted = self.perform_checked_left_shift_u32(old_value, *imm);
923+
let value = self.registers.read_reg_u32(reg, privilege);
924+
let shifted = self.perform_checked_left_shift_u32(value, *imm);
916925

917926
self.write_reg_u32(reg, shifted, privilege);
918927
}
919928
I::LeftShiftU32RegU32Reg(shift_reg, reg) => {
920929
let shift_by = self.registers.read_reg_u32(shift_reg, privilege);
921-
let old_value = self.registers.read_reg_u32(reg, privilege);
922-
let shifted = self.perform_checked_left_shift_u32(old_value, shift_by as u8);
930+
let value = self.registers.read_reg_u32(reg, privilege);
931+
let shifted = self.perform_checked_left_shift_u32(value, shift_by as u8);
923932

924933
self.write_reg_u32(reg, shifted, privilege);
925934
}
926935
I::ArithLeftShiftU8ImmU32Reg(imm, reg) => {
927-
let old_value = self.registers.read_reg_u32(reg, privilege);
928-
let shifted = self.perform_arithmetic_left_shift_u32(old_value, *imm as u32);
936+
let value = self.registers.read_reg_u32(reg, privilege);
937+
let shifted = self.perform_arithmetic_left_shift_u32(value, *imm as u32);
929938

930939
self.write_reg_u32(reg, shifted, privilege);
931940
}
932941
I::ArithLeftShiftU32RegU32Reg(shift_reg, reg) => {
933942
let shift_by = self.registers.read_reg_u32(shift_reg, privilege);
934-
let old_value = self.registers.read_reg_u32(reg, privilege);
935-
let shifted = self.perform_arithmetic_left_shift_u32(old_value, shift_by);
943+
let value = self.registers.read_reg_u32(reg, privilege);
944+
let shifted = self.perform_arithmetic_left_shift_u32(value, shift_by);
936945

937946
self.write_reg_u32(reg, shifted, privilege);
938947
}
939948
I::RightShiftU8ImmU32Reg(imm, reg) => {
940-
let old_value = self.registers.read_reg_u32(reg, privilege);
941-
let shifted = self.perform_right_shift_u32(old_value, *imm);
949+
let value = self.registers.read_reg_u32(reg, privilege);
950+
let shifted = self.perform_right_shift_u32(value, *imm);
942951

943952
self.write_reg_u32(reg, shifted, privilege);
944953
}
945954
I::RightShiftU32RegU32Reg(shift_reg, reg) => {
946955
let shift_by = self.registers.read_reg_u32(shift_reg, privilege);
947-
let old_value = self.registers.read_reg_u32(reg, privilege);
948-
let shifted = self.perform_right_shift_u32(old_value, shift_by as u8);
956+
let value = self.registers.read_reg_u32(reg, privilege);
957+
let shifted = self.perform_right_shift_u32(value, shift_by as u8);
949958

950959
self.write_reg_u32(reg, shifted, privilege);
951960
}
952961
I::ArithRightShiftU8ImmU32Reg(imm, reg) => {
953-
let old_value = self.registers.read_reg_u32(reg, privilege);
954-
let shifted = self.perform_arithmetic_right_shift_u32(old_value, *imm as u32);
962+
let value = self.registers.read_reg_u32(reg, privilege);
963+
let shifted = self.perform_arithmetic_right_shift_u32(value, *imm as u32);
955964

956965
self.write_reg_u32(reg, shifted, privilege);
957966
}
958967
I::ArithRightShiftU32RegU32Reg(shift_reg, reg) => {
959968
let shift_by = self.registers.read_reg_u32(shift_reg, privilege);
960-
let old_value = self.registers.read_reg_u32(reg, privilege);
961-
let shifted = self.perform_arithmetic_right_shift_u32(old_value, shift_by);
969+
let value = self.registers.read_reg_u32(reg, privilege);
970+
let shifted = self.perform_arithmetic_right_shift_u32(value, shift_by);
962971

963972
self.write_reg_u32(reg, shifted, privilege);
964973
}
@@ -1041,20 +1050,20 @@ impl Cpu {
10411050
}
10421051
I::MovU32ImmMemExpr(imm, expr) => {
10431052
// mov imm, &[addr] - move immediate to address.
1044-
let addr = self.decode_evaluate_u32_move_expression(expr, privilege);
1053+
let addr = self.decode_evaluate_u32_expression(expr, privilege);
10451054

10461055
com_bus.mem.set_u32(addr as usize, *imm);
10471056
}
10481057
I::MovMemExprU32Reg(expr, reg) => {
10491058
// mov &[addr], register - move value at address to register.
1050-
let addr = self.decode_evaluate_u32_move_expression(expr, privilege);
1059+
let addr = self.decode_evaluate_u32_expression(expr, privilege);
10511060
let value = com_bus.mem.get_u32(addr as usize);
10521061

10531062
self.write_reg_u32(reg, value, privilege);
10541063
}
10551064
I::MovU32RegMemExpr(reg, expr) => {
10561065
// mov &reg, &[addr] - move value of a register to an address.
1057-
let addr = self.decode_evaluate_u32_move_expression(expr, privilege);
1066+
let addr = self.decode_evaluate_u32_expression(expr, privilege);
10581067
let value = self.registers.read_reg_u32(reg, privilege);
10591068

10601069
com_bus.mem.set_u32(addr as usize, value);

redox-terminal/src/main.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,12 @@ fn main() {
6969

7070
let code = "call :LABEL_1";
7171

72-
/*let mut parser = AsmParser::new();
72+
let mut parser = AsmParser::new();
7373
parser.parse_code(code);
7474

7575
println!("parsed = {:?}", parser.parsed_instructions);
7676
println!("labels = {:?}", parser.labeled_instructions);
77-
return;*/
77+
return;
7878

7979
let instructions = &[
8080
// Indicate that we want to make a seeded random number generator.

0 commit comments

Comments
 (0)