aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/arm/interpreter/mmu/wb.cpp
blob: 5ddda41ee3f4a03f8cddfa2b46fa60948c372b6d (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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include "core/arm/skyeye_common/armdefs.h"

/* wb_init
 * @wb_t	:wb_t to init
 * @num		:num of entrys
 * @nb		:num of byte of each entry
 *
 * $	-1:error
 * 		 0:ok
 * */
int
mmu_wb_init (wb_s * wb_t, int num, int nb)
{
	int i;
	wb_entry_t *entrys, *wb;

	entrys = (wb_entry_t *) malloc (sizeof (*entrys) * num);
	if (entrys == NULL) {
		ERROR_LOG(ARM11, "malloc size %d\n", sizeof (*entrys) * num);
		goto entrys_malloc_error;
	}

	for (wb = entrys, i = 0; i < num; i++, wb++) {
		/*chy 2004-06-06, fix bug found by wenye@cs.ucsb.edu */
		//wb->data = (ARMword *)malloc(sizeof(ARMword) * nb);
		wb->data = (ARMbyte *) malloc (nb);
		if (wb->data == NULL) {
			ERROR_LOG(ARM11, "malloc size of %d\n", nb);
			goto data_malloc_error;
		}

	};

	wb_t->first = wb_t->last = wb_t->used = 0;
	wb_t->num = num;
	wb_t->nb = nb;
	wb_t->entrys = entrys;
	return 0;

      data_malloc_error:
	while (--i >= 0)
		free (entrys[i].data);
	free (entrys);
      entrys_malloc_error:
	return -1;
};

/* wb_exit
 * @wb_t :wb_t to exit
 * */
void
mmu_wb_exit (wb_s * wb_t)
{
	int i;
	wb_entry_t *wb;

	wb = wb_t->entrys;
	for (i = 0; i < wb_t->num; i++, wb++) {
		free (wb->data);
	}
	free (wb_t->entrys);
};

/* wb_write_words :put words in Write Buffer
 * @state:	ARMul_State
 * @wb_t:	write buffer
 * @pa:		physical address
 * @data:	data ptr
 * @n		number of word to write
 *
 * Note: write buffer merge is not implemented, can be done late
 * */
void
mmu_wb_write_bytes (ARMul_State * state, wb_s * wb_t, ARMword pa,
		    ARMbyte * data, int n)
{
	int i;
	wb_entry_t *wb;

	while (n) {
		if (wb_t->num == wb_t->used) {
			/*clean the last wb entry */
			ARMword t;

			wb = &wb_t->entrys[wb_t->last];
			t = wb->pa;
			for (i = 0; i < wb->nb; i++) {
				//mem_write_byte (state, t, wb->data[i]);
				bus_write(8, t, wb->data[i]);
				//t += WORD_SIZE;
				t++;
			}
			wb_t->last++;
			if (wb_t->last == wb_t->num)
				wb_t->last = 0;
			wb_t->used--;
		}

		wb = &wb_t->entrys[wb_t->first];
		i = (n < wb_t->nb) ? n : wb_t->nb;

		wb->pa = pa;
		//pa += i << WORD_SHT;
		pa += i;

		wb->nb = i;
		//memcpy(wb->data, data, i << WORD_SHT);
		memcpy (wb->data, data, i);
		data += i;
		n -= i;
		wb_t->first++;
		if (wb_t->first == wb_t->num)
			wb_t->first = 0;
		wb_t->used++;
	};
//teawater add for set_dirty fflash cache function 2005.07.18-------------------
#ifdef DBCT
	if (!skyeye_config.no_dbct) {
		tb_setdirty (state, pa, NULL);
	}
#endif
//AJ2D--------------------------------------------------------------------------
}

/* wb_drain_all
 * @wb_t wb_t to drain
 * */
void
mmu_wb_drain_all (ARMul_State * state, wb_s * wb_t)
{
	ARMword pa;
	wb_entry_t *wb;
	int i;

	while (wb_t->used) {
		wb = &wb_t->entrys[wb_t->last];
		pa = wb->pa;
		for (i = 0; i < wb->nb; i++) {
			//mem_write_byte (state, pa, wb->data[i]);
			bus_write(8, pa, wb->data[i]);
			//pa += WORD_SIZE;
			pa++;
		}
		wb_t->last++;
		if (wb_t->last == wb_t->num)
			wb_t->last = 0;
		wb_t->used--;
	};
}