/[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

Annotation of /trunk/src/cpus/cpu_arm_instr_dpi.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 16 - (hide 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 dpavlin 14 /*
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 dpavlin 16 * $Id: cpu_arm_instr_dpi.c,v 1.10 2005/10/09 21:32:07 debug Exp $
29 dpavlin 14 *
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 dpavlin 16 * arg[1] = int32_t immediate value OR ptr to a reg_func() function
68 dpavlin 14 * arg[2] = pointer to rd
69     */
70     void A__NAME(struct cpu *cpu, struct arm_instr_call *ic)
71     {
72 dpavlin 16 #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 dpavlin 14 #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 dpavlin 16 reg_func(cpu, ic);
97 dpavlin 14 #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