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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 16 - (show annotations)
Mon Oct 8 16:19:01 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 10274 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.988 2005/10/11 03:53:57 debug Exp $

==============  RELEASE 0.3.6  ==============

20051008	The bug was not because of faulty ARM documentation after all,
		but it was related to those parts of the code.
		Fixing the RTC (dev_mc146818) to work with CATS.
20051009	Rewriting the R() function; now there are 8192 automatically
		generated smaller functions doing the same thing, but hopefully
		faster. This also fixes some bugs which were triggered when
		trying to compile GXemul inside itself. :-)
		Adding a dummy dev_lpt.
20051010	Small hack to not update virtual translation tables if memory
		accesses are done with the NO_EXCEPTION flag; a time reduction
		of almost a factor 2 for a full NetBSD/cats install. :-)
20051011	Passing -A as the default boot arg for CATS (works fine with
		OpenBSD/cats).

==============  RELEASE 0.3.6.1  ==============


1 /*
2 * Copyright (C) 2005 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_arm_instr_dpi.c,v 1.10 2005/10/09 21:32:07 debug Exp $
29 *
30 *
31 * ARM Data Processing Instructions
32 * --------------------------------
33 *
34 * xxxx000a aaaSnnnn ddddcccc ctttmmmm Register form
35 * xxxx001a aaaSnnnn ddddrrrr bbbbbbbb Immediate form
36 *
37 * 4 bits to select which instruction, one of the following:
38 *
39 * 0000 and 1000 tst
40 * 0001 eor 1001 teq
41 * 0010 sub 1010 cmp
42 * 0011 rsb 1011 cmn
43 * 0100 add 1100 orr
44 * 0101 adc 1101 mov
45 * 0110 sbc 1110 bic
46 * 0111 rsc 1111 mvn
47 *
48 * 1 bit to select Status flag update.
49 *
50 * 1 bit to select Register form or Immediate form.
51 *
52 * 1 bit to select if the PC register is used.
53 *
54 * Each function must also (as always) be repeated for each possible ARM
55 * condition code (15 in total). Total: 1920 functions.
56 *
57 * NOTE: This does not include any special common cases, which might be
58 * nice to have. Examples: comparing against zero, moving common
59 * constants.
60 *
61 * See src/tools/generate_arm_dpi.c for more details.
62 */
63
64
65 /*
66 * arg[0] = pointer to rn
67 * arg[1] = int32_t immediate value OR ptr to a reg_func() function
68 * arg[2] = pointer to rd
69 */
70 void A__NAME(struct cpu *cpu, struct arm_instr_call *ic)
71 {
72 #ifdef A__REG
73 uint32_t (*reg_func)(struct cpu *, struct arm_instr_call *)
74 = (void *)(size_t)ic->arg[1];
75 #endif
76
77 #ifdef A__S
78 uint32_t c32;
79 #endif
80 #if defined(A__CMP) || defined(A__CMN) || defined(A__ADC) || defined(A__ADD) \
81 || defined(A__RSC) || defined(A__RSC) || defined(A__SBC) || defined(A__SUB)
82 #ifdef A__S
83 uint64_t
84 #else
85 uint32_t
86 #endif
87 #else
88 uint32_t
89 #endif
90 c64,
91 #if !defined(A__MOV) && !defined(A__MVN)
92 a = reg(ic->arg[0]),
93 #endif
94 b =
95 #ifdef A__REG
96 reg_func(cpu, ic);
97 #else
98 ic->arg[1];
99 #endif
100
101
102 #if defined(A__MOV) || defined(A__MVN) || defined(A__TST) || defined(A__TEQ) \
103 || defined(A__AND) || defined(A__BIC) || defined(A__EOR) || defined(A__ORR)
104 #if !defined(A__REG) && defined(A__S)
105 /*
106 * TODO: This is not 100% correct, but should work with "recommended"
107 * ARM code: Immediate values larger than 255 are encoded with
108 * rotation. If the S-bit is set, then the carry bit is set to the
109 * highest bit of the operand.
110 *
111 * TODO 2: Perhaps this check should be moved out from here, and into
112 * cpu_arm_instr.c. (More correct, and higher performance.)
113 */
114 if (b > 255) {
115 cpu->cd.arm.cpsr &= ~ARM_FLAG_C;
116 if (b & 0x80000000)
117 cpu->cd.arm.cpsr |= ARM_FLAG_C;
118 }
119 #endif
120 #endif
121
122
123 #if !defined(A__MOV) && !defined(A__MVN)
124 #ifdef A__PC
125 if (ic->arg[0] == (size_t)&cpu->cd.arm.r[ARM_PC]) {
126 uint32_t low_pc;
127 low_pc = ((size_t)ic - (size_t)
128 cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
129 a = cpu->pc & ~((ARM_IC_ENTRIES_PER_PAGE-1)
130 << ARM_INSTR_ALIGNMENT_SHIFT);
131 a += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT) + 8;
132 }
133 #endif
134 #endif
135
136
137 #if defined(A__RSB) || defined(A__RSC)
138 { uint32_t tmp = a; a = b; b = tmp; }
139 #endif
140
141 /*
142 * Perform the operation:
143 */
144 #if defined(A__AND) || defined(A__TST)
145 c64 = a & b;
146 #endif
147 #if defined(A__EOR) || defined(A__TEQ)
148 c64 = a ^ b;
149 #endif
150 #if defined(A__SUB) || defined(A__CMP) || defined(A__RSB)
151 c64 = a - b;
152 #endif
153 #if defined(A__ADD) || defined(A__CMN)
154 c64 = a + b;
155 #endif
156 #if defined(A__ADC)
157 c64 = a + b + (cpu->cd.arm.cpsr & ARM_FLAG_C? 1 : 0);
158 #endif
159 #if defined(A__SBC) || defined(A__RSC)
160 c64 = a - b - (1 - (cpu->cd.arm.cpsr & ARM_FLAG_C? 1 : 0));
161 #endif
162 #if defined(A__ORR)
163 c64 = a | b;
164 #endif
165 #if defined(A__MOV)
166 c64 = b;
167 #endif
168 #if defined(A__BIC)
169 c64 = a & ~b;
170 #endif
171 #if defined(A__MVN)
172 c64 = ~b;
173 #endif
174
175
176 #if defined(A__CMP) || defined(A__CMN) || defined(A__TST) || defined(A__TEQ)
177 /* No write to rd for compare/test. */
178 #else
179 #ifdef A__PC
180 if (ic->arg[2] == (size_t)&cpu->cd.arm.r[ARM_PC]) {
181 #ifndef A__S
182 uint32_t old_pc = cpu->cd.arm.r[ARM_PC];
183 uint32_t mask_within_page = ((ARM_IC_ENTRIES_PER_PAGE-1)
184 << ARM_INSTR_ALIGNMENT_SHIFT) |
185 ((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);
186 #endif
187 cpu->pc = reg(ic->arg[2]) = c64;
188 #ifdef A__S
189 /* Copy the right SPSR into CPSR: */
190 arm_save_register_bank(cpu);
191 switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
192 case ARM_MODE_FIQ32:
193 cpu->cd.arm.cpsr = cpu->cd.arm.spsr_fiq; break;
194 case ARM_MODE_IRQ32:
195 cpu->cd.arm.cpsr = cpu->cd.arm.spsr_irq; break;
196 case ARM_MODE_SVC32:
197 cpu->cd.arm.cpsr = cpu->cd.arm.spsr_svc; break;
198 case ARM_MODE_ABT32:
199 cpu->cd.arm.cpsr = cpu->cd.arm.spsr_abt; break;
200 case ARM_MODE_UND32:
201 cpu->cd.arm.cpsr = cpu->cd.arm.spsr_und; break;
202 default:fatal("huh? weird mode in dpi s with pc\n");
203 exit(1);
204 }
205 arm_load_register_bank(cpu);
206 #else
207 if ((old_pc & ~mask_within_page) ==
208 (cpu->pc & ~mask_within_page)) {
209 cpu->cd.arm.next_ic = cpu->cd.arm.cur_ic_page +
210 ((cpu->pc & mask_within_page) >>
211 ARM_INSTR_ALIGNMENT_SHIFT);
212 } else
213 #endif
214 arm_pc_to_pointers(cpu);
215 return;
216 } else
217 reg(ic->arg[2]) = c64;
218 #else
219 reg(ic->arg[2]) = c64;
220 #endif
221 #endif
222
223
224 /*
225 * Status flag update (if the S-bit is set):
226 */
227 #ifdef A__S
228 c32 = c64;
229 cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N
230 #if defined(A__CMP) || defined(A__CMN) || defined(A__ADC) || defined(A__ADD) \
231 || defined(A__RSB) || defined(A__RSC) || defined(A__SBC) || defined(A__SUB)
232 | ARM_FLAG_V | ARM_FLAG_C
233 #endif
234 );
235
236 #if defined(A__CMP) || defined(A__RSB) || defined(A__SUB)
237 if ((uint32_t)a >= (uint32_t)b)
238 cpu->cd.arm.cpsr |= ARM_FLAG_C;
239 #else
240 #if defined(A__ADC) || defined(A__ADD) || defined(A__CMN)
241 if (c32 != c64)
242 cpu->cd.arm.cpsr |= ARM_FLAG_C;
243 #else
244 #if defined(A__RSC) || defined(A__SBC)
245 {
246 uint32_t low_pc;
247 low_pc = ((size_t)ic - (size_t)
248 cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
249 a = cpu->pc & ~((ARM_IC_ENTRIES_PER_PAGE-1)
250 << ARM_INSTR_ALIGNMENT_SHIFT);
251 a += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT) + 8;
252 fatal("TODO: C flag: pc = 0x%08x\n", a);
253 exit(1);
254 }
255 #endif
256 #endif
257 #endif
258
259 if (c32 == 0)
260 cpu->cd.arm.cpsr |= ARM_FLAG_Z;
261
262 if ((int32_t)c32 < 0)
263 cpu->cd.arm.cpsr |= ARM_FLAG_N;
264
265 /* Calculate the Overflow bit: */
266 #if defined(A__CMP) || defined(A__CMN) || defined(A__ADC) || defined(A__ADD) \
267 || defined(A__RSB) || defined(A__RSC) || defined(A__SBC) || defined(A__SUB)
268 {
269 int v = 0;
270 #if defined(A__ADD) || defined(A__CMN)
271 if (((int32_t)a >= 0 && (int32_t)b >= 0 &&
272 (int32_t)c32 < 0) ||
273 ((int32_t)a < 0 && (int32_t)b < 0 &&
274 (int32_t)c32 >= 0))
275 v = 1;
276 #else
277 #if defined(A__SUB) || defined(A__RSB) || defined(A__CMP)
278 if (((int32_t)a >= 0 && (int32_t)b < 0 &&
279 (int32_t)c32 < 0) ||
280 ((int32_t)a < 0 && (int32_t)b >= 0 &&
281 (int32_t)c32 >= 0))
282 v = 1;
283 #else
284 fatal("NO\n");
285 exit(1);
286 #endif
287 #endif
288 if (v)
289 cpu->cd.arm.cpsr |= ARM_FLAG_V;
290 }
291 #endif
292 #endif /* A__S */
293 }
294
295
296 void A__NAME__eq(struct cpu *cpu, struct arm_instr_call *ic)
297 { if (cpu->cd.arm.cpsr & ARM_FLAG_Z) A__NAME(cpu, ic); }
298 void A__NAME__ne(struct cpu *cpu, struct arm_instr_call *ic)
299 { if (!(cpu->cd.arm.cpsr & ARM_FLAG_Z)) A__NAME(cpu, ic); }
300 void A__NAME__cs(struct cpu *cpu, struct arm_instr_call *ic)
301 { if (cpu->cd.arm.cpsr & ARM_FLAG_C) A__NAME(cpu, ic); }
302 void A__NAME__cc(struct cpu *cpu, struct arm_instr_call *ic)
303 { if (!(cpu->cd.arm.cpsr & ARM_FLAG_C)) A__NAME(cpu, ic); }
304 void A__NAME__mi(struct cpu *cpu, struct arm_instr_call *ic)
305 { if (cpu->cd.arm.cpsr & ARM_FLAG_N) A__NAME(cpu, ic); }
306 void A__NAME__pl(struct cpu *cpu, struct arm_instr_call *ic)
307 { if (!(cpu->cd.arm.cpsr & ARM_FLAG_N)) A__NAME(cpu, ic); }
308 void A__NAME__vs(struct cpu *cpu, struct arm_instr_call *ic)
309 { if (cpu->cd.arm.cpsr & ARM_FLAG_V) A__NAME(cpu, ic); }
310 void A__NAME__vc(struct cpu *cpu, struct arm_instr_call *ic)
311 { if (!(cpu->cd.arm.cpsr & ARM_FLAG_V)) A__NAME(cpu, ic); }
312
313 void A__NAME__hi(struct cpu *cpu, struct arm_instr_call *ic)
314 { if (cpu->cd.arm.cpsr & ARM_FLAG_C &&
315 !(cpu->cd.arm.cpsr & ARM_FLAG_Z)) A__NAME(cpu, ic); }
316 void A__NAME__ls(struct cpu *cpu, struct arm_instr_call *ic)
317 { if (cpu->cd.arm.cpsr & ARM_FLAG_Z ||
318 !(cpu->cd.arm.cpsr & ARM_FLAG_C)) A__NAME(cpu, ic); }
319 void A__NAME__ge(struct cpu *cpu, struct arm_instr_call *ic)
320 { if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) ==
321 ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0)) A__NAME(cpu, ic); }
322 void A__NAME__lt(struct cpu *cpu, struct arm_instr_call *ic)
323 { if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) !=
324 ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0)) A__NAME(cpu, ic); }
325 void A__NAME__gt(struct cpu *cpu, struct arm_instr_call *ic)
326 { if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) ==
327 ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0) &&
328 !(cpu->cd.arm.cpsr & ARM_FLAG_Z)) A__NAME(cpu, ic); }
329 void A__NAME__le(struct cpu *cpu, struct arm_instr_call *ic)
330 { if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) !=
331 ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0) ||
332 (cpu->cd.arm.cpsr & ARM_FLAG_Z)) A__NAME(cpu, ic); }
333

  ViewVC Help
Powered by ViewVC 1.1.26