diff --git a/3B2/3b2_cpu.c b/3B2/3b2_cpu.c index c16b637b..ec7443a9 100644 --- a/3B2/3b2_cpu.c +++ b/3B2/3b2_cpu.c @@ -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; diff --git a/3B2/3b2_cpu.h b/3B2/3b2_cpu.h index 2e89bc72..b4ffa25c 100644 --- a/3B2/3b2_cpu.h +++ b/3B2/3b2_cpu.h @@ -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) { \ diff --git a/3B2/3b2_ctc.c b/3B2/3b2_ctc.c index 0f6f086b..3c77d5b4 100644 --- a/3B2/3b2_ctc.c +++ b/3B2/3b2_ctc.c @@ -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; diff --git a/3B2/3b2_ctc.h b/3B2/3b2_ctc.h index 14e3b401..08773fe4 100644 --- a/3B2/3b2_ctc.h +++ b/3B2/3b2_ctc.h @@ -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_ */ diff --git a/3B2/3b2_defs.h b/3B2/3b2_defs.h index b0fede4c..343fe13f 100644 --- a/3B2/3b2_defs.h +++ b/3B2/3b2_defs.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; diff --git a/3B2/3b2_dmac.c b/3B2/3b2_dmac.c index 677d9bd6..bf84ca8d 100644 --- a/3B2/3b2_dmac.c +++ b/3B2/3b2_dmac.c @@ -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; diff --git a/3B2/3b2_id.c b/3B2/3b2_id.c index af43bb2a..fd87e129 100644 --- a/3B2/3b2_id.c +++ b/3B2/3b2_id.c @@ -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 */ diff --git a/3B2/3b2_id.h b/3B2/3b2_id.h index 852a6081..457ef4ad 100644 --- a/3B2/3b2_id.h +++ b/3B2/3b2_id.h @@ -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 diff --git a/3B2/3b2_if.c b/3B2/3b2_if.c index 41c36220..5765a738 100644 --- a/3B2/3b2_if.c +++ b/3B2/3b2_if.c @@ -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)) diff --git a/3B2/3b2_if.h b/3B2/3b2_if.h index 7b867d8f..1c794a07 100644 --- a/3B2/3b2_if.h +++ b/3B2/3b2_if.h @@ -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); diff --git a/3B2/3b2_io.c b/3B2/3b2_io.c index 48a27b73..808019c2 100644 --- a/3B2/3b2_io.c +++ b/3B2/3b2_io.c @@ -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 }, diff --git a/3B2/3b2_iu.c b/3B2/3b2_iu.c index ee524129..c50e679a 100644 --- a/3B2/3b2_iu.c +++ b/3B2/3b2_iu.c @@ -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 diff --git a/3B2/3b2_iu.h b/3B2/3b2_iu.h index 1da96755..d3004fd5 100644 --- a/3B2/3b2_iu.h +++ b/3B2/3b2_iu.h @@ -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 diff --git a/3B2/3b2_mmu.c b/3B2/3b2_mmu.c index d6b9e5b9..d0a048e8 100644 --- a/3B2/3b2_mmu.c +++ b/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(); diff --git a/3B2/3b2_mmu.h b/3B2/3b2_mmu.h index 5e4fdb12..0bc3c713 100644 --- a/3B2/3b2_mmu.h +++ b/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); diff --git a/3B2/3b2_ports.c b/3B2/3b2_ports.c index 56a06272..33f7e7a8 100644 --- a/3B2/3b2_ports.c +++ b/3B2/3b2_ports.c @@ -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; diff --git a/3B2/3b2_ports.h b/3B2/3b2_ports.h index 5d5330d1..cef3b4bc 100644 --- a/3B2/3b2_ports.h +++ b/3B2/3b2_ports.h @@ -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_ */