3B2: Remove unused code, move static declarations
This change cleans up warnings issued when compiled with -Wall. - Removed unused functions and variables. - Moved static declarations out of headers and into source files - Added braces around initialization where suggested.
This commit is contained in:
parent
5ae2e4c49d
commit
71ee25be1a
17 changed files with 319 additions and 387 deletions
|
@ -33,6 +33,43 @@
|
|||
|
||||
#define MAX_SUB_RETURN_SKIP 9
|
||||
|
||||
/* Static function declarations */
|
||||
static uint32 cpu_effective_address(operand * op);
|
||||
static uint32 cpu_read_op(operand * op);
|
||||
static void cpu_write_op(operand * op, t_uint64 val);
|
||||
static void cpu_set_nz_flags(t_uint64 data, operand * op);
|
||||
static void cpu_calc_ints();
|
||||
static SIM_INLINE void cpu_on_normal_exception(uint8 isc);
|
||||
static SIM_INLINE void cpu_on_stack_exception(uint8 isc);
|
||||
static SIM_INLINE void cpu_on_process_exception(uint8 isc);
|
||||
static SIM_INLINE void cpu_on_reset_exception(uint8 isc);
|
||||
static SIM_INLINE void cpu_perform_gate(uint32 index1, uint32 index2);
|
||||
static SIM_INLINE void clear_instruction(instr *inst);
|
||||
static SIM_INLINE int8 op_type(operand *op);
|
||||
static SIM_INLINE t_bool op_signed(operand *op);
|
||||
static SIM_INLINE uint32 sign_extend_b(uint8 val);
|
||||
static SIM_INLINE uint32 sign_extend_h(uint16 val);
|
||||
static SIM_INLINE t_bool cpu_z_flag();
|
||||
static SIM_INLINE t_bool cpu_n_flag();
|
||||
static SIM_INLINE t_bool cpu_c_flag();
|
||||
static SIM_INLINE t_bool cpu_v_flag();
|
||||
static SIM_INLINE void cpu_set_z_flag(t_bool val);
|
||||
static SIM_INLINE void cpu_set_n_flag(t_bool val);
|
||||
static SIM_INLINE void cpu_set_c_flag(t_bool val);
|
||||
static SIM_INLINE void cpu_set_v_flag(t_bool val);
|
||||
static SIM_INLINE void cpu_set_v_flag_op(t_uint64 val, operand *op);
|
||||
static SIM_INLINE uint8 cpu_execution_level();
|
||||
static SIM_INLINE void cpu_push_word(uint32 val);
|
||||
static SIM_INLINE uint32 cpu_pop_word();
|
||||
static SIM_INLINE void irq_push_word(uint32 val);
|
||||
static SIM_INLINE uint32 irq_pop_word();
|
||||
static SIM_INLINE void cpu_context_switch_1(uint32 pcbp);
|
||||
static SIM_INLINE void cpu_context_switch_2(uint32 pcbp);
|
||||
static SIM_INLINE void cpu_context_switch_3(uint32 pcbp);
|
||||
static SIM_INLINE t_bool op_is_psw(operand *op);
|
||||
static SIM_INLINE void add(t_uint64 a, t_uint64 b, operand *dst);
|
||||
static SIM_INLINE void sub(t_uint64 a, t_uint64 b, operand *dst);
|
||||
|
||||
/* RO memory. */
|
||||
uint32 *ROM = NULL;
|
||||
|
||||
|
@ -3436,43 +3473,6 @@ static SIM_INLINE t_bool op_signed(operand *op) {
|
|||
return (op_type(op) == WD || op_type(op) == HW || op_type(op) == SB);
|
||||
}
|
||||
|
||||
static SIM_INLINE t_bool is_byte_immediate(operand * oper)
|
||||
{
|
||||
return oper->mode == 6 && oper->reg == 15;
|
||||
}
|
||||
|
||||
static SIM_INLINE t_bool is_halfword_immediate(operand * oper)
|
||||
{
|
||||
return oper->mode == 5 && oper->reg == 15;
|
||||
}
|
||||
|
||||
static SIM_INLINE t_bool is_word_immediate(operand * oper)
|
||||
{
|
||||
return oper->mode == 4 && oper->reg == 15;
|
||||
}
|
||||
|
||||
static SIM_INLINE t_bool is_positive_literal(operand * oper)
|
||||
{
|
||||
return (oper->mode == 0 ||
|
||||
oper->mode == 1 ||
|
||||
oper->mode == 2);
|
||||
}
|
||||
|
||||
static SIM_INLINE t_bool is_negative_literal(operand * oper)
|
||||
{
|
||||
return oper->mode == 15;
|
||||
}
|
||||
|
||||
/* Returns true if the operand may not be used as a destination */
|
||||
static SIM_INLINE t_bool invalid_destination(operand * oper)
|
||||
{
|
||||
return (is_byte_immediate(oper) ||
|
||||
is_halfword_immediate(oper) ||
|
||||
is_word_immediate(oper) ||
|
||||
is_positive_literal(oper) ||
|
||||
is_negative_literal(oper));
|
||||
}
|
||||
|
||||
static SIM_INLINE uint32 sign_extend_b(uint8 val)
|
||||
{
|
||||
if (val & 0x80)
|
||||
|
@ -3480,11 +3480,6 @@ static SIM_INLINE uint32 sign_extend_b(uint8 val)
|
|||
return (uint32) val;
|
||||
}
|
||||
|
||||
static SIM_INLINE uint32 zero_extend_b(uint8 val)
|
||||
{
|
||||
return (uint32) val & BYTE_MASK;
|
||||
}
|
||||
|
||||
static SIM_INLINE uint32 sign_extend_h(uint16 val)
|
||||
{
|
||||
if (val & 0x8000)
|
||||
|
@ -3492,11 +3487,6 @@ static SIM_INLINE uint32 sign_extend_h(uint16 val)
|
|||
return (uint32) val;
|
||||
}
|
||||
|
||||
static SIM_INLINE uint32 zero_extend_h(uint16 val)
|
||||
{
|
||||
return (uint32) val & HALF_MASK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the current CPU execution level.
|
||||
*/
|
||||
|
@ -3639,11 +3629,6 @@ static SIM_INLINE t_bool op_is_psw(operand *op)
|
|||
return (op->mode == 4 && op->reg == NUM_PSW);
|
||||
}
|
||||
|
||||
static SIM_INLINE t_bool op_is_sp(operand *op)
|
||||
{
|
||||
return op->reg == NUM_SP;
|
||||
}
|
||||
|
||||
static SIM_INLINE void sub(t_uint64 a, t_uint64 b, operand *dst)
|
||||
{
|
||||
t_uint64 result;
|
||||
|
|
|
@ -414,58 +414,6 @@ instr *cpu_next_instruction(void);
|
|||
uint8 decode_instruction(instr *instr);
|
||||
void cpu_on_interrupt(uint16 vec);
|
||||
|
||||
static uint32 cpu_effective_address(operand * op);
|
||||
static uint32 cpu_read_op(operand * op);
|
||||
static void cpu_write_op(operand * op, t_uint64 val);
|
||||
static void cpu_set_nz_flags(t_uint64 data, operand * op);
|
||||
static void cpu_calc_ints();
|
||||
|
||||
static SIM_INLINE void cpu_on_normal_exception(uint8 isc);
|
||||
static SIM_INLINE void cpu_on_stack_exception(uint8 isc);
|
||||
static SIM_INLINE void cpu_on_process_exception(uint8 isc);
|
||||
static SIM_INLINE void cpu_on_reset_exception(uint8 isc);
|
||||
static SIM_INLINE void cpu_perform_gate(uint32 index1, uint32 index2);
|
||||
static SIM_INLINE t_bool mem_exception();
|
||||
static SIM_INLINE void clear_exceptions();
|
||||
static SIM_INLINE void set_psw_tm(t_bool val);
|
||||
static SIM_INLINE void clear_instruction(instr *inst);
|
||||
static SIM_INLINE int8 op_type(operand *op);
|
||||
static SIM_INLINE t_bool op_signed(operand *op);
|
||||
static SIM_INLINE t_bool is_byte_immediate(operand * oper);
|
||||
static SIM_INLINE t_bool is_halfword_immediate(operand * oper);
|
||||
static SIM_INLINE t_bool is_word_immediate(operand * oper);
|
||||
static SIM_INLINE t_bool is_positive_literal(operand * oper);
|
||||
static SIM_INLINE t_bool is_negative_literal(operand * oper);
|
||||
static SIM_INLINE t_bool invalid_destination(operand * oper);
|
||||
static SIM_INLINE uint32 sign_extend_n(uint8 val);
|
||||
static SIM_INLINE uint32 sign_extend_b(uint8 val);
|
||||
static SIM_INLINE uint32 zero_extend_b(uint8 val);
|
||||
static SIM_INLINE uint32 sign_extend_h(uint16 val);
|
||||
static SIM_INLINE uint32 zero_extend_h(uint16 val);
|
||||
static SIM_INLINE t_bool cpu_z_flag();
|
||||
static SIM_INLINE t_bool cpu_n_flag();
|
||||
static SIM_INLINE t_bool cpu_c_flag();
|
||||
static SIM_INLINE t_bool cpu_v_flag();
|
||||
static SIM_INLINE void cpu_set_z_flag(t_bool val);
|
||||
static SIM_INLINE void cpu_set_n_flag(t_bool val);
|
||||
static SIM_INLINE void cpu_set_c_flag(t_bool val);
|
||||
static SIM_INLINE void cpu_set_v_flag(t_bool val);
|
||||
static SIM_INLINE void cpu_set_v_flag_op(t_uint64 val, operand *op);
|
||||
static SIM_INLINE uint8 cpu_execution_level();
|
||||
static SIM_INLINE void cpu_set_execution_level(uint8 level);
|
||||
static SIM_INLINE void cpu_push_word(uint32 val);
|
||||
static SIM_INLINE uint32 cpu_pop_word();
|
||||
static SIM_INLINE void irq_push_word(uint32 val);
|
||||
static SIM_INLINE uint32 irq_pop_word();
|
||||
static SIM_INLINE void cpu_context_switch_1(uint32 pcbp);
|
||||
static SIM_INLINE void cpu_context_switch_2(uint32 pcbp);
|
||||
static SIM_INLINE void cpu_context_switch_3(uint32 pcbp);
|
||||
static SIM_INLINE t_bool op_is_psw(operand *op);
|
||||
static SIM_INLINE t_bool op_is_sp(operand *op);
|
||||
static SIM_INLINE uint32 cpu_next_pc();
|
||||
static SIM_INLINE void add(t_uint64 a, t_uint64 b, operand *dst);
|
||||
static SIM_INLINE void sub(t_uint64 a, t_uint64 b, operand *dst);
|
||||
|
||||
/* Helper macros */
|
||||
|
||||
#define MOD(A,B,OP1,OP2,SZ) { \
|
||||
|
|
|
@ -61,6 +61,11 @@ extern UNIT cio_unit;
|
|||
#define ATOW(arr,i) ((uint32)arr[i+3] + ((uint32)arr[i+2] << 8) + \
|
||||
((uint32)arr[i+1] << 16) + ((uint32)arr[i] << 24))
|
||||
|
||||
/* Static function declarations */
|
||||
static t_stat ctc_show_cqueue(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
static t_stat ctc_show_rqueue(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
static t_stat ctc_show_queue_common(FILE *st, UNIT *uptr, int32 val, CONST void *desc, t_bool rq);
|
||||
|
||||
static uint8 int_cid; /* Interrupting card ID */
|
||||
static uint8 int_subdev; /* Interrupting subdevice */
|
||||
static t_bool ctc_conf = FALSE; /* Has a CTC card been configured? */
|
||||
|
@ -262,7 +267,7 @@ static void ctc_cmd(uint8 cid,
|
|||
uint8 sec_buf[512];
|
||||
int32 b, i, j;
|
||||
t_seccnt secrw = 0;
|
||||
struct vtoc vtoc = {0};
|
||||
struct vtoc vtoc = {{0}};
|
||||
struct pdinfo pdinfo = {0};
|
||||
t_stat result;
|
||||
|
||||
|
|
|
@ -151,9 +151,4 @@ void ctc_sysgen(uint8 cid);
|
|||
void ctc_express(uint8 cid);
|
||||
void ctc_full(uint8 cid);
|
||||
|
||||
/* Largely here for debugging purposes */
|
||||
static t_stat ctc_show_cqueue(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
static t_stat ctc_show_rqueue(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
static t_stat ctc_show_queue_common(FILE *st, UNIT *uptr, int32 val, CONST void *desc, t_bool rq);
|
||||
|
||||
#endif /* _3B2_CTC_H_ */
|
||||
|
|
|
@ -357,17 +357,11 @@ typedef struct {
|
|||
uint8 status;
|
||||
} DMA_STATE;
|
||||
|
||||
|
||||
/* global symbols from DMA */
|
||||
extern DMA_STATE dma_state;
|
||||
|
||||
static SIM_INLINE uint32 dma_address(uint8 channel, uint32 offset, t_bool r) {
|
||||
uint32 addr;
|
||||
addr = (PHYS_MEM_BASE + dma_state.channels[channel].addr + offset);
|
||||
/* The top bit of the page address is a R/W bit, so we mask it here */
|
||||
addr |= (uint32) (((uint32)dma_state.channels[channel].page & 0x7f) << 16);
|
||||
return addr;
|
||||
}
|
||||
|
||||
extern DEVICE dmac_dev;
|
||||
uint32 dma_address(uint8 channel, uint32 offset, t_bool r);
|
||||
|
||||
/* global symbols from the CSR */
|
||||
extern uint16 csr_data;
|
||||
|
|
|
@ -60,6 +60,14 @@ dmac_dma_handler device_dma_handlers[] = {
|
|||
{0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
uint32 dma_address(uint8 channel, uint32 offset, t_bool r) {
|
||||
uint32 addr;
|
||||
addr = (PHYS_MEM_BASE + dma_state.channels[channel].addr + offset);
|
||||
/* The top bit of the page address is a R/W bit, so we mask it here */
|
||||
addr |= (uint32) (((uint32)dma_state.channels[channel].page & 0x7f) << 16);
|
||||
return addr;
|
||||
}
|
||||
|
||||
t_stat dmac_reset(DEVICE *dptr)
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -53,6 +53,9 @@
|
|||
#define ID_SIS_WAIT 142
|
||||
#define ID_CMD_WAIT 140
|
||||
|
||||
/* Static function declarations */
|
||||
static SIM_INLINE t_lba id_lba(uint16 cyl, uint8 head, uint8 sec);
|
||||
|
||||
/* Data FIFO pointer - Read */
|
||||
uint8 id_dpr = 0;
|
||||
/* Data FIFO pointer - Write */
|
||||
|
|
|
@ -184,6 +184,4 @@ void id_handle_data(uint8 val);
|
|||
void id_handle_command(uint8 val);
|
||||
void id_after_dma();
|
||||
|
||||
static SIM_INLINE t_lba id_lba(uint16 cyl, uint8 head, uint8 sec);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,10 +30,11 @@
|
|||
|
||||
#include "3b2_if.h"
|
||||
|
||||
/*
|
||||
* TODO: Macros used for debugging timers. Remove when debugging is complete.
|
||||
*/
|
||||
double if_start_time;
|
||||
/* Static function declarations */
|
||||
static SIM_INLINE void if_set_irq();
|
||||
static SIM_INLINE void if_clear_irq();
|
||||
static SIM_INLINE void if_cancel_pending_irq();
|
||||
static SIM_INLINE uint32 if_buf_offset();
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(x,y) ((x) > (y) ? (x) : (y))
|
||||
|
|
|
@ -124,10 +124,6 @@ extern t_bool if_irq;
|
|||
|
||||
/* Function prototypes */
|
||||
|
||||
static SIM_INLINE void if_set_irq();
|
||||
static SIM_INLINE void if_clear_irq();
|
||||
static SIM_INLINE void if_cancel_pending_irq();
|
||||
static SIM_INLINE uint32 if_buf_offset();
|
||||
t_stat if_svc(UNIT *uptr);
|
||||
t_stat if_reset(DEVICE *dptr);
|
||||
uint32 if_read(uint32 pa, size_t size);
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
#define CRC_POLYNOMIAL 0xEDB88320
|
||||
|
||||
CIO_STATE cio[CIO_SLOTS] = { 0 };
|
||||
CIO_STATE cio[CIO_SLOTS] = {{0}};
|
||||
|
||||
struct iolink iotable[] = {
|
||||
{ MMUBASE, MMUBASE+MMUSIZE, &mmu_read, &mmu_write },
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
#include "3b2_iu.h"
|
||||
#include "sim_tmxr.h"
|
||||
|
||||
/* Static function declarations */
|
||||
static SIM_INLINE void iu_w_cmd(uint8 portno, uint8 val);
|
||||
|
||||
/*
|
||||
* The 3B2/400 has two on-board serial ports, labeled CONSOLE and
|
||||
* CONTTY. The CONSOLE port is (naturally) the system console. The
|
||||
|
|
|
@ -212,9 +212,4 @@ void iu_txrdy_a_irq();
|
|||
void iu_txrdy_b_irq();
|
||||
void iu_dma(uint8 channel, uint32 service_address);
|
||||
|
||||
static SIM_INLINE void iu_w_buf(uint8 portno, uint8 val);
|
||||
static SIM_INLINE void iu_w_cmd(uint8 portno, uint8 val);
|
||||
static SIM_INLINE void iu_update_rxi(uint8 c);
|
||||
static SIM_INLINE void iu_update_txi();
|
||||
|
||||
#endif
|
||||
|
|
249
3B2/3b2_mmu.c
249
3B2/3b2_mmu.c
|
@ -59,6 +59,255 @@ DEVICE mmu_dev = {
|
|||
DEV_DEBUG, 0, sys_deb_tab
|
||||
};
|
||||
|
||||
/*
|
||||
* Find an SD in the cache.
|
||||
*/
|
||||
static SIM_INLINE t_stat get_sdce(uint32 va, uint32 *sd0, uint32 *sd1)
|
||||
{
|
||||
uint32 tag, sdch, sdcl;
|
||||
uint8 ci;
|
||||
|
||||
ci = (SID(va) * NUM_SDCE) + SD_IDX(va);
|
||||
tag = SD_TAG(va);
|
||||
|
||||
sdch = mmu_state.sdch[ci];
|
||||
sdcl = mmu_state.sdcl[ci];
|
||||
|
||||
if ((sdch & SD_GOOD_MASK) && SDCE_TAG(sdcl) == tag) {
|
||||
*sd0 = SDCE_TO_SD0(sdch, sdcl);
|
||||
*sd1 = SDCE_TO_SD1(sdch);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
return SCPE_NXM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a PD in the cache. Sets both the PD and the cached access
|
||||
* permissions.
|
||||
*/
|
||||
static SIM_INLINE t_stat get_pdce(uint32 va, uint32 *pd, uint8 *pd_acc)
|
||||
{
|
||||
uint32 tag, pdcll, pdclh, pdcrl, pdcrh;
|
||||
uint8 ci;
|
||||
|
||||
ci = (SID(va) * NUM_PDCE) + PD_IDX(va);
|
||||
tag = PD_TAG(va);
|
||||
|
||||
/* Left side */
|
||||
pdcll = mmu_state.pdcll[ci];
|
||||
pdclh = mmu_state.pdclh[ci];
|
||||
|
||||
/* Right side */
|
||||
pdcrl = mmu_state.pdcrl[ci];
|
||||
pdcrh = mmu_state.pdcrh[ci];
|
||||
|
||||
/* Search L and R to find a good entry with a matching tag. */
|
||||
if ((pdclh & PD_GOOD_MASK) && PDCXL_TAG(pdcll) == tag) {
|
||||
*pd = PDCXH_TO_PD(pdclh);
|
||||
*pd_acc = PDCXL_TO_ACC(pdcll);
|
||||
return SCPE_OK;
|
||||
} else if ((pdcrh & PD_GOOD_MASK) && PDCXL_TAG(pdcrl) == tag) {
|
||||
*pd = PDCXH_TO_PD(pdcrh);
|
||||
*pd_acc = PDCXL_TO_ACC(pdcrl);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
return SCPE_NXM;
|
||||
}
|
||||
|
||||
static SIM_INLINE void put_sdce(uint32 va, uint32 sd0, uint32 sd1)
|
||||
{
|
||||
uint8 ci;
|
||||
|
||||
ci = (SID(va) * NUM_SDCE) + SD_IDX(va);
|
||||
|
||||
mmu_state.sdcl[ci] = SD_TO_SDCL(va, sd0);
|
||||
mmu_state.sdch[ci] = SD_TO_SDCH(sd0, sd1);
|
||||
}
|
||||
|
||||
|
||||
static SIM_INLINE void put_pdce(uint32 va, uint32 sd0, uint32 pd)
|
||||
{
|
||||
uint8 ci;
|
||||
|
||||
ci = (SID(va) * NUM_PDCE) + PD_IDX(va);
|
||||
|
||||
/* Cache Replacement Algorithm
|
||||
* (from the WE32101 MMU Information Manual)
|
||||
*
|
||||
* 1. If G==0 for the left-hand entry, the new PD is cached in the
|
||||
* left-hand entry and the U bit (left-hand side) is cleared to
|
||||
* 0.
|
||||
*
|
||||
* 2. If G==1 for the left-hand entry, and G==0 for the right-hand
|
||||
* entry, the new PD is cached in the right-hand entry and the
|
||||
* U bit (left-hand side) is set to 1.
|
||||
*
|
||||
* 3. If G==1 for both entries, the U bit in the left-hand entry
|
||||
* is examined. If U==0, the new PD is cached in the right-hand
|
||||
* entry of the PDC row and U is set to 1. If U==1, it is
|
||||
* cached in the left-hand entry and U is cleared to 0.
|
||||
*/
|
||||
|
||||
if ((mmu_state.pdclh[ci] & PD_GOOD_MASK) == 0) {
|
||||
/* Use the left entry */
|
||||
mmu_state.pdcll[ci] = SD_TO_PDCXL(va, sd0);
|
||||
mmu_state.pdclh[ci] = PD_TO_PDCXH(pd, sd0);
|
||||
mmu_state.pdclh[ci] &= ~PDCLH_USED_MASK;
|
||||
} else if ((mmu_state.pdcrh[ci] & PD_GOOD_MASK) == 0) {
|
||||
/* Use the right entry */
|
||||
mmu_state.pdcrl[ci] = SD_TO_PDCXL(va, sd0);
|
||||
mmu_state.pdcrh[ci] = PD_TO_PDCXH(pd, sd0);
|
||||
mmu_state.pdclh[ci] |= PDCLH_USED_MASK;
|
||||
} else {
|
||||
/* Pick the least-recently-replaced side */
|
||||
if (mmu_state.pdclh[ci] & PDCLH_USED_MASK) {
|
||||
mmu_state.pdcll[ci] = SD_TO_PDCXL(va, sd0);
|
||||
mmu_state.pdclh[ci] = PD_TO_PDCXH(pd, sd0);
|
||||
mmu_state.pdclh[ci] &= ~PDCLH_USED_MASK;
|
||||
} else {
|
||||
mmu_state.pdcrl[ci] = SD_TO_PDCXL(va, sd0);
|
||||
mmu_state.pdcrh[ci] = PD_TO_PDCXH(pd, sd0);
|
||||
mmu_state.pdclh[ci] |= PDCLH_USED_MASK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static SIM_INLINE void flush_sdce(uint32 va)
|
||||
{
|
||||
uint8 ci;
|
||||
|
||||
ci = (SID(va) * NUM_SDCE) + SD_IDX(va);
|
||||
|
||||
if (mmu_state.sdch[ci] & SD_GOOD_MASK) {
|
||||
mmu_state.sdch[ci] &= ~SD_GOOD_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
static SIM_INLINE void flush_pdce(uint32 va)
|
||||
{
|
||||
uint32 tag, pdcll, pdclh, pdcrl, pdcrh;
|
||||
uint8 ci;
|
||||
|
||||
ci = (SID(va) * NUM_PDCE) + PD_IDX(va);
|
||||
tag = PD_TAG(va);
|
||||
|
||||
/* Left side */
|
||||
pdcll = mmu_state.pdcll[ci];
|
||||
pdclh = mmu_state.pdclh[ci];
|
||||
/* Right side */
|
||||
pdcrl = mmu_state.pdcrl[ci];
|
||||
pdcrh = mmu_state.pdcrh[ci];
|
||||
|
||||
/* Search L and R to find a good entry with a matching tag. */
|
||||
if ((pdclh & PD_GOOD_MASK) && PDCXL_TAG(pdcll) == tag) {
|
||||
mmu_state.pdclh[ci] &= ~PD_GOOD_MASK;
|
||||
} else if ((pdcrh & PD_GOOD_MASK) && PDCXL_TAG(pdcrl) == tag) {
|
||||
mmu_state.pdcrh[ci] &= ~PD_GOOD_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
static SIM_INLINE void flush_cache_sec(uint8 sec)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_SDCE; i++) {
|
||||
mmu_state.sdch[(sec * NUM_SDCE) + i] &= ~SD_GOOD_MASK;
|
||||
}
|
||||
for (i = 0; i < NUM_PDCE; i++) {
|
||||
mmu_state.pdclh[(sec * NUM_PDCE) + i] &= ~PD_GOOD_MASK;
|
||||
mmu_state.pdcrh[(sec * NUM_PDCE) + i] &= ~PD_GOOD_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
static SIM_INLINE void flush_caches()
|
||||
{
|
||||
uint8 i;
|
||||
|
||||
for (i = 0; i < NUM_SEC; i++) {
|
||||
flush_cache_sec(i);
|
||||
}
|
||||
}
|
||||
|
||||
static SIM_INLINE t_stat mmu_check_perm(uint8 flags, uint8 r_acc)
|
||||
{
|
||||
switch(MMU_PERM(flags)) {
|
||||
case 0: /* No Access */
|
||||
return SCPE_NXM;
|
||||
case 1: /* Exec Only */
|
||||
if (r_acc != ACC_IF && r_acc != ACC_IFAD) {
|
||||
return SCPE_NXM;
|
||||
}
|
||||
return SCPE_OK;
|
||||
case 2: /* Read / Execute */
|
||||
if (r_acc != ACC_AF && r_acc != ACC_OF &&
|
||||
r_acc != ACC_IF && r_acc != ACC_IFAD &&
|
||||
r_acc != ACC_MT) {
|
||||
return SCPE_NXM;
|
||||
}
|
||||
return SCPE_OK;
|
||||
default:
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the M (modified) or R (referenced) bit the SD and cache
|
||||
*/
|
||||
static SIM_INLINE void mmu_update_sd(uint32 va, uint32 mask)
|
||||
{
|
||||
uint32 sd0;
|
||||
uint8 ci;
|
||||
|
||||
ci = (SID(va) * NUM_SDCE) + SD_IDX(va);
|
||||
|
||||
/* We go back to main memory to find the SD because the SD may
|
||||
have been loaded from cache, which is lossy. */
|
||||
sd0 = pread_w(SD_ADDR(va));
|
||||
pwrite_w(SD_ADDR(va), sd0|mask);
|
||||
|
||||
/* There is no 'R' bit in the SD cache, only an 'M' bit. */
|
||||
if (mask == SD_M_MASK) {
|
||||
mmu_state.sdch[ci] |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the M (modified) or R (referenced) bit the PD and cache
|
||||
*/
|
||||
static SIM_INLINE void mmu_update_pd(uint32 va, uint32 pd_addr, uint32 mask)
|
||||
{
|
||||
uint32 pd, tag, pdcll, pdclh, pdcrl, pdcrh;
|
||||
uint8 ci;
|
||||
|
||||
tag = PD_TAG(va);
|
||||
ci = (SID(va) * NUM_PDCE) + PD_IDX(va);
|
||||
|
||||
/* We go back to main memory to find the PD because the PD may
|
||||
have been loaded from cache, which is lossy. */
|
||||
pd = pread_w(pd_addr);
|
||||
pwrite_w(pd_addr, pd|mask);
|
||||
|
||||
/* Update in the cache */
|
||||
|
||||
/* Left side */
|
||||
pdcll = mmu_state.pdcll[ci];
|
||||
pdclh = mmu_state.pdclh[ci];
|
||||
|
||||
/* Right side */
|
||||
pdcrl = mmu_state.pdcrl[ci];
|
||||
pdcrh = mmu_state.pdcrh[ci];
|
||||
|
||||
/* Search L and R to find a good entry with a matching tag, then
|
||||
update the appropriate bit */
|
||||
if ((pdclh & PD_GOOD_MASK) && PDCXL_TAG(pdcll) == tag) {
|
||||
mmu_state.pdclh[ci] |= mask;
|
||||
} else if ((pdcrh & PD_GOOD_MASK) && PDCXL_TAG(pdcrl) == tag) {
|
||||
mmu_state.pdcrh[ci] |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
t_stat mmu_init(DEVICE *dptr)
|
||||
{
|
||||
flush_caches();
|
||||
|
|
249
3B2/3b2_mmu.h
249
3B2/3b2_mmu.h
|
@ -355,255 +355,6 @@ t_stat mmu_decode_vaddr(uint32 vaddr, uint8 r_acc,
|
|||
#define SHOULD_UPDATE_PD_M_BIT(pd) \
|
||||
(r_acc == ACC_W && !((pd) & PD_M_MASK))
|
||||
|
||||
/*
|
||||
* Find an SD in the cache.
|
||||
*/
|
||||
static SIM_INLINE t_stat get_sdce(uint32 va, uint32 *sd0, uint32 *sd1)
|
||||
{
|
||||
uint32 tag, sdch, sdcl;
|
||||
uint8 ci;
|
||||
|
||||
ci = (SID(va) * NUM_SDCE) + SD_IDX(va);
|
||||
tag = SD_TAG(va);
|
||||
|
||||
sdch = mmu_state.sdch[ci];
|
||||
sdcl = mmu_state.sdcl[ci];
|
||||
|
||||
if ((sdch & SD_GOOD_MASK) && SDCE_TAG(sdcl) == tag) {
|
||||
*sd0 = SDCE_TO_SD0(sdch, sdcl);
|
||||
*sd1 = SDCE_TO_SD1(sdch);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
return SCPE_NXM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a PD in the cache. Sets both the PD and the cached access
|
||||
* permissions.
|
||||
*/
|
||||
static SIM_INLINE t_stat get_pdce(uint32 va, uint32 *pd, uint8 *pd_acc)
|
||||
{
|
||||
uint32 tag, pdcll, pdclh, pdcrl, pdcrh;
|
||||
uint8 ci;
|
||||
|
||||
ci = (SID(va) * NUM_PDCE) + PD_IDX(va);
|
||||
tag = PD_TAG(va);
|
||||
|
||||
/* Left side */
|
||||
pdcll = mmu_state.pdcll[ci];
|
||||
pdclh = mmu_state.pdclh[ci];
|
||||
|
||||
/* Right side */
|
||||
pdcrl = mmu_state.pdcrl[ci];
|
||||
pdcrh = mmu_state.pdcrh[ci];
|
||||
|
||||
/* Search L and R to find a good entry with a matching tag. */
|
||||
if ((pdclh & PD_GOOD_MASK) && PDCXL_TAG(pdcll) == tag) {
|
||||
*pd = PDCXH_TO_PD(pdclh);
|
||||
*pd_acc = PDCXL_TO_ACC(pdcll);
|
||||
return SCPE_OK;
|
||||
} else if ((pdcrh & PD_GOOD_MASK) && PDCXL_TAG(pdcrl) == tag) {
|
||||
*pd = PDCXH_TO_PD(pdcrh);
|
||||
*pd_acc = PDCXL_TO_ACC(pdcrl);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
return SCPE_NXM;
|
||||
}
|
||||
|
||||
static SIM_INLINE void put_sdce(uint32 va, uint32 sd0, uint32 sd1)
|
||||
{
|
||||
uint8 ci;
|
||||
|
||||
ci = (SID(va) * NUM_SDCE) + SD_IDX(va);
|
||||
|
||||
mmu_state.sdcl[ci] = SD_TO_SDCL(va, sd0);
|
||||
mmu_state.sdch[ci] = SD_TO_SDCH(sd0, sd1);
|
||||
}
|
||||
|
||||
|
||||
static SIM_INLINE void put_pdce(uint32 va, uint32 sd0, uint32 pd)
|
||||
{
|
||||
uint8 ci;
|
||||
|
||||
ci = (SID(va) * NUM_PDCE) + PD_IDX(va);
|
||||
|
||||
/* Cache Replacement Algorithm
|
||||
* (from the WE32101 MMU Information Manual)
|
||||
*
|
||||
* 1. If G==0 for the left-hand entry, the new PD is cached in the
|
||||
* left-hand entry and the U bit (left-hand side) is cleared to
|
||||
* 0.
|
||||
*
|
||||
* 2. If G==1 for the left-hand entry, and G==0 for the right-hand
|
||||
* entry, the new PD is cached in the right-hand entry and the
|
||||
* U bit (left-hand side) is set to 1.
|
||||
*
|
||||
* 3. If G==1 for both entries, the U bit in the left-hand entry
|
||||
* is examined. If U==0, the new PD is cached in the right-hand
|
||||
* entry of the PDC row and U is set to 1. If U==1, it is
|
||||
* cached in the left-hand entry and U is cleared to 0.
|
||||
*/
|
||||
|
||||
if ((mmu_state.pdclh[ci] & PD_GOOD_MASK) == 0) {
|
||||
/* Use the left entry */
|
||||
mmu_state.pdcll[ci] = SD_TO_PDCXL(va, sd0);
|
||||
mmu_state.pdclh[ci] = PD_TO_PDCXH(pd, sd0);
|
||||
mmu_state.pdclh[ci] &= ~PDCLH_USED_MASK;
|
||||
} else if ((mmu_state.pdcrh[ci] & PD_GOOD_MASK) == 0) {
|
||||
/* Use the right entry */
|
||||
mmu_state.pdcrl[ci] = SD_TO_PDCXL(va, sd0);
|
||||
mmu_state.pdcrh[ci] = PD_TO_PDCXH(pd, sd0);
|
||||
mmu_state.pdclh[ci] |= PDCLH_USED_MASK;
|
||||
} else {
|
||||
/* Pick the least-recently-replaced side */
|
||||
if (mmu_state.pdclh[ci] & PDCLH_USED_MASK) {
|
||||
mmu_state.pdcll[ci] = SD_TO_PDCXL(va, sd0);
|
||||
mmu_state.pdclh[ci] = PD_TO_PDCXH(pd, sd0);
|
||||
mmu_state.pdclh[ci] &= ~PDCLH_USED_MASK;
|
||||
} else {
|
||||
mmu_state.pdcrl[ci] = SD_TO_PDCXL(va, sd0);
|
||||
mmu_state.pdcrh[ci] = PD_TO_PDCXH(pd, sd0);
|
||||
mmu_state.pdclh[ci] |= PDCLH_USED_MASK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static SIM_INLINE void flush_sdce(uint32 va)
|
||||
{
|
||||
uint8 ci;
|
||||
|
||||
ci = (SID(va) * NUM_SDCE) + SD_IDX(va);
|
||||
|
||||
if (mmu_state.sdch[ci] & SD_GOOD_MASK) {
|
||||
mmu_state.sdch[ci] &= ~SD_GOOD_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
static SIM_INLINE void flush_pdce(uint32 va)
|
||||
{
|
||||
uint32 tag, pdcll, pdclh, pdcrl, pdcrh;
|
||||
uint8 ci;
|
||||
|
||||
ci = (SID(va) * NUM_PDCE) + PD_IDX(va);
|
||||
tag = PD_TAG(va);
|
||||
|
||||
/* Left side */
|
||||
pdcll = mmu_state.pdcll[ci];
|
||||
pdclh = mmu_state.pdclh[ci];
|
||||
/* Right side */
|
||||
pdcrl = mmu_state.pdcrl[ci];
|
||||
pdcrh = mmu_state.pdcrh[ci];
|
||||
|
||||
/* Search L and R to find a good entry with a matching tag. */
|
||||
if ((pdclh & PD_GOOD_MASK) && PDCXL_TAG(pdcll) == tag) {
|
||||
mmu_state.pdclh[ci] &= ~PD_GOOD_MASK;
|
||||
} else if ((pdcrh & PD_GOOD_MASK) && PDCXL_TAG(pdcrl) == tag) {
|
||||
mmu_state.pdcrh[ci] &= ~PD_GOOD_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
static SIM_INLINE void flush_cache_sec(uint8 sec)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_SDCE; i++) {
|
||||
mmu_state.sdch[(sec * NUM_SDCE) + i] &= ~SD_GOOD_MASK;
|
||||
}
|
||||
for (i = 0; i < NUM_PDCE; i++) {
|
||||
mmu_state.pdclh[(sec * NUM_PDCE) + i] &= ~PD_GOOD_MASK;
|
||||
mmu_state.pdcrh[(sec * NUM_PDCE) + i] &= ~PD_GOOD_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
static SIM_INLINE void flush_caches()
|
||||
{
|
||||
uint8 i;
|
||||
|
||||
for (i = 0; i < NUM_SEC; i++) {
|
||||
flush_cache_sec(i);
|
||||
}
|
||||
}
|
||||
|
||||
static SIM_INLINE t_stat mmu_check_perm(uint8 flags, uint8 r_acc)
|
||||
{
|
||||
switch(MMU_PERM(flags)) {
|
||||
case 0: /* No Access */
|
||||
return SCPE_NXM;
|
||||
case 1: /* Exec Only */
|
||||
if (r_acc != ACC_IF && r_acc != ACC_IFAD) {
|
||||
return SCPE_NXM;
|
||||
}
|
||||
return SCPE_OK;
|
||||
case 2: /* Read / Execute */
|
||||
if (r_acc != ACC_AF && r_acc != ACC_OF &&
|
||||
r_acc != ACC_IF && r_acc != ACC_IFAD &&
|
||||
r_acc != ACC_MT) {
|
||||
return SCPE_NXM;
|
||||
}
|
||||
return SCPE_OK;
|
||||
default:
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the M (modified) or R (referenced) bit the SD and cache
|
||||
*/
|
||||
static SIM_INLINE void mmu_update_sd(uint32 va, uint32 mask)
|
||||
{
|
||||
uint32 sd0;
|
||||
uint8 ci;
|
||||
|
||||
ci = (SID(va) * NUM_SDCE) + SD_IDX(va);
|
||||
|
||||
/* We go back to main memory to find the SD because the SD may
|
||||
have been loaded from cache, which is lossy. */
|
||||
sd0 = pread_w(SD_ADDR(va));
|
||||
pwrite_w(SD_ADDR(va), sd0|mask);
|
||||
|
||||
/* There is no 'R' bit in the SD cache, only an 'M' bit. */
|
||||
if (mask == SD_M_MASK) {
|
||||
mmu_state.sdch[ci] |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the M (modified) or R (referenced) bit the PD and cache
|
||||
*/
|
||||
static SIM_INLINE void mmu_update_pd(uint32 va, uint32 pd_addr, uint32 mask)
|
||||
{
|
||||
uint32 pd, tag, pdcll, pdclh, pdcrl, pdcrh;
|
||||
uint8 ci;
|
||||
|
||||
tag = PD_TAG(va);
|
||||
ci = (SID(va) * NUM_PDCE) + PD_IDX(va);
|
||||
|
||||
/* We go back to main memory to find the PD because the PD may
|
||||
have been loaded from cache, which is lossy. */
|
||||
pd = pread_w(pd_addr);
|
||||
pwrite_w(pd_addr, pd|mask);
|
||||
|
||||
/* Update in the cache */
|
||||
|
||||
/* Left side */
|
||||
pdcll = mmu_state.pdcll[ci];
|
||||
pdclh = mmu_state.pdclh[ci];
|
||||
|
||||
/* Right side */
|
||||
pdcrl = mmu_state.pdcrl[ci];
|
||||
pdcrh = mmu_state.pdcrh[ci];
|
||||
|
||||
/* Search L and R to find a good entry with a matching tag, then
|
||||
update the appropriate bit */
|
||||
if ((pdclh & PD_GOOD_MASK) && PDCXL_TAG(pdcll) == tag) {
|
||||
mmu_state.pdclh[ci] |= mask;
|
||||
} else if ((pdcrh & PD_GOOD_MASK) && PDCXL_TAG(pdcrl) == tag) {
|
||||
mmu_state.pdcrh[ci] |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special functions for reading operands and examining memory
|
||||
safely */
|
||||
t_stat read_operand(uint32 va, uint8 *val);
|
||||
|
|
|
@ -44,6 +44,10 @@
|
|||
|
||||
#include "3b2_ports.h"
|
||||
|
||||
/* Static function declarations */
|
||||
static t_stat ports_show_queue_common(FILE *st, UNIT *uptr, int32 val,
|
||||
CONST void *desc, t_bool rq);
|
||||
|
||||
extern CIO_STATE cio[CIO_SLOTS];
|
||||
extern UNIT cio_unit;
|
||||
|
||||
|
|
|
@ -231,7 +231,4 @@ void ports_sysgen(uint8 cid);
|
|||
void ports_express(uint8 cid);
|
||||
void ports_full(uint8 cid);
|
||||
|
||||
static t_stat ports_show_queue_common(FILE *st, UNIT *uptr, int32 val,
|
||||
CONST void *desc, t_bool rq);
|
||||
|
||||
#endif /* _3B2_PORTS_H_ */
|
||||
|
|
Loading…
Add table
Reference in a new issue