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

📄 write.cc

📁 一个mips虚拟机非常好代码,使用C++来编写的,希望大家多学学,
💻 CC
字号:
#include "bus.hh"const ClockValue addr_latency = 5;const ClockValue mem_latency = 20;static ClockValuewrite_doubleword(Device* dev, UInt64 addr, UInt64 x){    if (dev->width == 8)	return dev->write(addr, &x, 8);    else {	ClockValue latency = 0;	if (/* big_endian_mem() */ 1) {	    int shift = 64;	    int size = 8;	    do {		shift -= dev->width * 8;		UInt64 tmp = x >> shift;		latency += dev->write(addr, &tmp, dev->width);		size -= dev->width;		addr += dev->width;	    } while (size);	}	else {	    int size = 8;	    do {		latency += dev->write(addr, &x, dev->width);		x >>= dev->width * 8;		size -= dev->width;		addr += dev->width;	    } while (size);	}	return latency;    }}static ClockValuewrite_block(Device* dev, UInt64 addr, const UInt64* buf, int size){    // Do a burst write with a correct subblock ordering.    assert(size >= 8 && size % 8 == 0);    ClockValue latency = 0;    int counter = 0;    do {	latency +=	    write_doubleword(dev, addr ^ counter, buf[counter / 8]);	counter += 8;    } while (counter < size);    return latency;}static ClockValuewrite_short(Device* dev, UInt64 addr, UInt64 x, int size){    if (is_power_of_two(size) && size <= dev->width)	return dev->write(addr, &x, size);    else {	int width = (is_power_of_two(size)) ? dev->width : 1;	ClockValue latency = 0;	if (/* big_endian_mem() */ 1) {	    int shift = size * 8;	    do {		shift -= width * 8;		UInt64 tmp = x >> shift;		latency += dev->write(addr, &tmp, width);		size -= width;		addr += width;	    } while (size);	}	else {	    do {		latency += dev->write(addr, &x, width);		x >>= width * 8;		size -= width;		addr += width;	    } while (size);	}	return latency;    }}ClockValueMIPS64SimpleBus::write(UInt64 addr, const 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* dst = &ram[addr / 8];	    int i = 0;	    for (; i < size / 8; ++i)		*dst++ = *buf++;	    return addr_latency + i * mem_latency;	}	else {	    unsigned offset = bits(addr, 2, 0) * 8;	    if (!big_endian_host())		offset = 64 - (size * 8) - offset;	    ram[addr / 8] = set_bits(ram[addr / 8], *buf,				     offset + size * 8 - 1, offset);	    return addr_latency + mem_latency;	}    }    else if (addr < 0x10000000) {	// Don't do anything.	return addr_latency;    }    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) ?		write_short(device, addr, *buf, size) :		write_block(device, addr, buf, size);	    if (is_bus_error(latency)) {		return bus_latency(latency);	    }	    else {		return latency;	    }	}    }    else if (addr < 0x14000000) {	assert(!"PCI mem space");	return 0;    }    else if (addr < 0x1c000000) {	reg = addr - 0x14000000;	val = *buf;	val = byte_swap(val);	switch (reg)	{	    case 0x850:	    case 0x854:	    case 0x858:	    case 0x85c:		timer[(reg-0x850)/4]->write(val);		break;	    case 0x864:		timer_control = val;		for (int i = 0; i < 4; i++)		{			timer[i]->control(val & 1, val & 2);			val >>= 2;		}		break;	    case 0xc18:		intr_pending &= val;		check_interrupts();		break;	    case 0xc1c:		intr_mask = val;		check_interrupts();		break;	    case 0xcf8:		pciconfig_address = val;		break;	    case 0xcfc:		pciconfig_write(pciconfig_address, &val, size);		break;	    default:		log("Write unimplemented GT register %x %x", reg, val);		break;	}	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) ?		write_short(device, addr, *buf, size) :		write_block(device, addr, buf, size);	    if (is_bus_error(latency)) {		return bus_latency(latency);	    }	    else {		return latency;	    }	}    }    else {	// A bus interrupt.	return addr_latency;    }}ClockValueMIPS64SimpleBus::pciconfig_write(UInt32 addr, const 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];	if ((reg >= 0x10) && (reg < 0x28)) /* BAR */        {	    unsigned int bar = (reg - 0x10) >> 2;	    device->bar[bar] &= ~(0xffc00000);	    device->bar[bar] |= *buf & 0xffc00000;	}    }    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -