📄 mem.c
字号:
else if ((addr >= stack_bot) && (addr < STACK_TOP)) stack_seg_b [addr - stack_bot] = (BYTE_TYPE) value; else if ((addr >= K_DATA_BOT) && (addr < k_data_top)) k_data_seg_b [addr - K_DATA_BOT] = (BYTE_TYPE) value; else bad_mem_write (addr, value, 0);}voidset_mem_half(mem_addr addr, reg_word value){ data_modified = 1; if ((addr >= DATA_BOT) && (addr < data_top) && !(addr & 0x1)) data_seg_h [(addr - DATA_BOT) >> 1] = (short) value; else if ((addr >= stack_bot) && (addr < STACK_TOP) && !(addr & 0x1)) stack_seg_h [(addr - stack_bot) >> 1] = (short) value; else if ((addr >= K_DATA_BOT) && (addr < k_data_top) && !(addr & 0x1)) k_data_seg_h [(addr - K_DATA_BOT) >> 1] = (short) value; else bad_mem_write (addr, value, 0x1);}voidset_mem_word(mem_addr addr, reg_word value){ data_modified = 1; if ((addr >= DATA_BOT) && (addr < data_top) && !(addr & 0x3)) data_seg [(addr - DATA_BOT) >> 2] = (mem_word) value; else if ((addr >= stack_bot) && (addr < STACK_TOP) && !(addr & 0x3)) stack_seg [(addr - stack_bot) >> 2] = (mem_word) value; else if ((addr >= K_DATA_BOT) && (addr < k_data_top) && !(addr & 0x3)) k_data_seg [(addr - K_DATA_BOT) >> 2] = (mem_word) value; else bad_mem_write (addr, value, 0x3);}/* Handle the infrequent and erroneous cases in memory accesses. */static instruction *bad_text_read (mem_addr addr){ RAISE_EXCEPTION (ExcCode_IBE, CP0_BadVAddr = addr); return (inst_decode (0));}static voidbad_text_write (mem_addr addr, instruction *inst){ RAISE_EXCEPTION (ExcCode_IBE, CP0_BadVAddr = addr); set_mem_word (addr, ENCODING (inst));}static mem_wordbad_mem_read (mem_addr addr, int mask){ mem_word tmp; if ((addr & mask) != 0) RAISE_EXCEPTION (ExcCode_AdEL, CP0_BadVAddr = addr) else if (addr >= TEXT_BOT && addr < text_top) switch (mask) { case 0x0: tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]);#ifdef BIGENDIAN tmp = (unsigned)tmp >> (8 * (3 - (addr & 0x3)));#else tmp = (unsigned)tmp >> (8 * (addr & 0x3));#endif return (0xff & tmp); case 0x1: tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]);#ifdef BIGENDIAN tmp = (unsigned)tmp >> (8 * (2 - (addr & 0x2)));#else tmp = (unsigned)tmp >> (8 * (addr & 0x2));#endif return (0xffff & tmp); case 0x3: { instruction *inst = text_seg [(addr - TEXT_BOT) >> 2]; if (inst == NULL) return 0; else return (ENCODING (inst)); } default: run_error ("Bad mask (0x%x) in bad_mem_read\n", mask); } else if (addr > data_top && addr < stack_bot /* If more than 16 MB below stack, probably is bad data ref */ && addr > stack_bot - 16*K*K) { /* Grow stack segment */ expand_stack (stack_bot - addr + 4); return (0); } else if (MM_IO_BOT <= addr && addr <= MM_IO_TOP) return (read_memory_mapped_IO (addr)); else /* Address out of range */ RAISE_EXCEPTION (ExcCode_DBE, CP0_BadVAddr = addr) return (0);}static voidbad_mem_write (mem_addr addr, mem_word value, int mask){ mem_word tmp; if ((addr & mask) != 0) /* Unaligned address fault */ RAISE_EXCEPTION (ExcCode_AdES, CP0_BadVAddr = addr) else if (addr >= TEXT_BOT && addr < text_top) { switch (mask) { case 0x0: tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]);#ifdef BIGENDIAN tmp = ((tmp & ~(0xff << (8 * (3 - (addr & 0x3))))) | (value & 0xff) << (8 * (3 - (addr & 0x3))));#else tmp = ((tmp & ~(0xff << (8 * (addr & 0x3)))) | (value & 0xff) << (8 * (addr & 0x3)));#endif text_seg [(addr - TEXT_BOT) >> 2] = inst_decode (tmp); break; case 0x1: tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]);#ifdef BIGENDIAN tmp = ((tmp & ~(0xffff << (8 * (2 - (addr & 0x2))))) | (value & 0xffff) << (8 * (2 - (addr & 0x2))));#else tmp = ((tmp & ~(0xffff << (8 * (addr & 0x2)))) | (value & 0xffff) << (8 * (addr & 0x2)));#endif text_seg [(addr - TEXT_BOT) >> 2] = inst_decode (tmp); break; case 0x3: text_seg [(addr - TEXT_BOT) >> 2] = inst_decode (value); break; default: run_error ("Bad mask (0x%x) in bad_mem_read\n", mask); } text_modified = 1; } else if (addr > data_top && addr < stack_bot /* If more than 16 MB below stack, probably is bad data ref */ && addr > stack_bot - 16*K*K) { /* Grow stack segment */ expand_stack (stack_bot - addr + 4); if (addr >= stack_bot) { if (mask == 0) stack_seg_b [addr - stack_bot] = (char)value; else if (mask == 1) stack_seg_h [(addr - stack_bot) >> 1] = (short)value; else stack_seg [(addr - stack_bot) >> 2] = value; } else RAISE_EXCEPTION (ExcCode_DBE, CP0_BadVAddr = addr) data_modified = 1; } else if (MM_IO_BOT <= addr && addr <= MM_IO_TOP) write_memory_mapped_IO (addr, value); else /* Address out of range */ RAISE_EXCEPTION (ExcCode_DBE, CP0_BadVAddr = addr)}/* Memory-mapped IO routines. */static int recv_control = 0; /* No input */static int recv_buffer;static int recv_buffer_full_timer = 0;static int trans_control = TRANS_READY; /* Ready to write */static int trans_buffer;static int trans_buffer_full_timer = 0;/* Check if input is available and output is possible. If so, update the memory-mapped control registers and buffers. */voidcheck_memory_mapped_IO (){ if (recv_buffer_full_timer > 0) { /* Do not check for more input until this interval expires. */ recv_buffer_full_timer -= 1; } else if (console_input_available ()) { /* Read new char into the buffer and raise an interrupt, if interrupts are enabled for device. */ /* assert(recv_buffer_full_timer == 0); */ recv_buffer = get_console_char (); recv_control |= RECV_READY; recv_buffer_full_timer = RECV_INTERVAL; if (recv_control & RECV_INT_ENABLE) { RAISE_INTERRUPT (RECV_INT_LEVEL); } } if (trans_buffer_full_timer > 0) { /* Do not allow output until this interval expires. */ trans_buffer_full_timer -= 1; } else if (!(trans_control & TRANS_READY)) { /* Done writing: empty the buffer and raise an interrupt, if interrupts are enabled for device. */ /* assert(trans_buffer_full_timer == 0); */ trans_control |= TRANS_READY; if (trans_control & TRANS_INT_ENABLE) { RAISE_INTERRUPT (TRANS_INT_LEVEL); } }}/* Invoked on a write to the memory-mapped IO area. */static voidwrite_memory_mapped_IO (mem_addr addr, mem_word value){ switch (addr) { case TRANS_CTRL_ADDR: /* Program can only set the interrupt enable, not ready, bit. */ if ((value & TRANS_INT_ENABLE) != 0) { /* Enable interrupts: */ trans_control |= TRANS_INT_ENABLE; if (trans_control & TRANS_READY) { /* Raise interrupt on enabling a ready transmitter */ RAISE_INTERRUPT (TRANS_INT_LEVEL); } } else { /* Disable interrupts: */ trans_control &= ~TRANS_INT_ENABLE; CLEAR_INTERRUPT (TRANS_INT_LEVEL); /* Clear IP bit in Cause */ } break; case TRANS_BUFFER_ADDR: /* Ignore write if device is not ready. */ if ((trans_control & TRANS_READY) != 0) { /* Write char: */ trans_buffer = value & 0xff; put_console_char ((char)trans_buffer); /* Device is busy for a while: */ trans_control &= ~TRANS_READY; trans_buffer_full_timer = TRANS_LATENCY; CLEAR_INTERRUPT (TRANS_INT_LEVEL); /* Clear IP bit in Cause */ } break; case RECV_CTRL_ADDR: /* Program can only set the interrupt enable, not ready, bit. */ if ((value & RECV_INT_ENABLE) != 0) { /* Enable interrupts: */ recv_control |= RECV_INT_ENABLE; if (recv_control & RECV_READY) { /* Raise interrupt on enabling a ready receiver */ RAISE_INTERRUPT (RECV_INT_LEVEL); } } else { /* Disable interrupts: */ recv_control &= ~RECV_INT_ENABLE; CLEAR_INTERRUPT (RECV_INT_LEVEL); /* Clear IP bit in Cause */ } break; case RECV_BUFFER_ADDR: /* Nop: program can't change buffer. */ break; default: run_error ("Write to unused memory-mapped IO address (0x%x)\n", addr); }}/* Invoked on a read in the memory-mapped IO area. */static mem_wordread_memory_mapped_IO (mem_addr addr){ switch (addr) { case TRANS_CTRL_ADDR: return (trans_control); case TRANS_BUFFER_ADDR: return (trans_buffer & 0xff); case RECV_CTRL_ADDR: return (recv_control); case RECV_BUFFER_ADDR: recv_control &= ~RECV_READY; /* Buffer now empty */ recv_buffer_full_timer = 0; CLEAR_INTERRUPT (RECV_INT_LEVEL); /* Clear IP bit in Cause */ return (recv_buffer & 0xff); default: run_error ("Read from unused memory-mapped IO address (0x%x)\n", addr); return (0); }}/* Misc. routines */voidprint_mem (mem_addr addr){ mem_word value; if ((addr & 0x3) != 0) addr &= ~0x3; /* Address must be word-aligned */ if (TEXT_BOT <= addr && addr < text_top) print_inst (addr); else if (DATA_BOT <= addr && addr < data_top) { value = read_mem_word (addr); write_output (message_out, "Data seg @ 0x%08x (%d) = 0x%08x (%d)\n", addr, addr, value, value); } else if (stack_bot <= addr && addr < STACK_TOP) { value = read_mem_word (addr); write_output (message_out, "Stack seg @ 0x%08x (%d) = 0x%08x (%d)\n", addr, addr, value, value); } else if (K_TEXT_BOT <= addr && addr < k_text_top) print_inst (addr); else if (K_DATA_BOT <= addr && addr < k_data_top) { value = read_mem_word (addr); write_output (message_out, "Kernel Data seg @ 0x%08x (%d) = 0x%08x (%d)\n", addr, addr, value, value); } else error ("Address 0x%08x (%d) to print_mem is out of bounds\n", addr, addr);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -