1use crate::{
4 CoreInterface, CoreRegister, CoreStatus, CoreType, Error, HaltReason, InstructionSet,
5 MemoryInterface, MemoryMappedRegister,
6 architecture::riscv::sequences::RiscvDebugSequence,
7 core::{
8 Architecture, BreakpointCause, CoreInformation, CoreRegisters, RegisterId, RegisterValue,
9 },
10 memory::{CoreMemoryInterface, valid_32bit_address},
11 memory_mapped_bitfield_register,
12 probe::DebugProbeError,
13 semihosting::SemihostingCommand,
14 semihosting::decode_semihosting_syscall,
15};
16use bitfield::bitfield;
17use communication_interface::{AbstractCommandErrorKind, RiscvCommunicationInterface, RiscvError};
18use registers::{FP, RA, RISCV_CORE_REGISTERS, RISCV_WITH_FP_CORE_REGISTERS, SP};
19use std::{
20 sync::Arc,
21 time::{Duration, Instant},
22};
23
24#[macro_use]
25pub mod registers;
26pub use registers::PC;
27pub(crate) mod assembly;
28pub mod communication_interface;
29pub(crate) mod dtm;
30pub mod sequences;
31
32pub use dtm::jtag_dtm::JtagDtmBuilder;
33
34pub struct Riscv32<'state> {
36 interface: RiscvCommunicationInterface<'state>,
37 state: &'state mut RiscvCoreState,
38 sequence: Arc<dyn RiscvDebugSequence>,
39}
40
41impl<'state> Riscv32<'state> {
42 pub fn new(
44 mut interface: RiscvCommunicationInterface<'state>,
45 state: &'state mut RiscvCoreState,
46 sequence: Arc<dyn RiscvDebugSequence>,
47 ) -> Result<Self, RiscvError> {
48 if !state.misa_read {
49 let misa_val = interface
51 .read_csr(Misa::get_mmio_address() as u16)
52 .unwrap_or(0);
53 let isa_extensions = Misa::from(misa_val).extensions();
54 let fp_mask = (1 << 3) | (1 << 5) | (1 << 16);
55 state.fp_present = isa_extensions & fp_mask != 0;
56 state.misa_read = true;
57 }
58
59 Ok(Self {
60 interface,
61 state,
62 sequence,
63 })
64 }
65
66 fn read_csr(&mut self, address: u16) -> Result<u32, RiscvError> {
67 self.interface.read_csr(address)
68 }
69
70 fn write_csr(&mut self, address: u16, value: u32) -> Result<(), RiscvError> {
71 tracing::debug!("Writing CSR {:#x}", address);
72
73 match self.interface.abstract_cmd_register_write(address, value) {
74 Err(RiscvError::AbstractCommand(AbstractCommandErrorKind::NotSupported)) => {
75 tracing::debug!(
76 "Could not write core register {:#x} with abstract command, falling back to program buffer",
77 address
78 );
79 self.interface.write_csr_progbuf(address, value)
80 }
81 other => other,
82 }
83 }
84
85 fn resume_core(&mut self) -> Result<(), crate::Error> {
87 self.state.semihosting_command = None;
88 self.interface.resume_core()?;
89
90 Ok(())
91 }
92
93 fn check_for_semihosting(&mut self) -> Result<Option<SemihostingCommand>, Error> {
95 const TRAP_INSTRUCTIONS: [u32; 3] = [
100 0x01f01013, 0x00100073, 0x40705013, ];
104
105 if let Some(command) = self.state.semihosting_command {
107 return Ok(Some(command));
108 }
109
110 let pc: u32 = self.read_core_reg(self.program_counter().id)?.try_into()?;
111
112 let mut actual_instructions = [0u32; 3];
114 self.read_32((pc - 4) as u64, &mut actual_instructions)?;
115 let actual_instructions = actual_instructions.as_slice();
116
117 tracing::debug!(
118 "Semihosting check pc={pc:#x} instructions={0:#08x} {1:#08x} {2:#08x}",
119 actual_instructions[0],
120 actual_instructions[1],
121 actual_instructions[2]
122 );
123
124 let command = if TRAP_INSTRUCTIONS == actual_instructions {
125 let syscall = decode_semihosting_syscall(self)?;
126 if let SemihostingCommand::Unknown(details) = syscall {
127 self.sequence
128 .clone()
129 .on_unknown_semihosting_command(self, details)?
130 } else {
131 Some(syscall)
132 }
133 } else {
134 None
135 };
136 self.state.semihosting_command = command;
137
138 Ok(command)
139 }
140
141 fn determine_number_of_hardware_breakpoints(&mut self) -> Result<u32, RiscvError> {
142 tracing::debug!("Determining number of HW breakpoints supported");
143
144 let tselect = 0x7a0;
145 let tdata1 = 0x7a1;
146 let tinfo = 0x7a4;
147
148 let mut tselect_index = 0;
149
150 loop {
152 tracing::debug!("Trying tselect={}", tselect_index);
153 if let Err(e) = self.write_csr(tselect, tselect_index) {
154 match e {
155 RiscvError::AbstractCommand(AbstractCommandErrorKind::Exception) => break,
156 other_error => return Err(other_error),
157 }
158 }
159
160 let readback = self.read_csr(tselect)?;
161
162 if readback != tselect_index {
163 break;
164 }
165
166 match self.read_csr(tinfo) {
167 Ok(tinfo_val) => {
168 if tinfo_val & 0xffff == 1 {
169 break;
171 } else {
172 tracing::info!(
173 "Discovered trigger with index {} and type {}",
174 tselect_index,
175 tinfo_val & 0xffff
176 );
177 }
178 }
179 Err(RiscvError::AbstractCommand(AbstractCommandErrorKind::Exception)) => {
180 let tdata_val = self.read_csr(tdata1)?;
182
183 let misa_value = Misa(self.read_csr(0x301)?);
185 let xlen = u32::pow(2, misa_value.mxl() + 4);
186
187 let trigger_type = tdata_val >> (xlen - 4);
188
189 if trigger_type == 0 {
190 break;
191 }
192
193 tracing::info!(
194 "Discovered trigger with index {} and type {}",
195 tselect_index,
196 trigger_type,
197 );
198 }
199 Err(other) => return Err(other),
200 }
201
202 tselect_index += 1;
203 }
204
205 tracing::debug!("Target supports {} breakpoints.", tselect_index);
206
207 Ok(tselect_index)
208 }
209
210 fn on_halted(&mut self) -> Result<(), Error> {
211 let status = self.status()?;
212 tracing::debug!("Core halted: {:#?}", status);
213
214 if status.is_halted() {
215 self.sequence.on_halt(&mut self.interface)?;
216 }
217
218 Ok(())
219 }
220}
221
222impl CoreInterface for Riscv32<'_> {
223 fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), crate::Error> {
224 self.interface.wait_for_core_halted(timeout)?;
225 self.on_halted()?;
226 self.state.pc_written = false;
227 Ok(())
228 }
229
230 fn core_halted(&mut self) -> Result<bool, crate::Error> {
231 Ok(self.interface.core_halted()?)
232 }
233
234 fn status(&mut self) -> Result<crate::core::CoreStatus, crate::Error> {
235 let status: Dmstatus = self.interface.read_dm_register()?;
239
240 if status.allhalted() {
241 let dcsr = Dcsr(self.read_core_reg(RegisterId::from(0x7b0))?.try_into()?);
243
244 let reason = match dcsr.cause() {
245 1 => {
247 self.state.pc_written = false;
249 if let Some(cmd) = self.check_for_semihosting()? {
250 HaltReason::Breakpoint(BreakpointCause::Semihosting(cmd))
251 } else {
252 HaltReason::Breakpoint(BreakpointCause::Software)
253 }
254 }
256 2 => HaltReason::Breakpoint(BreakpointCause::Hardware),
258 3 => HaltReason::Request,
260 4 => HaltReason::Step,
262 5 => HaltReason::Exception,
264 _ => HaltReason::Unknown,
266 };
267
268 Ok(CoreStatus::Halted(reason))
269 } else if status.allrunning() {
270 Ok(CoreStatus::Running)
271 } else {
272 Err(Error::Other(
273 "Some cores are running while some are halted, this should not happen.".to_string(),
274 ))
275 }
276 }
277
278 fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
279 self.interface.halt(timeout)?;
280 self.on_halted()?;
281 Ok(self.interface.core_info()?)
282 }
283
284 fn run(&mut self) -> Result<(), Error> {
285 if !self.state.pc_written {
286 self.step()?;
288 }
289
290 self.resume_core()?;
292
293 Ok(())
294 }
295
296 fn reset(&mut self) -> Result<(), Error> {
297 self.reset_and_halt(Duration::from_secs(1))?;
298 self.resume_core()?;
299
300 Ok(())
301 }
302
303 fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
304 self.sequence
305 .reset_system_and_halt(&mut self.interface, timeout)?;
306
307 self.on_halted()?;
308 let pc = self.read_core_reg(RegisterId(0x7b1))?;
309
310 Ok(CoreInformation { pc: pc.try_into()? })
311 }
312
313 fn step(&mut self) -> Result<CoreInformation, crate::Error> {
314 let halt_reason = self.status()?;
315 if matches!(
316 halt_reason,
317 CoreStatus::Halted(HaltReason::Breakpoint(
318 BreakpointCause::Software | BreakpointCause::Semihosting(_)
319 ))
320 ) {
321 let mut debug_pc = self.read_core_reg(RegisterId(0x7b1))?;
323 if matches!(self.instruction_set()?, InstructionSet::RV32C) {
325 let instruction = self.read_word_32(debug_pc.try_into().unwrap())?;
328 if instruction & 0x3 != 0x3 {
329 debug_pc.increment_address(2)?;
331 } else {
332 debug_pc.increment_address(4)?;
333 }
334 } else {
335 debug_pc.increment_address(4)?;
336 }
337
338 self.write_core_reg(RegisterId(0x7b1), debug_pc)?;
339 return Ok(CoreInformation {
340 pc: debug_pc.try_into()?,
341 });
342 } else if matches!(
343 halt_reason,
344 CoreStatus::Halted(HaltReason::Breakpoint(BreakpointCause::Hardware))
345 ) {
346 self.enable_breakpoints(false)?;
348 }
349
350 let mut dcsr = Dcsr(self.read_core_reg(RegisterId(0x7b0))?.try_into()?);
351 dcsr.set_step(true);
353 dcsr.set_stepie(false);
355 dcsr.set_stopcount(true);
356 self.write_csr(0x7b0, dcsr.0)?;
357
358 self.resume_core()?;
360 self.wait_for_core_halted(Duration::from_millis(100))?;
361
362 let pc = self.read_core_reg(RegisterId(0x7b1))?;
363
364 let mut dcsr = Dcsr(self.read_core_reg(RegisterId(0x7b0))?.try_into()?);
366 dcsr.set_step(false);
367 dcsr.set_stepie(true);
369 dcsr.set_stopcount(false);
370 self.write_csr(0x7b0, dcsr.0)?;
371
372 if matches!(
374 halt_reason,
375 CoreStatus::Halted(HaltReason::Breakpoint(BreakpointCause::Hardware))
376 ) {
377 self.enable_breakpoints(true)?;
379 }
380
381 self.on_halted()?;
382 self.state.pc_written = false;
383 Ok(CoreInformation { pc: pc.try_into()? })
384 }
385
386 fn read_core_reg(&mut self, address: RegisterId) -> Result<RegisterValue, crate::Error> {
387 self.read_csr(address.0)
388 .map(|v| v.into())
389 .map_err(|e| e.into())
390 }
391
392 fn write_core_reg(
393 &mut self,
394 address: RegisterId,
395 value: RegisterValue,
396 ) -> Result<(), crate::Error> {
397 let value: u32 = value.try_into()?;
398
399 if address == self.program_counter().id {
400 self.state.pc_written = true;
401 }
402
403 self.write_csr(address.0, value).map_err(|e| e.into())
404 }
405
406 fn available_breakpoint_units(&mut self) -> Result<u32, crate::Error> {
407 match self.state.hw_breakpoints {
408 Some(bp) => Ok(bp),
409 None => {
410 let bp = self.determine_number_of_hardware_breakpoints()?;
411 self.state.hw_breakpoints = Some(bp);
412 Ok(bp)
413 }
414 }
415 }
416
417 fn hw_breakpoints(&mut self) -> Result<Vec<Option<u64>>, Error> {
420 let was_running = !self.core_halted()?;
423 if was_running {
424 self.halt(Duration::from_millis(100))?;
425 }
426
427 let tselect = 0x7a0;
428 let tdata1 = 0x7a1;
429 let tdata2 = 0x7a2;
430
431 let mut breakpoints = vec![];
432 let num_hw_breakpoints = self.available_breakpoint_units()? as usize;
433 for bp_unit_index in 0..num_hw_breakpoints {
434 self.write_csr(tselect, bp_unit_index as u32)?;
436
437 let tdata_value = Mcontrol(self.read_csr(tdata1)?);
439
440 tracing::debug!("Breakpoint {}: {:?}", bp_unit_index, tdata_value);
441
442 let trigger_any_mode_active = tdata_value.m() || tdata_value.s() || tdata_value.u();
444
445 let trigger_any_action_enabled =
446 tdata_value.execute() || tdata_value.store() || tdata_value.load();
447
448 if tdata_value.type_() == 0b10
450 && tdata_value.action() == 1
451 && tdata_value.match_() == 0
452 && trigger_any_mode_active
453 && trigger_any_action_enabled
454 {
455 let breakpoint = self.read_csr(tdata2)?;
456 breakpoints.push(Some(breakpoint as u64));
457 } else {
458 breakpoints.push(None);
459 }
460 }
461
462 if was_running {
463 self.resume_core()?;
464 }
465
466 Ok(breakpoints)
467 }
468
469 fn enable_breakpoints(&mut self, state: bool) -> Result<(), crate::Error> {
470 let tselect = 0x7a0;
472 let tdata1 = 0x7a1;
473
474 for bp_unit_index in 0..self.available_breakpoint_units()? as usize {
475 self.write_csr(tselect, bp_unit_index as u32)?;
477
478 let mut tdata_value = Mcontrol(self.read_csr(tdata1)?);
480
481 if tdata_value.type_() == 2
483 && tdata_value.action() == 1
484 && tdata_value.match_() == 0
485 && tdata_value.execute()
486 && ((tdata_value.m() && tdata_value.u()) || (!tdata_value.m() && !tdata_value.u()))
487 {
488 tracing::debug!(
489 "Will modify breakpoint enabled={} for {}: {:?}",
490 state,
491 bp_unit_index,
492 tdata_value
493 );
494 tdata_value.set_m(state);
495 tdata_value.set_u(state);
496 self.write_csr(tdata1, tdata_value.0)?;
497 }
498 }
499
500 self.state.hw_breakpoints_enabled = state;
501 Ok(())
502 }
503
504 fn set_hw_breakpoint(&mut self, bp_unit_index: usize, addr: u64) -> Result<(), crate::Error> {
505 let addr = valid_32bit_address(addr)?;
506
507 let tselect = 0x7a0;
509 let tdata1 = 0x7a1;
510 let tdata2 = 0x7a2;
511
512 tracing::info!("Setting breakpoint {}", bp_unit_index);
513
514 self.write_csr(tselect, bp_unit_index as u32)?;
515
516 let tdata_value = Mcontrol(self.read_csr(tdata1)?);
519
520 let trigger_type = tdata_value.type_();
522 if trigger_type != 0b10 {
523 return Err(RiscvError::UnexpectedTriggerType(trigger_type).into());
524 }
525
526 let mut instruction_breakpoint = Mcontrol(0);
529
530 instruction_breakpoint.set_action(1);
532
533 instruction_breakpoint.set_type(2);
535 instruction_breakpoint.set_match(0);
536
537 instruction_breakpoint.set_m(true);
538
539 instruction_breakpoint.set_u(true);
540
541 instruction_breakpoint.set_execute(true);
543
544 instruction_breakpoint.set_dmode(true);
545
546 instruction_breakpoint.set_select(false);
548
549 self.write_csr(tdata1, 0)?;
550 self.write_csr(tdata2, addr)?;
551 self.write_csr(tdata1, instruction_breakpoint.0)?;
552
553 Ok(())
554 }
555
556 fn clear_hw_breakpoint(&mut self, unit_index: usize) -> Result<(), crate::Error> {
557 tracing::info!("Clearing breakpoint {}", unit_index);
559
560 let was_running = !self.core_halted()?;
561 if was_running {
562 self.halt(Duration::from_millis(100))?;
563 }
564
565 let tselect = 0x7a0;
566 let tdata1 = 0x7a1;
567 let tdata2 = 0x7a2;
568
569 self.write_csr(tselect, unit_index as u32)?;
570 self.write_csr(tdata1, 0)?;
571 self.write_csr(tdata2, 0)?;
572
573 if was_running {
574 self.resume_core()?;
575 }
576
577 Ok(())
578 }
579
580 fn registers(&self) -> &'static CoreRegisters {
581 if self.state.fp_present {
582 &RISCV_WITH_FP_CORE_REGISTERS
583 } else {
584 &RISCV_CORE_REGISTERS
585 }
586 }
587
588 fn program_counter(&self) -> &'static CoreRegister {
589 &PC
590 }
591
592 fn frame_pointer(&self) -> &'static CoreRegister {
593 &FP
594 }
595
596 fn stack_pointer(&self) -> &'static CoreRegister {
597 &SP
598 }
599
600 fn return_address(&self) -> &'static CoreRegister {
601 &RA
602 }
603
604 fn hw_breakpoints_enabled(&self) -> bool {
605 self.state.hw_breakpoints_enabled
606 }
607
608 fn architecture(&self) -> Architecture {
609 Architecture::Riscv
610 }
611
612 fn core_type(&self) -> CoreType {
613 CoreType::Riscv
614 }
615
616 fn instruction_set(&mut self) -> Result<InstructionSet, Error> {
617 let misa_value = Misa(self.read_csr(0x301)?);
618
619 if misa_value.extensions() & (1 << 2) != 0 {
621 Ok(InstructionSet::RV32C)
622 } else {
623 Ok(InstructionSet::RV32)
624 }
625 }
626
627 fn floating_point_register_count(&mut self) -> Result<usize, Error> {
629 Ok(self
630 .registers()
631 .all_registers()
632 .filter(|r| r.register_has_role(crate::RegisterRole::FloatingPoint))
633 .count())
634 }
635
636 fn fpu_support(&mut self) -> Result<bool, crate::error::Error> {
637 Ok(self.state.fp_present)
638 }
639
640 fn reset_catch_set(&mut self) -> Result<(), Error> {
641 self.sequence.reset_catch_set(&mut self.interface)?;
642 Ok(())
643 }
644
645 fn reset_catch_clear(&mut self) -> Result<(), Error> {
646 self.sequence.reset_catch_clear(&mut self.interface)?;
647 Ok(())
648 }
649
650 fn debug_core_stop(&mut self) -> Result<(), Error> {
651 self.interface.disable_debug_module()?;
652 Ok(())
653 }
654}
655
656impl CoreMemoryInterface for Riscv32<'_> {
657 type ErrorType = Error;
658
659 fn memory(&self) -> &dyn MemoryInterface<Self::ErrorType> {
660 &self.interface
661 }
662 fn memory_mut(&mut self) -> &mut dyn MemoryInterface<Self::ErrorType> {
663 &mut self.interface
664 }
665}
666
667#[derive(Debug)]
668pub struct RiscvCoreState {
670 hw_breakpoints_enabled: bool,
672
673 hw_breakpoints: Option<u32>,
674
675 pc_written: bool,
678
679 semihosting_command: Option<SemihostingCommand>,
681
682 fp_present: bool,
684
685 misa_read: bool,
687}
688
689impl RiscvCoreState {
690 pub(crate) fn new() -> Self {
691 Self {
692 hw_breakpoints_enabled: false,
693 hw_breakpoints: None,
694 pc_written: false,
695 semihosting_command: None,
696 fp_present: false,
697 misa_read: false,
698 }
699 }
700}
701
702memory_mapped_bitfield_register! {
703 pub struct Dmcontrol(u32);
705 0x10, "dmcontrol",
706 impl From;
707
708 pub _, set_haltreq: 31;
710
711 pub _, set_resumereq: 30;
713
714 pub hartreset, set_hartreset: 29;
716
717 pub _, set_ackhavereset: 28;
719
720 pub hasel, set_hasel: 26;
722
723 pub hartsello, set_hartsello: 25, 16;
725
726 pub hartselhi, set_hartselhi: 15, 6;
728
729 pub _, set_resethaltreq: 3;
731
732 pub _, set_clrresethaltreq: 2;
734
735 pub ndmreset, set_ndmreset: 1;
737
738 pub dmactive, set_dmactive: 0;
740}
741
742impl Dmcontrol {
743 pub fn hartsel(&self) -> u32 {
747 (self.hartselhi() << 10) | self.hartsello()
748 }
749
750 pub fn set_hartsel(&mut self, value: u32) {
755 self.set_hartsello(value & 0x3ff);
756 self.set_hartselhi((value >> 10) & 0x3ff);
757 }
758}
759
760memory_mapped_bitfield_register! {
761 pub struct Dmstatus(u32);
765 0x11, "dmstatus",
766 impl From;
767
768 pub impebreak, _: 22;
775
776 pub allhavereset, _: 19;
779
780 pub anyhavereset, _: 18;
783
784 pub allresumeack, _: 17;
787
788 pub anyresumeack, _: 16;
791
792 pub allnonexistent, _: 15;
795
796 pub anynonexistent, _: 14;
799
800 pub allunavail, _: 13;
802
803 pub anyunavail, _: 12;
805
806 pub allrunning, _: 11;
808
809 pub anyrunning, _: 10;
811
812 pub allhalted, _: 9;
814
815 pub anyhalted, _: 8;
817
818 pub authenticated, _: 7;
820
821 pub authbusy, _: 6;
823
824 pub hasresethaltreq, _: 5;
827
828 pub confstrptrvalid, _: 4;
830
831 pub version, _: 3, 0;
833}
834
835bitfield! {
836 struct Dcsr(u32);
837 impl Debug;
838
839 xdebugver, _: 31, 28;
840 ebreakm, set_ebreakm: 15;
841 ebreaks, set_ebreaks: 13;
842 ebreaku, set_ebreaku: 12;
843 stepie, set_stepie: 11;
844 stopcount, set_stopcount: 10;
845 stoptime, set_stoptime: 9;
846 cause, set_cause: 8, 6;
847 mprven, set_mprven: 4;
848 nmip, _: 3;
849 step, set_step: 2;
850 prv, set_prv: 1,0;
851}
852
853memory_mapped_bitfield_register! {
854 pub struct Abstractcs(u32);
856 0x16, "abstractcs",
857 impl From;
858
859 progbufsize, _: 28, 24;
860 busy, _: 12;
861 cmderr, set_cmderr: 10, 8;
862 datacount, _: 3, 0;
863}
864
865memory_mapped_bitfield_register! {
866 pub struct Hartinfo(u32);
868 0x12, "hartinfo",
869 impl From;
870
871 nscratch, _: 23, 20;
872 dataaccess, _: 16;
873 datasize, _: 15, 12;
874 dataaddr, _: 11, 0;
875}
876
877memory_mapped_bitfield_register! { pub struct Data0(u32); 0x04, "data0", impl From; }
878memory_mapped_bitfield_register! { pub struct Data1(u32); 0x05, "data1", impl From; }
879memory_mapped_bitfield_register! { pub struct Data2(u32); 0x06, "data2", impl From; }
880memory_mapped_bitfield_register! { pub struct Data3(u32); 0x07, "data3", impl From; }
881memory_mapped_bitfield_register! { pub struct Data4(u32); 0x08, "data4", impl From; }
882memory_mapped_bitfield_register! { pub struct Data5(u32); 0x09, "data5", impl From; }
883memory_mapped_bitfield_register! { pub struct Data6(u32); 0x0A, "data6", impl From; }
884memory_mapped_bitfield_register! { pub struct Data7(u32); 0x0B, "data7", impl From; }
885memory_mapped_bitfield_register! { pub struct Data8(u32); 0x0C, "data8", impl From; }
886memory_mapped_bitfield_register! { pub struct Data9(u32); 0x0D, "data9", impl From; }
887memory_mapped_bitfield_register! { pub struct Data10(u32); 0x0E, "data10", impl From; }
888memory_mapped_bitfield_register! { pub struct Data11(u32); 0x0f, "data11", impl From; }
889
890memory_mapped_bitfield_register! { struct Command(u32); 0x17, "command", impl From; }
891
892memory_mapped_bitfield_register! { pub struct Progbuf0(u32); 0x20, "progbuf0", impl From; }
893memory_mapped_bitfield_register! { pub struct Progbuf1(u32); 0x21, "progbuf1", impl From; }
894memory_mapped_bitfield_register! { pub struct Progbuf2(u32); 0x22, "progbuf2", impl From; }
895memory_mapped_bitfield_register! { pub struct Progbuf3(u32); 0x23, "progbuf3", impl From; }
896memory_mapped_bitfield_register! { pub struct Progbuf4(u32); 0x24, "progbuf4", impl From; }
897memory_mapped_bitfield_register! { pub struct Progbuf5(u32); 0x25, "progbuf5", impl From; }
898memory_mapped_bitfield_register! { pub struct Progbuf6(u32); 0x26, "progbuf6", impl From; }
899memory_mapped_bitfield_register! { pub struct Progbuf7(u32); 0x27, "progbuf7", impl From; }
900memory_mapped_bitfield_register! { pub struct Progbuf8(u32); 0x28, "progbuf8", impl From; }
901memory_mapped_bitfield_register! { pub struct Progbuf9(u32); 0x29, "progbuf9", impl From; }
902memory_mapped_bitfield_register! { pub struct Progbuf10(u32); 0x2A, "progbuf10", impl From; }
903memory_mapped_bitfield_register! { pub struct Progbuf11(u32); 0x2B, "progbuf11", impl From; }
904memory_mapped_bitfield_register! { pub struct Progbuf12(u32); 0x2C, "progbuf12", impl From; }
905memory_mapped_bitfield_register! { pub struct Progbuf13(u32); 0x2D, "progbuf13", impl From; }
906memory_mapped_bitfield_register! { pub struct Progbuf14(u32); 0x2E, "progbuf14", impl From; }
907memory_mapped_bitfield_register! { pub struct Progbuf15(u32); 0x2F, "progbuf15", impl From; }
908
909bitfield! {
910 struct Mcontrol(u32);
911 impl Debug;
912
913 type_, set_type: 31, 28;
914 dmode, set_dmode: 27;
915 maskmax, _: 26, 21;
916 hit, set_hit: 20;
917 select, set_select: 19;
918 timing, set_timing: 18;
919 sizelo, set_sizelo: 17, 16;
920 action, set_action: 15, 12;
921 chain, set_chain: 11;
922 match_, set_match: 10, 7;
923 m, set_m: 6;
924 s, set_s: 4;
925 u, set_u: 3;
926 execute, set_execute: 2;
927 store, set_store: 1;
928 load, set_load: 0;
929}
930
931memory_mapped_bitfield_register! {
932 pub struct Misa(u32);
934 0x301, "misa",
935 impl From;
936
937 mxl, _: 31, 30;
939 extensions, _: 25, 0;
941}