parasol_cpu/proc/ops/
load.rs1use crate::{
2 Byte, Ciphertext, Error, Memory, Ptr32, Register, Result,
3 proc::{DispatchIsaOp, fhe_processor::FheProcessor, ops::is_invalid_load_store_alignment},
4 tomasulo::{registers::RobEntryRef, tomasulo_processor::RetirementInfo},
5 unwrap_registers,
6};
7
8impl FheProcessor {
9 #[allow(clippy::too_many_arguments)]
10 pub fn load(
12 &mut self,
13 retirement_info: RetirementInfo<DispatchIsaOp>,
14 memory: &Memory,
15 src: RobEntryRef<Register>,
16 dst: RobEntryRef<Register>,
17 offset: i32,
18 width: u32,
19 instruction_id: usize,
20 pc: u32,
21 ) {
22 let load_impl = || -> Result<()> {
23 unwrap_registers!((mut dst) (src));
24
25 match src {
26 Register::Plaintext { val: ptr, width: _ } => {
27 let num_bytes = width / 8;
28
29 let base_addr = Ptr32::from(*ptr as u32).try_signed_offset(offset)?;
30
31 if is_invalid_load_store_alignment(base_addr, num_bytes) {
32 return Err(Error::UnalignedAccess(base_addr.0));
33 }
34
35 match memory.try_load(base_addr)? {
38 Byte::Plaintext(val) => {
39 let mut result = val as u128;
40
41 for i in 1..num_bytes {
42 match memory.try_load(base_addr.try_offset(i).unwrap())? {
44 Byte::Plaintext(b) => {
45 result |= (b as u128) << (8 * i);
46 }
47 _ => {
48 return Err(Error::buffer_not_a_plaintext());
49 }
50 }
51 }
52
53 *dst = Register::Plaintext { val: result, width };
54 }
55 Byte::Ciphertext(val) => {
56 let mut result = val.clone();
57
58 for i in 1..num_bytes {
59 match memory.try_load(base_addr.try_offset(i).unwrap())? {
61 Byte::Ciphertext(mut b) => {
62 result.append(&mut b);
63 }
64 _ => {
65 return Err(Error::buffer_not_a_ciphertext());
66 }
67 }
68 }
69
70 *dst = Register::Ciphertext(Ciphertext::L1Glwe { data: result });
71 }
72 };
73
74 FheProcessor::retire(&retirement_info, Ok(()));
75 }
76 _ => {
77 return Err(Error::IllegalOperands {
78 inst_id: instruction_id,
79 pc,
80 });
81 }
82 };
83
84 Ok(())
85 };
86
87 if let Err(e) = load_impl() {
88 FheProcessor::retire(&retirement_info, Err(e));
89 }
90 }
91}