/[gxemul]/trunk/src/cpus/cpu_sparc_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_sparc_instr_loadstore.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (show annotations)
Mon Oct 8 16:20:40 2007 UTC (13 years ago) by dpavlin
File MIME type: text/plain
File size: 6366 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 0.4.2  ==============


1 /*
2 * Copyright (C) 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_sparc_instr_loadstore.c,v 1.3 2006/07/26 23:21:48 debug Exp $
29 *
30 * SPARC load/store instructions; the following args are used:
31 *
32 * arg[0] = pointer to the register to load to or store from
33 * arg[1] = pointer to the base register
34 * arg[2] = if LS_USE_IMM is defined: an int32_t immediate offset
35 * otherwise: pointer to the offset register
36 */
37
38
39 void LS_GENERIC_N(struct cpu *cpu, struct sparc_instr_call *ic)
40 {
41 MODE_int_t addr = reg(ic->arg[1]) +
42 #ifdef LS_USE_IMM
43 (int32_t)ic->arg[2];
44 #else
45 reg(ic->arg[2]);
46 #endif
47 uint8_t data[LS_SIZE];
48 #ifdef LS_LOAD
49 uint64_t x;
50 #endif
51
52 /* Synchronize the PC: */
53 int low_pc = ((size_t)ic - (size_t)cpu->cd.sparc.cur_ic_page)
54 / sizeof(struct sparc_instr_call);
55 cpu->pc &= ~((SPARC_IC_ENTRIES_PER_PAGE - 1)
56 << SPARC_INSTR_ALIGNMENT_SHIFT);
57 cpu->pc += (low_pc << SPARC_INSTR_ALIGNMENT_SHIFT);
58
59 #ifndef LS_1
60 /* Check alignment: */
61 if (addr & (LS_SIZE - 1)) {
62 fatal("TODO: sparc dyntrans alignment exception, size = %i,"
63 " addr = %016"PRIx64", pc = %016"PRIx64"\n", LS_SIZE,
64 (uint64_t) addr, cpu->pc);
65
66 /* TODO: Generalize this into a abort_call, or similar: */
67 cpu->running = 0;
68 debugger_n_steps_left_before_interaction = 0;
69 cpu->cd.sparc.next_ic = &nothing_call;
70 return;
71 }
72 #endif
73
74 #ifdef LS_LOAD
75 if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),
76 MEM_READ, CACHE_DATA)) {
77 /* Exception. */
78 return;
79 }
80 x = memory_readmax64(cpu, data, LS_SIZE);
81 #ifdef LS_SIGNED
82 #ifdef LS_1
83 x = (int8_t)x;
84 #endif
85 #ifdef LS_2
86 x = (int16_t)x;
87 #endif
88 #ifdef LS_4
89 x = (int32_t)x;
90 #endif
91 #endif
92 reg(ic->arg[0]) = x;
93 #else /* LS_STORE: */
94 memory_writemax64(cpu, data, LS_SIZE, reg(ic->arg[0]));
95 if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),
96 MEM_WRITE, CACHE_DATA)) {
97 /* Exception. */
98 return;
99 }
100 #endif
101 }
102
103
104 void LS_N(struct cpu *cpu, struct sparc_instr_call *ic)
105 {
106 MODE_uint_t addr = reg(ic->arg[1]) +
107 #ifdef LS_USE_IMM
108 (int32_t)ic->arg[2];
109 #else
110 reg(ic->arg[2]);
111 #endif
112 unsigned char *p;
113 #ifdef MODE32
114 #ifdef LS_LOAD
115 p = cpu->cd.sparc.host_load[addr >> 12];
116 #else
117 p = cpu->cd.sparc.host_store[addr >> 12];
118 #endif
119 #else /* !MODE32 */
120 const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
121 const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
122 const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
123 uint32_t x1, x2, x3;
124 struct DYNTRANS_L2_64_TABLE *l2;
125 struct DYNTRANS_L3_64_TABLE *l3;
126
127 x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
128 x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
129 x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) & mask3;
130 /* fatal("X3: addr=%016"PRIx64" x1=%x x2=%x x3=%x\n",
131 (uint64_t) addr, (int) x1, (int) x2, (int) x3); */
132 l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
133 /* fatal(" l2 = %p\n", l2); */
134 l3 = l2->l3[x2];
135 /* fatal(" l3 = %p\n", l3); */
136 #ifdef LS_LOAD
137 p = l3->host_load[x3];
138 #else
139 p = l3->host_store[x3];
140 #endif
141 /* fatal(" p = %p\n", p); */
142 #endif
143
144 if (p == NULL
145 #ifndef LS_1
146 || addr & (LS_SIZE - 1)
147 #endif
148 ) {
149 LS_GENERIC_N(cpu, ic);
150 return;
151 }
152
153 addr &= 0xfff;
154
155 #ifdef LS_LOAD
156 /* Load: */
157
158 #ifdef LS_1
159 reg(ic->arg[0]) =
160 #ifdef LS_SIGNED
161 (int8_t)
162 #endif
163 p[addr];
164 #endif /* LS_1 */
165
166 #ifdef LS_2
167 reg(ic->arg[0]) =
168 #ifdef LS_SIGNED
169 (int16_t)
170 #endif
171 #ifdef HOST_BIG_ENDIAN
172 ( *(uint16_t *)(p + addr) );
173 #else
174 ((p[addr]<<8) + p[addr+1]);
175 #endif
176 #endif /* LS_2 */
177
178 #ifdef LS_4
179 reg(ic->arg[0]) =
180 #ifdef LS_SIGNED
181 (int32_t)
182 #else
183 (uint32_t)
184 #endif
185 #ifdef HOST_BIG_ENDIAN
186 ( *(uint32_t *)(p + addr) );
187 #else
188 ((p[addr]<<24) + (p[addr+1]<<16) + (p[addr+2]<<8) + p[addr+3]);
189 #endif
190 #endif /* LS_4 */
191
192 #ifdef LS_8
193 *((uint64_t *)ic->arg[0]) =
194 #ifdef HOST_BIG_ENDIAN
195 ( *(uint64_t *)(p + addr) );
196 #else
197 ((uint64_t)p[addr] << 56) + ((uint64_t)p[addr+1] << 48) +
198 ((uint64_t)p[addr+2] << 40) + ((uint64_t)p[addr+3] << 32) +
199 ((uint64_t)p[addr+4] << 24) +
200 (p[addr+5] << 16) + (p[addr+6] << 8) + p[addr+7];
201 #endif
202 #endif /* LS_8 */
203
204 #else
205 /* Store: */
206
207 #ifdef LS_1
208 p[addr] = reg(ic->arg[0]);
209 #endif
210 #ifdef LS_2
211 { uint32_t x = reg(ic->arg[0]);
212 #ifdef HOST_BIG_ENDIAN
213 *((uint16_t *)(p+addr)) = x; }
214 #else
215 p[addr] = x >> 8; p[addr+1] = x; }
216 #endif
217 #endif /* LS_2 */
218 #ifdef LS_4
219 { uint32_t x = reg(ic->arg[0]);
220 #ifdef HOST_BIG_ENDIAN
221 *((uint32_t *)(p+addr)) = x; }
222 #else
223 p[addr] = x >> 24; p[addr+1] = x >> 16;
224 p[addr+2] = x >> 8; p[addr+3] = x; }
225 #endif
226 #endif /* LS_4 */
227 #ifdef LS_8
228 { uint64_t x = *(uint64_t *)(ic->arg[0]);
229 #ifdef HOST_BIG_ENDIAN
230 *((uint64_t *)(p+addr)) = x; }
231 #else
232 p[addr] = x >> 56; p[addr+1] = x >> 48; p[addr+2] = x >> 40;
233 p[addr+3] = x >> 32; p[addr+4] = x >> 24; p[addr+5] = x >> 16;
234 p[addr+6] = x >> 8; p[addr+7] = x; }
235 #endif
236 #endif /* LS_8 */
237
238 #endif /* store */
239 }
240

  ViewVC Help
Powered by ViewVC 1.1.26