aboutsummaryrefslogtreecommitdiffstats
path: root/src/shared/mips_mem_ram.cpp
blob: 179c8fd8bf5ee935af5908515230001e8e6095d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/* This file is an implementation of the functions
   defined in mips_mem.h. It is designed to be
   linked against something which needs an implementation
   of a RAM device following that memory mapping
   interface.
*/
#include "mips_mem.h"

#include <stdio.h>
#include <stdlib.h>

struct mips_mem_provider
{
	uint32_t length;
	uint8_t *data;
};

extern "C" mips_mem_h mips_mem_create_ram(
	uint32_t cbMem	//!< Total number of bytes of ram
){
	if(cbMem>0x20000000){
		return 0; // No more than 512MB of RAM
	}
	
	uint8_t *data=(uint8_t*)malloc(cbMem);
	if(data==0)
		return 0;
	
	struct mips_mem_provider *mem=(struct mips_mem_provider*)malloc(sizeof(struct mips_mem_provider));
	if(mem==0){
		free(data);
		return 0;
	}
	
	mem->length=cbMem;
	mem->data=data;
	
	return mem;
}

static mips_error mips_mem_read_write(
	bool write,
    mips_mem_h mem,
    uint32_t address,
    uint32_t length,
    uint8_t *dataOut
)
{	
	if(mem==0){
		return mips_ErrorInvalidHandle;
	}
	
	if( (length!=1) && (length!=2) && (length!=4) ){
		return mips_ExceptionInvalidLength;
	}
	
	if(0 != (address % length) ){
		return mips_ExceptionInvalidAlignment;
	}
	if(((address+length) > mem->length) || (address > (UINT32_MAX - length))){	// A subtle bug here, maybe?
		return mips_ExceptionInvalidAddress;
	}
	
	if(write){
		for(unsigned i=0; i<length; i++){
			mem->data[address+i]=dataOut[i];
		}
	}else{
		for(unsigned i=0; i<length; i++){
			dataOut[i]=mem->data[address+i];
		}
	}
	return mips_Success;
}

mips_error mips_mem_read(
    mips_mem_h mem,		//!< Handle to target memory
    uint32_t address,	//!< Byte address to start transaction at
    uint32_t length,	//!< Number of bytes to transfer
    uint8_t *dataOut	//!< Receives the target bytes
)
{	
	return mips_mem_read_write(
		false,	// we want to read
		mem,
		address,
		length,
		dataOut
	);
}

mips_error mips_mem_write(
	mips_mem_h mem,	//! Handle to target memory
	uint32_t address,		//! Byte address to start transaction at
	uint32_t length,			//! Number of bytes to transfer
	const uint8_t *dataIn	//! Receives the target bytes
)
{
	return mips_mem_read_write(
		true,	// we want to write
		mem,
		address,
		length,
		(uint8_t*)dataIn
	);
}

void mips_mem_free(mips_mem_h mem)
{
	if(mem){
		free(mem->data);
		mem->data=0;
		free(mem);
	}
}