|  |  |  | @@ -554,42 +554,36 @@ template <typename BASE, features_e FEAT> bool riscv_hart_mu_p<BASE, FEAT>::pmp_ | 
		
	
		
			
				|  |  |  |  |     constexpr auto PMP_TOR =0x1U; | 
		
	
		
			
				|  |  |  |  |     constexpr auto PMP_NA4 =0x2U; | 
		
	
		
			
				|  |  |  |  |     constexpr auto PMP_NAPOT =0x3U; | 
		
	
		
			
				|  |  |  |  |     reg_t base = 0; | 
		
	
		
			
				|  |  |  |  |     constexpr auto pmp_num_regs = 16; | 
		
	
		
			
				|  |  |  |  |     reg_t tor_base = 0; | 
		
	
		
			
				|  |  |  |  |     auto any_active = false; | 
		
	
		
			
				|  |  |  |  |     for (size_t i = 0; i < 16; i++) { | 
		
	
		
			
				|  |  |  |  |         reg_t tor = csr[pmpaddr0+i] << PMP_SHIFT; | 
		
	
		
			
				|  |  |  |  |     auto lower_addr = addr >>2; | 
		
	
		
			
				|  |  |  |  |     auto upper_addr = (addr+len-1)>>2; | 
		
	
		
			
				|  |  |  |  |     for (size_t i = 0; i < pmp_num_regs; i++) { | 
		
	
		
			
				|  |  |  |  |         uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4); | 
		
	
		
			
				|  |  |  |  |         uint8_t cfg_next = i==(pmp_num_regs-1)? 0 : csr[pmpcfg0+((i+1)/4)]>>((i+1)%4); | 
		
	
		
			
				|  |  |  |  |         auto pmpaddr = csr[pmpaddr0+i]; | 
		
	
		
			
				|  |  |  |  |         if (cfg & PMP_A) { | 
		
	
		
			
				|  |  |  |  |             any_active=true; | 
		
	
		
			
				|  |  |  |  |             auto pmp_a = (cfg & PMP_A) >> 3; | 
		
	
		
			
				|  |  |  |  |             auto is_tor = pmp_a == PMP_TOR; | 
		
	
		
			
				|  |  |  |  |             auto is_na4 = pmp_a == PMP_NA4; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |             reg_t mask = (csr[pmpaddr0+i] << 1) | (!is_na4); | 
		
	
		
			
				|  |  |  |  |             mask = ~(mask & ~(mask + 1)) << PMP_SHIFT; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |             // Check each 4-byte sector of the access | 
		
	
		
			
				|  |  |  |  |             auto any_match = false; | 
		
	
		
			
				|  |  |  |  |             auto all_match = true; | 
		
	
		
			
				|  |  |  |  |             for (reg_t offset = 0; offset < len; offset += 1 << PMP_SHIFT) { | 
		
	
		
			
				|  |  |  |  |                 reg_t cur_addr = addr + offset; | 
		
	
		
			
				|  |  |  |  |                 auto napot_match = ((cur_addr ^ tor) & mask) == 0; | 
		
	
		
			
				|  |  |  |  |                 auto tor_match = base <= cur_addr && cur_addr < tor; | 
		
	
		
			
				|  |  |  |  |                 auto match = is_tor ? tor_match : napot_match; | 
		
	
		
			
				|  |  |  |  |                 any_match |= match; | 
		
	
		
			
				|  |  |  |  |                 all_match &= match; | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |             if (any_match) { | 
		
	
		
			
				|  |  |  |  |                 // If the PMP matches only a strict subset of the access, fail it | 
		
	
		
			
				|  |  |  |  |                 if (!all_match) | 
		
	
		
			
				|  |  |  |  |                     return false; | 
		
	
		
			
				|  |  |  |  |                 return  (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || | 
		
	
		
			
				|  |  |  |  |                         (type == access_type::READ && (cfg & PMP_R)) || | 
		
	
		
			
				|  |  |  |  |                         (type == access_type::WRITE && (cfg & PMP_W)) || | 
		
	
		
			
				|  |  |  |  |                         (type == access_type::FETCH && (cfg & PMP_X)); | 
		
	
		
			
				|  |  |  |  |             auto is_tor = bit_sub<3, 2>(cfg) == PMP_TOR; | 
		
	
		
			
				|  |  |  |  |             auto is_napot = bit_sub<4, 1>(cfg) && bit_sub<3, 2>(cfg_next)!= PMP_TOR; | 
		
	
		
			
				|  |  |  |  |             if(is_napot) { | 
		
	
		
			
				|  |  |  |  |                 reg_t mask = bit_sub<3, 1>(cfg)?~( pmpaddr & ~(pmpaddr + 1)): 0x3fffffff; | 
		
	
		
			
				|  |  |  |  |                 auto mpmpaddr = pmpaddr & mask; | 
		
	
		
			
				|  |  |  |  |                 if((lower_addr&mask) == mpmpaddr && (upper_addr&mask)==mpmpaddr) | 
		
	
		
			
				|  |  |  |  |                     return  (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || | 
		
	
		
			
				|  |  |  |  |                             (type == access_type::READ && (cfg & PMP_R)) || | 
		
	
		
			
				|  |  |  |  |                             (type == access_type::WRITE && (cfg & PMP_W)) || | 
		
	
		
			
				|  |  |  |  |                             (type == access_type::FETCH && (cfg & PMP_X)); | 
		
	
		
			
				|  |  |  |  |             } else if(is_tor) { | 
		
	
		
			
				|  |  |  |  |                 if(lower_addr>=tor_base && upper_addr<=pmpaddr) | 
		
	
		
			
				|  |  |  |  |                     return  (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || | 
		
	
		
			
				|  |  |  |  |                             (type == access_type::READ && (cfg & PMP_R)) || | 
		
	
		
			
				|  |  |  |  |                             (type == access_type::WRITE && (cfg & PMP_W)) || | 
		
	
		
			
				|  |  |  |  |                             (type == access_type::FETCH && (cfg & PMP_X)); | 
		
	
		
			
				|  |  |  |  |             } | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         base = tor; | 
		
	
		
			
				|  |  |  |  |         tor_base = pmpaddr; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     return !any_active || this->reg.PRIV == PRIV_M; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					
					|  |  |  |   |