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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (hide annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 45428 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

1 dpavlin 40 /*
2     * Copyright (C) 2007 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 44 * $Id: cpu_m88k_instr.c,v 1.42 2007/06/28 13:36:46 debug Exp $
29 dpavlin 40 *
30     * M88K 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 dpavlin 42 #define SYNCH_PC { \
40     int low_pc = ((size_t)ic - (size_t)cpu->cd.m88k.cur_ic_page) \
41     / sizeof(struct m88k_instr_call); \
42     cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1) \
43     << M88K_INSTR_ALIGNMENT_SHIFT); \
44     cpu->pc += (low_pc << M88K_INSTR_ALIGNMENT_SHIFT); \
45     }
46    
47    
48 dpavlin 40 /*
49     * nop: Do nothing.
50     */
51     X(nop)
52     {
53     }
54    
55    
56     /*
57 dpavlin 42 * br_samepage: Branch (to within the same translated page)
58     * bsr_samepage: Branch to subroutine (to within the same translated page)
59 dpavlin 40 *
60     * arg[0] = pointer to new instr_call
61 dpavlin 44 * arg[2] = offset to return address, from start of page
62 dpavlin 40 */
63     X(br_samepage)
64     {
65     cpu->cd.m88k.next_ic = (struct m88k_instr_call *) ic->arg[0];
66     }
67 dpavlin 42 X(bsr_samepage)
68     {
69 dpavlin 44 cpu->cd.m88k.r[M88K_RETURN_REG] = (cpu->pc &
70     ~((M88K_IC_ENTRIES_PER_PAGE-1) << M88K_INSTR_ALIGNMENT_SHIFT))
71     + ic->arg[2];
72 dpavlin 42 cpu->cd.m88k.next_ic = (struct m88k_instr_call *) ic->arg[0];
73     }
74 dpavlin 40
75    
76     /*
77 dpavlin 42 * br: Branch (to a different translated page)
78     * br.n: Branch (to a different translated page) with delay slot
79     * bsr: Branch to subroutine (to a different translated page)
80     * bsr.n: Branch to subroutine (to a different page) with delay slot
81 dpavlin 40 *
82 dpavlin 42 * arg[1] = relative offset from start of page
83 dpavlin 44 * arg[2] = offset to return address, from start of page
84 dpavlin 40 */
85     X(br)
86     {
87 dpavlin 42 cpu->pc = (uint32_t)((cpu->pc & 0xfffff000) + (int32_t)ic->arg[1]);
88     quick_pc_to_pointers(cpu);
89     }
90     X(br_n)
91     {
92     cpu->cd.m88k.delay_target = (cpu->pc & ~((M88K_IC_ENTRIES_PER_PAGE-1) <<
93     M88K_INSTR_ALIGNMENT_SHIFT)) + (int32_t)ic->arg[1];
94     cpu->delay_slot = TO_BE_DELAYED;
95     ic[1].f(cpu, ic+1);
96     cpu->n_translated_instrs ++;
97     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
98     /* Note: Must be non-delayed when jumping to the new pc: */
99     cpu->delay_slot = NOT_DELAYED;
100     cpu->pc = cpu->cd.m88k.delay_target;
101     quick_pc_to_pointers(cpu);
102     } else
103     cpu->delay_slot = NOT_DELAYED;
104     }
105     X(bsr)
106     {
107 dpavlin 44 cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1) <<
108     M88K_INSTR_ALIGNMENT_SHIFT);
109     cpu->cd.m88k.r[M88K_RETURN_REG] = cpu->pc + ic->arg[2];
110     cpu->pc = (uint32_t) (cpu->pc + ic->arg[1]);
111 dpavlin 42 quick_pc_to_pointers(cpu);
112     }
113     X(bsr_n)
114     {
115 dpavlin 44 cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1) <<
116     M88K_INSTR_ALIGNMENT_SHIFT);
117     cpu->cd.m88k.r[M88K_RETURN_REG] = cpu->pc + ic->arg[2] + 4;
118     cpu->cd.m88k.delay_target = cpu->pc + ic->arg[1];
119 dpavlin 42 cpu->delay_slot = TO_BE_DELAYED;
120     ic[1].f(cpu, ic+1);
121     cpu->n_translated_instrs ++;
122     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
123     /* Note: Must be non-delayed when jumping to the new pc: */
124     cpu->delay_slot = NOT_DELAYED;
125     cpu->pc = cpu->cd.m88k.delay_target;
126     quick_pc_to_pointers(cpu);
127     } else
128     cpu->delay_slot = NOT_DELAYED;
129     }
130     X(bsr_trace)
131     {
132 dpavlin 44 cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1) <<
133     M88K_INSTR_ALIGNMENT_SHIFT);
134     cpu->cd.m88k.r[M88K_RETURN_REG] = cpu->pc + ic->arg[2];
135     cpu->pc = (uint32_t) (cpu->pc + ic->arg[1]);
136 dpavlin 42 cpu_functioncall_trace(cpu, cpu->pc);
137     quick_pc_to_pointers(cpu);
138     }
139     X(bsr_n_trace)
140     {
141 dpavlin 44 cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1) <<
142     M88K_INSTR_ALIGNMENT_SHIFT);
143     cpu->cd.m88k.r[M88K_RETURN_REG] = cpu->pc + ic->arg[2] + 4;
144     cpu->cd.m88k.delay_target = cpu->pc + ic->arg[1];
145 dpavlin 42 cpu->delay_slot = TO_BE_DELAYED;
146     ic[1].f(cpu, ic+1);
147     cpu->n_translated_instrs ++;
148     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
149     /* Note: Must be non-delayed when jumping to the new pc: */
150     cpu->delay_slot = NOT_DELAYED;
151     cpu->pc = cpu->cd.m88k.delay_target;
152     cpu_functioncall_trace(cpu, cpu->pc);
153     quick_pc_to_pointers(cpu);
154     } else
155     cpu->delay_slot = NOT_DELAYED;
156     }
157 dpavlin 40
158 dpavlin 42
159     /*
160     * bb? Branch if a bit in a register is 0 or 1.
161     * bb?_samepage: Branch within the same translated page.
162     * bb?_n_*: With delay slot.
163     *
164     * arg[0] = pointer to source register to test (s1).
165     * arg[1] = uint32_t mask to test (e.g. 0x00010000 to test bit 16)
166     * arg[2] = offset from start of current page _OR_ pointer to new instr_call
167     */
168     X(bb0)
169     {
170     if (!(reg(ic->arg[0]) & ic->arg[1])) {
171     cpu->pc = (cpu->pc & 0xfffff000) + (int32_t)ic->arg[2];
172     quick_pc_to_pointers(cpu);
173     }
174     }
175     X(bb0_samepage)
176     {
177     if (!(reg(ic->arg[0]) & ic->arg[1]))
178     cpu->cd.m88k.next_ic = (struct m88k_instr_call *) ic->arg[2];
179     }
180     X(bb0_n)
181     {
182 dpavlin 44 int cond = !(reg(ic->arg[0]) & (uint32_t)ic->arg[1]);
183 dpavlin 42 cpu->cd.m88k.delay_target = (cpu->pc & ~((M88K_IC_ENTRIES_PER_PAGE-1) <<
184     M88K_INSTR_ALIGNMENT_SHIFT)) + (int32_t)ic->arg[2];
185     cpu->delay_slot = TO_BE_DELAYED;
186     ic[1].f(cpu, ic+1);
187     cpu->n_translated_instrs ++;
188     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
189     /* Note: Must be non-delayed when jumping to the new pc: */
190     cpu->delay_slot = NOT_DELAYED;
191     if (cond) {
192     cpu->pc = cpu->cd.m88k.delay_target;
193     quick_pc_to_pointers(cpu);
194     } else
195     cpu->cd.m88k.next_ic ++;
196     } else
197     cpu->delay_slot = NOT_DELAYED;
198     }
199     X(bb1)
200     {
201     if (reg(ic->arg[0]) & ic->arg[1]) {
202     cpu->pc = (cpu->pc & 0xfffff000) + (int32_t)ic->arg[2];
203     quick_pc_to_pointers(cpu);
204     }
205     }
206     X(bb1_samepage)
207     {
208     if (reg(ic->arg[0]) & ic->arg[1])
209     cpu->cd.m88k.next_ic = (struct m88k_instr_call *) ic->arg[2];
210     }
211     X(bb1_n)
212     {
213     int cond = reg(ic->arg[0]) & ic->arg[1];
214     cpu->cd.m88k.delay_target = (cpu->pc & ~((M88K_IC_ENTRIES_PER_PAGE-1) <<
215     M88K_INSTR_ALIGNMENT_SHIFT)) + (int32_t)ic->arg[2];
216     cpu->delay_slot = TO_BE_DELAYED;
217     ic[1].f(cpu, ic+1);
218     cpu->n_translated_instrs ++;
219     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
220     /* Note: Must be non-delayed when jumping to the new pc: */
221     cpu->delay_slot = NOT_DELAYED;
222     if (cond) {
223     cpu->pc = cpu->cd.m88k.delay_target;
224     quick_pc_to_pointers(cpu);
225     } else
226     cpu->cd.m88k.next_ic ++;
227     } else
228     cpu->delay_slot = NOT_DELAYED;
229     }
230    
231    
232     /*
233     * ff0, ff1: Find first cleared/set bit in a register
234     *
235     * arg[0] = pointer to register d
236     * arg[2] = pointer to register s2
237     */
238     X(ff0)
239     {
240     uint32_t mask = 0x80000000, s2 = reg(ic->arg[2]);
241     int n = 31;
242    
243     for (;;) {
244     if (!(s2 & mask)) {
245     reg(ic->arg[0]) = n;
246     return;
247     }
248     mask >>= 1; n--;
249     if (mask == 0) {
250     reg(ic->arg[0]) = 32;
251     return;
252     }
253     }
254     }
255     X(ff1)
256     {
257     uint32_t mask = 0x80000000, s2 = reg(ic->arg[2]);
258     int n = 31;
259    
260     for (;;) {
261     if (s2 & mask) {
262     reg(ic->arg[0]) = n;
263     return;
264     }
265     mask >>= 1; n--;
266     if (mask == 0) {
267     reg(ic->arg[0]) = 32;
268     return;
269     }
270     }
271     }
272    
273    
274     /* Include all automatically generated bcnd and bcnd.n instructions: */
275     #include "tmp_m88k_bcnd.c"
276    
277    
278     /* Include all automatically generated load/store instructions: */
279     #include "tmp_m88k_loadstore.c"
280     #define M88K_LOADSTORE_STORE 4
281     #define M88K_LOADSTORE_SIGNEDNESS 8
282     #define M88K_LOADSTORE_ENDIANNESS 16
283     #define M88K_LOADSTORE_SCALEDNESS 32
284     #define M88K_LOADSTORE_USR 64
285     #define M88K_LOADSTORE_REGISTEROFFSET 128
286    
287    
288     /*
289     * jmp: Jump to register
290     * jmp.n: Jump to register, with delay slot
291     * jsr: Jump to register, set r1 to return address
292     * jsr.n: Jump to register, set r1 to return address, with delay slot
293     *
294     * arg[1] = offset to return address, from start of current page
295     * arg[2] = pointer to register s2
296     */
297     X(jmp)
298     {
299     cpu->pc = reg(ic->arg[2]) & ~3;
300 dpavlin 40 quick_pc_to_pointers(cpu);
301     }
302 dpavlin 42 X(jmp_n)
303     {
304     cpu->cd.m88k.delay_target = reg(ic->arg[2]) & ~3;
305     cpu->delay_slot = TO_BE_DELAYED;
306     ic[1].f(cpu, ic+1);
307     cpu->n_translated_instrs ++;
308     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
309     /* Note: Must be non-delayed when jumping to the new pc: */
310     cpu->delay_slot = NOT_DELAYED;
311     cpu->pc = cpu->cd.m88k.delay_target;
312     quick_pc_to_pointers(cpu);
313     } else
314     cpu->delay_slot = NOT_DELAYED;
315     }
316     X(jmp_trace)
317     {
318     cpu->pc = reg(ic->arg[2]) & ~3;
319     cpu_functioncall_trace_return(cpu);
320     quick_pc_to_pointers(cpu);
321     }
322     X(jmp_n_trace)
323     {
324     cpu->cd.m88k.delay_target = reg(ic->arg[2]) & ~3;
325     cpu->delay_slot = TO_BE_DELAYED;
326     ic[1].f(cpu, ic+1);
327     cpu->n_translated_instrs ++;
328     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
329     /* Note: Must be non-delayed when jumping to the new pc: */
330     cpu->delay_slot = NOT_DELAYED;
331     cpu->pc = cpu->cd.m88k.delay_target;
332     cpu_functioncall_trace_return(cpu);
333     quick_pc_to_pointers(cpu);
334     } else
335     cpu->delay_slot = NOT_DELAYED;
336     }
337     X(jsr)
338     {
339     cpu->cd.m88k.r[M88K_RETURN_REG] = (cpu->pc & 0xfffff000) + ic->arg[1];
340     cpu->pc = reg(ic->arg[2]) & ~3;
341     quick_pc_to_pointers(cpu);
342     }
343     X(jsr_n)
344     {
345     cpu->cd.m88k.delay_target = reg(ic->arg[2]) & ~3;
346     cpu->cd.m88k.r[M88K_RETURN_REG] = (cpu->pc & 0xfffff000) + ic->arg[1];
347     cpu->delay_slot = TO_BE_DELAYED;
348     ic[1].f(cpu, ic+1);
349     cpu->n_translated_instrs ++;
350     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
351     /* Note: Must be non-delayed when jumping to the new pc: */
352     cpu->delay_slot = NOT_DELAYED;
353     cpu->pc = cpu->cd.m88k.delay_target;
354     quick_pc_to_pointers(cpu);
355     } else
356     cpu->delay_slot = NOT_DELAYED;
357     }
358     X(jsr_trace)
359     {
360     cpu->cd.m88k.r[M88K_RETURN_REG] = (cpu->pc & 0xfffff000) + ic->arg[1];
361     cpu->pc = reg(ic->arg[2]) & ~3;
362     cpu_functioncall_trace(cpu, cpu->pc);
363     quick_pc_to_pointers(cpu);
364     }
365     X(jsr_n_trace)
366     {
367     cpu->cd.m88k.delay_target = reg(ic->arg[2]) & ~3;
368     cpu->cd.m88k.r[M88K_RETURN_REG] = (cpu->pc & 0xfffff000) + ic->arg[1];
369     cpu->delay_slot = TO_BE_DELAYED;
370     ic[1].f(cpu, ic+1);
371     cpu->n_translated_instrs ++;
372     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
373     /* Note: Must be non-delayed when jumping to the new pc: */
374     cpu->delay_slot = NOT_DELAYED;
375     cpu->pc = cpu->cd.m88k.delay_target;
376     cpu_functioncall_trace(cpu, cpu->pc);
377     quick_pc_to_pointers(cpu);
378     } else
379     cpu->delay_slot = NOT_DELAYED;
380     }
381 dpavlin 40
382    
383     /*
384 dpavlin 42 * cmp_imm: Compare S1 with immediate value.
385     * cmp: Compare S1 with S2.
386     *
387     * arg[0] = pointer to register d
388     * arg[1] = pointer to register s1
389     * arg[2] = pointer to register s2 or imm
390     */
391     static void m88k_cmp(struct cpu *cpu, struct m88k_instr_call *ic, uint32_t y)
392     {
393     uint32_t x = reg(ic->arg[1]);
394     uint32_t r;
395    
396     if (x == y) {
397     r = M88K_CMP_HS | M88K_CMP_LS | M88K_CMP_GE
398     | M88K_CMP_LE | M88K_CMP_EQ;
399     } else {
400     if (x > y)
401     r = M88K_CMP_NE | M88K_CMP_HS | M88K_CMP_HI;
402     else
403     r = M88K_CMP_NE | M88K_CMP_LO | M88K_CMP_LS;
404     if ((int32_t)x > (int32_t)y)
405     r |= M88K_CMP_GE | M88K_CMP_GT;
406     else
407     r |= M88K_CMP_LT | M88K_CMP_LE;
408     }
409    
410     reg(ic->arg[0]) = r;
411     }
412     X(cmp_imm) { m88k_cmp(cpu, ic, ic->arg[2]); }
413     X(cmp) { m88k_cmp(cpu, ic, reg(ic->arg[2])); }
414    
415    
416     /*
417     * extu_imm: Extract bits, unsigned, immediate W<O>.
418     * extu: Extract bits, unsigned, W<O> taken from register s2.
419     * ext_imm: Extract bits, signed, immediate W<O>.
420     * ext: Extract bits, signed, W<O> taken from register s2.
421     * mak_imm: Make bit field, immediate W<O>.
422     * mak: Make bit field, W<O> taken from register s2.
423     * clr: Clear bits, W<O> taken from register s2.
424     * set: Set bits, W<O> taken from register s2.
425     *
426     * arg[0] = pointer to register d
427     * arg[1] = pointer to register s1
428     * arg[2] = pointer to register s2 or 10 bits wwwwwooooo
429     */
430     static void m88k_extu(struct cpu *cpu, struct m88k_instr_call *ic, int w, int o)
431     {
432     uint32_t x = reg(ic->arg[1]) >> o;
433     if (w != 0) {
434     x <<= (32-w);
435     x >>= (32-w);
436     }
437     reg(ic->arg[0]) = x;
438     }
439     static void m88k_ext(struct cpu *cpu, struct m88k_instr_call *ic, int w, int o)
440     {
441     int32_t x = reg(ic->arg[1]) >> o;
442     if (w != 0) {
443     x <<= (32-w);
444     x >>= (32-w);
445     }
446     reg(ic->arg[0]) = x;
447     }
448     static void m88k_mak(struct cpu *cpu, struct m88k_instr_call *ic, int w, int o)
449     {
450     uint32_t x = reg(ic->arg[1]);
451     if (w != 0) {
452     x <<= (32-w);
453     x >>= (32-w);
454     }
455     reg(ic->arg[0]) = x << o;
456     }
457     X(extu_imm)
458     {
459     m88k_extu(cpu, ic, ic->arg[2] >> 5, ic->arg[2] & 0x1f);
460     }
461     X(extu)
462     {
463     m88k_extu(cpu, ic, (reg(ic->arg[2]) >> 5) & 0x1f,
464     reg(ic->arg[2]) & 0x1f);
465     }
466     X(ext_imm)
467     {
468     m88k_ext(cpu, ic, ic->arg[2] >> 5, ic->arg[2] & 0x1f);
469     }
470     X(ext)
471     {
472     m88k_ext(cpu, ic, (reg(ic->arg[2]) >> 5) & 0x1f,
473     reg(ic->arg[2]) & 0x1f);
474     }
475     X(mak_imm)
476     {
477     m88k_mak(cpu, ic, ic->arg[2] >> 5, ic->arg[2] & 0x1f);
478     }
479     X(mak)
480     {
481     m88k_mak(cpu, ic, (reg(ic->arg[2]) >> 5) & 0x1f,
482     reg(ic->arg[2]) & 0x1f);
483     }
484     X(clr)
485     {
486     int w = (reg(ic->arg[2]) >> 5) & 0x1f, o = reg(ic->arg[2]) & 0x1f;
487 dpavlin 44 uint32_t x = w == 0? 0xffffffff : ((uint32_t)1 << w) - 1;
488 dpavlin 42 x <<= o;
489     reg(ic->arg[0]) = reg(ic->arg[1]) & ~x;
490     }
491     X(set)
492     {
493     int w = (reg(ic->arg[2]) >> 5) & 0x1f, o = reg(ic->arg[2]) & 0x1f;
494 dpavlin 44 uint32_t x = w == 0? 0xffffffff : ((uint32_t)1 << w) - 1;
495 dpavlin 42 x <<= o;
496     reg(ic->arg[0]) = reg(ic->arg[1]) | x;
497     }
498    
499    
500     /*
501     * or_r0_imm0: d = 0 (optimized case when s1 = r0, imm = 0)
502     * or_r0_imm: d = imm (optimized case when s1 = r0)
503 dpavlin 40 * or_imm: d = s1 | imm
504 dpavlin 42 * xor_imm: d = s1 ^ imm
505     * and_imm: d = (s1 & imm) | (s1 & 0xffff0000)
506     * and_u_imm: d = (s1 & imm) | (s1 & 0xffff)
507     * mask_imm: d = s1 & imm
508     * addu_imm: d = s1 + imm
509     * subu_imm: d = s1 - imm
510     * inc_reg: d ++; (addu special case; d = d + 1)
511     * dec_reg: d --; (subu special case; d = d - 1)
512     * mulu_imm: d = s1 * imm
513     * divu_imm: d = s1 / imm (unsigned)
514     * div_imm: d = s1 / imm (signed)
515     * sub_imm: d = s1 - imm (subtraction with overflow exception)
516 dpavlin 40 *
517     * arg[0] = pointer to register d
518     * arg[1] = pointer to register s1
519     * arg[2] = imm
520     */
521 dpavlin 42 X(or_r0_imm0) { reg(ic->arg[0]) = 0; }
522     X(or_r0_imm) { reg(ic->arg[0]) = ic->arg[2]; }
523     X(or_imm) { reg(ic->arg[0]) = reg(ic->arg[1]) | ic->arg[2]; }
524     X(xor_imm) { reg(ic->arg[0]) = reg(ic->arg[1]) ^ ic->arg[2]; }
525     X(and_imm) { reg(ic->arg[0]) = (reg(ic->arg[1]) & ic->arg[2])
526     | (reg(ic->arg[1]) & 0xffff0000); }
527     X(and_u_imm) { reg(ic->arg[0]) = (reg(ic->arg[1]) & ic->arg[2])
528     | (reg(ic->arg[1]) & 0xffff); }
529     X(mask_imm) { reg(ic->arg[0]) = reg(ic->arg[1]) & ic->arg[2]; }
530     X(addu_imm) { reg(ic->arg[0]) = reg(ic->arg[1]) + ic->arg[2]; }
531     X(subu_imm) { reg(ic->arg[0]) = reg(ic->arg[1]) - ic->arg[2]; }
532     X(inc_reg) { reg(ic->arg[0]) ++; }
533     X(dec_reg) { reg(ic->arg[0]) --; }
534     X(mulu_imm)
535 dpavlin 40 {
536 dpavlin 42 if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
537     SYNCH_PC;
538     m88k_exception(cpu, M88K_EXCEPTION_SFU1_PRECISE, 0);
539     } else
540     reg(ic->arg[0]) = reg(ic->arg[1]) * ic->arg[2];
541 dpavlin 40 }
542 dpavlin 42 X(divu_imm)
543 dpavlin 40 {
544 dpavlin 42 if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
545     SYNCH_PC;
546     m88k_exception(cpu, M88K_EXCEPTION_SFU1_PRECISE, 0);
547     } else if (ic->arg[2] == 0) {
548     SYNCH_PC;
549     m88k_exception(cpu, M88K_EXCEPTION_ILLEGAL_INTEGER_DIVIDE, 0);
550     } else
551     reg(ic->arg[0]) = (uint32_t) reg(ic->arg[1]) / ic->arg[2];
552 dpavlin 40 }
553 dpavlin 42 X(div_imm)
554     {
555     if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
556     SYNCH_PC;
557     m88k_exception(cpu, M88K_EXCEPTION_SFU1_PRECISE, 0);
558     } else if (ic->arg[2] == 0) {
559     SYNCH_PC;
560     m88k_exception(cpu, M88K_EXCEPTION_ILLEGAL_INTEGER_DIVIDE, 0);
561     } else
562     reg(ic->arg[0]) = (int32_t) reg(ic->arg[1]) / ic->arg[2];
563     }
564     X(sub_imm)
565     {
566     int32_t a = reg(ic->arg[1]);
567     int32_t b = ic->arg[2];
568     int32_t res = a - b;
569 dpavlin 40
570 dpavlin 42 if (a < 0 && res >= 0) {
571     SYNCH_PC;
572     m88k_exception(cpu, M88K_EXCEPTION_INTEGER_OVERFLOW, 0);
573     return;
574     }
575 dpavlin 40
576 dpavlin 42 reg(ic->arg[0]) = res;
577     }
578    
579    
580     /*
581     * or: d = s1 | s2
582     * or_c: d = s1 | ~s2
583     * or_r0: d = s2
584     * xor: d = s1 ^ s2
585     * xor_c: d = s1 ^ ~s2
586     * and: d = s1 & s2
587     * and_c: d = s1 & ~s2
588     * addu: d = s1 + s2
589     * addu_co: d = s1 + s2 carry out
590     * addu_ci: d = s1 + s2 + carry carry in
591     * lda_reg_X: same as addu, but s2 is scaled by 2, 4, or 8
592     * subu: d = s1 - s2
593     * subu_co: d = s1 - s2 carry/borrow out
594     * subu_ci: d = s1 - s2 - (carry? 0 : 1) carry in
595     * mul: d = s1 * s2
596     * divu: d = s1 / s2 (unsigned)
597     * div: d = s1 / s2 (signed)
598     *
599     * arg[0] = pointer to register d
600     * arg[1] = pointer to register s1
601     * arg[2] = pointer to register s2
602     */
603     X(or) { reg(ic->arg[0]) = reg(ic->arg[1]) | reg(ic->arg[2]); }
604     X(or_c) { reg(ic->arg[0]) = reg(ic->arg[1]) | ~(reg(ic->arg[2])); }
605     X(or_r0){ reg(ic->arg[0]) = reg(ic->arg[2]); }
606     X(xor) { reg(ic->arg[0]) = reg(ic->arg[1]) ^ reg(ic->arg[2]); }
607     X(xor_c){ reg(ic->arg[0]) = reg(ic->arg[1]) ^ ~(reg(ic->arg[2])); }
608     X(and) { reg(ic->arg[0]) = reg(ic->arg[1]) & reg(ic->arg[2]); }
609     X(and_c){ reg(ic->arg[0]) = reg(ic->arg[1]) & ~(reg(ic->arg[2])); }
610     X(addu) { reg(ic->arg[0]) = reg(ic->arg[1]) + reg(ic->arg[2]); }
611     X(addu_s2r0) { reg(ic->arg[0]) = reg(ic->arg[1]); }
612     X(lda_reg_2) { reg(ic->arg[0]) = reg(ic->arg[1]) + reg(ic->arg[2]) * 2; }
613     X(lda_reg_4) { reg(ic->arg[0]) = reg(ic->arg[1]) + reg(ic->arg[2]) * 4; }
614     X(lda_reg_8) { reg(ic->arg[0]) = reg(ic->arg[1]) + reg(ic->arg[2]) * 8; }
615     X(subu) { reg(ic->arg[0]) = reg(ic->arg[1]) - reg(ic->arg[2]); }
616     X(mul)
617     {
618     if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
619     SYNCH_PC;
620     m88k_exception(cpu, M88K_EXCEPTION_SFU1_PRECISE, 0);
621     } else
622     reg(ic->arg[0]) = reg(ic->arg[1]) * reg(ic->arg[2]);
623     }
624     X(divu)
625     {
626     if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
627     SYNCH_PC;
628     m88k_exception(cpu, M88K_EXCEPTION_SFU1_PRECISE, 0);
629     } else if (reg(ic->arg[2]) == 0) {
630     SYNCH_PC;
631     m88k_exception(cpu, M88K_EXCEPTION_ILLEGAL_INTEGER_DIVIDE, 0);
632     } else
633     reg(ic->arg[0]) = (uint32_t) reg(ic->arg[1]) / reg(ic->arg[2]);
634     }
635     X(div)
636     {
637     if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
638     SYNCH_PC;
639     m88k_exception(cpu, M88K_EXCEPTION_SFU1_PRECISE, 0);
640     } else if (reg(ic->arg[2]) == 0) {
641     SYNCH_PC;
642     m88k_exception(cpu, M88K_EXCEPTION_ILLEGAL_INTEGER_DIVIDE, 0);
643     } else
644     reg(ic->arg[0]) = (int32_t) reg(ic->arg[1]) / reg(ic->arg[2]);
645     }
646     X(addu_co)
647     {
648     uint64_t a = reg(ic->arg[1]), b = reg(ic->arg[2]);
649     a += b;
650     reg(ic->arg[0]) = a;
651     cpu->cd.m88k.cr[M88K_CR_PSR] &= ~M88K_PSR_C;
652     if ((a >> 32) & 1)
653     cpu->cd.m88k.cr[M88K_CR_PSR] |= M88K_PSR_C;
654     }
655     X(addu_ci)
656     {
657     uint32_t result = reg(ic->arg[1]) + reg(ic->arg[2]);
658     if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_C)
659     result ++;
660     reg(ic->arg[0]) = result;
661     }
662     X(subu_co)
663     {
664     uint64_t a = reg(ic->arg[1]), b = reg(ic->arg[2]);
665     a -= b;
666     reg(ic->arg[0]) = a;
667     cpu->cd.m88k.cr[M88K_CR_PSR] |= M88K_PSR_C;
668     if ((a >> 32) & 1)
669     cpu->cd.m88k.cr[M88K_CR_PSR] &= ~M88K_PSR_C;
670     }
671     X(subu_ci)
672     {
673     uint32_t result = reg(ic->arg[1]) - reg(ic->arg[2]);
674     if (!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_C))
675     result --;
676     reg(ic->arg[0]) = result;
677     }
678    
679    
680     /*
681     * ldcr: Load value from a control register, store in register d.
682     * fldcr: Load value from a floating point control register, store in reg d.
683     *
684     * arg[0] = pointer to register d
685     * arg[1] = 6-bit control register number
686     */
687     X(ldcr)
688     {
689     SYNCH_PC;
690    
691     if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE)
692     m88k_ldcr(cpu, (uint32_t *) (void *) ic->arg[0], ic->arg[1]);
693     else
694     m88k_exception(cpu, M88K_EXCEPTION_PRIVILEGE_VIOLATION, 0);
695     }
696     X(fldcr)
697     {
698     SYNCH_PC;
699    
700     if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE || ic->arg[1] >= 62)
701     reg(ic->arg[0]) = cpu->cd.m88k.fcr[ic->arg[1]];
702     else {
703     /* TODO: The manual says "floating point privilege
704     violation", not just "privilege violation"! */
705     m88k_exception(cpu, M88K_EXCEPTION_PRIVILEGE_VIOLATION, 0);
706     }
707     }
708    
709    
710     /*
711     * stcr: Store a value into a control register.
712     * fstcr: Store a value into a floating point control register.
713     *
714     * arg[0] = pointer to source register
715     * arg[1] = 6-bit control register number
716     */
717     X(stcr)
718     {
719     SYNCH_PC;
720    
721     if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE)
722     m88k_stcr(cpu, reg(ic->arg[0]), ic->arg[1], 0);
723     else
724     m88k_exception(cpu, M88K_EXCEPTION_PRIVILEGE_VIOLATION, 0);
725     }
726     X(fstcr)
727     {
728     SYNCH_PC;
729    
730     if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE || ic->arg[1] >= 62)
731     m88k_fstcr(cpu, reg(ic->arg[0]), ic->arg[1]);
732     else {
733     /* TODO: The manual says "floating point privilege
734     violation", not just "privilege violation"! */
735     m88k_exception(cpu, M88K_EXCEPTION_PRIVILEGE_VIOLATION, 0);
736     }
737     }
738    
739    
740     /*
741     * xcr: Exchange (load + store) control register.
742     *
743     * arg[0] = pointer to register d
744     * arg[1] = pointer to register s1
745     * arg[2] = 6-bit control register number
746     */
747     X(xcr)
748     {
749     uint32_t tmp, tmp2;
750     SYNCH_PC;
751    
752     if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE) {
753     tmp = reg(ic->arg[1]);
754     m88k_ldcr(cpu, &tmp2, ic->arg[2]);
755     m88k_stcr(cpu, tmp, ic->arg[2], 0);
756     reg(ic->arg[0]) = tmp2;
757     } else
758     m88k_exception(cpu, M88K_EXCEPTION_PRIVILEGE_VIOLATION, 0);
759     }
760    
761    
762     /*
763     * rte: Return from exception
764     */
765     X(rte)
766     {
767     /* If executed from user mode, then cause an exception: */
768     if (!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE)) {
769     SYNCH_PC;
770     m88k_exception(cpu, M88K_EXCEPTION_PRIVILEGE_VIOLATION, 0);
771     return;
772     }
773    
774     m88k_stcr(cpu, cpu->cd.m88k.cr[M88K_CR_EPSR], M88K_CR_PSR, 1);
775    
776     /* First try the NIP, if it is Valid: */
777 dpavlin 44 cpu->pc = cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_ADDR;
778     if (cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_E) {
779     fatal("rte: NIP: TODO: single-step support\n");
780     goto abort_dump;
781 dpavlin 42 }
782    
783     if (cpu->cd.m88k.cr[M88K_CR_SFIP] & M88K_FIP_E) {
784     fatal("rte: TODO: FIP single-step support\n");
785     goto abort_dump;
786     }
787    
788 dpavlin 44 if ((cpu->cd.m88k.cr[M88K_CR_SFIP] & M88K_FIP_ADDR)
789     == (cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_ADDR)) {
790     cpu->cd.m88k.cr[M88K_CR_SFIP] = cpu->pc + 4;
791     }
792    
793     if ((cpu->cd.m88k.cr[M88K_CR_SFIP] & M88K_FIP_ADDR)
794 dpavlin 42 != (cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_ADDR) + 4) {
795     /*
796     * The NIP instruction should first be executed (this
797     * is the one the exception handler choose to return to),
798     * and then the FIP instruction should run (the target
799     * of a delayed branch).
800     */
801    
802     fatal("FIP != NIP + 4: TODO\n");
803     goto abort_dump;
804     }
805    
806     quick_pc_to_pointers(cpu);
807     return;
808    
809     abort_dump:
810     fatal("NIP=0x%08"PRIx32", FIP=0x%08"PRIx32"\n",
811     cpu->cd.m88k.cr[M88K_CR_SNIP], cpu->cd.m88k.cr[M88K_CR_SFIP]);
812     exit(1);
813     }
814    
815    
816     /*
817     * xmem_slow: Unoptimized xmem (exchange register with memory)
818     *
819     * arg[0] = copy of the instruction word
820     */
821     X(xmem_slow)
822     {
823     uint32_t iword = ic->arg[0], addr;
824     uint8_t tmp[4];
825     uint8_t data[4];
826     int d = (iword >> 21) & 0x1f;
827     int s1 = (iword >> 16) & 0x1f;
828     int s2 = iword & 0x1f;
829     int imm16 = iword & 0xffff;
830     int scaled = iword & 0x200;
831     int size = iword & 0x400;
832     int user = iword & 0x80;
833    
834     SYNCH_PC;
835    
836     if (user) {
837     fatal("xmem_slow: user: not yet (TODO)\n");
838     exit(1);
839     }
840    
841     if ((iword & 0xf0000000) == 0) {
842     /* immediate offset: */
843     addr = imm16;
844     scaled = 0;
845     size = (iword >> 26) & 1;
846     user = 0;
847     } else {
848     /* register offset: */
849     addr = cpu->cd.m88k.r[s2];
850     if (scaled && size)
851     addr *= sizeof(uint32_t);
852     }
853    
854     addr += cpu->cd.m88k.r[s1];
855    
856     if (size) {
857     uint32_t x = cpu->cd.m88k.r[d];
858     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
859     x = LE32_TO_HOST(x);
860     else
861     x = BE32_TO_HOST(x);
862     *((uint32_t *)&tmp[0]) = x;
863    
864     if (addr & 3) {
865     m88k_exception(cpu,
866     M88K_EXCEPTION_MISALIGNED_ACCESS, 0);
867     return;
868     }
869     } else
870     tmp[0] = cpu->cd.m88k.r[d];
871    
872     if (!cpu->memory_rw(cpu, cpu->mem, addr, (uint8_t *) &data,
873     size? 4 : 1, MEM_READ, CACHE_DATA)) {
874     /* Exception. */
875    
876     fatal("XMEM exception: TODO: update the transaction"
877     " registers!\n");
878     exit(1);
879     /* return; */
880     }
881    
882     if (!cpu->memory_rw(cpu, cpu->mem, addr, (uint8_t *) &tmp,
883     size? 4 : 1, MEM_WRITE, CACHE_DATA)) {
884     /* Exception. */
885    
886     fatal("XMEM exception: TODO: update the transaction"
887     " registers!\n");
888     exit(1);
889     /* return; */
890     }
891    
892     if (size) {
893     uint32_t x = *((uint32_t *)&data[0]);
894     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
895     x = LE32_TO_HOST(x);
896     else
897     x = BE32_TO_HOST(x);
898     cpu->cd.m88k.r[d] = x;
899     } else
900     cpu->cd.m88k.r[d] = data[0];
901     }
902    
903    
904     /*
905     * prom-call:
906     */
907     X(prom_call)
908     {
909     /* If executed from user mode, then cause an exception: */
910     if (!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE)) {
911     SYNCH_PC;
912     m88k_exception(cpu, M88K_EXCEPTION_UNIMPLEMENTED_OPCODE, 0);
913     return;
914     }
915    
916     switch (cpu->machine->machine_type) {
917     case MACHINE_MVME88K:
918     mvmeprom_emul(cpu);
919     break;
920     default:fatal("m88k prom_call: unimplemented machine type\n");
921     exit(1);
922     }
923    
924     if (!cpu->running) {
925     cpu->n_translated_instrs --;
926     cpu->cd.m88k.next_ic = &nothing_call;
927     }
928     }
929    
930    
931     /*
932     * tb0, tb1: Trap on bit Clear/Set
933     *
934     * arg[0] = bitmask to check (e.g. 0x00020000 for bit 17)
935     * arg[1] = pointer to register s1
936     * arg[2] = 9-bit vector number
937     */
938     X(tb0)
939     {
940     SYNCH_PC;
941    
942     if (!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE)
943     && ic->arg[2] < M88K_EXCEPTION_USER_TRAPS_START) {
944     m88k_exception(cpu, M88K_EXCEPTION_PRIVILEGE_VIOLATION, 0);
945     return;
946     }
947    
948     if (!(reg(ic->arg[1]) & ic->arg[0]))
949     m88k_exception(cpu, ic->arg[2], 1);
950     }
951     X(tb1)
952     {
953     SYNCH_PC;
954    
955     if (!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE)
956     && ic->arg[2] < M88K_EXCEPTION_USER_TRAPS_START) {
957     m88k_exception(cpu, M88K_EXCEPTION_PRIVILEGE_VIOLATION, 0);
958     return;
959     }
960    
961     if (reg(ic->arg[1]) & ic->arg[0])
962     m88k_exception(cpu, ic->arg[2], 1);
963     }
964    
965    
966 dpavlin 40 /*****************************************************************************/
967    
968    
969     X(end_of_page)
970     {
971     /* Update the PC: (offset 0, but on the next page) */
972     cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1) <<
973     M88K_INSTR_ALIGNMENT_SHIFT);
974     cpu->pc += (M88K_IC_ENTRIES_PER_PAGE << M88K_INSTR_ALIGNMENT_SHIFT);
975    
976     /* end_of_page doesn't count as an executed instruction: */
977     cpu->n_translated_instrs --;
978    
979     /*
980     * Find the new physpage and update translation pointers.
981     *
982     * Note: This may cause an exception, if e.g. the new page is
983     * not accessible.
984     */
985     quick_pc_to_pointers(cpu);
986    
987     /* Simple jump to the next page (if we are lucky): */
988     if (cpu->delay_slot == NOT_DELAYED)
989     return;
990    
991     /*
992     * If we were in a delay slot, and we got an exception while doing
993     * quick_pc_to_pointers, then return. The function which called
994     * end_of_page should handle this case.
995     */
996     if (cpu->delay_slot == EXCEPTION_IN_DELAY_SLOT)
997     return;
998    
999     /*
1000     * Tricky situation; the delay slot is on the next virtual page.
1001     * Calling to_be_translated will translate one instruction manually,
1002     * execute it, and then discard it.
1003     */
1004     /* fatal("[ end_of_page: delay slot across page boundary! ]\n"); */
1005    
1006     instr(to_be_translated)(cpu, cpu->cd.m88k.next_ic);
1007    
1008     /* The instruction in the delay slot has now executed. */
1009     /* fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
1010     cpu->delay_slot); */
1011    
1012     /* Find the physpage etc of the instruction in the delay slot
1013     (or, if there was an exception, the exception handler): */
1014     quick_pc_to_pointers(cpu);
1015     }
1016    
1017    
1018     X(end_of_page2)
1019     {
1020     /* Synchronize PC on the _second_ instruction on the next page: */
1021     int low_pc = ((size_t)ic - (size_t)cpu->cd.m88k.cur_ic_page)
1022     / sizeof(struct m88k_instr_call);
1023     cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1)
1024     << M88K_INSTR_ALIGNMENT_SHIFT);
1025     cpu->pc += (low_pc << M88K_INSTR_ALIGNMENT_SHIFT);
1026    
1027 dpavlin 44 if (low_pc < 0 || low_pc > ((M88K_IC_ENTRIES_PER_PAGE+1)
1028     << M88K_INSTR_ALIGNMENT_SHIFT)) {
1029     printf("[ end_of_page2: HUH? low_pc=%i, cpu->pc = %08"
1030     PRIx32" ]\n", low_pc, (uint32_t) cpu->pc);
1031     }
1032    
1033 dpavlin 40 /* This doesn't count as an executed instruction. */
1034     cpu->n_translated_instrs --;
1035    
1036     quick_pc_to_pointers(cpu);
1037    
1038     if (cpu->delay_slot == NOT_DELAYED)
1039     return;
1040    
1041     fatal("end_of_page2: fatal error, we're in a delay slot\n");
1042     exit(1);
1043     }
1044    
1045    
1046     /*****************************************************************************/
1047    
1048    
1049     /*
1050     * m88k_instr_to_be_translated():
1051     *
1052     * Translate an instruction word into a m88k_instr_call. ic is filled in with
1053     * valid data for the translated instruction, or a "nothing" instruction if
1054     * there was a translation failure. The newly translated instruction is then
1055     * executed.
1056     */
1057     X(to_be_translated)
1058     {
1059     uint32_t addr, low_pc, iword;
1060     unsigned char *page;
1061     unsigned char ib[4];
1062 dpavlin 42 uint32_t op26, op10, d, s1, s2, cr6, imm16;
1063 dpavlin 40 int32_t d16, d26, simm16;
1064     int offset, shift;
1065     int in_crosspage_delayslot = 0;
1066 dpavlin 42 void (*samepage_function)(struct cpu *, struct m88k_instr_call *)=NULL;
1067 dpavlin 40
1068     /* Figure out the (virtual) address of the instruction: */
1069     low_pc = ((size_t)ic - (size_t)cpu->cd.m88k.cur_ic_page)
1070     / sizeof(struct m88k_instr_call);
1071    
1072     /* Special case for branch with delayslot on the next page: */
1073     if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
1074     /* fatal("[ delay-slot translation across page "
1075     "boundary ]\n"); */
1076     in_crosspage_delayslot = 1;
1077     }
1078    
1079     addr = cpu->pc & ~((M88K_IC_ENTRIES_PER_PAGE-1)
1080     << M88K_INSTR_ALIGNMENT_SHIFT);
1081     addr += (low_pc << M88K_INSTR_ALIGNMENT_SHIFT);
1082     cpu->pc = (MODE_int_t)addr;
1083     addr &= ~((1 << M88K_INSTR_ALIGNMENT_SHIFT) - 1);
1084    
1085     /* Read the instruction word from memory: */
1086     page = cpu->cd.m88k.host_load[(uint32_t)addr >> 12];
1087    
1088     if (page != NULL) {
1089     /* fatal("TRANSLATION HIT!\n"); */
1090     memcpy(ib, page + (addr & 0xffc), sizeof(ib));
1091     } else {
1092     /* fatal("TRANSLATION MISS!\n"); */
1093     if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
1094     sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
1095     fatal("to_be_translated(): read failed: TODO\n");
1096     goto bad;
1097     }
1098     }
1099    
1100     iword = *((uint32_t *)&ib[0]);
1101     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1102     iword = LE32_TO_HOST(iword);
1103     else
1104     iword = BE32_TO_HOST(iword);
1105    
1106    
1107     #define DYNTRANS_TO_BE_TRANSLATED_HEAD
1108     #include "cpu_dyntrans.c"
1109     #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
1110    
1111    
1112     /*
1113     * Translate the instruction:
1114     *
1115     * NOTE: _NEVER_ allow writes to the zero register; all instructions
1116     * that use the zero register as their destination should be treated
1117     * as NOPs, except those that access memory (they should use the
1118     * scratch register instead).
1119     */
1120 dpavlin 42 if (cpu->cd.m88k.r[M88K_ZERO_REG] != 0) {
1121     fatal("INTERNAL ERROR! M88K_ZERO_REG != 0?\n");
1122     exit(1);
1123     }
1124 dpavlin 40
1125     op26 = (iword >> 26) & 0x3f;
1126     op10 = (iword >> 10) & 0x3f;
1127     d = (iword >> 21) & 0x1f;
1128     s1 = (iword >> 16) & 0x1f;
1129     s2 = iword & 0x1f;
1130     imm16 = iword & 0xffff;
1131     simm16 = (int16_t) (iword & 0xffff);
1132 dpavlin 42 cr6 = (iword >> 5) & 0x3f;
1133 dpavlin 40 d16 = ((int16_t) (iword & 0xffff)) * 4;
1134     d26 = ((int32_t)((iword & 0x03ffffff) << 6)) >> 4;
1135    
1136     switch (op26) {
1137    
1138 dpavlin 42 case 0x00:
1139     case 0x01:
1140     ic->f = instr(xmem_slow);
1141     ic->arg[0] = iword;
1142     if (d == M88K_ZERO_REG)
1143     ic->f = instr(nop);
1144     if (iword == 0)
1145     goto bad;
1146     break;
1147    
1148     case 0x02: /* ld.hu */
1149     case 0x03: /* ld.bu */
1150     case 0x04: /* ld.d */
1151     case 0x05: /* ld */
1152     case 0x06: /* ld.h */
1153     case 0x07: /* ld.b */
1154     case 0x08: /* st.d */
1155     case 0x09: /* st */
1156     case 0x0a: /* st.h */
1157     case 0x0b: /* st.b */
1158     {
1159     int store = 0, signedness = 0, opsize = 0;
1160    
1161     ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
1162     ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
1163     ic->arg[2] = imm16;
1164    
1165     switch (op26) {
1166     case 0x02: opsize = 1; break;
1167     case 0x03: opsize = 0; break;
1168     case 0x04: opsize = 3; break;
1169     case 0x05: opsize = 2; break;
1170     case 0x06: opsize = 1; signedness = 1; break;
1171     case 0x07: opsize = 0; signedness = 1; break;
1172     case 0x08: store = 1; opsize = 3; break;
1173     case 0x09: store = 1; opsize = 2; break;
1174     case 0x0a: store = 1; opsize = 1; break;
1175     case 0x0b: store = 1; opsize = 0; break;
1176     }
1177    
1178     if (opsize == 3 && d == 31) {
1179     fatal("m88k load/store of register pair r31/r0"
1180     " is not yet implemented\n");
1181     goto bad;
1182     }
1183    
1184     ic->f = m88k_loadstore[ opsize
1185     + (store? M88K_LOADSTORE_STORE : 0)
1186     + (signedness? M88K_LOADSTORE_SIGNEDNESS:0)
1187     + (cpu->byte_order == EMUL_BIG_ENDIAN?
1188     M88K_LOADSTORE_ENDIANNESS : 0) ];
1189     }
1190     break;
1191    
1192     case 0x10: /* and imm */
1193     case 0x11: /* and.u imm */
1194     case 0x12: /* mask imm */
1195     case 0x13: /* mask.u imm */
1196     case 0x14: /* xor imm */
1197     case 0x15: /* xor.u imm */
1198     case 0x16: /* or imm */
1199     case 0x17: /* or.u imm */
1200     case 0x18: /* addu imm */
1201     case 0x19: /* subu imm */
1202     case 0x1a: /* divu imm */
1203     case 0x1b: /* mulu imm */
1204     case 0x1d: /* sub imm */
1205     case 0x1e: /* div imm */
1206     case 0x1f: /* cmp imm */
1207 dpavlin 40 shift = 0;
1208     switch (op26) {
1209 dpavlin 42 case 0x10: ic->f = instr(and_imm); break;
1210     case 0x11: ic->f = instr(and_u_imm); shift = 16; break;
1211     case 0x12: ic->f = instr(mask_imm); break;
1212     case 0x13: ic->f = instr(mask_imm); shift = 16; break;
1213     case 0x14: ic->f = instr(xor_imm); break;
1214     case 0x15: ic->f = instr(xor_imm); shift = 16; break;
1215 dpavlin 40 case 0x16: ic->f = instr(or_imm); break;
1216     case 0x17: ic->f = instr(or_imm); shift = 16; break;
1217 dpavlin 42 case 0x18: ic->f = instr(addu_imm); break;
1218     case 0x19: ic->f = instr(subu_imm); break;
1219     case 0x1a: ic->f = instr(divu_imm); break;
1220     case 0x1b: ic->f = instr(mulu_imm); break;
1221     case 0x1d: ic->f = instr(sub_imm); break;
1222     case 0x1e: ic->f = instr(div_imm); break;
1223     case 0x1f: ic->f = instr(cmp_imm); break;
1224 dpavlin 40 }
1225    
1226     ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
1227     ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
1228     ic->arg[2] = imm16 << shift;
1229    
1230 dpavlin 42 /* Optimization for or d,r0,imm and similar */
1231     if (s1 == M88K_ZERO_REG && ic->f == instr(or_imm)) {
1232     if (ic->arg[2] == 0)
1233     ic->f = instr(or_r0_imm0);
1234     else
1235     ic->f = instr(or_r0_imm);
1236     }
1237     if (ic->arg[2] == 0 && ic->f == instr(addu_imm))
1238     ic->f = instr(addu_s2r0);
1239 dpavlin 40
1240 dpavlin 42 if (d == s1 && ic->arg[2] == 1) {
1241     if (ic->f == instr(addu_imm))
1242     ic->f = instr(inc_reg);
1243     if (ic->f == instr(subu_imm))
1244     ic->f = instr(dec_reg);
1245     }
1246    
1247 dpavlin 40 if (d == M88K_ZERO_REG)
1248     ic->f = instr(nop);
1249     break;
1250    
1251 dpavlin 42 case 0x20:
1252     if ((iword & 0x001ff81f) == 0x00004000) {
1253     ic->f = instr(ldcr);
1254     ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
1255     ic->arg[1] = cr6;
1256     if (d == M88K_ZERO_REG)
1257     ic->arg[0] = (size_t)
1258     &cpu->cd.m88k.zero_scratch;
1259     } else if ((iword & 0x001ff81f) == 0x00004800) {
1260     ic->f = instr(fldcr);
1261     ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
1262     ic->arg[1] = cr6;
1263     if (d == M88K_ZERO_REG)
1264     ic->arg[0] = (size_t)
1265     &cpu->cd.m88k.zero_scratch;
1266     } else if ((iword & 0x03e0f800) == 0x00008000) {
1267     ic->f = instr(stcr);
1268     ic->arg[0] = (size_t) &cpu->cd.m88k.r[s1];
1269     ic->arg[1] = cr6;
1270     if (s1 != s2)
1271     goto bad;
1272     } else if ((iword & 0x03e0f800) == 0x00008800) {
1273     ic->f = instr(fstcr);
1274     ic->arg[0] = (size_t) &cpu->cd.m88k.r[s1];
1275     ic->arg[1] = cr6;
1276     if (s1 != s2)
1277     goto bad;
1278     } else if ((iword & 0x0000f800) == 0x0000c000) {
1279     ic->f = instr(xcr);
1280     ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
1281     ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
1282     ic->arg[2] = cr6;
1283     if (s1 != s2)
1284     goto bad;
1285     } else
1286     goto bad;
1287     break;
1288 dpavlin 40
1289 dpavlin 42 case 0x30: /* br */
1290     case 0x31: /* br.n */
1291     case 0x32: /* bsr */
1292     case 0x33: /* bsr.n */
1293     switch (op26) {
1294     case 0x30:
1295     ic->f = instr(br);
1296     samepage_function = instr(br_samepage);
1297     if (cpu->translation_readahead > 1)
1298     cpu->translation_readahead = 1;
1299     break;
1300     case 0x31:
1301     ic->f = instr(br_n);
1302     if (cpu->translation_readahead > 2)
1303     cpu->translation_readahead = 2;
1304     break;
1305     case 0x32:
1306     ic->f = instr(bsr);
1307     samepage_function = instr(bsr_samepage);
1308     break;
1309     case 0x33:
1310     ic->f = instr(bsr_n);
1311     break;
1312     }
1313    
1314 dpavlin 40 offset = (addr & 0xffc) + d26;
1315 dpavlin 42
1316     /* Prepare both samepage and offset style args.
1317     (Only one will be used in the actual instruction.) */
1318     ic->arg[0] = (size_t) ( cpu->cd.m88k.cur_ic_page +
1319     (offset >> M88K_INSTR_ALIGNMENT_SHIFT) );
1320     ic->arg[1] = offset;
1321 dpavlin 44 ic->arg[2] = (addr & 0xffc) + 4; /* Return offset
1322     for bsr_samepage */
1323 dpavlin 42
1324     if (offset >= 0 && offset <= 0xffc &&
1325     samepage_function != NULL)
1326     ic->f = samepage_function;
1327    
1328     if (cpu->machine->show_trace_tree) {
1329     if (op26 == 0x32)
1330     ic->f = instr(bsr_trace);
1331     if (op26 == 0x33)
1332     ic->f = instr(bsr_n_trace);
1333     }
1334    
1335     break;
1336    
1337     case 0x34: /* bb0 */
1338     case 0x35: /* bb0.n */
1339     case 0x36: /* bb1 */
1340     case 0x37: /* bb1.n */
1341     switch (op26) {
1342     case 0x34:
1343     ic->f = instr(bb0);
1344     samepage_function = instr(bb0_samepage);
1345     break;
1346     case 0x35:
1347     ic->f = instr(bb0_n);
1348     break;
1349     case 0x36:
1350     ic->f = instr(bb1);
1351     samepage_function = instr(bb1_samepage);
1352     break;
1353     case 0x37:
1354     ic->f = instr(bb1_n);
1355     break;
1356     }
1357    
1358     ic->arg[0] = (size_t) &cpu->cd.m88k.r[s1];
1359     ic->arg[1] = (uint32_t) (1 << d);
1360    
1361     offset = (addr & 0xffc) + d16;
1362     ic->arg[2] = offset;
1363    
1364     if (offset >= 0 && offset <= 0xffc &&
1365     samepage_function != NULL) {
1366     ic->f = samepage_function;
1367     ic->arg[2] = (size_t) ( cpu->cd.m88k.cur_ic_page +
1368 dpavlin 40 (offset >> M88K_INSTR_ALIGNMENT_SHIFT) );
1369 dpavlin 42 }
1370     break;
1371    
1372     case 0x3a: /* bcnd */
1373     case 0x3b: /* bcnd.n */
1374     ic->f = m88k_bcnd[d + 32 * (op26 & 1)];
1375     samepage_function = m88k_bcnd[64 + d + 32 * (op26 & 1)];
1376    
1377     if (ic->f == NULL)
1378     goto bad;
1379    
1380     ic->arg[0] = (size_t) &cpu->cd.m88k.r[s1];
1381    
1382     offset = (addr & 0xffc) + d16;
1383     ic->arg[2] = offset;
1384    
1385     if (offset >= 0 && offset <= 0xffc &&
1386     samepage_function != NULL) {
1387 dpavlin 40 ic->f = samepage_function;
1388 dpavlin 42 ic->arg[2] = (size_t) ( cpu->cd.m88k.cur_ic_page +
1389     (offset >> M88K_INSTR_ALIGNMENT_SHIFT) );
1390 dpavlin 40 }
1391     break;
1392    
1393 dpavlin 42 case 0x3c:
1394     switch (op10) {
1395    
1396     case 0x20: /* clr */
1397     case 0x22: /* set */
1398     case 0x24: /* ext */
1399     case 0x26: /* extu */
1400     case 0x28: /* mak */
1401     ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
1402     ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
1403     ic->arg[2] = iword & 0x3ff;
1404    
1405     switch (op10) {
1406     case 0x20: ic->f = instr(mask_imm);
1407     {
1408     int w = ic->arg[2] >> 5;
1409     int o = ic->arg[2] & 0x1f;
1410     uint32_t x = w == 0? 0xffffffff
1411 dpavlin 44 : ((uint32_t)1 << w) - 1;
1412 dpavlin 42 x <<= o;
1413     ic->arg[2] = ~x;
1414     }
1415     break;
1416     case 0x22: ic->f = instr(or_imm);
1417     {
1418     int w = ic->arg[2] >> 5;
1419     int o = ic->arg[2] & 0x1f;
1420     uint32_t x = w == 0? 0xffffffff
1421 dpavlin 44 : ((uint32_t)1 << w) - 1;
1422 dpavlin 42 x <<= o;
1423     ic->arg[2] = x;
1424     }
1425     break;
1426     case 0x24: ic->f = instr(ext_imm); break;
1427     case 0x26: ic->f = instr(extu_imm); break;
1428     case 0x28: ic->f = instr(mak_imm); break;
1429     }
1430    
1431     if (d == M88K_ZERO_REG)
1432     ic->f = instr(nop);
1433     break;
1434    
1435     case 0x34: /* tb0 */
1436     case 0x36: /* tb1 */
1437     ic->arg[0] = 1 << d;
1438     ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
1439     ic->arg[2] = iword & 0x1ff;
1440     switch (op10) {
1441     case 0x34: ic->f = instr(tb0); break;
1442     case 0x36: ic->f = instr(tb1); break;
1443     }
1444     break;
1445    
1446     default:goto bad;
1447     }
1448     break;
1449    
1450     case 0x3d:
1451     if ((iword & 0xf000) <= 0x3fff ) {
1452     /* Load, Store, xmem, and lda: */
1453     int op = 0, opsize, user = 0, wt = 0;
1454     int signedness = 1, scaled = 0;
1455    
1456     switch (iword & 0xf000) {
1457     case 0x2000: op = 1; /* st */ break;
1458     case 0x3000: op = 2; /* lda */ break;
1459     default: if ((iword & 0xf800) >= 0x0800)
1460     op = 0; /* ld */
1461     else
1462     op = 3; /* xmem */
1463     }
1464    
1465     /* for (most) ld, st, lda: */
1466     opsize = (iword >> 10) & 3;
1467    
1468     /* Turn opsize into x, where size = 1 << x: */
1469     opsize = 3 - opsize;
1470    
1471     if (op == 3) {
1472     /* xmem: */
1473     switch ((iword >> 10) & 3) {
1474     case 0: opsize = 0; break;
1475     case 1: opsize = 2; break;
1476     default:fatal("Weird xmem opsize/type?\n");
1477     goto bad;
1478     }
1479     } else {
1480     if ((iword & 0xf800) == 0x800) {
1481     signedness = 0;
1482     if ((iword & 0xf00) < 0xc00)
1483     opsize = 1;
1484     else
1485     opsize = 0;
1486     } else {
1487     if (opsize >= 2 || op == 1)
1488     signedness = 0;
1489     }
1490     }
1491    
1492     if (iword & 0x100)
1493     user = 1;
1494     if (iword & 0x80)
1495     wt = 1;
1496     if (iword & 0x200)
1497     scaled = 1;
1498    
1499     if (wt) {
1500     fatal("wt bit not yet implemented! TODO\n");
1501     goto bad;
1502     }
1503    
1504     ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
1505     ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
1506     ic->arg[2] = (size_t) &cpu->cd.m88k.r[s2];
1507    
1508     if (op == 0 || op == 1) {
1509     /* ld or st: */
1510     ic->f = m88k_loadstore[ opsize
1511     + (op==1? M88K_LOADSTORE_STORE : 0)
1512     + (signedness? M88K_LOADSTORE_SIGNEDNESS:0)
1513     + (cpu->byte_order == EMUL_BIG_ENDIAN?
1514     M88K_LOADSTORE_ENDIANNESS : 0)
1515     + (scaled? M88K_LOADSTORE_SCALEDNESS : 0)
1516     + (user? M88K_LOADSTORE_USR : 0)
1517     + M88K_LOADSTORE_REGISTEROFFSET ];
1518    
1519     if (op == 0 && d == M88K_ZERO_REG)
1520     ic->f = instr(nop);
1521    
1522     if (opsize == 3 && d == 31) {
1523     fatal("m88k load/store of register "
1524     "pair r31/r0: TODO\n");
1525     goto bad;
1526     }
1527     } else if (op == 2) {
1528     /* lda: */
1529     if (scaled) {
1530     switch (opsize) {
1531     case 0: ic->f = instr(addu); break;
1532     case 1: ic->f = instr(lda_reg_2); break;
1533     case 2: ic->f = instr(lda_reg_4); break;
1534     case 3: ic->f = instr(lda_reg_8); break;
1535     }
1536     } else {
1537     ic->f = instr(addu);
1538     }
1539     } else {
1540     /* xmem: */
1541     ic->f = instr(xmem_slow);
1542     ic->arg[0] = iword;
1543     if (d == M88K_ZERO_REG)
1544     ic->f = instr(nop);
1545     }
1546     } else switch ((iword >> 8) & 0xff) {
1547     case 0x40: /* and */
1548     case 0x44: /* and.c */
1549     case 0x50: /* xor */
1550     case 0x54: /* xor.c */
1551     case 0x58: /* or */
1552     case 0x5c: /* or.c */
1553     case 0x60: /* addu */
1554     case 0x61: /* addu.co */
1555     case 0x62: /* addu.ci */
1556     case 0x64: /* subu */
1557     case 0x65: /* subu.co */
1558     case 0x66: /* subu.ci */
1559     case 0x68: /* divu */
1560     case 0x6c: /* mul */
1561     case 0x78: /* div */
1562     case 0x7c: /* cmp */
1563     case 0x80: /* clr */
1564     case 0x88: /* set */
1565     case 0x90: /* ext */
1566     case 0x98: /* extu */
1567     case 0xa0: /* mak */
1568     ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
1569     ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
1570     ic->arg[2] = (size_t) &cpu->cd.m88k.r[s2];
1571    
1572     switch ((iword >> 8) & 0xff) {
1573     case 0x40: ic->f = instr(and); break;
1574     case 0x44: ic->f = instr(and_c); break;
1575     case 0x50: ic->f = instr(xor); break;
1576     case 0x54: ic->f = instr(xor_c); break;
1577     case 0x58: ic->f = instr(or); break;
1578     case 0x5c: ic->f = instr(or_c); break;
1579     case 0x60: ic->f = instr(addu); break;
1580     case 0x61: ic->f = instr(addu_co); break;
1581     case 0x62: ic->f = instr(addu_ci); break;
1582     case 0x64: ic->f = instr(subu); break;
1583     case 0x65: ic->f = instr(subu_co); break;
1584     case 0x66: ic->f = instr(subu_ci); break;
1585     case 0x68: ic->f = instr(divu); break;
1586     case 0x6c: ic->f = instr(mul); break;
1587     case 0x78: ic->f = instr(div); break;
1588     case 0x7c: ic->f = instr(cmp); break;
1589     case 0x80: ic->f = instr(clr); break;
1590     case 0x88: ic->f = instr(set); break;
1591     case 0x90: ic->f = instr(ext); break;
1592     case 0x98: ic->f = instr(extu); break;
1593     case 0xa0: ic->f = instr(mak); break;
1594     }
1595    
1596     /* Optimization for or rX,r0,rY etc: */
1597     if (s1 == M88K_ZERO_REG && ic->f == instr(or))
1598     ic->f = instr(or_r0);
1599     if (s2 == M88K_ZERO_REG && ic->f == instr(addu))
1600     ic->f = instr(addu_s2r0);
1601     if (d == M88K_ZERO_REG)
1602     ic->f = instr(nop);
1603     break;
1604     case 0xc0: /* jmp */
1605     case 0xc4: /* jmp.n */
1606     case 0xc8: /* jsr */
1607     case 0xcc: /* jsr.n */
1608     switch ((iword >> 8) & 0xff) {
1609     case 0xc0: ic->f = instr(jmp);
1610     if (cpu->translation_readahead > 1)
1611     cpu->translation_readahead = 1;
1612     break;
1613     case 0xc4: ic->f = instr(jmp_n);
1614     if (cpu->translation_readahead > 2)
1615     cpu->translation_readahead = 2;
1616     break;
1617     case 0xc8: ic->f = instr(jsr); break;
1618     case 0xcc: ic->f = instr(jsr_n); break;
1619     }
1620    
1621     ic->arg[1] = (addr & 0xffc) + 4;
1622     ic->arg[2] = (size_t) &cpu->cd.m88k.r[s2];
1623    
1624     if (((iword >> 8) & 0x04) == 0x04)
1625     ic->arg[1] = (addr & 0xffc) + 8;
1626    
1627     if (cpu->machine->show_trace_tree &&
1628     s2 == M88K_RETURN_REG) {
1629     if (ic->f == instr(jmp))
1630     ic->f = instr(jmp_trace);
1631     if (ic->f == instr(jmp_n))
1632     ic->f = instr(jmp_n_trace);
1633     }
1634     if (cpu->machine->show_trace_tree) {
1635     if (ic->f == instr(jsr))
1636     ic->f = instr(jsr_trace);
1637     if (ic->f == instr(jsr_n))
1638     ic->f = instr(jsr_n_trace);
1639     }
1640     break;
1641     case 0xe8: /* ff1 */
1642     case 0xec: /* ff0 */
1643     switch ((iword >> 8) & 0xff) {
1644     case 0xe8: ic->f = instr(ff1); break;
1645     case 0xec: ic->f = instr(ff0); break;
1646     }
1647    
1648     ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
1649     ic->arg[2] = (size_t) &cpu->cd.m88k.r[s2];
1650    
1651     if (d == M88K_ZERO_REG)
1652     ic->f = instr(nop);
1653     break;
1654     case 0xfc:
1655     switch (iword & 0xff) {
1656     case 0x00:
1657     ic->f = instr(rte);
1658     break;
1659     case (M88K_PROM_INSTR & 0xff):
1660     ic->f = instr(prom_call);
1661     break;
1662     default:fatal("Unimplemented 3d/fc instruction\n");
1663     goto bad;
1664     }
1665     break;
1666     default:goto bad;
1667     }
1668     break;
1669    
1670 dpavlin 40 default:goto bad;
1671     }
1672    
1673    
1674     #define DYNTRANS_TO_BE_TRANSLATED_TAIL
1675     #include "cpu_dyntrans.c"
1676     #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
1677     }
1678    

  ViewVC Help
Powered by ViewVC 1.1.26