⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 read.cc

📁 一个mips虚拟机非常好代码,使用C++来编写的,希望大家多学学,
💻 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 + -