zingen/jump/
pc.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//! Program counter handlers.
//!
//! This module provides functionality to shift the program counter for various jump types
//! and manage the relationships between labels and their corresponding program counters.

use crate::{jump::JumpTable, Error, Result, BUFFER_LIMIT};

impl JumpTable {
    /// Shifts the program counter for all jump items.
    ///
    /// This function updates the program counters based on a starting point and an offset.
    pub fn shift_pc(&mut self, start: u16, offset: u16) -> Result<()> {
        tracing::trace!("shift pc from 0x{start:x} with offset={offset}");
        self.shift_label_pc(start, offset)?;
        self.shift_label_target(start, offset)?;
        self.shift_func_target(start, offset)
    }

    /// Shifts the program counter for labels.
    ///
    /// This function updates the program counters of labels based on the specified start
    /// point and offset.
    pub fn shift_label_pc(&mut self, start: u16, offset: u16) -> Result<()> {
        let mut new_jump = Vec::new();
        for (label, jump) in self.jump.iter() {
            let mut label = *label;
            let next_label = label + offset;
            if label > start {
                tracing::trace!(
                    "shift {jump} pc with offset={offset}: 0x{label:x}(0x{start:x}) -> 0x{:x}",
                    next_label
                );
                label = next_label;

                if label > BUFFER_LIMIT as u16 {
                    return Err(Error::InvalidPC(label as usize));
                }
            }

            new_jump.push((label, jump.clone()));
        }

        self.jump = new_jump.into_iter().collect();
        Ok(())
    }
}