162 lines
8.2 KiB
C
162 lines
8.2 KiB
C
/* hp3000_mem.h: HP 3000 memory subsystem interface declarations
|
|
|
|
Copyright (c) 2016, J. David Bryan
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name of the author shall not be used
|
|
in advertising or otherwise to promote the sale, use or other dealings in
|
|
this Software without prior written authorization from the author.
|
|
|
|
10-Oct-16 JDB Created
|
|
|
|
|
|
This file contains declarations used by the CPU, I/O Processor, Multiplexer
|
|
Channel, and Selector Channel to interface with the HP 3000 memory subsystem.
|
|
*/
|
|
|
|
|
|
|
|
/* Debug flags.
|
|
|
|
|
|
Implementation notes:
|
|
|
|
1. Memory debug flags are allocated in descending order, as they may be used
|
|
by other modules (e.g., CPU) that allocate their own flags in ascending
|
|
order. No check is made for overlapping values.
|
|
*/
|
|
|
|
#define DEB_MDATA (1u << 31) /* trace memory reads and writes */
|
|
#define DEB_MFETCH (1u << 30) /* trace memory instruction fetches */
|
|
#define DEB_MOPND (1u << 29) /* trace memory operand accesses */
|
|
|
|
|
|
/* Architectural constants.
|
|
|
|
The type used to represent a main memory word value is defined. An array of
|
|
this type is used to simulate the CPU main memory.
|
|
|
|
|
|
Implementation notes:
|
|
|
|
1. The MEMORY_WORD type is a 16-bit unsigned type, corresponding with the
|
|
16-bit main memory in the HP 3000. Unlike the general data type, which
|
|
is a 32-bit type for speed, main memory does not benefit from the faster
|
|
32-bit execution on IA-32 processors, as only one instruction in the
|
|
cpu_read_memory and cpu_write_memory routines has an operand override
|
|
that invokes the slower instruction fetch path. There is a negligible
|
|
difference in the Memory Pattern Test diagnostic execution speeds for the
|
|
uint32 vs. uint16 definition, whereas the VM requirements are doubled for
|
|
the former.
|
|
*/
|
|
|
|
typedef uint16 MEMORY_WORD; /* HP 16-bit memory word representation */
|
|
|
|
|
|
/* Byte accessors.
|
|
|
|
The HP 3000 is a word-addressable machine. Byte addressing is implemented by
|
|
assuming that a memory of N physical words may be addressed as 2N bytes. The
|
|
"byte-capable" machine instructions use "relative byte addresses" that are
|
|
used to obtain absolute word addresses by dividing by two and then accessing
|
|
the upper or lower byte of the resulting word, depending on the LSB of the
|
|
byte address.
|
|
|
|
In simulation, this module provides a byte access structure and a set of
|
|
routines that read or write the next byte in ascending byte-offset order.
|
|
The structure is initialized with the starting byte offset from a specified
|
|
base register value and then is passed as a parameter to the other routines,
|
|
which update the fields accordingly for the access requested. This relieves
|
|
the caller from having to manage the continual logical-to-physical address
|
|
translation, word buffering, byte selection, etc.
|
|
|
|
Byte accessors are also used to provide debug traces of byte operands in
|
|
memory. Initializing an accessor sets a field containing the absolute byte
|
|
memory address; this address may be passed to the byte formatters to print
|
|
the operand.
|
|
|
|
In most cases, operands are defined by starting byte addresses and byte
|
|
counts. However, some operands (e.g., EDIT instruction operands) are
|
|
delineated only by the extents of the accesses. For these operands, byte
|
|
accessors maintain the lowest byte addresses and offsets actually accessed,
|
|
as well as the lengths of the extent of the accesses.
|
|
*/
|
|
|
|
typedef struct { /* byte access descriptor */
|
|
HP_WORD *byte_offset; /* relative byte offset of the next byte */
|
|
HP_WORD data_word; /* memory data word containing the current byte */
|
|
ACCESS_CLASS class; /* memory access classification */
|
|
uint32 word_address; /* logical word address containing the next byte */
|
|
t_bool write_needed; /* TRUE if the data word must be written to memory */
|
|
uint32 count; /* current count of bytes accessed */
|
|
uint32 length; /* (trace) length of extent of access */
|
|
uint32 initial_byte_address; /* (trace) initial absolute byte address */
|
|
uint32 initial_byte_offset; /* (trace) initial relative byte offset */
|
|
uint32 first_byte_address; /* (trace) lowest absolute byte address accessed */
|
|
uint32 first_byte_offset; /* (trace) lowest relative byte offset accessed */
|
|
} BYTE_ACCESS;
|
|
|
|
|
|
/* Memory global SCP support routines */
|
|
|
|
t_stat mem_examine (t_value *eval_array, t_addr address, UNIT *uptr, int32 switches);
|
|
t_stat mem_deposit (t_value value, t_addr address, UNIT *uptr, int32 switches);
|
|
|
|
|
|
/* Global memory functions.
|
|
|
|
mem_initialize : allocate main memory
|
|
mem_is_empty : check for a non-zero value within a range of memory locations
|
|
mem_fill : set all memory locations to a specified value
|
|
|
|
mem_read : read a word from main memory
|
|
mem_write : write a word to main memory
|
|
|
|
mem_init_byte : initialize a memory byte access structure
|
|
mem_set_byte : set the access structure to a new byte offset
|
|
mem_lookup_byte : return a byte at a specified index in a table
|
|
mem_read_byte : read the next byte from memory
|
|
mem_write_byte : write the next byte to memory
|
|
mem_modify_byte : replace the last byte written to memory
|
|
mem_post_byte : post the word containing the last byte modified in place to memory
|
|
mem_update_byte : rewrite the word containing the last byte written to memory
|
|
|
|
fmt_byte_operand : format a byte operand in memory into a character string
|
|
fmt_bcd_operand : format a BCD operand in memory into a character string
|
|
*/
|
|
|
|
extern t_bool mem_initialize (uint32 memory_size);
|
|
extern t_bool mem_is_empty (uint32 starting_address);
|
|
extern void mem_fill (uint32 starting_address, HP_WORD fill_value);
|
|
|
|
extern t_bool mem_read (DEVICE *dptr, ACCESS_CLASS classification, uint32 offset, HP_WORD *value);
|
|
extern t_bool mem_write (DEVICE *dptr, ACCESS_CLASS classification, uint32 offset, HP_WORD value);
|
|
|
|
extern void mem_init_byte (BYTE_ACCESS *bap, ACCESS_CLASS class, HP_WORD *byte_offset, uint32 block_length);
|
|
extern void mem_set_byte (BYTE_ACCESS *bap);
|
|
extern uint8 mem_lookup_byte (BYTE_ACCESS *bap, uint8 index);
|
|
extern uint8 mem_read_byte (BYTE_ACCESS *bap);
|
|
extern void mem_write_byte (BYTE_ACCESS *bap, uint8 byte);
|
|
extern void mem_modify_byte (BYTE_ACCESS *bap, uint8 byte);
|
|
extern void mem_post_byte (BYTE_ACCESS *bap);
|
|
extern void mem_update_byte (BYTE_ACCESS *bap);
|
|
|
|
extern char *fmt_byte_operand (uint32 byte_address, uint32 byte_count);
|
|
extern char *fmt_translated_byte_operand (uint32 byte_address, uint32 byte_count, uint32 table_address);
|
|
extern char *fmt_bcd_operand (uint32 byte_address, uint32 digit_count);
|