/[gxemul]/trunk/src/cpus/cpu_alpha_instr_loadstore.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/cpus/cpu_alpha_instr_loadstore.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (show annotations)
Mon Oct 8 16:20:26 2007 UTC (13 years ago) by dpavlin
File MIME type: text/plain
File size: 6969 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


1 /*
2 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_alpha_instr_loadstore.c,v 1.5 2006/06/30 20:22:53 debug Exp $
29 *
30 * Alpha load/store instructions. (Included from cpu_alpha_instr_inc.c.)
31 *
32 *
33 * Load/store instructions have the following arguments:
34 *
35 * arg[0] = pointer to the register to load to or store from (uint64_t)
36 * arg[1] = pointer to the base register (uint64_t)
37 * arg[2] = offset (as an int32_t)
38 *
39 * NOTE:
40 * Alpha byte and word loads (8- and 16-bit) are unsigned, while
41 * 32-bit long words are sign-extended up to 64 bits during a load!
42 */
43
44
45 #ifndef LS_IGNORE_OFFSET
46 static void LS_GENERIC_N(struct cpu *cpu, struct alpha_instr_call *ic)
47 {
48 #ifdef LS_B
49 unsigned char data[1];
50 #endif
51 #ifdef LS_W
52 unsigned char data[2];
53 #endif
54 #ifdef LS_L
55 unsigned char data[4];
56 #endif
57 #ifdef LS_Q
58 unsigned char data[8];
59 #endif
60 uint64_t addr = *((uint64_t *)ic->arg[1]);
61 uint64_t data_x;
62
63 addr += (int32_t)ic->arg[2];
64 #ifdef LS_UNALIGNED
65 addr &= ~7;
66 #endif
67
68 #ifdef LS_LOAD
69 /* Load: */
70 if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),
71 MEM_READ, CACHE_DATA)) {
72 fatal("store failed: TODO\n");
73 exit(1);
74 }
75
76 data_x = data[0];
77 #ifndef LS_B
78 data_x += (data[1] << 8);
79 #ifndef LS_W
80 data_x += (data[2] << 16);
81 data_x += ((uint64_t)data[3] << 24);
82 #ifdef LS_L
83 data_x = (int64_t)(int32_t)data_x;
84 #endif
85 #ifndef LS_L
86 data_x += ((uint64_t)data[4] << 32);
87 data_x += ((uint64_t)data[5] << 40);
88 data_x += ((uint64_t)data[6] << 48);
89 data_x += ((uint64_t)data[7] << 56);
90 #endif
91 #endif
92 #endif
93 *((uint64_t *)ic->arg[0]) = data_x;
94 #else
95 /* Store: */
96 data_x = *((uint64_t *)ic->arg[0]);
97 data[0] = data_x;
98 #ifndef LS_B
99 data[1] = data_x >> 8;
100 #ifndef LS_W
101 data[2] = data_x >> 16;
102 data[3] = data_x >> 24;
103 #ifndef LS_L
104 data[4] = data_x >> 32;
105 data[5] = data_x >> 40;
106 data[6] = data_x >> 48;
107 data[7] = data_x >> 56;
108 #endif
109 #endif
110 #endif
111
112 if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),
113 MEM_WRITE, CACHE_DATA)) {
114 fatal("store failed: TODO\n");
115 exit(1);
116 }
117
118 #ifdef LS_LLSC
119 #ifndef LS_LOAD
120 *((uint64_t *)ic->arg[0]) = 1;
121 #endif
122 #endif
123
124 #endif
125 }
126 #endif
127
128
129 static void LS_N(struct cpu *cpu, struct alpha_instr_call *ic)
130 {
131 unsigned char *page;
132 uint64_t addr = (*((uint64_t *)ic->arg[1]))
133 #ifndef LS_IGNORE_OFFSET
134 + (int32_t)ic->arg[2]
135 #endif
136 ;
137
138 const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
139 const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
140 const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
141 uint32_t x1, x2, x3, c;
142 struct DYNTRANS_L2_64_TABLE *l2;
143 struct DYNTRANS_L3_64_TABLE *l3;
144 x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
145 x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
146 x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) & mask3;
147 /* fatal("X3: addr=%016"PRIx64" x1=%x x2=%x x3=%x\n",
148 (uint64_t) addr, (int) x1, (int) x2, (int) x3); */
149 l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
150 /* fatal(" l2 = %p\n", l2); */
151 l3 = l2->l3[x2];
152 /* fatal(" l3 = %p\n", l3); */
153 #ifdef LS_LOAD
154 page = l3->host_load[x3];
155 #else
156 page = l3->host_store[x3];
157 #endif
158
159 #ifdef LS_UNALIGNED
160 addr &= ~7;
161 #endif
162
163 #ifdef LS_LLSC
164 #ifdef LS_LOAD
165 /* TODO: cache-line size! */
166 cpu->cd.alpha.load_linked_addr = addr & ~63;
167 cpu->cd.alpha.ll_flag = 1;
168 #else
169 /* TODO: only invalidate per cache line, not everything! */
170 if (cpu->cd.alpha.ll_flag == 1) {
171 int i;
172 for (i=0; i<cpu->machine->ncpus; i++)
173 cpu->machine->cpus[i]->cd.alpha.ll_flag = 0;
174 } else {
175 *((uint64_t *)ic->arg[0]) = 0;
176 return;
177 }
178 #endif
179 #endif
180
181 c = addr & 8191;
182
183 #ifndef LS_B
184 if (c &
185 #ifdef LS_W
186 1
187 #endif
188 #ifdef LS_L
189 3
190 #endif
191 #ifdef LS_Q
192 7
193 #endif
194 ) {
195 LS_GENERIC_N(cpu, ic);
196 return;
197 }
198 else
199 #endif
200
201 if (page != NULL) {
202 #ifdef LS_LOAD
203 #ifdef HOST_BIG_ENDIAN
204 uint64_t data_x;
205 data_x = page[c];
206 #ifndef LS_B
207 data_x += (page[c+1] << 8);
208 #ifndef LS_W
209 data_x += (page[c+2] << 16);
210 data_x += ((uint64_t)page[c+3] << 24);
211 #ifndef LS_L
212 data_x += ((uint64_t)page[c+4] << 32);
213 data_x += ((uint64_t)page[c+5] << 40);
214 data_x += ((uint64_t)page[c+6] << 48);
215 data_x += ((uint64_t)page[c+7] << 56);
216 #endif
217 #endif
218 #endif
219 #ifdef LS_L
220 *((uint64_t *)ic->arg[0]) = (int64_t)(int32_t)data_x;
221 #else
222 *((uint64_t *)ic->arg[0]) = data_x;
223 #endif
224 #else
225 #ifdef LS_B
226 *((uint64_t *)ic->arg[0]) = page[c];
227 #endif
228 #ifdef LS_W
229 uint16_t d = *((uint16_t *) (page + c));
230 *((uint64_t *)ic->arg[0]) = d;
231 #endif
232 #ifdef LS_L
233 int32_t d = *((int32_t *) (page + c));
234 *((uint64_t *)ic->arg[0]) = (int64_t)d;
235 #endif
236 #ifdef LS_Q
237 uint64_t d = *((uint64_t *) (page + c));
238 *((uint64_t *)ic->arg[0]) = d;
239 #endif
240 #endif
241 #else
242 /* Store: */
243 #ifdef HOST_BIG_ENDIAN
244 uint64_t data_x = *((uint64_t *)ic->arg[0]);
245 page[c] = data_x;
246 #ifndef LS_B
247 page[c+1] = data_x >> 8;
248 #ifndef LS_W
249 page[c+2] = data_x >> 16;
250 page[c+3] = data_x >> 24;
251 #ifndef LS_L
252 page[c+4] = data_x >> 32;
253 page[c+5] = data_x >> 40;
254 page[c+6] = data_x >> 48;
255 page[c+7] = data_x >> 56;
256 #endif
257 #endif
258 #endif
259 #else
260 /* Native byte order: */
261 #ifdef LS_B
262 page[c] = *((uint64_t *)ic->arg[0]);
263 #endif
264 #ifdef LS_W
265 uint32_t d = *((uint64_t *)ic->arg[0]);
266 *((uint16_t *) (page + c)) = d;
267 #endif
268 #ifdef LS_L
269 uint32_t d = *((uint64_t *)ic->arg[0]);
270 *((uint32_t *) (page + c)) = d;
271 #endif
272 #ifdef LS_Q
273 uint64_t d = *((uint64_t *)ic->arg[0]);
274 *((uint64_t *) (page + c)) = d;
275 #endif
276 #endif
277
278 #ifdef LS_LLSC
279 #ifndef LS_LOAD
280 *((uint64_t *)ic->arg[0]) = 1;
281 #endif
282 #endif
283
284 #endif /* !LS_LOAD */
285 } else
286 LS_GENERIC_N(cpu, ic);
287 }
288

  ViewVC Help
Powered by ViewVC 1.1.26