/[gxemul]/trunk/src/cpus/cpu_arm_instr.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.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: 45576 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.c,v 1.29 2005/10/11 03:31:28 debug Exp $
29 dpavlin 14 *
30     * ARM instructions.
31     *
32     * Individual functions should keep track of cpu->n_translated_instrs.
33     * (If no instruction was executed, then it should be decreased. If, say, 4
34     * instructions were combined into one function and executed, then it should
35     * be increased by 3.)
36     */
37    
38    
39     /*
40     * Helper definitions:
41     *
42     * Each instruction is defined like this:
43     *
44     * X(foo)
45     * {
46     * code for foo;
47     * }
48     * Y(foo)
49     *
50     * The Y macro defines 14 copies of the instruction, one for each possible
51     * condition code. (The NV condition code is not included, and the AL code
52     * uses the main foo function.) Y also defines an array with pointers to
53     * all of these functions.
54     */
55    
56     #define Y(n) void arm_instr_ ## n ## __eq(struct cpu *cpu, \
57     struct arm_instr_call *ic) \
58     { if (cpu->cd.arm.cpsr & ARM_FLAG_Z) \
59     arm_instr_ ## n (cpu, ic); } \
60     void arm_instr_ ## n ## __ne(struct cpu *cpu, \
61     struct arm_instr_call *ic) \
62     { if (!(cpu->cd.arm.cpsr & ARM_FLAG_Z)) \
63     arm_instr_ ## n (cpu, ic); } \
64     void arm_instr_ ## n ## __cs(struct cpu *cpu, \
65     struct arm_instr_call *ic) \
66     { if (cpu->cd.arm.cpsr & ARM_FLAG_C) \
67     arm_instr_ ## n (cpu, ic); } \
68     void arm_instr_ ## n ## __cc(struct cpu *cpu, \
69     struct arm_instr_call *ic) \
70     { if (!(cpu->cd.arm.cpsr & ARM_FLAG_C)) \
71     arm_instr_ ## n (cpu, ic); } \
72     void arm_instr_ ## n ## __mi(struct cpu *cpu, \
73     struct arm_instr_call *ic) \
74     { if (cpu->cd.arm.cpsr & ARM_FLAG_N) \
75     arm_instr_ ## n (cpu, ic); } \
76     void arm_instr_ ## n ## __pl(struct cpu *cpu, \
77     struct arm_instr_call *ic) \
78     { if (!(cpu->cd.arm.cpsr & ARM_FLAG_N)) \
79     arm_instr_ ## n (cpu, ic); } \
80     void arm_instr_ ## n ## __vs(struct cpu *cpu, \
81     struct arm_instr_call *ic) \
82     { if (cpu->cd.arm.cpsr & ARM_FLAG_V) \
83     arm_instr_ ## n (cpu, ic); } \
84     void arm_instr_ ## n ## __vc(struct cpu *cpu, \
85     struct arm_instr_call *ic) \
86     { if (!(cpu->cd.arm.cpsr & ARM_FLAG_V)) \
87     arm_instr_ ## n (cpu, ic); } \
88     void arm_instr_ ## n ## __hi(struct cpu *cpu, \
89     struct arm_instr_call *ic) \
90     { if (cpu->cd.arm.cpsr & ARM_FLAG_C && \
91     !(cpu->cd.arm.cpsr & ARM_FLAG_Z)) \
92     arm_instr_ ## n (cpu, ic); } \
93     void arm_instr_ ## n ## __ls(struct cpu *cpu, \
94     struct arm_instr_call *ic) \
95     { if (cpu->cd.arm.cpsr & ARM_FLAG_Z || \
96     !(cpu->cd.arm.cpsr & ARM_FLAG_C)) \
97     arm_instr_ ## n (cpu, ic); } \
98     void arm_instr_ ## n ## __ge(struct cpu *cpu, \
99     struct arm_instr_call *ic) \
100     { if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) == \
101     ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0)) \
102     arm_instr_ ## n (cpu, ic); } \
103     void arm_instr_ ## n ## __lt(struct cpu *cpu, \
104     struct arm_instr_call *ic) \
105     { if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) != \
106     ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0)) \
107     arm_instr_ ## n (cpu, ic); } \
108     void arm_instr_ ## n ## __gt(struct cpu *cpu, \
109     struct arm_instr_call *ic) \
110     { if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) == \
111     ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0) && \
112     !(cpu->cd.arm.cpsr & ARM_FLAG_Z)) \
113     arm_instr_ ## n (cpu, ic); } \
114     void arm_instr_ ## n ## __le(struct cpu *cpu, \
115     struct arm_instr_call *ic) \
116     { if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) != \
117     ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0) || \
118     (cpu->cd.arm.cpsr & ARM_FLAG_Z)) \
119     arm_instr_ ## n (cpu, ic); } \
120     void (*arm_cond_instr_ ## n [16])(struct cpu *, \
121     struct arm_instr_call *) = { \
122     arm_instr_ ## n ## __eq, arm_instr_ ## n ## __ne, \
123     arm_instr_ ## n ## __cs, arm_instr_ ## n ## __cc, \
124     arm_instr_ ## n ## __mi, arm_instr_ ## n ## __pl, \
125     arm_instr_ ## n ## __vs, arm_instr_ ## n ## __vc, \
126     arm_instr_ ## n ## __hi, arm_instr_ ## n ## __ls, \
127     arm_instr_ ## n ## __ge, arm_instr_ ## n ## __lt, \
128     arm_instr_ ## n ## __gt, arm_instr_ ## n ## __le, \
129     arm_instr_ ## n , arm_instr_nop };
130    
131     #define cond_instr(n) ( arm_cond_instr_ ## n [condition_code] )
132    
133    
134     /*****************************************************************************/
135    
136    
137     /*
138     * nop: Do nothing.
139     * invalid: Invalid instructions end up here.
140     */
141     X(nop) { }
142     X(invalid) {
143     uint32_t low_pc;
144     low_pc = ((size_t)ic - (size_t)
145     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
146     cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
147     << ARM_INSTR_ALIGNMENT_SHIFT);
148     cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
149     cpu->pc = cpu->cd.arm.r[ARM_PC];
150    
151     fatal("Invalid ARM instruction: pc=0x%08x\n", (int)cpu->pc);
152    
153     cpu->running = 0;
154     cpu->running_translated = 0;
155     cpu->n_translated_instrs --;
156     cpu->cd.arm.next_ic = &nothing_call;
157     }
158    
159    
160     /*
161     * b: Branch (to a different translated page)
162     *
163     * arg[0] = relative offset
164     */
165     X(b)
166     {
167     uint32_t low_pc;
168    
169     /* Calculate new PC from this instruction + arg[0] */
170     low_pc = ((size_t)ic - (size_t)
171     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
172     cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
173     << ARM_INSTR_ALIGNMENT_SHIFT);
174     cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
175     cpu->cd.arm.r[ARM_PC] += (int32_t)ic->arg[0];
176     cpu->pc = cpu->cd.arm.r[ARM_PC];
177    
178     /* Find the new physical page and update the translation pointers: */
179     arm_pc_to_pointers(cpu);
180     }
181     Y(b)
182    
183    
184     /*
185     * b_samepage: Branch (to within the same translated page)
186     *
187     * arg[0] = pointer to new arm_instr_call
188     */
189     X(b_samepage)
190     {
191     cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
192     }
193     Y(b_samepage)
194    
195    
196     /*
197     * bx: Branch, potentially exchanging Thumb/ARM encoding
198     *
199     * arg[0] = ptr to rm
200     */
201     X(bx)
202     {
203     cpu->pc = cpu->cd.arm.r[ARM_PC] = reg(ic->arg[0]);
204     if (cpu->pc & 1) {
205     fatal("thumb: TODO\n");
206     exit(1);
207     }
208     cpu->pc &= ~3;
209    
210     /* Find the new physical page and update the translation pointers: */
211     arm_pc_to_pointers(cpu);
212     }
213     Y(bx)
214    
215    
216     /*
217     * bx_trace: As bx, but with trace enabled, arg[0] = the link register.
218     *
219     * arg[0] = ignored
220     */
221     X(bx_trace)
222     {
223     cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];
224     if (cpu->pc & 1) {
225     fatal("thumb: TODO\n");
226     exit(1);
227     }
228     cpu->pc &= ~3;
229    
230     cpu_functioncall_trace_return(cpu);
231    
232     /* Find the new physical page and update the translation pointers: */
233     arm_pc_to_pointers(cpu);
234     }
235     Y(bx_trace)
236    
237    
238     /*
239     * bl: Branch and Link (to a different translated page)
240     *
241     * arg[0] = relative address
242     */
243     X(bl)
244     {
245     uint32_t lr, low_pc;
246    
247     /* Figure out what the return (link) address will be: */
248     low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)
249     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
250     lr = cpu->cd.arm.r[ARM_PC];
251     lr &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
252     lr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
253    
254     /* Link: */
255     cpu->cd.arm.r[ARM_LR] = lr;
256    
257     /* Calculate new PC from this instruction + arg[0] */
258     cpu->pc = cpu->cd.arm.r[ARM_PC] = lr - 4 + (int32_t)ic->arg[0];
259    
260     /* Find the new physical page and update the translation pointers: */
261     arm_pc_to_pointers(cpu);
262     }
263     Y(bl)
264    
265    
266     /*
267     * blx: Branch and Link, potentially exchanging Thumb/ARM encoding
268     *
269     * arg[0] = ptr to rm
270     */
271     X(blx)
272     {
273     uint32_t lr, low_pc;
274    
275     /* Figure out what the return (link) address will be: */
276     low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)
277     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
278     lr = cpu->cd.arm.r[ARM_PC];
279     lr &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
280     lr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
281    
282     /* Link: */
283     cpu->cd.arm.r[ARM_LR] = lr;
284    
285     cpu->pc = cpu->cd.arm.r[ARM_PC] = reg(ic->arg[0]);
286     if (cpu->pc & 1) {
287     fatal("thumb: TODO\n");
288     exit(1);
289     }
290     cpu->pc &= ~3;
291    
292     /* Find the new physical page and update the translation pointers: */
293     arm_pc_to_pointers(cpu);
294     }
295     Y(blx)
296    
297    
298     /*
299     * bl_trace: Branch and Link (to a different translated page), with trace
300     *
301     * Same as for bl.
302     */
303     X(bl_trace)
304     {
305     uint32_t lr, low_pc;
306    
307     /* Figure out what the return (link) address will be: */
308     low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)
309     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
310     lr = cpu->cd.arm.r[ARM_PC];
311     lr &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
312     lr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
313    
314     /* Link: */
315     cpu->cd.arm.r[ARM_LR] = lr;
316    
317     /* Calculate new PC from this instruction + arg[0] */
318     cpu->pc = cpu->cd.arm.r[ARM_PC] = lr - 4 + (int32_t)ic->arg[0];
319    
320     cpu_functioncall_trace(cpu, cpu->pc);
321    
322     /* Find the new physical page and update the translation pointers: */
323     arm_pc_to_pointers(cpu);
324     }
325     Y(bl_trace)
326    
327    
328     /*
329     * bl_samepage: A branch + link within the same page
330     *
331     * arg[0] = pointer to new arm_instr_call
332     */
333     X(bl_samepage)
334     {
335     uint32_t lr, low_pc;
336    
337     /* Figure out what the return (link) address will be: */
338     low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)
339     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
340     lr = cpu->cd.arm.r[ARM_PC];
341     lr &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
342     lr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
343    
344     /* Link: */
345     cpu->cd.arm.r[ARM_LR] = lr;
346    
347     /* Branch: */
348     cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
349     }
350     Y(bl_samepage)
351    
352    
353     /*
354     * bl_samepage_trace: Branch and Link (to the same page), with trace
355     *
356     * Same as for bl_samepage.
357     */
358     X(bl_samepage_trace)
359     {
360     uint32_t tmp_pc, lr, low_pc;
361    
362     /* Figure out what the return (link) address will be: */
363     low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)
364     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
365     lr = cpu->cd.arm.r[ARM_PC];
366     lr &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
367     lr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
368    
369     /* Link: */
370     cpu->cd.arm.r[ARM_LR] = lr;
371    
372     /* Branch: */
373     cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
374    
375     low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)
376     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
377     tmp_pc = cpu->cd.arm.r[ARM_PC];
378     tmp_pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
379     << ARM_INSTR_ALIGNMENT_SHIFT);
380     tmp_pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
381     cpu_functioncall_trace(cpu, tmp_pc);
382     }
383     Y(bl_samepage_trace)
384    
385    
386     /*
387     * mul: Multiplication
388     *
389     * arg[0] = ptr to rd
390     * arg[1] = ptr to rm
391     * arg[2] = ptr to rs
392     */
393     X(mul)
394     {
395     reg(ic->arg[0]) = reg(ic->arg[1]) * reg(ic->arg[2]);
396     }
397     Y(mul)
398     X(muls)
399     {
400     uint32_t result = reg(ic->arg[1]) * reg(ic->arg[2]);
401     cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N);
402     if (result == 0)
403     cpu->cd.arm.cpsr |= ARM_FLAG_Z;
404     if (result & 0x80000000)
405     cpu->cd.arm.cpsr |= ARM_FLAG_N;
406     reg(ic->arg[0]) = result;
407     }
408     Y(muls)
409    
410    
411     /*
412     * mla: Multiplication with addition
413     *
414     * arg[0] = copy of instruction word
415     */
416     X(mla)
417     {
418     /* xxxx0000 00ASdddd nnnnssss 1001mmmm (Rd,Rm,Rs[,Rn]) */
419     uint32_t iw = ic->arg[0];
420     int rd = (iw >> 16) & 15, rn = (iw >> 12) & 15,
421     rs = (iw >> 8) & 15, rm = iw & 15;
422     cpu->cd.arm.r[rd] = cpu->cd.arm.r[rm] * cpu->cd.arm.r[rs]
423     + cpu->cd.arm.r[rn];
424     }
425     Y(mla)
426     X(mlas)
427     {
428     /* xxxx0000 00ASdddd nnnnssss 1001mmmm (Rd,Rm,Rs[,Rn]) */
429     uint32_t iw = ic->arg[0];
430     int rd = (iw >> 16) & 15, rn = (iw >> 12) & 15,
431     rs = (iw >> 8) & 15, rm = iw & 15;
432     cpu->cd.arm.r[rd] = cpu->cd.arm.r[rm] * cpu->cd.arm.r[rs]
433     + cpu->cd.arm.r[rn];
434     cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N);
435     if (cpu->cd.arm.r[rd] == 0)
436     cpu->cd.arm.cpsr |= ARM_FLAG_Z;
437     if (cpu->cd.arm.r[rd] & 0x80000000)
438     cpu->cd.arm.cpsr |= ARM_FLAG_N;
439     }
440     Y(mlas)
441    
442    
443     /*
444     * mull: Long multiplication
445     *
446     * arg[0] = copy of instruction word
447     */
448     X(mull)
449     {
450     /* xxxx0000 1UAShhhh llllssss 1001mmmm */
451     uint32_t iw = ic->arg[0];
452     int u_bit = (iw >> 22) & 1, a_bit = (iw >> 21) & 1;
453     uint64_t tmp = cpu->cd.arm.r[iw & 15];
454     if (u_bit)
455     tmp = (int64_t)(int32_t)tmp
456     * (int64_t)(int32_t)cpu->cd.arm.r[(iw >> 8) & 15];
457     else
458     tmp *= (uint64_t)cpu->cd.arm.r[(iw >> 8) & 15];
459     if (a_bit) {
460     uint64_t x = ((uint64_t)cpu->cd.arm.r[(iw >> 16) & 15] << 32)
461     | cpu->cd.arm.r[(iw >> 12) & 15];
462     x += tmp;
463     cpu->cd.arm.r[(iw >> 16) & 15] = (x >> 32);
464     cpu->cd.arm.r[(iw >> 12) & 15] = x;
465     } else {
466     cpu->cd.arm.r[(iw >> 16) & 15] = (tmp >> 32);
467     cpu->cd.arm.r[(iw >> 12) & 15] = tmp;
468     }
469     }
470     Y(mull)
471    
472    
473     /*
474     * mov_reg_reg: Move a register to another.
475     *
476     * arg[0] = ptr to source register
477     * arg[1] = ptr to destination register
478     */
479     X(mov_reg_reg)
480     {
481     reg(ic->arg[1]) = reg(ic->arg[0]);
482     }
483     Y(mov_reg_reg)
484    
485    
486     /*
487     * ret_trace: "mov pc,lr" with trace enabled
488     *
489     * arg[0] = ignored
490     */
491     X(ret_trace)
492     {
493     uint32_t old_pc = cpu->cd.arm.r[ARM_PC];
494     uint32_t mask_within_page = ((ARM_IC_ENTRIES_PER_PAGE-1)
495     << ARM_INSTR_ALIGNMENT_SHIFT) |
496     ((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);
497    
498     /* Update the PC register: */
499     cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];
500    
501     cpu_functioncall_trace_return(cpu);
502    
503     /*
504     * Is this a return to code within the same page? Then there is no
505     * need to update all pointers, just next_ic.
506     */
507     if ((old_pc & ~mask_within_page) == (cpu->pc & ~mask_within_page)) {
508     cpu->cd.arm.next_ic = cpu->cd.arm.cur_ic_page +
509     ((cpu->pc & mask_within_page) >> ARM_INSTR_ALIGNMENT_SHIFT);
510     } else {
511     /* Find the new physical page and update pointers: */
512     arm_pc_to_pointers(cpu);
513     }
514     }
515     Y(ret_trace)
516    
517    
518     /*
519     * msr: Move to status register from a normal register or immediate value.
520     *
521     * arg[0] = immediate value
522     * arg[1] = mask
523     * arg[2] = pointer to rm
524     *
525     * msr_imm and msr_imm_spsr use arg[1] and arg[0].
526     * msr and msr_spsr use arg[1] and arg[2].
527     */
528     X(msr_imm)
529     {
530     uint32_t mask = ic->arg[1];
531     int switch_register_banks = (mask & ARM_FLAG_MODE) &&
532     ((cpu->cd.arm.cpsr & ARM_FLAG_MODE) !=
533     (ic->arg[0] & ARM_FLAG_MODE));
534     uint32_t new_value = ic->arg[0];
535    
536     if (switch_register_banks)
537     arm_save_register_bank(cpu);
538    
539     cpu->cd.arm.cpsr &= ~mask;
540     cpu->cd.arm.cpsr |= (new_value & mask);
541    
542     if (switch_register_banks)
543     arm_load_register_bank(cpu);
544     }
545     Y(msr_imm)
546     X(msr)
547     {
548     ic->arg[0] = reg(ic->arg[2]);
549     instr(msr_imm)(cpu, ic);
550     }
551     Y(msr)
552     X(msr_imm_spsr)
553     {
554     uint32_t mask = ic->arg[1];
555     uint32_t new_value = ic->arg[0];
556     switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
557     case ARM_MODE_FIQ32:
558     cpu->cd.arm.spsr_fiq &= ~mask;
559     cpu->cd.arm.spsr_fiq |= (new_value & mask);
560     break;
561     case ARM_MODE_ABT32:
562     cpu->cd.arm.spsr_abt &= ~mask;
563     cpu->cd.arm.spsr_abt |= (new_value & mask);
564     break;
565     case ARM_MODE_UND32:
566     cpu->cd.arm.spsr_und &= ~mask;
567     cpu->cd.arm.spsr_und |= (new_value & mask);
568     break;
569     case ARM_MODE_IRQ32:
570     cpu->cd.arm.spsr_irq &= ~mask;
571     cpu->cd.arm.spsr_irq |= (new_value & mask);
572     break;
573     case ARM_MODE_SVC32:
574     cpu->cd.arm.spsr_svc &= ~mask;
575     cpu->cd.arm.spsr_svc |= (new_value & mask);
576     break;
577     default:fatal("msr_spsr: unimplemented mode %i\n",
578     cpu->cd.arm.cpsr & ARM_FLAG_MODE);
579     {
580     /* Synchronize the program counter: */
581     uint32_t old_pc, low_pc = ((size_t)ic - (size_t)
582     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
583     cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
584     << ARM_INSTR_ALIGNMENT_SHIFT);
585     cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
586     old_pc = cpu->pc = cpu->cd.arm.r[ARM_PC];
587     printf("msr_spsr: old pc = 0x%08x\n", old_pc);
588     }
589     exit(1);
590     }
591     }
592     Y(msr_imm_spsr)
593     X(msr_spsr)
594     {
595     ic->arg[0] = reg(ic->arg[2]);
596     instr(msr_imm_spsr)(cpu, ic);
597     }
598     Y(msr_spsr)
599    
600    
601     /*
602     * mrs: Move from status/flag register to a normal register.
603     *
604     * arg[0] = pointer to rd
605     */
606     X(mrs)
607     {
608     reg(ic->arg[0]) = cpu->cd.arm.cpsr;
609     }
610     Y(mrs)
611    
612    
613     /*
614     * mrs: Move from status/flag register to a normal register.
615     *
616     * arg[0] = pointer to rd
617     */
618     X(mrs_spsr)
619     {
620     switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
621     case ARM_MODE_FIQ32: reg(ic->arg[0]) = cpu->cd.arm.spsr_fiq; break;
622     case ARM_MODE_ABT32: reg(ic->arg[0]) = cpu->cd.arm.spsr_abt; break;
623     case ARM_MODE_UND32: reg(ic->arg[0]) = cpu->cd.arm.spsr_und; break;
624     case ARM_MODE_IRQ32: reg(ic->arg[0]) = cpu->cd.arm.spsr_irq; break;
625     case ARM_MODE_SVC32: reg(ic->arg[0]) = cpu->cd.arm.spsr_svc; break;
626     case ARM_MODE_USR32:
627     case ARM_MODE_SYS32: reg(ic->arg[0]) = 0; break;
628     default:fatal("mrs_spsr: unimplemented mode %i\n",
629     cpu->cd.arm.cpsr & ARM_FLAG_MODE);
630     exit(1);
631     }
632     }
633     Y(mrs_spsr)
634    
635    
636     /*
637     * mcr_mrc: Coprocessor move
638     * cdp: Coprocessor operation
639     *
640     * arg[0] = copy of the instruction word
641     */
642     X(mcr_mrc) {
643     uint32_t low_pc;
644     low_pc = ((size_t)ic - (size_t)
645     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
646     cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
647     << ARM_INSTR_ALIGNMENT_SHIFT);
648     cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
649     cpu->pc = cpu->cd.arm.r[ARM_PC];
650     arm_mcr_mrc(cpu, ic->arg[0]);
651     }
652     Y(mcr_mrc)
653     X(cdp) {
654     uint32_t low_pc;
655     low_pc = ((size_t)ic - (size_t)
656     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
657     cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
658     << ARM_INSTR_ALIGNMENT_SHIFT);
659     cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
660     cpu->pc = cpu->cd.arm.r[ARM_PC];
661     arm_cdp(cpu, ic->arg[0]);
662     }
663     Y(cdp)
664    
665    
666     /*
667     * openfirmware:
668     */
669     X(openfirmware)
670     {
671     of_emul(cpu);
672     cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];
673     if (cpu->machine->show_trace_tree)
674     cpu_functioncall_trace_return(cpu);
675     arm_pc_to_pointers(cpu);
676     }
677    
678    
679     /*
680     * swi_useremul: Syscall.
681     *
682     * arg[0] = swi number
683     */
684     X(swi_useremul)
685     {
686     /* Synchronize the program counter: */
687     uint32_t old_pc, low_pc = ((size_t)ic - (size_t)
688     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
689     cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
690     << ARM_INSTR_ALIGNMENT_SHIFT);
691     cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
692     old_pc = cpu->pc = cpu->cd.arm.r[ARM_PC];
693    
694     useremul_syscall(cpu, ic->arg[0]);
695    
696     if (!cpu->running) {
697     cpu->running_translated = 0;
698     cpu->n_translated_instrs --;
699     cpu->cd.arm.next_ic = &nothing_call;
700     } else if (cpu->pc != old_pc) {
701     /* PC was changed by the SWI call. Find the new physical
702     page and update the translation pointers: */
703     arm_pc_to_pointers(cpu);
704     }
705     }
706     Y(swi_useremul)
707    
708    
709     /*
710     * swi: Software interrupt.
711     */
712     X(swi)
713     {
714     /* Synchronize the program counter: */
715     uint32_t low_pc = ((size_t)ic - (size_t)
716     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
717     cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
718     << ARM_INSTR_ALIGNMENT_SHIFT);
719     cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
720     cpu->pc = cpu->cd.arm.r[ARM_PC];
721    
722     arm_exception(cpu, ARM_EXCEPTION_SWI);
723     }
724     Y(swi)
725    
726    
727     /*
728     * swp, swpb: Swap (word or byte).
729     *
730     * arg[0] = ptr to rd
731     * arg[1] = ptr to rm
732     * arg[2] = ptr to rn
733     */
734     X(swp)
735     {
736     uint32_t addr = reg(ic->arg[2]), data, data2;
737     unsigned char d[4];
738     /* Synchronize the program counter: */
739     uint32_t low_pc = ((size_t)ic - (size_t)
740     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
741     cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
742     << ARM_INSTR_ALIGNMENT_SHIFT);
743     cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
744     cpu->pc = cpu->cd.arm.r[ARM_PC];
745    
746     if (!cpu->memory_rw(cpu, cpu->mem, addr, d, sizeof(d), MEM_READ,
747     CACHE_DATA)) {
748     fatal("swp: load failed\n");
749     return;
750     }
751     data = d[0] + (d[1] << 8) + (d[2] << 16) + (d[3] << 24);
752     data2 = reg(ic->arg[1]);
753     d[0] = data2; d[1] = data2 >> 8; d[2] = data2 >> 16; d[3] = data2 >> 24;
754     if (!cpu->memory_rw(cpu, cpu->mem, addr, d, sizeof(d), MEM_WRITE,
755     CACHE_DATA)) {
756     fatal("swp: store failed\n");
757     return;
758     }
759     reg(ic->arg[0]) = data;
760     }
761     Y(swp)
762     X(swpb)
763     {
764     uint32_t addr = reg(ic->arg[2]), data;
765     unsigned char d[1];
766     /* Synchronize the program counter: */
767     uint32_t low_pc = ((size_t)ic - (size_t)
768     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
769     cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
770     << ARM_INSTR_ALIGNMENT_SHIFT);
771     cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
772     cpu->pc = cpu->cd.arm.r[ARM_PC];
773    
774     if (!cpu->memory_rw(cpu, cpu->mem, addr, d, sizeof(d), MEM_READ,
775     CACHE_DATA)) {
776     fatal("swp: load failed\n");
777     return;
778     }
779     data = d[0];
780     d[0] = reg(ic->arg[1]);
781     if (!cpu->memory_rw(cpu, cpu->mem, addr, d, sizeof(d), MEM_WRITE,
782     CACHE_DATA)) {
783     fatal("swp: store failed\n");
784     return;
785     }
786     reg(ic->arg[0]) = data;
787     }
788     Y(swpb)
789    
790    
791     extern void (*arm_load_store_instr[1024])(struct cpu *,
792     struct arm_instr_call *);
793     X(store_w0_byte_u1_p0_imm);
794     X(store_w0_word_u1_p0_imm);
795    
796     extern void (*arm_load_store_instr_pc[1024])(struct cpu *,
797     struct arm_instr_call *);
798    
799     extern void (*arm_load_store_instr_3[2048])(struct cpu *,
800     struct arm_instr_call *);
801    
802     extern void (*arm_load_store_instr_3_pc[2048])(struct cpu *,
803     struct arm_instr_call *);
804    
805 dpavlin 16 extern uint32_t (*arm_r[8192])(struct cpu *, struct arm_instr_call *);
806    
807 dpavlin 14 extern void (*arm_dpi_instr[2 * 2 * 2 * 16 * 16])(struct cpu *,
808     struct arm_instr_call *);
809     X(cmps);
810     X(sub);
811     X(subs);
812    
813    
814    
815     /*
816     * bdt_load: Block Data Transfer, Load
817     *
818     * arg[0] = pointer to uint32_t in host memory, pointing to the base register
819     * arg[1] = 32-bit instruction word. Most bits are read from this.
820     */
821     X(bdt_load)
822     {
823     unsigned char data[4];
824     uint32_t *np = (uint32_t *)ic->arg[0];
825     uint32_t addr = *np, low_pc;
826     unsigned char *page;
827     uint32_t iw = ic->arg[1]; /* xxxx100P USWLnnnn llllllll llllllll */
828     int p_bit = iw & 0x01000000;
829     int u_bit = iw & 0x00800000;
830     int s_bit = iw & 0x00400000;
831     int w_bit = iw & 0x00200000;
832 dpavlin 16 int i, return_flag = 0;
833 dpavlin 14 uint32_t new_values[16];
834    
835     /* Synchronize the program counter: */
836     low_pc = ((size_t)ic - (size_t)
837     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
838     cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) <<
839     ARM_INSTR_ALIGNMENT_SHIFT);
840     cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
841     cpu->pc = cpu->cd.arm.r[ARM_PC];
842    
843     if (s_bit) {
844 dpavlin 16 /* Load to USR registers: */
845 dpavlin 14 if ((cpu->cd.arm.cpsr & ARM_FLAG_MODE) == ARM_MODE_USR32) {
846     fatal("[ bdt_load: s-bit: in usermode? ]\n");
847     s_bit = 0;
848 dpavlin 16 }
849     if (iw & 0x8000) {
850 dpavlin 14 s_bit = 0;
851     return_flag = 1;
852     }
853     }
854    
855     for (i=(u_bit? 0 : 15); i>=0 && i<=15; i+=(u_bit? 1 : -1)) {
856     uint32_t value;
857    
858     if (!((iw >> i) & 1)) {
859     /* Skip register i: */
860     continue;
861     }
862    
863     if (p_bit) {
864     if (u_bit)
865     addr += sizeof(uint32_t);
866     else
867     addr -= sizeof(uint32_t);
868     }
869    
870     page = cpu->cd.arm.host_load[addr >> 12];
871     if (page != NULL) {
872     uint32_t *p32 = (uint32_t *) page;
873     value = p32[(addr & 0xfff) >> 2];
874     /* Change byte order of value if
875     host and emulated endianness differ: */
876     #ifdef HOST_LITTLE_ENDIAN
877     if (cpu->byte_order == EMUL_BIG_ENDIAN)
878     #else
879     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
880     #endif
881     value = ((value & 0xff) << 24) |
882     ((value & 0xff00) << 8) |
883     ((value & 0xff0000) >> 8) |
884     ((value & 0xff000000) >> 24);
885     } else {
886     if (!cpu->memory_rw(cpu, cpu->mem, addr, data,
887     sizeof(data), MEM_READ, CACHE_DATA)) {
888     /* load failed */
889     return;
890     }
891     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
892     value = data[0] +
893     (data[1] << 8) + (data[2] << 16)
894     + (data[3] << 24);
895     } else {
896     value = data[3] +
897     (data[2] << 8) + (data[1] << 16)
898     + (data[0] << 24);
899     }
900     }
901    
902     new_values[i] = value;
903    
904     if (!p_bit) {
905     if (u_bit)
906     addr += sizeof(uint32_t);
907     else
908     addr -= sizeof(uint32_t);
909     }
910     }
911    
912     for (i=(u_bit? 0 : 15); i>=0 && i<=15; i+=(u_bit? 1 : -1)) {
913     if (!((iw >> i) & 1)) {
914     /* Skip register i: */
915     continue;
916     }
917    
918     if (!s_bit) {
919     cpu->cd.arm.r[i] = new_values[i];
920     } else {
921 dpavlin 16 switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
922 dpavlin 14 case ARM_MODE_USR32:
923     case ARM_MODE_SYS32:
924 dpavlin 16 cpu->cd.arm.r[i] = new_values[i];
925 dpavlin 14 break;
926     case ARM_MODE_FIQ32:
927     if (i >= 8 && i <= 14)
928 dpavlin 16 cpu->cd.arm.default_r8_r14[i-8] =
929 dpavlin 14 new_values[i];
930     else
931     cpu->cd.arm.r[i] = new_values[i];
932     break;
933     case ARM_MODE_SVC32:
934     case ARM_MODE_ABT32:
935     case ARM_MODE_UND32:
936 dpavlin 16 case ARM_MODE_IRQ32:
937 dpavlin 14 if (i >= 13 && i <= 14)
938 dpavlin 16 cpu->cd.arm.default_r8_r14[i-8] =
939 dpavlin 14 new_values[i];
940     else
941     cpu->cd.arm.r[i] = new_values[i];
942     break;
943     }
944     }
945     }
946    
947     if (w_bit)
948     *np = addr;
949    
950     if (return_flag) {
951     uint32_t new_cpsr;
952     int switch_register_banks;
953    
954     switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
955     case ARM_MODE_FIQ32:
956     new_cpsr = cpu->cd.arm.spsr_fiq; break;
957     case ARM_MODE_ABT32:
958     new_cpsr = cpu->cd.arm.spsr_abt; break;
959     case ARM_MODE_UND32:
960     new_cpsr = cpu->cd.arm.spsr_und; break;
961     case ARM_MODE_IRQ32:
962     new_cpsr = cpu->cd.arm.spsr_irq; break;
963     case ARM_MODE_SVC32:
964     new_cpsr = cpu->cd.arm.spsr_svc; break;
965     default:fatal("bdt_load: unimplemented mode %i\n",
966     cpu->cd.arm.cpsr & ARM_FLAG_MODE);
967     exit(1);
968     }
969    
970     switch_register_banks = (cpu->cd.arm.cpsr & ARM_FLAG_MODE) !=
971     (new_cpsr & ARM_FLAG_MODE);
972    
973     if (switch_register_banks)
974     arm_save_register_bank(cpu);
975    
976     cpu->cd.arm.cpsr = new_cpsr;
977    
978     if (switch_register_banks)
979     arm_load_register_bank(cpu);
980     }
981    
982     /* NOTE: Special case: Loading the PC */
983     if (iw & 0x8000) {
984     cpu->cd.arm.r[ARM_PC] &= ~3;
985     cpu->pc = cpu->cd.arm.r[ARM_PC];
986     if (cpu->machine->show_trace_tree)
987     cpu_functioncall_trace_return(cpu);
988     /* TODO: There is no need to update the
989     pointers if this is a return to the
990     same page! */
991     /* Find the new physical page and update the
992     translation pointers: */
993     arm_pc_to_pointers(cpu);
994     }
995     }
996     Y(bdt_load)
997    
998    
999     /*
1000     * bdt_store: Block Data Transfer, Store
1001     *
1002     * arg[0] = pointer to uint32_t in host memory, pointing to the base register
1003     * arg[1] = 32-bit instruction word. Most bits are read from this.
1004     */
1005     X(bdt_store)
1006     {
1007     unsigned char data[4];
1008     uint32_t *np = (uint32_t *)ic->arg[0];
1009     uint32_t low_pc, value, addr = *np;
1010     uint32_t iw = ic->arg[1]; /* xxxx100P USWLnnnn llllllll llllllll */
1011     unsigned char *page;
1012     int p_bit = iw & 0x01000000;
1013     int u_bit = iw & 0x00800000;
1014     int s_bit = iw & 0x00400000;
1015     int w_bit = iw & 0x00200000;
1016 dpavlin 16 int i;
1017 dpavlin 14
1018     /* Synchronize the program counter: */
1019     low_pc = ((size_t)ic - (size_t)
1020     cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
1021     cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) <<
1022     ARM_INSTR_ALIGNMENT_SHIFT);
1023     cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
1024     cpu->pc = cpu->cd.arm.r[ARM_PC];
1025    
1026     for (i=(u_bit? 0 : 15); i>=0 && i<=15; i+=(u_bit? 1 : -1)) {
1027     if (!((iw >> i) & 1)) {
1028     /* Skip register i: */
1029     continue;
1030     }
1031    
1032     value = cpu->cd.arm.r[i];
1033    
1034     if (s_bit) {
1035 dpavlin 16 switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
1036 dpavlin 14 case ARM_MODE_FIQ32:
1037     if (i >= 8 && i <= 14)
1038 dpavlin 16 value = cpu->cd.arm.default_r8_r14[i-8];
1039 dpavlin 14 break;
1040     case ARM_MODE_ABT32:
1041     case ARM_MODE_UND32:
1042     case ARM_MODE_IRQ32:
1043     case ARM_MODE_SVC32:
1044     if (i >= 13 && i <= 14)
1045 dpavlin 16 value = cpu->cd.arm.default_r8_r14[i-8];
1046 dpavlin 14 break;
1047     case ARM_MODE_USR32:
1048     case ARM_MODE_SYS32:
1049     break;
1050     }
1051     }
1052    
1053     if (i == ARM_PC)
1054     value += 12; /* NOTE/TODO: 8 on some ARMs */
1055    
1056     if (p_bit) {
1057     if (u_bit)
1058     addr += sizeof(uint32_t);
1059     else
1060     addr -= sizeof(uint32_t);
1061     }
1062    
1063     page = cpu->cd.arm.host_store[addr >> 12];
1064     if (page != NULL) {
1065     uint32_t *p32 = (uint32_t *) page;
1066     /* Change byte order of value if
1067     host and emulated endianness differ: */
1068     #ifdef HOST_LITTLE_ENDIAN
1069     if (cpu->byte_order == EMUL_BIG_ENDIAN)
1070     #else
1071     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1072     #endif
1073     value = ((value & 0xff) << 24) |
1074     ((value & 0xff00) << 8) |
1075     ((value & 0xff0000) >> 8) |
1076     ((value & 0xff000000) >> 24);
1077     p32[(addr & 0xfff) >> 2] = value;
1078     } else {
1079     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
1080     data[0] = value;
1081     data[1] = value >> 8;
1082     data[2] = value >> 16;
1083     data[3] = value >> 24;
1084     } else {
1085     data[0] = value >> 24;
1086     data[1] = value >> 16;
1087     data[2] = value >> 8;
1088     data[3] = value;
1089     }
1090     if (!cpu->memory_rw(cpu, cpu->mem, addr, data,
1091     sizeof(data), MEM_WRITE, CACHE_DATA)) {
1092     /* store failed */
1093     return;
1094     }
1095     }
1096    
1097     if (!p_bit) {
1098     if (u_bit)
1099     addr += sizeof(uint32_t);
1100     else
1101     addr -= sizeof(uint32_t);
1102     }
1103     }
1104    
1105     if (w_bit)
1106     *np = addr;
1107     }
1108     Y(bdt_store)
1109    
1110    
1111     /*****************************************************************************/
1112    
1113    
1114     /*
1115     * fill_loop_test:
1116     *
1117     * A byte-fill loop. Fills at most one page at a time. If the page was not
1118     * in the host_store table, then the original sequence (beginning with
1119     * cmps rZ,#0) is executed instead.
1120     *
1121     * L: cmps rZ,#0 ic[0]
1122     * strb rX,[rY],#1 ic[1]
1123     * sub rZ,rZ,#1 ic[2]
1124     * bgt L ic[3]
1125     *
1126     * A maximum of 4 pages are filled before returning.
1127     */
1128     X(fill_loop_test)
1129     {
1130     int max_pages_left = 4;
1131     uint32_t addr, a, n, ofs, maxlen;
1132     uint32_t *rzp = (uint32_t *)(size_t)ic[0].arg[0];
1133     unsigned char *page;
1134    
1135     restart_loop:
1136     addr = reg(ic[1].arg[0]);
1137     page = cpu->cd.arm.host_store[addr >> 12];
1138     if (page == NULL) {
1139     instr(cmps)(cpu, ic);
1140     return;
1141     }
1142    
1143     n = reg(rzp) + 1;
1144     ofs = addr & 0xfff;
1145     maxlen = 4096 - ofs;
1146     if (n > maxlen)
1147     n = maxlen;
1148    
1149     /* printf("x = %x, n = %i\n", reg(ic[1].arg[2]), n); */
1150     memset(page + ofs, reg(ic[1].arg[2]), n);
1151    
1152     reg(ic[1].arg[0]) = addr + n;
1153    
1154     reg(rzp) -= n;
1155     cpu->n_translated_instrs += (4 * n);
1156    
1157     a = reg(rzp);
1158    
1159     cpu->cd.arm.cpsr &=
1160     ~(ARM_FLAG_Z | ARM_FLAG_N | ARM_FLAG_V | ARM_FLAG_C);
1161     if (a != 0)
1162     cpu->cd.arm.cpsr |= ARM_FLAG_C;
1163     else
1164     cpu->cd.arm.cpsr |= ARM_FLAG_Z;
1165     if ((int32_t)a < 0)
1166     cpu->cd.arm.cpsr |= ARM_FLAG_N;
1167    
1168     if (max_pages_left-- > 0 && (int32_t)a > 0)
1169     goto restart_loop;
1170    
1171     cpu->n_translated_instrs --;
1172    
1173     if ((int32_t)a > 0)
1174     cpu->cd.arm.next_ic = ic;
1175     else
1176     cpu->cd.arm.next_ic = &ic[4];
1177     }
1178    
1179    
1180     /*
1181     * fill_loop_test2:
1182     *
1183     * A word-fill loop. Fills at most one page at a time. If the page was not
1184     * in the host_store table, then the original sequence (beginning with
1185     * cmps rZ,#0) is executed instead.
1186     *
1187     * L: str rX,[rY],#4 ic[0]
1188     * subs rZ,rZ,#4 ic[1]
1189     * bgt L ic[2]
1190     *
1191     * A maximum of 5 pages are filled before returning.
1192     */
1193     X(fill_loop_test2)
1194     {
1195     int max_pages_left = 5;
1196     unsigned char x1,x2,x3,x4;
1197     uint32_t addr, a, n, x, ofs, maxlen;
1198     uint32_t *rzp = (uint32_t *)(size_t)ic[1].arg[0];
1199     unsigned char *page;
1200    
1201     x = reg(ic[0].arg[2]);
1202     x1 = x; x2 = x >> 8; x3 = x >> 16; x4 = x >> 24;
1203     if (x1 != x2 || x1 != x3 || x1 != x4) {
1204     instr(store_w0_word_u1_p0_imm)(cpu, ic);
1205     return;
1206     }
1207    
1208     restart_loop:
1209     addr = reg(ic[0].arg[0]);
1210     page = cpu->cd.arm.host_store[addr >> 12];
1211     if (page == NULL || (addr & 3) != 0) {
1212     instr(store_w0_word_u1_p0_imm)(cpu, ic);
1213     return;
1214     }
1215    
1216     /* printf("addr = 0x%08x, page = %p\n", addr, page);
1217     printf("*rzp = 0x%08x\n", reg(rzp)); */
1218    
1219     n = reg(rzp) / 4;
1220     if (n == 0)
1221     n++;
1222     /* n = nr of _words_ */
1223     ofs = addr & 0xfff;
1224     maxlen = 4096 - ofs;
1225     if (n*4 > maxlen)
1226     n = maxlen / 4;
1227    
1228     /* printf("x = %x, n = %i\n", x1, n); */
1229     memset(page + ofs, x1, n * 4);
1230    
1231     reg(ic[0].arg[0]) = addr + n * 4;
1232    
1233     reg(rzp) -= (n * 4);
1234     cpu->n_translated_instrs += (3 * n);
1235    
1236     a = reg(rzp);
1237    
1238     cpu->cd.arm.cpsr &=
1239     ~(ARM_FLAG_Z | ARM_FLAG_N | ARM_FLAG_V | ARM_FLAG_C);
1240     if (a != 0)
1241     cpu->cd.arm.cpsr |= ARM_FLAG_C;
1242     else
1243     cpu->cd.arm.cpsr |= ARM_FLAG_Z;
1244     if ((int32_t)a < 0)
1245     cpu->cd.arm.cpsr |= ARM_FLAG_N;
1246    
1247     if (max_pages_left-- > 0 && (int32_t)a > 0)
1248     goto restart_loop;
1249    
1250     cpu->n_translated_instrs --;
1251    
1252     if ((int32_t)a > 0)
1253     cpu->cd.arm.next_ic = ic;
1254     else
1255     cpu->cd.arm.next_ic = &ic[3];
1256     }
1257    
1258    
1259     /*****************************************************************************/
1260    
1261    
1262     X(end_of_page)
1263     {
1264     /* Update the PC: (offset 0, but on the next page) */
1265     cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
1266     << ARM_INSTR_ALIGNMENT_SHIFT);
1267     cpu->cd.arm.r[ARM_PC] += (ARM_IC_ENTRIES_PER_PAGE
1268     << ARM_INSTR_ALIGNMENT_SHIFT);
1269     cpu->pc = cpu->cd.arm.r[ARM_PC];
1270    
1271     /* Find the new physical page and update the translation pointers: */
1272     arm_pc_to_pointers(cpu);
1273    
1274     /* end_of_page doesn't count as an executed instruction: */
1275     cpu->n_translated_instrs --;
1276     }
1277    
1278    
1279     /*****************************************************************************/
1280    
1281    
1282     /*
1283     * arm_combine_instructions():
1284     *
1285     * Combine two or more instructions, if possible, into a single function call.
1286     */
1287     void arm_combine_instructions(struct cpu *cpu, struct arm_instr_call *ic,
1288     uint32_t addr)
1289     {
1290     int n_back;
1291     n_back = (addr >> ARM_INSTR_ALIGNMENT_SHIFT)
1292     & (ARM_IC_ENTRIES_PER_PAGE-1);
1293    
1294     if (n_back >= 2) {
1295     if (ic[-2].f == instr(store_w0_word_u1_p0_imm) &&
1296     ic[-2].arg[1] == 4 &&
1297     ic[-1].f == instr(subs) &&
1298     ic[-1].arg[0] == ic[-1].arg[2] && ic[-1].arg[1] == 4 &&
1299     ic[ 0].f == instr(b_samepage__gt) &&
1300     ic[ 0].arg[0] == (size_t)&ic[-2]) {
1301     ic[-2].f = instr(fill_loop_test2);
1302     combined;
1303     }
1304     }
1305    
1306     if (n_back >= 3) {
1307     if (ic[-3].f == instr(cmps) &&
1308     ic[-3].arg[0] == ic[-1].arg[0] &&
1309     ic[-3].arg[1] == 0 &&
1310     ic[-2].f == instr(store_w0_byte_u1_p0_imm) &&
1311     ic[-2].arg[1] == 1 &&
1312     ic[-1].f == instr(sub) &&
1313     ic[-1].arg[0] == ic[-1].arg[2] && ic[-1].arg[1] == 1 &&
1314     ic[ 0].f == instr(b_samepage__gt) &&
1315     ic[ 0].arg[0] == (size_t)&ic[-3]) {
1316     ic[-3].f = instr(fill_loop_test);
1317     combined;
1318     }
1319     }
1320    
1321     /* TODO: Combine forward as well */
1322     }
1323    
1324    
1325     /*****************************************************************************/
1326    
1327    
1328     /*
1329     * arm_instr_to_be_translated():
1330     *
1331     * Translate an instruction word into an arm_instr_call. ic is filled in with
1332     * valid data for the translated instruction, or a "nothing" instruction if
1333     * there was a translation failure. The newly translated instruction is then
1334     * executed.
1335     */
1336     X(to_be_translated)
1337     {
1338     uint32_t addr, low_pc, iword, imm = 0;
1339     unsigned char *page;
1340     unsigned char ib[4];
1341     int condition_code, main_opcode, secondary_opcode, s_bit, rn, rd, r8;
1342     int p_bit, u_bit, b_bit, w_bit, l_bit, regform, rm, c, t;
1343     int any_pc_reg;
1344     void (*samepage_function)(struct cpu *, struct arm_instr_call *);
1345    
1346     /* Figure out the address of the instruction: */
1347     low_pc = ((size_t)ic - (size_t)cpu->cd.arm.cur_ic_page)
1348     / sizeof(struct arm_instr_call);
1349     addr = cpu->cd.arm.r[ARM_PC] & ~((ARM_IC_ENTRIES_PER_PAGE-1) <<
1350     ARM_INSTR_ALIGNMENT_SHIFT);
1351     addr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
1352     cpu->pc = cpu->cd.arm.r[ARM_PC] = addr;
1353     addr &= ~((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);
1354    
1355     /* Read the instruction word from memory: */
1356     page = cpu->cd.arm.host_load[addr >> 12];
1357     if (page != NULL) {
1358     /* fatal("TRANSLATION HIT!\n"); */
1359     memcpy(ib, page + (addr & 0xfff), sizeof(ib));
1360     } else {
1361     /* fatal("TRANSLATION MISS!\n"); */
1362     if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],
1363     sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
1364     fatal("to_be_translated(): "
1365     "read failed: TODO\n");
1366     goto bad;
1367     }
1368     }
1369    
1370     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1371     iword = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
1372     else
1373     iword = ib[3] + (ib[2]<<8) + (ib[1]<<16) + (ib[0]<<24);
1374    
1375    
1376     #define DYNTRANS_TO_BE_TRANSLATED_HEAD
1377     #include "cpu_dyntrans.c"
1378     #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
1379    
1380    
1381     /* The idea of taking bits 27..24 was found here:
1382     http://armphetamine.sourceforge.net/oldinfo.html */
1383     condition_code = iword >> 28;
1384     main_opcode = (iword >> 24) & 15;
1385     secondary_opcode = (iword >> 21) & 15;
1386     u_bit = (iword >> 23) & 1;
1387     b_bit = (iword >> 22) & 1;
1388     w_bit = (iword >> 21) & 1;
1389     s_bit = l_bit = (iword >> 20) & 1;
1390     rn = (iword >> 16) & 15;
1391     rd = (iword >> 12) & 15;
1392     r8 = (iword >> 8) & 15;
1393     c = (iword >> 7) & 31;
1394     t = (iword >> 4) & 7;
1395     rm = iword & 15;
1396    
1397     if (condition_code == 0xf) {
1398     if ((iword & 0xfc70f000) == 0xf450f000) {
1399     /* Preload: TODO. Treat as NOP for now. */
1400     ic->f = instr(nop);
1401     goto okay;
1402     }
1403    
1404     fatal("TODO: ARM condition code 0x%x\n",
1405     condition_code);
1406     goto bad;
1407     }
1408    
1409    
1410     /*
1411     * Translate the instruction:
1412     */
1413    
1414     switch (main_opcode) {
1415    
1416     case 0x0:
1417     case 0x1:
1418     case 0x2:
1419     case 0x3:
1420     /* Check special cases first: */
1421     if ((iword & 0x0fc000f0) == 0x00000090) {
1422     /*
1423     * Multiplication:
1424     * xxxx0000 00ASdddd nnnnssss 1001mmmm (Rd,Rm,Rs[,Rn])
1425     */
1426     if (iword & 0x00200000) {
1427     if (s_bit)
1428     ic->f = cond_instr(mlas);
1429     else
1430     ic->f = cond_instr(mla);
1431     ic->arg[0] = iword;
1432     } else {
1433     if (s_bit)
1434     ic->f = cond_instr(muls);
1435     else
1436     ic->f = cond_instr(mul);
1437     /* NOTE: rn means rd in this case: */
1438     ic->arg[0] = (size_t)(&cpu->cd.arm.r[rn]);
1439     ic->arg[1] = (size_t)(&cpu->cd.arm.r[rm]);
1440     ic->arg[2] = (size_t)(&cpu->cd.arm.r[r8]);
1441     }
1442     break;
1443     }
1444     if ((iword & 0x0f8000f0) == 0x00800090) {
1445     /* Long multiplication: */
1446     if (s_bit) {
1447     fatal("TODO: sbit mull\n");
1448     goto bad;
1449     }
1450     ic->f = cond_instr(mull);
1451     ic->arg[0] = iword;
1452     break;
1453     }
1454     if ((iword & 0x0ff000d0) == 0x01200010) {
1455     /* bx or blx */
1456     if (iword & 0x20)
1457     ic->f = cond_instr(blx);
1458     else {
1459     if (cpu->machine->show_trace_tree &&
1460     rm == ARM_LR)
1461     ic->f = cond_instr(bx_trace);
1462     else
1463     ic->f = cond_instr(bx);
1464     }
1465     ic->arg[0] = (size_t)(&cpu->cd.arm.r[rm]);
1466     break;
1467     }
1468     if ((iword & 0x0fb00ff0) == 0x1000090) {
1469     if (iword & 0x00400000)
1470     ic->f = cond_instr(swpb);
1471     else
1472     ic->f = cond_instr(swp);
1473     ic->arg[0] = (size_t)(&cpu->cd.arm.r[rd]);
1474     ic->arg[1] = (size_t)(&cpu->cd.arm.r[rm]);
1475     ic->arg[2] = (size_t)(&cpu->cd.arm.r[rn]);
1476     break;
1477     }
1478     if ((iword & 0x0fb0fff0) == 0x0120f000 ||
1479     (iword & 0x0fb0f000) == 0x0320f000) {
1480     /* msr: move to [S|C]PSR from a register or
1481     immediate value */
1482     if (rm == ARM_PC) {
1483     fatal("msr PC?\n");
1484     goto bad;
1485     }
1486     if (iword & 0x02000000) {
1487     if (iword & 0x00400000)
1488     ic->f = cond_instr(msr_imm_spsr);
1489     else
1490     ic->f = cond_instr(msr_imm);
1491     } else {
1492     if (iword & 0x00400000)
1493     ic->f = cond_instr(msr_spsr);
1494     else
1495     ic->f = cond_instr(msr);
1496     }
1497     imm = iword & 0xff;
1498     while (r8-- > 0)
1499     imm = (imm >> 2) | ((imm & 3) << 30);
1500     ic->arg[0] = imm;
1501     ic->arg[2] = (size_t)(&cpu->cd.arm.r[rm]);
1502     switch ((iword >> 16) & 15) {
1503     case 1: ic->arg[1] = 0x000000ff; break;
1504     case 8: ic->arg[1] = 0xff000000; break;
1505     case 9: ic->arg[1] = 0xff0000ff; break;
1506     default:fatal("unimpl a: msr regform\n");
1507     goto bad;
1508     }
1509     break;
1510     }
1511     if ((iword & 0x0fbf0fff) == 0x010f0000) {
1512     /* mrs: move from CPSR/SPSR to a register: */
1513     if (rd == ARM_PC) {
1514     fatal("mrs PC?\n");
1515     goto bad;
1516     }
1517     if (iword & 0x00400000)
1518     ic->f = cond_instr(mrs_spsr);
1519     else
1520     ic->f = cond_instr(mrs);
1521     ic->arg[0] = (size_t)(&cpu->cd.arm.r[rd]);
1522     break;
1523     }
1524     if ((iword & 0x0e000090) == 0x00000090) {
1525     int imm = ((iword >> 4) & 0xf0) | (iword & 0xf);
1526     int regform = !(iword & 0x00400000);
1527     p_bit = main_opcode & 1;
1528     ic->arg[0] = (size_t)(&cpu->cd.arm.r[rn]);
1529     ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);
1530     if (rd == ARM_PC || rn == ARM_PC) {
1531     ic->f = arm_load_store_instr_3_pc[
1532     condition_code + (l_bit? 16 : 0)
1533     + (iword & 0x40? 32 : 0)
1534     + (w_bit? 64 : 0)
1535     + (iword & 0x20? 128 : 0)
1536     + (u_bit? 256 : 0) + (p_bit? 512 : 0)
1537     + (regform? 1024 : 0)];
1538     if (rn == ARM_PC)
1539     ic->arg[0] = (size_t)
1540     (&cpu->cd.arm.tmp_pc);
1541     if (!l_bit && rd == ARM_PC)
1542     ic->arg[2] = (size_t)
1543     (&cpu->cd.arm.tmp_pc);
1544     } else
1545     ic->f = arm_load_store_instr_3[
1546     condition_code + (l_bit? 16 : 0)
1547     + (iword & 0x40? 32 : 0)
1548     + (w_bit? 64 : 0)
1549     + (iword & 0x20? 128 : 0)
1550     + (u_bit? 256 : 0) + (p_bit? 512 : 0)
1551     + (regform? 1024 : 0)];
1552     if (regform)
1553 dpavlin 16 ic->arg[1] = (size_t)(void *)arm_r[iword & 0xf];
1554 dpavlin 14 else
1555     ic->arg[1] = imm;
1556     break;
1557     }
1558    
1559     if (iword & 0x80 && !(main_opcode & 2) && iword & 0x10) {
1560     fatal("reg form blah blah\n");
1561     goto bad;
1562     }
1563    
1564     /* "mov pc,lr" with trace enabled: */
1565     if ((iword & 0x0fffffff) == 0x01a0f00e &&
1566     cpu->machine->show_trace_tree) {
1567     ic->f = cond_instr(ret_trace);
1568     break;
1569     }
1570    
1571     /* "mov reg,reg": */
1572     if ((iword & 0x0fff0ff0) == 0x01a00000 &&
1573     (iword&15) != ARM_PC && rd != ARM_PC) {
1574     ic->f = cond_instr(mov_reg_reg);
1575     ic->arg[0] = (size_t)(&cpu->cd.arm.r[iword & 15]);
1576     ic->arg[1] = (size_t)(&cpu->cd.arm.r[rd]);
1577     break;
1578     }
1579    
1580     /*
1581     * Generic Data Processing Instructions:
1582     */
1583     if ((main_opcode & 2) == 0)
1584     regform = 1;
1585     else
1586     regform = 0;
1587    
1588 dpavlin 16 if (regform) {
1589     /* 0x1000 signifies Carry bit update on rotation,
1590     which is not necessary for add,adc,sub,sbc,
1591     rsb,rsc,cmp, or cmn, because they update the
1592     Carry bit manually anyway. */
1593     int q = 0x1000;
1594     if (s_bit == 0)
1595     q = 0;
1596     if ((secondary_opcode >= 2 && secondary_opcode <= 7)
1597     || secondary_opcode==0xa || secondary_opcode==0xb)
1598     q = 0;
1599     ic->arg[1] = (size_t)(void *)arm_r[(iword & 0xfff) + q];
1600     } else {
1601 dpavlin 14 imm = iword & 0xff;
1602     while (r8-- > 0)
1603     imm = (imm >> 2) | ((imm & 3) << 30);
1604     ic->arg[1] = imm;
1605     }
1606    
1607     ic->arg[0] = (size_t)(&cpu->cd.arm.r[rn]);
1608     ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);
1609     any_pc_reg = 0;
1610     if (rn == ARM_PC || rd == ARM_PC)
1611     any_pc_reg = 1;
1612    
1613     ic->f = arm_dpi_instr[condition_code +
1614     16 * secondary_opcode + (s_bit? 256 : 0) +
1615     (any_pc_reg? 512 : 0) + (regform? 1024 : 0)];
1616     break;
1617    
1618     case 0x4: /* Load and store... */
1619     case 0x5: /* xxxx010P UBWLnnnn ddddoooo oooooooo Immediate */
1620     case 0x6: /* xxxx011P UBWLnnnn ddddcccc ctt0mmmm Register */
1621     case 0x7:
1622     ic->arg[0] = (size_t)(&cpu->cd.arm.r[rn]);
1623     ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);
1624     if (rd == ARM_PC || rn == ARM_PC) {
1625     ic->f = arm_load_store_instr_pc[((iword >> 16)
1626     & 0x3f0) + condition_code];
1627     if (rn == ARM_PC)
1628     ic->arg[0] = (size_t)(&cpu->cd.arm.tmp_pc);
1629     if (!l_bit && rd == ARM_PC)
1630     ic->arg[2] = (size_t)(&cpu->cd.arm.tmp_pc);
1631     } else {
1632     ic->f = arm_load_store_instr[((iword >> 16) &
1633     0x3f0) + condition_code];
1634     }
1635     imm = iword & 0xfff;
1636     if (main_opcode < 6)
1637     ic->arg[1] = imm;
1638     else
1639 dpavlin 16 ic->arg[1] = (size_t)(void *)arm_r[iword & 0xfff];
1640 dpavlin 14 if ((iword & 0x0e000010) == 0x06000010) {
1641     fatal("Not a Load/store TODO\n");
1642     goto bad;
1643     }
1644     break;
1645    
1646     case 0x8: /* Multiple load/store... (Block data transfer) */
1647     case 0x9: /* xxxx100P USWLnnnn llllllll llllllll */
1648     if (l_bit)
1649     ic->f = cond_instr(bdt_load);
1650     else
1651     ic->f = cond_instr(bdt_store);
1652     ic->arg[0] = (size_t)(&cpu->cd.arm.r[rn]);
1653     ic->arg[1] = (size_t)iword;
1654     if (rn == ARM_PC) {
1655     fatal("TODO: bdt with PC as base\n");
1656     goto bad;
1657     }
1658     break;
1659    
1660     case 0xa: /* B: branch */
1661     case 0xb: /* BL: branch+link */
1662     if (main_opcode == 0x0a) {
1663     ic->f = cond_instr(b);
1664     samepage_function = cond_instr(b_samepage);
1665     } else {
1666     if (cpu->machine->show_trace_tree) {
1667     ic->f = cond_instr(bl_trace);
1668     samepage_function =
1669     cond_instr(bl_samepage_trace);
1670     } else {
1671     ic->f = cond_instr(bl);
1672     samepage_function = cond_instr(bl_samepage);
1673     }
1674     }
1675    
1676     ic->arg[0] = (iword & 0x00ffffff) << 2;
1677     /* Sign-extend: */
1678     if (ic->arg[0] & 0x02000000)
1679     ic->arg[0] |= 0xfc000000;
1680     /*
1681     * Branches are calculated as PC + 8 + offset.
1682     */
1683     ic->arg[0] = (int32_t)(ic->arg[0] + 8);
1684    
1685     /* Special case: branch within the same page: */
1686     {
1687     uint32_t mask_within_page =
1688     ((ARM_IC_ENTRIES_PER_PAGE-1) <<
1689     ARM_INSTR_ALIGNMENT_SHIFT) |
1690     ((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);
1691     uint32_t old_pc = addr;
1692     uint32_t new_pc = old_pc + (int32_t)ic->arg[0];
1693     if ((old_pc & ~mask_within_page) ==
1694     (new_pc & ~mask_within_page)) {
1695     ic->f = samepage_function;
1696     ic->arg[0] = (size_t) (
1697     cpu->cd.arm.cur_ic_page +
1698     ((new_pc & mask_within_page) >>
1699     ARM_INSTR_ALIGNMENT_SHIFT));
1700     }
1701     }
1702     break;
1703    
1704     case 0xe:
1705     if (iword & 0x10) {
1706     /* xxxx1110 oooLNNNN ddddpppp qqq1MMMM MCR/MRC */
1707     ic->arg[0] = iword;
1708     ic->f = cond_instr(mcr_mrc);
1709     } else {
1710     /* xxxx1110 oooonnnn ddddpppp qqq0mmmm CDP */
1711     ic->arg[0] = iword;
1712     ic->f = cond_instr(cdp);
1713     }
1714     break;
1715    
1716     case 0xf:
1717     /* SWI: */
1718     /* Default handler: */
1719     ic->f = cond_instr(swi);
1720     if (iword == 0xef8c64be) {
1721     /* Hack for openfirmware prom emulation: */
1722     ic->f = instr(openfirmware);
1723     } else if (cpu->machine->userland_emul != NULL) {
1724     if ((iword & 0x00f00000) == 0x00a00000) {
1725     ic->arg[0] = iword & 0x00ffffff;
1726     ic->f = cond_instr(swi_useremul);
1727     } else {
1728     fatal("Bad userland SWI?\n");
1729     goto bad;
1730     }
1731     }
1732     break;
1733    
1734     default:goto bad;
1735     }
1736    
1737     okay:
1738    
1739     #define DYNTRANS_TO_BE_TRANSLATED_TAIL
1740     #include "cpu_dyntrans.c"
1741     #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
1742     }
1743    

  ViewVC Help
Powered by ViewVC 1.1.26