?? RIGHT := 110 ??                                                                                            
?? NEWTITLE := 'NOS/VE Dump Analyzer : Virtual Memory Access' ??                                              
MODULE dum$virtual_memory_access;                                                                             
                                                                                                              
{ PURPOSE:                                                                                                    
{   This module contains the code for the virtual memory access.                                              
                                                                                                              
?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??                                      
?? PUSH (LISTEXT := ON) ??                                                                                    
*copyc due$exception_condition_codes                                                                          
*copyc dut$access_data                                                                                        
*copyc mmt$ast_index                                                                                          
*copyc ost$segment_access_control                                                                             
?? POP ??                                                                                                     
*copyc dup$access_real_memory                                                                                 
*copyc osp$append_status_integer                                                                              
*copyc osp$append_status_parameter                                                                            
*copyc osp$set_status_abnormal                                                                                
?? EJECT ??                                                                                                   
*copyc duv$dump_environment_p                                                                                 
*copyc duv$execution_environment                                                                              
?? OLDTITLE ??                                                                                                
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??                                        
  VAR                                                                                                         
    v$page_size: 512 .. 65536;                                                                                
?? OLDTITLE ??                                                                                                
?? NEWTITLE := 'append_pva', EJECT ??                                                                         
                                                                                                              
{ PURPOSE:                                                                                                    
{   This procedure appends a pva error message to the status message.                                         
                                                                                                              
  PROCEDURE append_pva                                                                                        
    (    pva: ost$pva;                                                                                        
     VAR status: ost$status);                                                                                 
                                                                                                              
    osp$append_status_parameter (osc$status_parameter_delimiter, ', segment = ', status);                     
    osp$append_status_integer (osc$status_parameter_delimiter, pva.seg, 16, TRUE, status);                    
    osp$append_status_parameter (osc$status_parameter_delimiter, ', offset = ', status);                      
    osp$append_status_integer (osc$status_parameter_delimiter, pva.offset, 16, TRUE, status);                 
                                                                                                              
  PROCEND append_pva;                                                                                         
?? OLDTITLE ??                                                                                                
?? NEWTITLE := 'append_sva', EJECT ??                                                                         
                                                                                                              
{ PURPOSE:                                                                                                    
{   This procedure appends an sva error message to the status message.                                        
                                                                                                              
  PROCEDURE append_sva                                                                                        
    (    sva: dut$ee_system_virtual_address;                                                                  
     VAR status: ost$status);                                                                                 
                                                                                                              
    osp$append_status_parameter (osc$status_parameter_delimiter, ', asid = ', status);                        
    osp$append_status_integer (osc$status_parameter_delimiter, sva.asid.value, 16, TRUE, status);             
    osp$append_status_parameter (osc$status_parameter_delimiter, ', offset = ', status);                      
    osp$append_status_integer (osc$status_parameter_delimiter, sva.offset, 16, TRUE, status);                 
                                                                                                              
  PROCEND append_sva;                                                                                         
?? OLDTITLE ??                                                                                                
?? NEWTITLE := 'initialize_access_data', EJECT ??                                                             
                                                                                                              
{ PURPOSE:                                                                                                    
{   This procedure initializes the access data record.                                                        
                                                                                                              
  PROCEDURE initialize_access_data                                                                            
    (VAR access_data: dut$access_data);                                                                       
                                                                                                              
    access_data.valid_segment := TRUE;                                                                        
    access_data.page_fault := FALSE;                                                                          
    access_data.memory_found := TRUE;                                                                         
                                                                                                              
  PROCEND initialize_access_data;                                                                             
?? OLDTITLE ??                                                                                                
?? NEWTITLE := 'dup$copy_virtual_memory_pva', EJECT ??                                                        
                                                                                                              
{ PURPOSE:                                                                                                    
{   This procedure copies memory by using a pva.                                                              
                                                                                                              
  PROCEDURE [XDCL] dup$copy_virtual_memory_pva                                                                
    (    process_virtual_address: ost$pva;                                                                    
         exchange: dut$exchange_package;                                                                      
         processor: 0 .. duc$de_maximum_processors;                                                           
         byte_count: 1 .. osc$max_segment_length;                                                             
         continue_if_possible: boolean;                                                                       
     VAR bytes_returned: ost$segment_length;                                                                  
     VAR file_data_seq_p: ^SEQ ( * );                                                                         
     VAR access_data: dut$access_data;                                                                        
     VAR status: ost$status);                                                                                 
                                                                                                              
    VAR                                                                                                       
      bytes_left: 0 .. 10000(16),                                                                             
      file_data_p: ^ARRAY [ * ] OF cell,                                                                      
      memory_file_data_p: ^ARRAY [ * ] OF cell,                                                               
      memory_file_p: ^cell,                                                                                   
      new_byte_size: ost$segment_length,                                                                      
      pva: ost$pva,                                                                                           
      remaining: 0 .. osc$max_segment_length,                                                                 
      rma: ost$real_memory_address;                                                                           
                                                                                                              
    status.normal := TRUE;                                                                                    
    initialize_access_data (access_data);                                                                     
    bytes_returned := 0;                                                                                      
    pva := process_virtual_address;                                                                           
    remaining := byte_count;                                                                                  
                                                                                                              
    WHILE TRUE DO                                                                                             
      dup$translate_pva (pva, exchange, processor, rma, bytes_left, access_data, status);                     
      IF NOT status.normal OR NOT access_data.memory_found THEN                                               
        RETURN;  {---->                                                                                       
      IFEND;                                                                                                  
                                                                                                              
      IF bytes_left >= remaining THEN                                                                         
        bytes_left := remaining;                                                                              
        remaining := 0;                                                                                       
      ELSE                                                                                                    
        remaining := remaining - bytes_left;                                                                  
      IFEND;                                                                                                  
                                                                                                              
      { Retrieve a pointer to the start of the current data.                                                  
                                                                                                              
      dup$access_real_memory (bytes_left, rma, memory_file_p, new_byte_size, status);                         
      IF NOT status.normal AND (status.condition <> due$memory_partially_avail) THEN                          
        RETURN;  {---->                                                                                       
      IFEND;                                                                                                  
                                                                                                              
      { Retrieve a pointer to the data on the memory file.                                                    
                                                                                                              
      RESET duv$execution_environment.memory_file_p^.segment_pointer.sequence_pointer TO memory_file_p;       
      NEXT memory_file_data_p: [1 .. bytes_left] IN                                                           
            duv$execution_environment.memory_file_p^.segment_pointer.sequence_pointer;                        
      IF memory_file_data_p = NIL THEN                                                                        
        osp$set_status_abnormal (duc$dump_analyzer_id, due$nil_pointer, '', status);                          
        RETURN;  {---->                                                                                       
      IFEND;                                                                                                  
                                                                                                              
      { Retrieve a pointer to the data on the output file.                                                    
                                                                                                              
      NEXT file_data_p: [1 .. bytes_left] IN file_data_seq_p;                                                 
      IF file_data_p = NIL THEN                                                                               
        osp$set_status_abnormal (duc$dump_analyzer_id, due$nil_pointer, '', status);                          
        RETURN;  {---->                                                                                       
      IFEND;                                                                                                  
                                                                                                              
      { Copy the data from the memory file to the output file.                                                
                                                                                                              
      file_data_p^ := memory_file_data_p^;                                                                    
      bytes_returned := bytes_returned + bytes_left;                                                          
      IF remaining <= 0 THEN                                                                                  
        RETURN;  {---->                                                                                       
      IFEND;                                                                                                  
                                                                                                              
      IF access_data.page_fault AND NOT continue_if_possible THEN                                             
        RETURN;  {---->                                                                                       
      IFEND;                                                                                                  
                                                                                                              
      pva.offset := pva.offset + bytes_left;                                                                  
    WHILEND;                                                                                                  
                                                                                                              
  PROCEND dup$copy_virtual_memory_pva;                                                                        
?? OLDTITLE ??                                                                                                
?? NEWTITLE := 'dup$copy_virtual_memory_sva', EJECT ??                                                        
                                                                                                              
{ PURPOSE:                                                                                                    
{   This procedure copies memory using an sva.                                                                
                                                                                                              
  PROCEDURE [XDCL] dup$copy_virtual_memory_sva                                                                
    (    system_virtual_address: dut$ee_system_virtual_address;                                               
         processor: 0 .. duc$de_maximum_processors;                                                           
         byte_count: 1 .. osc$max_segment_length;                                                             
         continue_if_possible: boolean;                                                                       
     VAR bytes_returned: ost$segment_length;                                                                  
     VAR file_data_seq_p: ^SEQ ( * );                                                                         
     VAR access_data: dut$access_data;                                                                        
     VAR status: ost$status);                                                                                 
                                                                                                              
    VAR                                                                                                       
      bytes_left: 0 .. 10000(16),                                                                             
      file_data_p: ^ARRAY [ * ] OF cell,                                                                      
      memory_file_data_p: ^ARRAY [ * ] OF cell,                                                               
      memory_file_p: ^cell,                                                                                   
      new_byte_size: ost$segment_length,                                                                      
      remaining: 0 .. osc$max_segment_length,                                                                 
      rma: ost$real_memory_address,                                                                           
      sva: dut$ee_system_virtual_address;                                                                     
                                                                                                              
    status.normal := TRUE;                                                                                    
    initialize_access_data (access_data);                                                                     
    bytes_returned := 0;                                                                                      
    sva := system_virtual_address;                                                                            
    remaining := byte_count;                                                                                  
                                                                                                              
    WHILE TRUE DO                                                                                             
      dup$translate_sva (sva, processor, rma, bytes_left, access_data, status);                               
      IF NOT status.normal OR NOT access_data.memory_found THEN                                               
        RETURN;  {---->                                                                                       
      IFEND;                                                                                                  
                                                                                                              
      IF bytes_left >= remaining THEN                                                                         
        bytes_left := remaining;                                                                              
        remaining := 0;                                                                                       
      ELSE                                                                                                    
        remaining := remaining - bytes_left;                                                                  
      IFEND;                                                                                                  
                                                                                                              
      { Retrieve a pointer to the start of the current data.                                                  
                                                                                                              
      dup$access_real_memory (bytes_left, rma, memory_file_p, new_byte_size, status);                         
      IF NOT status.normal AND (status.condition <> due$memory_partially_avail) THEN                          
        RETURN;  {---->                                                                                       
      IFEND;                                                                                                  
                                                                                                              
      { Retrieve a pointer to the data on the memory file.                                                    
                                                                                                              
      RESET duv$execution_environment.memory_file_p^.segment_pointer.sequence_pointer TO memory_file_p;       
      NEXT memory_file_data_p: [1 .. bytes_left] IN                                                           
            duv$execution_environment.memory_file_p^.segment_pointer.sequence_pointer;                        
      IF memory_file_data_p = NIL THEN                                                                        
        osp$set_status_abnormal (duc$dump_analyzer_id, due$nil_pointer, '', status);                          
        RETURN;  {---->                                                                                       
      IFEND;                                                                                                  
                                                                                                              
      { Retrieve a pointer to the data on the output file.                                                    
                                                                                                              
      NEXT file_data_p: [1 .. bytes_left] IN file_data_seq_p;                                                 
      IF file_data_p = NIL THEN                                                                               
        osp$set_status_abnormal (duc$dump_analyzer_id, due$nil_pointer, '', status);                          
        RETURN;  {---->                                                                                       
      IFEND;                                                                                                  
                                                                                                              
      { Copy the data from the memory file to the output file.                                                
                                                                                                              
      file_data_p^ := memory_file_data_p^;                                                                    
      bytes_returned := bytes_returned + bytes_left;                                                          
      IF remaining <= 0 THEN                                                                                  
        RETURN;  {---->                                                                                       
      IFEND;                                                                                                  
                                                                                                              
      IF (NOT access_data.valid_segment OR access_data.page_fault OR NOT access_data.memory_found)            
            AND NOT continue_if_possible THEN                                                                 
        RETURN;  {---->                                                                                       
      IFEND;                                                                                                  
                                                                                                              
      sva.offset := sva.offset + bytes_left;                                                                  
    WHILEND;                                                                                                  
                                                                                                              
  PROCEND dup$copy_virtual_memory_sva;                                                                        
?? OLDTITLE ??                                                                                                
?? NEWTITLE := 'dup$translate_pva', EJECT ??                                                                  
                                                                                                              
{ PURPOSE:                                                                                                    
{   This procedure translates a pva and determines if it is valid.                                            
                                                                                                              
  PROCEDURE [XDCL] dup$translate_pva                                                                          
    (    pva: ost$pva;                                                                                        
         exchange: dut$exchange_package;                                                                      
         processor: 0 .. duc$de_maximum_processors;                                                           
     VAR rma: ost$real_memory_address;                                                                        
     VAR bytes_left: 0 .. 10000(16);                                                                          
     VAR access_data: dut$access_data;                                                                        
     VAR status: ost$status);                                                                                 
                                                                                                              
    TYPE                                                                                                      
      t$segment_descriptor = RECORD                                                                           
        ste: t$segment_descriptor_entry,                                                                      
        fill1: 0 .. 0ff(16),                                                                                  
        asti: mmt$ast_index,                                                                                  
      RECEND,                                                                                                 
                                                                                                              
      t$segment_descriptor_entry = PACKED RECORD                                                              
        vl: (c$vl_invalid_entry, c$vl_reserved, c$vl_regular_segment, c$vl_cache_bypass),                     
        xp: ost$execute_privilege,                                                                            
        rp: ost$read_privilege,                                                                               
        wp: ost$write_privilege,                                                                              
        r1: ost$ring,                                                                                         
        r2: ost$ring,                                                                                         
        asid: dut$ee_asid,                                                                                    
        key_lock: ost$key_lock,                                                                               
      RECEND,                                                                                                 
                                                                                                              
      t$segment_descriptor_table = RECORD                                                                     
        st: ARRAY [0 .. * ] OF t$segment_descriptor,                                                          
      RECEND,                                                                                                 
                                                                                                              
      t$segment_desc_table_address = RECORD                                                                   
        CASE boolean OF                                                                                       
        = TRUE =                                                                                              
          value: ost$real_memory_address,                                                                     
        = FALSE =                                                                                             
          part_1: 0 .. 0ffff(16),                                                                             
          part_2: 0 .. 0ffff(16),                                                                             
        CASEND,                                                                                               
      RECEND;                                                                                                 
                                                                                                              
    VAR                                                                                                       
      new_byte_size: ost$segment_length,                                                                      
      sdt_p: ^t$segment_descriptor_table,                                                                     
      sdta: t$segment_desc_table_address,                                                                     
      segment_descriptor_p: ^t$segment_descriptor,                                                            
      sva: dut$ee_system_virtual_address,                                                                     
      valid_segment: boolean;                                                                                 
                                                                                                              
    status.normal := TRUE;                                                                                    
    initialize_access_data (access_data);                                                                     
    valid_segment := TRUE;                                                                                    
                                                                                                              
    IF NOT duv$execution_environment.processor_registers [processor].available THEN                           
      osp$set_status_abnormal (duc$dump_analyzer_id, due$data_not_on_dump,                                    
            'The processor registers psm, pta and ptl for processor', status);                                
      osp$append_status_integer (osc$status_parameter_delimiter, processor, 10, FALSE, status);               
      osp$append_status_parameter (osc$status_parameter_delimiter, 'are', status);                            
      RETURN;  {---->                                                                                         
    IFEND;                                                                                                    
                                                                                                              
    { Check if the segment number is valid.                                                                   
                                                                                                              
    IF pva.seg > exchange.segment_table_length THEN                                                           
      osp$set_status_abnormal (duc$dump_analyzer_id, due$address_translation_error,                           
            'invalid segment: the segment number is greater than segment table length.', status);             
      append_pva (pva, status);                                                                               
      RETURN;  {---->                                                                                         
    IFEND;                                                                                                    
                                                                                                              
    { Retrieve a pointer to the segment descriptor.                                                           
                                                                                                              
    sdta.part_1 := exchange.segment_table_address_1;                                                          
    sdta.part_2 := exchange.segment_table_address_2;                                                          
    dup$access_real_memory ((#SIZE (t$segment_descriptor) * pva.seg), sdta.value, segment_descriptor_p,       
          new_byte_size, status);                                                                             
    IF NOT status.normal THEN                                                                                 
      IF status.condition = due$invalid_offset THEN                                                           
        osp$set_status_abnormal (duc$dump_analyzer_id, due$address_translation_error,                         
              'The segment table address and/or the segment table length in the exchange package is invalid.',
              status);                                                                                        
      IFEND;                                                                                                  
      RETURN;  {---->                                                                                         
    IFEND;                                                                                                    
                                                                                                              
    { Retrieve the segment descriptor table from the segment descriptor.                                      
                                                                                                              
    RESET duv$execution_environment.memory_file_p^.segment_pointer.sequence_pointer TO segment_descriptor_p;  
    NEXT sdt_p: [0 .. pva.seg] IN duv$execution_environment.memory_file_p^.segment_pointer.sequence_pointer;  
    IF sdt_p = NIL THEN                                                                                       
      osp$set_status_abnormal (duc$dump_analyzer_id, due$nil_pointer, '', status);                            
      RETURN;  {---->                                                                                         
    IFEND;                                                                                                    
                                                                                                              
    { Determine if the segment is valid.                                                                      
                                                                                                              
    IF sdt_p^.st [pva.seg].ste.vl = c$vl_invalid_entry THEN                                                   
      IF sdt_p^.st [pva.seg].ste.asid.value = 0 THEN                                                          
        osp$set_status_abnormal (duc$dump_analyzer_id, due$address_translation_error,                         
              'invalid segment (the invalid entry bit is set in the segment table entry).', status);          
        append_pva (pva, status);                                                                             
        RETURN;  {---->                                                                                       
      ELSE                                                                                                    
        valid_segment := FALSE;                                                                               
      IFEND;                                                                                                  
    IFEND;                                                                                                    
                                                                                                              
    { Check for a negative pva offset.                                                                        
                                                                                                              
    IF pva.offset < 0 THEN                                                                                    
      osp$set_status_abnormal (duc$dump_analyzer_id, due$address_translation_error,                           
            'address specification error (the offset is negative).', status);                                 
      append_pva (pva, status);                                                                               
      RETURN;  {---->                                                                                         
    IFEND;                                                                                                    
                                                                                                              
    { Check for a valid sva.                                                                                  
                                                                                                              
    sva.asid.asid := sdt_p^.st [pva.seg].ste.asid.asid;                                                       
    sva.offset := pva.offset;                                                                                 
    dup$translate_sva (sva, processor, rma, bytes_left, access_data, status);                                 
    IF NOT status.normal THEN                                                                                 
      RETURN;  {---->                                                                                         
    IFEND;                                                                                                    
                                                                                                              
    access_data.valid_segment := valid_segment;                                                               
                                                                                                              
  PROCEND dup$translate_pva;                                                                                  
?? OLDTITLE ??                                                                                                
?? NEWTITLE := 'dup$translate_sva', EJECT ??                                                                  
                                                                                                              
{ PURPOSE:                                                                                                    
{   This procedure translates an sva and determines if it is valid.                                           
                                                                                                              
  PROCEDURE [XDCL] dup$translate_sva                                                                          
    (    system_virtual_address: dut$ee_system_virtual_address;                                               
         processor: 0 .. duc$de_maximum_processors;                                                           
     VAR rma: ost$real_memory_address;                                                                        
     VAR bytes_left: 0 .. 10000(16);                                                                          
     VAR access_data: dut$access_data;                                                                        
     VAR status: ost$status);                                                                                 
                                                                                                              
    TYPE                                                                                                      
      t$hash_index = PACKED RECORD                                                                            
        CASE boolean OF                                                                                       
        = TRUE =                                                                                              
          hash_result: t$hash_result,                                                                         
          zeros: 0 .. 0f(16),                                                                                 
        = FALSE =                                                                                             
          fill: 0 .. 3fff(16),                                                                                
          rightmost_12_bits: 0 .. 0fff(16),                                                                   
        CASEND,                                                                                               
      RECEND,                                                                                                 
                                                                                                              
      t$hash_result = PACKED RECORD                                                                           
        CASE boolean OF                                                                                       
        = TRUE =                                                                                              
          hash_upper: SET OF 0 .. 5,                                                                          
          value: SET OF 0 .. 15,                                                                              
        = FALSE =                                                                                             
          ptl: SET OF 0 .. 13,                                                                                
        CASEND,                                                                                               
      RECEND,                                                                                                 
                                                                                                              
      t$page_frame_address = PACKED RECORD                                                                    
        leftmost_15_bits: 0 .. 7fff(16),                                                                      
        psm: dut$ee_page_size_mask,                                                                           
      RECEND,                                                                                                 
                                                                                                              
      t$page_id = PACKED RECORD                                                                               
        asid: dut$ee_asid,                                                                                    
        pagenum: dut$ee_page_number,                                                                          
      RECEND,                                                                                                 
                                                                                                              
      t$page_table_entry = PACKED RECORD                                                                      
        v: boolean,                                                                                           
        c: boolean,                                                                                           
        u: boolean,                                                                                           
        m: boolean,                                                                                           
        pageid: t$page_id,                                                                                    
        pfa: t$page_frame_address,                                                                            
      RECEND,                                                                                                 
                                                                                                              
      t$page_table_reference = PACKED RECORD                                                                  
        CASE boolean OF                                                                                       
        = TRUE =                                                                                              
          rma: ost$real_memory_address,                                                                       
        = FALSE =                                                                                             
          leftmost_6_bits: 0 .. 03f(16),                                                                      
          ptl: dut$ee_page_table_length,                                                                      
          rightmost_12_bits: 0 .. 0fff(16),                                                                   
        CASEND,                                                                                               
      RECEND,                                                                                                 
                                                                                                              
      t$psm_integer = RECORD                                                                                  
        case boolean of                                                                                       
        = TRUE =                                                                                              
          psm: dut$ee_page_size_mask,                                                                         
        = FALSE =                                                                                             
          int: 0 .. 0ff(16),                                                                                  
        CASEND,                                                                                               
      RECEND,                                                                                                 
                                                                                                              
      t$pt_rma_formation = PACKED RECORD                                                                      
        CASE boolean OF                                                                                       
        = TRUE =                                                                                              
          value: ost$real_memory_address,                                                                     
        = FALSE =                                                                                             
          zero: 0 .. 1,                                                                                       
          pfa: t$page_frame_address,                                                                          
          rightmost_9_bits: 0 .. 1ff(16),                                                                     
        CASEND,                                                                                               
      RECEND;                                                                                                 
                                                                                                              
    VAR                                                                                                       
      hash_index: t$hash_index,                                                                               
      max_page_offset: dut$ee_page_offset,                                                                    
      new_byte_size: ost$segment_length,                                                                      
      page_number: dut$ee_page_number,                                                                        
      page_offset: dut$ee_page_offset,                                                                        
      page_table_entry_p: ^t$page_table_entry,                                                                
      page_table_reference: t$page_table_reference,                                                           
      psm: dut$ee_page_size_mask,                                                                             
      psm_int: t$psm_integer,                                                                                 
      pta: dut$ee_page_table_address,                                                                         
      ptl: dut$ee_page_table_length,                                                                          
      pt_rma: t$pt_rma_formation,                                                                             
      search_count: 0 .. 31,                                                                                  
      sva: dut$ee_system_virtual_address;                                                                     
                                                                                                              
    status.normal := TRUE;                                                                                    
    initialize_access_data (access_data);                                                                     
    sva := system_virtual_address;                                                                            
                                                                                                              
    IF NOT duv$execution_environment.processor_registers [processor].available THEN                           
      osp$set_status_abnormal (duc$dump_analyzer_id, due$data_not_on_dump,                                    
            'The processor registers psm, pta and ptl for processor', status);                                
      osp$append_status_integer (osc$status_parameter_delimiter, processor, 10, FALSE, status);               
      osp$append_status_parameter (osc$status_parameter_delimiter, 'are', status);                            
      RETURN;  {---->                                                                                         
    IFEND;                                                                                                    
                                                                                                              
    psm := duv$execution_environment.processor_registers [processor].page_size_mask;                          
    pta := duv$execution_environment.processor_registers [processor].page_table_address;                      
    ptl := duv$execution_environment.processor_registers [processor].page_table_length;                       
    page_number := sva.pn;                                                                                    
    page_offset := sva.po;                                                                                    
    psm_int.psm := - psm;                                                                                     
    psm_int.int := psm_int.int + 1;                                                                           
    page_number.value := page_number.value DIV psm_int.int;                                                   
    sva.pn.psm := sva.pn.psm * psm;                                                                           
    page_offset.psm := page_offset.psm * ( - psm);                                                            
                                                                                                              
    max_page_offset.value := 0ffff(16);                                                                       
    max_page_offset.psm := max_page_offset.psm * ( - psm);                                                    
    v$page_size := max_page_offset.value + 1;                                                                 
    bytes_left := v$page_size - page_offset.value;                                                            
                                                                                                              
    hash_index.hash_result.hash_upper := page_number.low_order_6_bits XOR sva.asid.asid_hash;                 
    hash_index.hash_result.value := page_number.low_order_16_bits XOR sva.asid.asid;                          
    hash_index.hash_result.ptl := hash_index.hash_result.ptl * ptl;                                           
    hash_index.zeros := 0;                                                                                    
                                                                                                              
    page_table_reference.leftmost_6_bits := pta.leftmost_6_bits;                                              
    page_table_reference.ptl := pta.ptl + hash_index.hash_result.ptl;                                         
    page_table_reference.rightmost_12_bits := hash_index.rightmost_12_bits;                                   
                                                                                                              
  /search_page_table/                                                                                         
    FOR search_count := 0 TO 31 DO                                                                            
      dup$access_real_memory (#SIZE (t$page_table_entry),                                                     
            (page_table_reference.rma + (search_count * #SIZE (t$page_table_entry))), page_table_entry_p,     
            new_byte_size, status);                                                                           
      IF NOT status.normal THEN                                                                               
        osp$set_status_abnormal (duc$dump_analyzer_id, due$address_translation_error,                         
              'The calculated page table index (rma used to search the page table) is not on the dump tape',  
              status);                                                                                        
        append_sva (sva, status);                                                                             
        RETURN;  {---->                                                                                       
      IFEND;                                                                                                  
                                                                                                              
      IF (page_table_entry_p^.pageid.pagenum.value = sva.pn.value) AND                                        
            (page_table_entry_p^.pageid.asid.asid = sva.asid.asid) THEN                                       
        pt_rma.zero := 0;                                                                                     
        pt_rma.pfa := page_table_entry_p^.pfa;                                                                
        pt_rma.pfa.psm := pt_rma.pfa.psm + page_offset.psm;                                                   
        pt_rma.rightmost_9_bits := page_offset.rightmost_9_bits;                                              
        rma := pt_rma.value;                                                                                  
        IF NOT page_table_entry_p^.v THEN                                                                     
          access_data.page_fault := TRUE;                                                                     
          access_data.memory_found := TRUE;                                                                   
          access_data.page_fault_offset := system_virtual_address.offset;                                     
          access_data.next_page_offset := system_virtual_address.offset + bytes_left;                         
        IFEND;                                                                                                
        RETURN;  {---->                                                                                       
      IFEND;                                                                                                  
                                                                                                              
      IF NOT page_table_entry_p^.c THEN                                                                       
        EXIT /search_page_table/                                                                              
      IFEND;                                                                                                  
    FOREND /search_page_table/;                                                                               
                                                                                                              
    access_data.page_fault := TRUE;                                                                           
    access_data.memory_found := FALSE;                                                                        
    access_data.page_fault_offset := system_virtual_address.offset;                                           
    access_data.next_page_offset := system_virtual_address.offset + bytes_left;                               
    bytes_left := 0;                                                                                          
                                                                                                              
  PROCEND dup$translate_sva;                                                                                  
MODEND dum$virtual_memory_access;                                                                             
