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

Diff of /trunk/src/cpus/cpu_m88k_instr.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.41  
changed lines
  Added in v.42

  ViewVC Help
Powered by ViewVC 1.1.26