@@ -651,12 +651,16 @@ def test(self):
651651 self .gdb .b ("_exit" )
652652 self .exit ()
653653
654- def MCONTROL_TYPE (xlen ):
654+ def TDATA1_TYPE (xlen ):
655655 return 0xf << ((xlen )- 4 )
656- def MCONTROL_DMODE (xlen ):
656+ def TDATA1_DMODE (xlen ):
657657 return 1 << ((xlen )- 5 )
658658def MCONTROL_MASKMAX (xlen ):
659- return 0x3 << ((xlen )- 11 )
659+ return 0x3f << ((xlen )- 11 )
660+
661+ TDATA1_TYPE_NONE = 0
662+ TDATA1_TYPE_MATCH = 2
663+ TDATA1_TYPE_MATCH6 = 6
660664
661665MCONTROL_SELECT = 1 << 19
662666MCONTROL_TIMING = 1 << 18
@@ -671,9 +675,6 @@ def MCONTROL_MASKMAX(xlen):
671675MCONTROL_STORE = 1 << 1
672676MCONTROL_LOAD = 1 << 0
673677
674- MCONTROL_TYPE_NONE = 0
675- MCONTROL_TYPE_MATCH = 2
676-
677678MCONTROL_ACTION_DEBUG_EXCEPTION = 0
678679MCONTROL_ACTION_DEBUG_MODE = 1
679680MCONTROL_ACTION_TRACE_START = 2
@@ -687,6 +688,37 @@ def MCONTROL_MASKMAX(xlen):
687688MCONTROL_MATCH_MASK_LOW = 4
688689MCONTROL_MATCH_MASK_HIGH = 5
689690
691+ MCONTROL6_UNCERTAIN = 1 << 26
692+ MCONTROL6_HIT1 = 1 << 25
693+ MCONTROL6_VS = 1 << 24
694+ MCONTROL6_VU = 1 << 23
695+ MCONTROL6_HIT0 = 1 << 22
696+ MCONTROL6_SELECT = 1 << 21
697+ MCONTROL6_SIZE = 0x7 << 16
698+ MCONTROL6_ACTION = 0xf << 12
699+ MCONTROL6_CHAIN = 1 << 11
700+ MCONTROL6_MATCH = 0xf << 7
701+ MCONTROL6_M = 1 << 6
702+ MCONTROL6_UNCERTAINEN = 1 << 5
703+ MCONTROL6_S = 1 << 4
704+ MCONTROL6_U = 1 << 3
705+ MCONTROL6_EXECUTE = 1 << 2
706+ MCONTROL6_STORE = 1 << 1
707+ MCONTROL6_LOAD = 1 << 0
708+
709+ MCONTROL6_ACTION_DEBUG_EXCEPTION = 0
710+ MCONTROL6_ACTION_DEBUG_MODE = 1
711+ MCONTROL6_ACTION_TRACE_START = 2
712+ MCONTROL6_ACTION_TRACE_STOP = 3
713+ MCONTROL6_ACTION_TRACE_EMIT = 4
714+
715+ MCONTROL6_MATCH_EQUAL = 0
716+ MCONTROL6_MATCH_NAPOT = 1
717+ MCONTROL6_MATCH_GE = 2
718+ MCONTROL6_MATCH_LT = 3
719+ MCONTROL6_MATCH_MASK_LOW = 4
720+ MCONTROL6_MATCH_MASK_HIGH = 5
721+
690722def set_field (reg , mask , val ):
691723 return ((reg ) & ~ (mask )) | (((val ) * ((mask ) & ~ ((mask ) << 1 ))) & (mask ))
692724
@@ -707,7 +739,7 @@ def check_reserve_trigger_support(self):
707739 not_supp_msg + "}" ).splitlines ():
708740 raise TestNotApplicable
709741
710- def set_manual_trigger (self , tdata1 , tdata2 ):
742+ def set_manual_trigger (self , tdata1 , tdata2 , maskmax_mask ):
711743 for tselect in itertools .count (0 ):
712744 self .gdb .p (f"$tselect={ tselect } " )
713745 if self .gdb .p ("$tselect" ) != tselect :
@@ -724,21 +756,23 @@ def set_manual_trigger(self, tdata1, tdata2):
724756
725757 tdata2_rb = self .gdb .p ("$tdata2" )
726758 tdata1_rb = self .gdb .p ("$tdata1" )
727- if tdata1_rb == tdata1 and tdata2_rb == tdata2 :
728- return tselect
729759
730- type_rb = tdata1_rb & MCONTROL_TYPE (self .hart .xlen )
731- type_none = set_field (0 , MCONTROL_TYPE (self .hart .xlen ),
732- MCONTROL_TYPE_NONE )
760+ type_rb = tdata1_rb & TDATA1_TYPE (self .hart .xlen )
761+ type_none = set_field (0 , TDATA1_TYPE (self .hart .xlen ),
762+ TDATA1_TYPE_NONE )
733763 if type_rb == type_none :
734764 raise TestNotApplicable
735765
766+ tdata1 = set_field (tdata1 , maskmax_mask , tdata1_rb & maskmax_mask )
767+ if tdata1_rb == tdata1 and tdata2_rb == tdata2 :
768+ return tselect
769+
736770 self .gdb .p ("$tdata1=0" )
737771 self .gdb .command (
738772 f"monitor riscv reserve_trigger { tselect } off" )
739773 assert False
740774
741- def test (self ):
775+ def run_test (self , tdata1 , maskmax_mask ):
742776 if not self .hart .honors_tdata1_dmode :
743777 # Run to main before setting the breakpoint, because startup code
744778 # will otherwise clear the trigger that we set.
@@ -753,20 +787,10 @@ def test(self):
753787 self .check_reserve_trigger_support ()
754788
755789 #self.gdb.hbreak("rot13")
756- tdata1 = MCONTROL_DMODE (self .hart .xlen )
757- tdata1 = set_field (tdata1 , MCONTROL_TYPE (self .hart .xlen ),
758- MCONTROL_TYPE_MATCH )
759- tdata1 = set_field (tdata1 , MCONTROL_ACTION , MCONTROL_ACTION_DEBUG_MODE )
760- tdata1 = set_field (tdata1 , MCONTROL_MATCH , MCONTROL_MATCH_EQUAL )
761- tdata1 |= MCONTROL_M | MCONTROL_EXECUTE
762- if self .hart .extensionSupported ("S" ):
763- tdata1 |= MCONTROL_S
764- if self .hart .extensionSupported ("U" ):
765- tdata1 |= MCONTROL_U
766790
767791 tdata2 = self .gdb .p ("&rot13" )
768792
769- tselect = self .set_manual_trigger (tdata1 , tdata2 )
793+ tselect = self .set_manual_trigger (tdata1 , tdata2 , maskmax_mask )
770794
771795 # The breakpoint should be hit exactly 2 times.
772796 for _ in range (2 ):
@@ -802,6 +826,39 @@ def test(self):
802826 self .gdb .b ("_exit" )
803827 self .exit ()
804828
829+ class McontrolManual (HwbpManual ):
830+ def test (self ):
831+ if not self .target .support_mcontrol :
832+ raise TestNotApplicable
833+
834+ tdata1 = TDATA1_DMODE (self .hart .xlen )
835+ tdata1 = set_field (tdata1 , TDATA1_TYPE (self .hart .xlen ),
836+ TDATA1_TYPE_MATCH )
837+ tdata1 = set_field (tdata1 , MCONTROL_ACTION , MCONTROL_ACTION_DEBUG_MODE )
838+ tdata1 = set_field (tdata1 , MCONTROL_MATCH , MCONTROL_MATCH_EQUAL )
839+ tdata1 |= MCONTROL_M | MCONTROL_EXECUTE
840+ if self .hart .extensionSupported ("S" ):
841+ tdata1 |= MCONTROL_S
842+ if self .hart .extensionSupported ("U" ):
843+ tdata1 |= MCONTROL_U
844+ self .run_test (tdata1 , MCONTROL_MASKMAX (self .hart .xlen ))
845+
846+ class Mcontrol6Manual (HwbpManual ):
847+ def test (self ):
848+ if not self .target .support_mcontrol6 :
849+ raise TestNotApplicable
850+
851+ tdata1 = TDATA1_DMODE (self .hart .xlen )
852+ tdata1 = set_field (tdata1 , TDATA1_TYPE (self .hart .xlen ),
853+ TDATA1_TYPE_MATCH6 )
854+ tdata1 = set_field (tdata1 , MCONTROL6_ACTION , MCONTROL6_ACTION_DEBUG_MODE )
855+ tdata1 = set_field (tdata1 , MCONTROL6_MATCH , MCONTROL6_MATCH_EQUAL )
856+ tdata1 |= MCONTROL6_M | MCONTROL6_EXECUTE
857+ if self .hart .extensionSupported ("S" ):
858+ tdata1 |= MCONTROL6_S
859+ if self .hart .extensionSupported ("U" ):
860+ tdata1 |= MCONTROL6_U
861+ self .run_test (tdata1 , 0 )
805862
806863class Hwbp2 (DebugTest ):
807864 def early_applicable (self ):
0 commit comments