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