📄 read.cc
字号:
#include "bus.hh"const ClockValue addr_latency = 5;const ClockValue mem_latency = 20;static ClockValueread_doubleword(Device* dev, UInt64 addr, UInt64* buf){ if (dev->width == 8) return dev->read(addr, buf, 8); else { ClockValue latency = 0; UInt64 x = 0; if (/* big_endian_mem() */ 1) { int size = 8; do { UInt64 tmp; latency += dev->read(addr, &tmp, dev->width); x = (x << (dev->width * 8)) | tmp; size -= dev->width; addr += dev->width; } while (size); } else { int size = 8; int shift = 0; do { UInt64 tmp; latency += dev->read(addr, &tmp, dev->width); x |= (tmp << shift); shift += dev->width * 8; size -= dev->width; addr += dev->width; } while (size); } *buf = x; return latency; }}static ClockValueread_block(Device* dev, UInt64 addr, UInt64* buf, int size){ // Do a burst read with a correct subblock ordering. assert(size >= 8 && size % 8 == 0); ClockValue latency = 0; int counter = 0; do { latency += read_doubleword(dev, addr ^ counter, &buf[counter / 8]); counter += 8; } while (counter < size); return latency;}static ClockValueread_short(Device* dev, UInt64 addr, UInt64* buf, int size){ if (is_power_of_two(size) && size <= dev->width) return dev->read(addr, buf, size); else { int width = (is_power_of_two(size)) ? dev->width : 1; ClockValue latency = 0; UInt64 x = 0; if (/* big_endian_mem() */ 1) { do { UInt64 tmp; latency += dev->read(addr, &tmp, width); x = (x << (width * 8)) | tmp; size -= width; addr += width; } while (size); } else { int shift = 0; do { UInt64 tmp; latency += dev->read(addr, &tmp, width); x |= (tmp << shift); shift += width * 8; size -= width; addr += width; } while (size); } *buf = x; return latency; }}ClockValueMIPS64SimpleBus::read(UInt64 addr, UInt64* buf, int size){ UInt32 reg, val; // Discard the coherency protocol. addr = physical_address(addr); assert(size > 0 && (size <= 8 || size % 8 == 0)); assert(!is_power_of_two(size) || (addr & (size - 1)) == 0); if (addr < memory_size) { // Fast access to the main memory. if (size > 8) { UInt64* src = &ram[addr / 8]; int i = 0; for (; i < size / 8; ++i) *buf++ = *src++; return addr_latency + i * mem_latency; } else { UInt64 x = ram[addr / 8]; unsigned offset = addr % 8;#if 0 *buf = (big_endian_host()) ? x >> (64 - (size + offset) * 8) : x >> (offset * 8);#endif *buf = (big_endian_host()) ? x >> (offset * 8) : x >> (64 - (size + offset) * 8); return addr_latency + mem_latency; } } else if (addr < 0x10000000) { // Return zero. for (; size > 0; size -= 8) *buf++ = 0; return addr_latency + mem_latency * (size / 8); } else if (addr < 0x14000000) { // PCI I/O space (8 x 4MB), memory space (8 x 4MB) // We treat the two spaces as equivalent Device* device = pcidev[((addr - 0x10000000) / (0x400000) + 1) & 7]; if (!device) { // Device not present. log("Device not present (%016lx)", addr); return bus_error(addr_latency); } else { ClockValue latency = addr_latency + (size < 8) ? read_short(device, addr, buf, size) : read_block(device, addr, buf, size); return latency; } } else if (addr < 0x1c000000) { reg = addr - 0x14000000; switch (reg) { case 0x850: case 0x854: case 0x858: case 0x85c: val = timer[(reg-0x850)/4]->read(); break; case 0x864: val = timer_control; break; case 0xc18: val = intr_pending; break; case 0xc1c: val = intr_mask; break; case 0xcf8: val = pciconfig_address; break; case 0xcfc: pciconfig_read(pciconfig_address, &val, size); break; default: log("Read unimplemented GT register %x", reg); val = 0; break; } *buf = byte_swap(val); return 0; } else if (addr < 0x20000000) { Device* device = decode[(addr - 0x1c000000) / (0x400000)]; if (!device && (addr >= 0x1c800000) && (addr < 0x1c800040)) device = cs1_subdecode[(addr - 0x1c800000) / (0x10)]; // U4600 hack if (!device) { // Device not present. log("Device not present (%016lx)", addr); return bus_error(addr_latency); } else { ClockValue latency = addr_latency + (size < 8) ? read_short(device, addr, buf, size) : read_block(device, addr, buf, size); return latency; } } else { return bus_error(addr_latency); }}ClockValue MIPS64SimpleBus::pciconfig_read(UInt32 addr, UInt32* buf, int size){ unsigned int bus = (addr >> 16) & 0xff; unsigned int devno = (addr >> 11) & 0x1f; unsigned int function = (addr >> 8) & 7; unsigned int reg = (addr & 0xff); if ((bus == 0) && (function == 0) && (devno < 8) && pcidev[devno]) { PCIDevice *device = pcidev[devno]; // HACK if (reg < 4) /* Vendor/Device ID */ *buf = (((UInt32)device->device_id << 16) | (UInt32)device->vendor_id) >> reg; else if ((reg >= 0x8) && (reg < 0xc)) /* Class ID, API ID, Revision ID */ *buf = ((UInt32)device->class_id << 16) >> (reg - 0x8); else if ((reg >= 0x10) && (reg < 0x28)) /* BAR */ *buf = device->bar[(reg - 0x10) >> 2]; else if (reg == 0x3c) /* IRQ */ *buf = device->irq; else *buf = 0; } else { *buf = 0xffffffff; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -