armv8_single_step/
armv8-single-step.rs1use std::cell::RefCell;
2use std::rc::Rc;
3use std::ops::DerefMut;
4use std::num::ParseIntError;
5use std::time::Instant;
6
7use jtag_taps::cable::{self, Cable};
8use jtag_taps::statemachine::JtagSM;
9use jtag_taps::taps::Taps;
10
11use jtag_adi::{ArmDebugInterface, MemAP};
12use jtag_adi::armv8::ARMv8;
13
14use clap::Parser;
15
16#[derive(Parser, Debug)]
17#[command(author, version, about, long_about = None)]
18struct Args {
19 #[arg(short, long)]
20 cable: String,
21 #[arg(short, long)]
22 baud: u32,
23 #[arg(short, long, default_value_t = 0)]
24 tap_index: usize,
26 #[arg(short, long, default_value_t = 0)]
27 ap_num: u32,
29 #[arg(long)]
30 cpu_base: String,
31 #[arg(long)]
32 cti_base: String,
33 command: Option<String>,
34}
35
36fn cpu_halt<T,U>(mem: &mut MemAP<T>, cti_base: u32)
37 where T: DerefMut<Target=U>,
38 U: Cable + ?Sized
39{
40 mem.write(cti_base + 0x140, 0).expect("write ctigate");
42
43 mem.write(cti_base + 0x0a0, 1).expect("write ctiouten");
45
46 mem.write(cti_base + 0x01c, 1).expect("write ctiouten");
48
49 mem.write(cti_base + 0x010, 3).expect("write ctiouten");
51 while mem.read(cti_base + 0x134).unwrap() != 0 {}
53}
54
55fn parse_int(x: &str) -> Result<u32, ParseIntError> {
56 if x.starts_with("0x") {
57 let len = x.len();
58 u32::from_str_radix(&x[2..len], 16)
59 } else {
60 str::parse(&x)
61 }
62}
63
64fn main() {
65 let args = Args::parse();
66 let cable = cable::new_from_string(&args.cable, args.baud).expect("cable");
67 let jtag = JtagSM::new(cable);
68 let mut taps = Taps::new(jtag);
69 taps.detect();
70
71 let ir = vec![14];
73 taps.select_tap(0, &ir);
74 let adi = Rc::new(RefCell::new(ArmDebugInterface::new(taps)));
79 let mut mem = MemAP::new(adi.clone(), args.ap_num);
80
81 let cpu_base = parse_int(&args.cpu_base).expect("invalid cpu base");
82 let edprsr = mem.read(cpu_base + 0x314).expect("read edprsr");
83 assert!(edprsr & 1 == 1);
85
86 mem.write(cpu_base + 0x300, 0).expect("write oslar");
88
89 mem.write(cpu_base + 0xfb0, 0xC5ACCE55).expect("write oslar");
91 let oslar = mem.read(cpu_base + 0xfb4).expect("read oslar");
92 assert_eq!(oslar & 2, 0);
94
95 let mut edscr = mem.read(cpu_base + 0x088).expect("read edscr");
97 println!("edscr {:x}", edscr);
98 edscr |= 1 << 14;
99 edscr &= !(1 << 20);
101 mem.write(cpu_base + 0x088, edscr).expect("write edscr");
102
103 let cti_base = parse_int(&args.cti_base).expect("invalid cti base");
105 mem.write(cti_base + 0xfb0, 0xC5ACCE55).expect("write cti");
106
107 let mut cti = mem.read(cti_base).expect("read cti");
109 cti |= 1;
111 mem.write(cti_base, cti).expect("write cti");
112 let cti = mem.read(cti_base).expect("read cti");
113 assert_eq!(cti & 1, 1);
115
116 cpu_halt(&mut mem, cti_base);
118 mem.write(cpu_base + 0x024, 1 << 2).expect("write edecr");
120 mem.write(cpu_base + 0x090, 1 << 2).expect("write edrcr");
122
123 let mut v8 = ARMv8::new(mem, cpu_base, cti_base);
124
125 loop {
127 let edscr = v8.read_cpu(0x088).expect("read edscr");
128 if edscr & (1 << 29) == 0 {
129 break;
130 }
131 println!("bit 29");
132 v8.read_cpu(0x08c).expect("read edscr");
133 }
134
135 loop {
137 let edscr = v8.read_cpu(0x088).expect("read edscr");
138 if edscr & (1 << 30) == 0 {
139 break;
140 }
141 println!("bit 30");
142 v8.run_instr(0xd5330400).expect("write EDITR");
144 }
145
146 v8.mem.write(cti_base + 0x140, 0).expect("write ctigate");
148 v8.mem.write(cti_base + 0x0a4, 2).expect("write ctiouten");
149
150 let start = Instant::now();
151 let mut count = 0;
152 loop {
153
154 let orig_x0 = v8.get_reg(0).expect("get x0");
156
157 v8.run_instr(0xd53b4520).expect("write EDITR");
159
160 let dlr = v8.get_reg(0).expect("get x0");
161 println!("dlr {:016x}", dlr);
162
163 v8.set_reg(0, orig_x0).expect("set x0");
165
166 count += 1;
167 if count % 100 == 0 {
168 let delta = start.elapsed().as_millis();
169 eprintln!("IPS {}", count * 1000 / delta);
170 }
171
172 v8.mem.write(cti_base + 0x01c, 2).expect("write ctiouten");
174 }
175}