@@ -2489,32 +2489,30 @@ csr_write_satp:
24892489 # TODO: this may not be strictly required by the spec
24902490 jump end_instruction_with_rd_and_invalidate_icache always
24912491
2492- # FIXME: add support for mcounteren/scounteren
2493-
24942492csr_read_cycle:
24952493#% do declare_locals(modify_csr_locals)
24962494 read rd {{CSRS}} "{{ 'mcycle'|csr }}"
2497- set @counter $$modify_csr_op
2495+ jump check_xcounteren always
24982496
24992497csr_read_cycleh:
25002498#% do declare_locals(modify_csr_locals)
25012499 read rd {{CSRS}} "{{ 'mcycleh'|csr }}"
2502- set @counter $$modify_csr_op
2500+ jump check_xcounteren always
25032501
25042502csr_read_time:
25052503#% do declare_locals(modify_csr_locals)
25062504 set rd csr_mtime
2507- set @counter $$modify_csr_op
2505+ jump check_xcounteren always
25082506
25092507csr_read_timeh:
25102508#% do declare_locals(modify_csr_locals)
25112509 set rd csr_mtimeh
2512- set @counter $$modify_csr_op
2510+ jump check_xcounteren always
25132511
25142512csr_read_minstret:
25152513#% do declare_locals(modify_csr_locals)
25162514 set rd csr_minstret
2517- set @counter $$modify_csr_op
2515+ jump check_xcounteren always
25182516
25192517csr_write_minstret:
25202518 # a value written to instret by one instruction should be the value read by the following instruction
@@ -2524,14 +2522,41 @@ csr_write_minstret:
25242522csr_read_minstreth:
25252523#% do declare_locals(modify_csr_locals)
25262524 set rd csr_minstreth
2527- set @counter $$modify_csr_op
2525+ jump check_xcounteren always
25282526
25292527csr_write_minstreth:
25302528 # a value written to instret by one instruction should be the value read by the following instruction
25312529 op sub csr_minstret csr_minstret 1
25322530 set csr_minstreth result
25332531 jump end_instruction_with_rd always
25342532
2533+ csr_read_hpmcounter:
2534+ #% do declare_locals(modify_csr_locals)
2535+ set rd 0
2536+ # continue into check_xcounteren
2537+
2538+ check_xcounteren:
2539+ # if in M-mode, always allow counter accesses
2540+ jump check_xcounteren__m_mode equal privilege_mode 0b11
2541+
2542+ # if in S-mode, only require the bit to be set in mcounteren
2543+ read $xcounteren {{CSRS}} "{{ 'mcounteren'|csr }}"
2544+ jump check_xcounteren__s_mode equal privilege_mode 0b01
2545+
2546+ # if in U-mode, also require the bit to be set in scounteren
2547+ read $scounteren {{CSRS}} "{{ 'scounteren'|csr }}"
2548+ op and $xcounteren $xcounteren $scounteren
2549+ check_xcounteren__s_mode:
2550+
2551+ # trap if the bit in xcounteren corresponding to the CSR being read is clear
2552+ op and $bit imm 31
2553+ op shr $bit $xcounteren $bit
2554+ op and $bit $bit 0b1
2555+ jump ILLEGAL_OP equal $bit 0
2556+
2557+ check_xcounteren__m_mode:
2558+ set @counter $$modify_csr_op
2559+
25352560MLOGSYS:
25362561 # I-type: rs1, imm=funct12, rd_id
25372562
@@ -2684,6 +2709,7 @@ jump decode_SYSTEM always
26842709jump csr_read_cycle always
26852710jump csr_read_time always
26862711jump csr_read_minstret always
2712+ jump csr_read_hpmcounter always
26872713jump csr_read_zero always
26882714jump csr_read_cycleh always
26892715jump csr_read_timeh always
0 commit comments