/[gxemul]/trunk/src/cpus/cpu_arm_instr.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

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

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

revision 18 by dpavlin, Mon Oct 8 16:19:11 2007 UTC revision 24 by dpavlin, Mon Oct 8 16:19:56 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2006  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_arm_instr.c,v 1.39 2005/10/27 14:01:13 debug Exp $   *  $Id: cpu_arm_instr.c,v 1.65 2006/06/23 12:49:46 debug Exp $
29   *   *
30   *  ARM instructions.   *  ARM instructions.
31   *   *
# Line 36  Line 36 
36   */   */
37    
38    
 #include "arm_quick_pc_to_pointers.h"  
   
39  /*  #define GATHER_BDT_STATISTICS  */  /*  #define GATHER_BDT_STATISTICS  */
40    
41    
# Line 125  static void update_bdt_statistics(uint32 Line 123  static void update_bdt_statistics(uint32
123   *  functions, otherwise they will simply call the X function.   *  functions, otherwise they will simply call the X function.
124   */   */
125    
126    uint8_t condition_hi[16] = { 0,0,1,1, 0,0,0,0, 0,0,1,1, 0,0,0,0 };
127    uint8_t condition_ge[16] = { 1,0,1,0, 1,0,1,0, 0,1,0,1, 0,1,0,1 };
128    uint8_t condition_gt[16] = { 1,0,1,0, 0,0,0,0, 0,1,0,1, 0,0,0,0 };
129    
130  #define Y(n) void arm_instr_ ## n ## __eq(struct cpu *cpu,              \  #define Y(n) void arm_instr_ ## n ## __eq(struct cpu *cpu,              \
131                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
132          {  if (cpu->cd.arm.cpsr & ARM_FLAG_Z)                           \          {  if (cpu->cd.arm.flags & ARM_F_Z)                             \
133                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
134          void arm_instr_ ## n ## __ne(struct cpu *cpu,                   \          void arm_instr_ ## n ## __ne(struct cpu *cpu,                   \
135                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
136          {  if (!(cpu->cd.arm.cpsr & ARM_FLAG_Z))                        \          {  if (!(cpu->cd.arm.flags & ARM_F_Z))                          \
137                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
138          void arm_instr_ ## n ## __cs(struct cpu *cpu,                   \          void arm_instr_ ## n ## __cs(struct cpu *cpu,                   \
139                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
140          {  if (cpu->cd.arm.cpsr & ARM_FLAG_C)                           \          {  if (cpu->cd.arm.flags & ARM_F_C)                             \
141                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
142          void arm_instr_ ## n ## __cc(struct cpu *cpu,                   \          void arm_instr_ ## n ## __cc(struct cpu *cpu,                   \
143                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
144          {  if (!(cpu->cd.arm.cpsr & ARM_FLAG_C))                        \          {  if (!(cpu->cd.arm.flags & ARM_F_C))                          \
145                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
146          void arm_instr_ ## n ## __mi(struct cpu *cpu,                   \          void arm_instr_ ## n ## __mi(struct cpu *cpu,                   \
147                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
148          {  if (cpu->cd.arm.cpsr & ARM_FLAG_N)                           \          {  if (cpu->cd.arm.flags & ARM_F_N)                             \
149                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
150          void arm_instr_ ## n ## __pl(struct cpu *cpu,                   \          void arm_instr_ ## n ## __pl(struct cpu *cpu,                   \
151                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
152          {  if (!(cpu->cd.arm.cpsr & ARM_FLAG_N))                        \          {  if (!(cpu->cd.arm.flags & ARM_F_N))                          \
153                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
154          void arm_instr_ ## n ## __vs(struct cpu *cpu,                   \          void arm_instr_ ## n ## __vs(struct cpu *cpu,                   \
155                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
156          {  if (cpu->cd.arm.cpsr & ARM_FLAG_V)                           \          {  if (cpu->cd.arm.flags & ARM_F_V)                             \
157                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
158          void arm_instr_ ## n ## __vc(struct cpu *cpu,                   \          void arm_instr_ ## n ## __vc(struct cpu *cpu,                   \
159                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
160          {  if (!(cpu->cd.arm.cpsr & ARM_FLAG_V))                        \          {  if (!(cpu->cd.arm.flags & ARM_F_V))                          \
161                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
162          void arm_instr_ ## n ## __hi(struct cpu *cpu,                   \          void arm_instr_ ## n ## __hi(struct cpu *cpu,                   \
163                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
164          {  if (cpu->cd.arm.cpsr & ARM_FLAG_C &&                         \          {  if (condition_hi[cpu->cd.arm.flags])                         \
                 !(cpu->cd.arm.cpsr & ARM_FLAG_Z))                       \  
165                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
166          void arm_instr_ ## n ## __ls(struct cpu *cpu,                   \          void arm_instr_ ## n ## __ls(struct cpu *cpu,                   \
167                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
168          {  if (cpu->cd.arm.cpsr & ARM_FLAG_Z ||                         \          {  if (!condition_hi[cpu->cd.arm.flags])                        \
                 !(cpu->cd.arm.cpsr & ARM_FLAG_C))                       \  
169                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
170          void arm_instr_ ## n ## __ge(struct cpu *cpu,                   \          void arm_instr_ ## n ## __ge(struct cpu *cpu,                   \
171                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
172          {  if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) ==                 \          {  if (condition_ge[cpu->cd.arm.flags])                         \
                 ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0))                  \  
173                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
174          void arm_instr_ ## n ## __lt(struct cpu *cpu,                   \          void arm_instr_ ## n ## __lt(struct cpu *cpu,                   \
175                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
176          {  if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) !=                 \          {  if (!condition_ge[cpu->cd.arm.flags])                        \
                 ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0))                  \  
177                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
178          void arm_instr_ ## n ## __gt(struct cpu *cpu,                   \          void arm_instr_ ## n ## __gt(struct cpu *cpu,                   \
179                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
180          {  if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) ==                 \          {  if (condition_gt[cpu->cd.arm.flags])                         \
                 ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0) &&                \  
                 !(cpu->cd.arm.cpsr & ARM_FLAG_Z))                       \  
181                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
182          void arm_instr_ ## n ## __le(struct cpu *cpu,                   \          void arm_instr_ ## n ## __le(struct cpu *cpu,                   \
183                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
184          {  if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) !=                 \          {  if (!condition_gt[cpu->cd.arm.flags])                        \
                 ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0) ||                \  
                 (cpu->cd.arm.cpsr & ARM_FLAG_Z))                        \  
185                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
186          void (*arm_cond_instr_ ## n  [16])(struct cpu *,                \          void (*arm_cond_instr_ ## n  [16])(struct cpu *,                \
187                          struct arm_instr_call *) = {                    \                          struct arm_instr_call *) = {                    \
# Line 207  static void update_bdt_statistics(uint32 Line 201  static void update_bdt_statistics(uint32
201    
202    
203  /*  /*
  *  nop:  Do nothing.  
204   *  invalid:  Invalid instructions end up here.   *  invalid:  Invalid instructions end up here.
205   */   */
 X(nop) { }  
206  X(invalid) {  X(invalid) {
207          uint32_t low_pc;          uint32_t low_pc;
208          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
209              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
210          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
211              << ARM_INSTR_ALIGNMENT_SHIFT);              << ARM_INSTR_ALIGNMENT_SHIFT);
212          cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
         cpu->pc = cpu->cd.arm.r[ARM_PC];  
213    
214          fatal("Invalid ARM instruction: pc=0x%08x\n", (int)cpu->pc);          fatal("FATAL ERROR: An internal error occured in the ARM"
215                " dyntrans code. Please contact the author with detailed"
216                " repro steps on how to trigger this bug. pc = 0x%08"PRIx32"\n",
217                (uint32_t)cpu->pc);
218            exit(1);
219    }
220    
221          cpu->running = 0;  
222          cpu->running_translated = 0;  /*
223          cpu->n_translated_instrs --;   *  nop:  Do nothing.
224          cpu->cd.arm.next_ic = &nothing_call;   */
225    X(nop)
226    {
227  }  }
228    
229    
# Line 236  X(invalid) { Line 234  X(invalid) {
234   */   */
235  X(b)  X(b)
236  {  {
237          uint32_t low_pc;          cpu->pc = (uint32_t)((cpu->pc & 0xfffff000) + (int32_t)ic->arg[0]);
   
         /*  Calculate new PC from this instruction + arg[0]  */  
         low_pc = ((size_t)ic - (size_t)  
             cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);  
         cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)  
             << ARM_INSTR_ALIGNMENT_SHIFT);  
         cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);  
         cpu->cd.arm.r[ARM_PC] += (int32_t)ic->arg[0];  
         cpu->pc = cpu->cd.arm.r[ARM_PC];  
238    
239          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
240          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
# Line 257  Y(b) Line 246  Y(b)
246   *  b_samepage:  Branch (to within the same translated page)   *  b_samepage:  Branch (to within the same translated page)
247   *   *
248   *  arg[0] = pointer to new arm_instr_call   *  arg[0] = pointer to new arm_instr_call
249     *  arg[1] = pointer to the next instruction.
250     *
251     *  NOTE: This instruction is manually inlined.
252   */   */
253  X(b_samepage)  X(b_samepage) {
 {  
254          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
255  }  }
256  Y(b_samepage)  X(b_samepage__eq) {
257            cpu->cd.arm.next_ic = (struct arm_instr_call *)
258                ic->arg[cpu->cd.arm.flags & ARM_F_Z? 0 : 1];
259    }
260    X(b_samepage__ne) {
261            cpu->cd.arm.next_ic = (struct arm_instr_call *)
262                ic->arg[cpu->cd.arm.flags & ARM_F_Z? 1 : 0];
263    }
264    X(b_samepage__cs) {
265            cpu->cd.arm.next_ic = (struct arm_instr_call *)
266                ic->arg[cpu->cd.arm.flags & ARM_F_C? 0 : 1];
267    }
268    X(b_samepage__cc) {
269            cpu->cd.arm.next_ic = (struct arm_instr_call *)
270                ic->arg[cpu->cd.arm.flags & ARM_F_C? 1 : 0];
271    }
272    X(b_samepage__mi) {
273            cpu->cd.arm.next_ic = (struct arm_instr_call *)
274                ic->arg[cpu->cd.arm.flags & ARM_F_N? 0 : 1];
275    }
276    X(b_samepage__pl) {
277            cpu->cd.arm.next_ic = (struct arm_instr_call *)
278                ic->arg[cpu->cd.arm.flags & ARM_F_N? 1 : 0];
279    }
280    X(b_samepage__vs) {
281            cpu->cd.arm.next_ic = (struct arm_instr_call *)
282                ic->arg[cpu->cd.arm.flags & ARM_F_V? 0 : 1];
283    }
284    X(b_samepage__vc) {
285            cpu->cd.arm.next_ic = (struct arm_instr_call *)
286                ic->arg[cpu->cd.arm.flags & ARM_F_V? 1 : 0];
287    }
288    X(b_samepage__hi) {
289            cpu->cd.arm.next_ic = (condition_hi[cpu->cd.arm.flags])?
290                (struct arm_instr_call *) ic->arg[0] :
291                (struct arm_instr_call *) ic->arg[1];
292    }
293    X(b_samepage__ls) {
294            cpu->cd.arm.next_ic = (struct arm_instr_call *)
295                ic->arg[condition_hi[cpu->cd.arm.flags]];
296    }
297    X(b_samepage__ge) {
298            cpu->cd.arm.next_ic = (condition_ge[cpu->cd.arm.flags])?
299                (struct arm_instr_call *) ic->arg[0] :
300                (struct arm_instr_call *) ic->arg[1];
301    }
302    X(b_samepage__lt) {
303            cpu->cd.arm.next_ic = (struct arm_instr_call *)
304                ic->arg[condition_ge[cpu->cd.arm.flags]];
305    }
306    X(b_samepage__gt) {
307            cpu->cd.arm.next_ic = (condition_gt[cpu->cd.arm.flags])?
308                (struct arm_instr_call *) ic->arg[0] :
309                (struct arm_instr_call *) ic->arg[1];
310    }
311    X(b_samepage__le) {
312            cpu->cd.arm.next_ic = (struct arm_instr_call *)
313                ic->arg[condition_gt[cpu->cd.arm.flags]];
314    }
315    void (*arm_cond_instr_b_samepage[16])(struct cpu *,
316            struct arm_instr_call *) = {
317            arm_instr_b_samepage__eq, arm_instr_b_samepage__ne,
318            arm_instr_b_samepage__cs, arm_instr_b_samepage__cc,
319            arm_instr_b_samepage__mi, arm_instr_b_samepage__pl,
320            arm_instr_b_samepage__vs, arm_instr_b_samepage__vc,
321            arm_instr_b_samepage__hi, arm_instr_b_samepage__ls,
322            arm_instr_b_samepage__ge, arm_instr_b_samepage__lt,
323            arm_instr_b_samepage__gt, arm_instr_b_samepage__le,
324            arm_instr_b_samepage, arm_instr_nop };
325    
326    
327  /*  /*
# Line 272  Y(b_samepage) Line 331  Y(b_samepage)
331   */   */
332  X(bx)  X(bx)
333  {  {
334          cpu->pc = cpu->cd.arm.r[ARM_PC] = reg(ic->arg[0]);          cpu->pc = reg(ic->arg[0]);
335          if (cpu->pc & 1) {          if (cpu->pc & 1) {
336                  fatal("thumb: TODO\n");                  fatal("thumb: TODO\n");
337                  exit(1);                  exit(1);
# Line 292  Y(bx) Line 351  Y(bx)
351   */   */
352  X(bx_trace)  X(bx_trace)
353  {  {
354          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
355          if (cpu->pc & 1) {          if (cpu->pc & 1) {
356                  fatal("thumb: TODO\n");                  fatal("thumb: TODO\n");
357                  exit(1);                  exit(1);
# Line 314  Y(bx_trace) Line 373  Y(bx_trace)
373   */   */
374  X(bl)  X(bl)
375  {  {
376          uint32_t lr, low_pc;          uint32_t pc = ((uint32_t)cpu->pc & 0xfffff000) + (int32_t)ic->arg[1];
377            cpu->cd.arm.r[ARM_LR] = pc + 4;
         /*  Figure out what the return (link) address will be:  */  
         low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)  
             cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);  
         lr = cpu->cd.arm.r[ARM_PC];  
         lr &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);  
         lr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);  
   
         /*  Link:  */  
         cpu->cd.arm.r[ARM_LR] = lr;  
378    
379          /*  Calculate new PC from this instruction + arg[0]  */          /*  Calculate new PC from this instruction + arg[0]  */
380          cpu->pc = cpu->cd.arm.r[ARM_PC] = lr - 4 + (int32_t)ic->arg[0];          cpu->pc = pc + (int32_t)ic->arg[0];
381    
382          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
383          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
# Line 342  Y(bl) Line 392  Y(bl)
392   */   */
393  X(blx)  X(blx)
394  {  {
395          uint32_t lr, low_pc;          uint32_t lr = ((uint32_t)cpu->pc & 0xfffff000) + (int32_t)ic->arg[2];
   
         /*  Figure out what the return (link) address will be:  */  
         low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)  
             cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);  
         lr = cpu->cd.arm.r[ARM_PC];  
         lr &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);  
         lr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);  
   
         /*  Link:  */  
396          cpu->cd.arm.r[ARM_LR] = lr;          cpu->cd.arm.r[ARM_LR] = lr;
397            cpu->pc = reg(ic->arg[0]);
         cpu->pc = cpu->cd.arm.r[ARM_PC] = reg(ic->arg[0]);  
398          if (cpu->pc & 1) {          if (cpu->pc & 1) {
399                  fatal("thumb: TODO\n");                  fatal("thumb: TODO\n");
400                  exit(1);                  exit(1);
# Line 374  Y(blx) Line 414  Y(blx)
414   */   */
415  X(bl_trace)  X(bl_trace)
416  {  {
417          uint32_t lr, low_pc;          uint32_t pc = ((uint32_t)cpu->pc & 0xfffff000) + (int32_t)ic->arg[1];
418            cpu->cd.arm.r[ARM_LR] = pc + 4;
         /*  Figure out what the return (link) address will be:  */  
         low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)  
             cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);  
         lr = cpu->cd.arm.r[ARM_PC];  
         lr &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);  
         lr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);  
   
         /*  Link:  */  
         cpu->cd.arm.r[ARM_LR] = lr;  
419    
420          /*  Calculate new PC from this instruction + arg[0]  */          /*  Calculate new PC from this instruction + arg[0]  */
421          cpu->pc = cpu->cd.arm.r[ARM_PC] = lr - 4 + (int32_t)ic->arg[0];          cpu->pc = pc + (int32_t)ic->arg[0];
422    
423          cpu_functioncall_trace(cpu, cpu->pc);          cpu_functioncall_trace(cpu, cpu->pc);
424    
# Line 404  Y(bl_trace) Line 435  Y(bl_trace)
435   */   */
436  X(bl_samepage)  X(bl_samepage)
437  {  {
438          uint32_t lr, low_pc;          cpu->cd.arm.r[ARM_LR] =
439                ((uint32_t)cpu->pc & 0xfffff000) + (int32_t)ic->arg[2];
         /*  Figure out what the return (link) address will be:  */  
         low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)  
             cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);  
         lr = cpu->cd.arm.r[ARM_PC];  
         lr &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);  
         lr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);  
   
         /*  Link:  */  
         cpu->cd.arm.r[ARM_LR] = lr;  
   
         /*  Branch:  */  
440          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
441  }  }
442  Y(bl_samepage)  Y(bl_samepage)
# Line 429  Y(bl_samepage) Line 449  Y(bl_samepage)
449   */   */
450  X(bl_samepage_trace)  X(bl_samepage_trace)
451  {  {
452          uint32_t tmp_pc, lr, low_pc;          uint32_t low_pc, lr = (cpu->pc & 0xfffff000) + ic->arg[2];
453    
454          /*  Figure out what the return (link) address will be:  */          /*  Link and branch:  */
         low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)  
             cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);  
         lr = cpu->cd.arm.r[ARM_PC];  
         lr &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);  
         lr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);  
   
         /*  Link:  */  
455          cpu->cd.arm.r[ARM_LR] = lr;          cpu->cd.arm.r[ARM_LR] = lr;
   
         /*  Branch:  */  
456          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
457    
458            /*  Synchronize the program counter:  */
459          low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)          low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)
460              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
461          tmp_pc = cpu->cd.arm.r[ARM_PC];          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
         tmp_pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)  
462              << ARM_INSTR_ALIGNMENT_SHIFT);              << ARM_INSTR_ALIGNMENT_SHIFT);
463          tmp_pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
464          cpu_functioncall_trace(cpu, tmp_pc);  
465            /*  ... and show trace:  */
466            cpu_functioncall_trace(cpu, cpu->pc);
467  }  }
468  Y(bl_samepage_trace)  Y(bl_samepage_trace)
469    
470    
471  #include "cpu_arm_instr_misc.c"  /*
472     *  clz: Count leading zeroes.
473     *
474     *  arg[0] = ptr to rm
475     *  arg[1] = ptr to rd
476     */
477    X(clz)
478    {
479            uint32_t rm = reg(ic->arg[0]);
480            int i = 32, n = 0, j;
481            while (i>0) {
482                    if (rm & 0xff000000) {
483                            for (j=0; j<8; j++) {
484                                    if (rm & 0x80000000)
485                                            break;
486                                    n ++;
487                                    rm <<= 1;
488                            }
489                            break;
490                    } else {
491                            rm <<= 8;
492                            i -= 8;
493                            n += 8;
494                    }
495            }
496            reg(ic->arg[1]) = n;
497    }
498    Y(clz)
499    
500    
501  /*  /*
# Line 474  X(muls) Line 514  X(muls)
514  {  {
515          uint32_t result;          uint32_t result;
516          result = reg(ic->arg[1]) * reg(ic->arg[2]);          result = reg(ic->arg[1]) * reg(ic->arg[2]);
517          cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N);          cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
518          if (result == 0)          if (result == 0)
519                  cpu->cd.arm.cpsr |= ARM_FLAG_Z;                  cpu->cd.arm.flags |= ARM_F_Z;
520          if (result & 0x80000000)          if (result & 0x80000000)
521                  cpu->cd.arm.cpsr |= ARM_FLAG_N;                  cpu->cd.arm.flags |= ARM_F_N;
522          reg(ic->arg[0]) = result;          reg(ic->arg[0]) = result;
523  }  }
524  Y(muls)  Y(muls)
# Line 509  X(mlas) Line 549  X(mlas)
549          rs = (iw >> 8) & 15;  rm = iw & 15;          rs = (iw >> 8) & 15;  rm = iw & 15;
550          cpu->cd.arm.r[rd] = cpu->cd.arm.r[rm] * cpu->cd.arm.r[rs]          cpu->cd.arm.r[rd] = cpu->cd.arm.r[rm] * cpu->cd.arm.r[rs]
551              + cpu->cd.arm.r[rn];              + cpu->cd.arm.r[rn];
552          cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N);          cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
553          if (cpu->cd.arm.r[rd] == 0)          if (cpu->cd.arm.r[rd] == 0)
554                  cpu->cd.arm.cpsr |= ARM_FLAG_Z;                  cpu->cd.arm.flags |= ARM_F_Z;
555          if (cpu->cd.arm.r[rd] & 0x80000000)          if (cpu->cd.arm.r[rd] & 0x80000000)
556                  cpu->cd.arm.cpsr |= ARM_FLAG_N;                  cpu->cd.arm.flags |= ARM_F_N;
557  }  }
558  Y(mlas)  Y(mlas)
559    
# Line 528  X(mull) Line 568  X(mull)
568          /*  xxxx0000 1UAShhhh llllssss 1001mmmm  */          /*  xxxx0000 1UAShhhh llllssss 1001mmmm  */
569          uint32_t iw; uint64_t tmp; int u_bit, a_bit;          uint32_t iw; uint64_t tmp; int u_bit, a_bit;
570          iw = ic->arg[0];          iw = ic->arg[0];
571          u_bit = (iw >> 22) & 1; a_bit = (iw >> 21) & 1;          u_bit = iw & 0x00400000; a_bit = iw & 0x00200000;
572          tmp = cpu->cd.arm.r[iw & 15];          tmp = cpu->cd.arm.r[iw & 15];
573          if (u_bit)          if (u_bit)
574                  tmp = (int64_t)(int32_t)tmp                  tmp = (int64_t)(int32_t)tmp
# Line 550  Y(mull) Line 590  Y(mull)
590    
591    
592  /*  /*
593     *  smulXY:  16-bit * 16-bit multiplication (32-bit result)
594     *
595     *  arg[0] = ptr to rm
596     *  arg[1] = ptr to rs
597     *  arg[2] = ptr to rd
598     */
599    X(smulbb)
600    {
601            reg(ic->arg[2]) = (int32_t)(int16_t)reg(ic->arg[0]) *
602                (int32_t)(int16_t)reg(ic->arg[1]);
603    }
604    Y(smulbb)
605    X(smultb)
606    {
607            reg(ic->arg[2]) = (int32_t)(int16_t)(reg(ic->arg[0]) >> 16) *
608                (int32_t)(int16_t)reg(ic->arg[1]);
609    }
610    Y(smultb)
611    X(smulbt)
612    {
613            reg(ic->arg[2]) = (int32_t)(int16_t)reg(ic->arg[0]) *
614                (int32_t)(int16_t)(reg(ic->arg[1]) >> 16);
615    }
616    Y(smulbt)
617    X(smultt)
618    {
619            reg(ic->arg[2]) = (int32_t)(int16_t)(reg(ic->arg[0]) >> 16) *
620                (int32_t)(int16_t)(reg(ic->arg[1]) >> 16);
621    }
622    Y(smultt)
623    
624    
625    /*
626   *  mov_reg_reg:  Move a register to another.   *  mov_reg_reg:  Move a register to another.
627   *   *
628   *  arg[0] = ptr to source register   *  arg[0] = ptr to source register
# Line 563  Y(mov_reg_reg) Line 636  Y(mov_reg_reg)
636    
637    
638  /*  /*
639     *  mov_reg_pc:  Move the PC register to a normal register.
640     *
641     *  arg[0] = offset compared to start of current page + 8
642     *  arg[1] = ptr to destination register
643     */
644    X(mov_reg_pc)
645    {
646            reg(ic->arg[1]) = ((uint32_t)cpu->pc&0xfffff000) + (int32_t)ic->arg[0];
647    }
648    Y(mov_reg_pc)
649    
650    
651    /*
652   *  ret_trace:  "mov pc,lr" with trace enabled   *  ret_trace:  "mov pc,lr" with trace enabled
653   *  ret:  "mov pc,lr" without trace enabled   *  ret:  "mov pc,lr" without trace enabled
654   *   *
# Line 571  Y(mov_reg_reg) Line 657  Y(mov_reg_reg)
657  X(ret_trace)  X(ret_trace)
658  {  {
659          uint32_t old_pc, mask_within_page;          uint32_t old_pc, mask_within_page;
660          old_pc = cpu->cd.arm.r[ARM_PC];          old_pc = cpu->pc;
661          mask_within_page = ((ARM_IC_ENTRIES_PER_PAGE-1)          mask_within_page = ((ARM_IC_ENTRIES_PER_PAGE-1)
662              << ARM_INSTR_ALIGNMENT_SHIFT) |              << ARM_INSTR_ALIGNMENT_SHIFT) |
663              ((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);              ((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);
664    
665          /*  Update the PC register:  */          /*  Update the PC register:  */
666          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
667    
668          cpu_functioncall_trace_return(cpu);          cpu_functioncall_trace_return(cpu);
669    
# Line 596  X(ret_trace) Line 682  X(ret_trace)
682  Y(ret_trace)  Y(ret_trace)
683  X(ret)  X(ret)
684  {  {
685          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
686          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
687  }  }
688  Y(ret)  Y(ret)
# Line 620  X(msr_imm) Line 706  X(msr_imm)
706              (ic->arg[0] & ARM_FLAG_MODE));              (ic->arg[0] & ARM_FLAG_MODE));
707          uint32_t new_value = ic->arg[0];          uint32_t new_value = ic->arg[0];
708    
709            cpu->cd.arm.cpsr &= 0x0fffffff;
710            cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
711    
712          if (switch_register_banks)          if (switch_register_banks)
713                  arm_save_register_bank(cpu);                  arm_save_register_bank(cpu);
714    
715          cpu->cd.arm.cpsr &= ~mask;          cpu->cd.arm.cpsr &= ~mask;
716          cpu->cd.arm.cpsr |= (new_value & mask);          cpu->cd.arm.cpsr |= (new_value & mask);
717    
718            cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
719    
720          if (switch_register_banks)          if (switch_register_banks)
721                  arm_load_register_bank(cpu);                  arm_load_register_bank(cpu);
722  }  }
# Line 667  X(msr_imm_spsr) Line 758  X(msr_imm_spsr)
758          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
759          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)
760              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
761          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
762              << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
763          cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          old_pc = cpu->pc;
764          old_pc = cpu->pc = cpu->cd.arm.r[ARM_PC];          printf("msr_spsr: old pc = 0x%08"PRIx32"\n", old_pc);
 printf("msr_spsr: old pc = 0x%08x\n", old_pc);  
765  }  }
766                  exit(1);                  exit(1);
767          }          }
# Line 692  Y(msr_spsr) Line 782  Y(msr_spsr)
782   */   */
783  X(mrs)  X(mrs)
784  {  {
785            cpu->cd.arm.cpsr &= 0x0fffffff;
786            cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
787          reg(ic->arg[0]) = cpu->cd.arm.cpsr;          reg(ic->arg[0]) = cpu->cd.arm.cpsr;
788  }  }
789  Y(mrs)  Y(mrs)
790    
791    
792  /*  /*
793   *  mrs: Move from status/flag register to a normal register.   *  mrs: Move from saved status/flag register to a normal register.
794   *   *
795   *  arg[0] = pointer to rd   *  arg[0] = pointer to rd
796   */   */
# Line 727  Y(mrs_spsr) Line 819  Y(mrs_spsr)
819   *  arg[0] = copy of the instruction word   *  arg[0] = copy of the instruction word
820   */   */
821  X(mcr_mrc) {  X(mcr_mrc) {
822          uint32_t low_pc;          uint32_t low_pc = ((size_t)ic - (size_t)
         low_pc = ((size_t)ic - (size_t)  
823              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
824          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
825              << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
         cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc = cpu->cd.arm.r[ARM_PC];  
826          arm_mcr_mrc(cpu, ic->arg[0]);          arm_mcr_mrc(cpu, ic->arg[0]);
827  }  }
828  Y(mcr_mrc)  Y(mcr_mrc)
829  X(cdp) {  X(cdp) {
830          uint32_t low_pc;          uint32_t low_pc = ((size_t)ic - (size_t)
         low_pc = ((size_t)ic - (size_t)  
831              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
832          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
833              << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
         cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc = cpu->cd.arm.r[ARM_PC];  
834          arm_cdp(cpu, ic->arg[0]);          arm_cdp(cpu, ic->arg[0]);
835  }  }
836  Y(cdp)  Y(cdp)
# Line 755  Y(cdp) Line 841  Y(cdp)
841   */   */
842  X(openfirmware)  X(openfirmware)
843  {  {
844            /*  TODO: sync pc?  */
845          of_emul(cpu);          of_emul(cpu);
846          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
847          if (cpu->machine->show_trace_tree)          if (cpu->machine->show_trace_tree)
848                  cpu_functioncall_trace_return(cpu);                  cpu_functioncall_trace_return(cpu);
849          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
# Line 764  X(openfirmware) Line 851  X(openfirmware)
851    
852    
853  /*  /*
854     *  reboot:
855     */
856    X(reboot)
857    {
858            cpu->running = 0;
859            cpu->running_translated = 0;
860            cpu->n_translated_instrs --;
861            cpu->cd.arm.next_ic = &nothing_call;
862    }
863    
864    
865    /*
866   *  swi_useremul: Syscall.   *  swi_useremul: Syscall.
867   *   *
868   *  arg[0] = swi number   *  arg[0] = swi number
# Line 773  X(swi_useremul) Line 872  X(swi_useremul)
872          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
873          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)
874              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
875          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
876              << ARM_INSTR_ALIGNMENT_SHIFT);              << ARM_INSTR_ALIGNMENT_SHIFT);
877          cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
878          old_pc = cpu->pc = cpu->cd.arm.r[ARM_PC];          old_pc = cpu->pc;
879    
880          useremul_syscall(cpu, ic->arg[0]);          useremul_syscall(cpu, ic->arg[0]);
881    
# Line 798  Y(swi_useremul) Line 897  Y(swi_useremul)
897   */   */
898  X(swi)  X(swi)
899  {  {
900          /*  Synchronize the program counter:  */          /*  Synchronize the program counter first:  */
901          uint32_t low_pc = ((size_t)ic - (size_t)          cpu->pc &= 0xfffff000;
902              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);          cpu->pc += ic->arg[0];
         cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)  
             << ARM_INSTR_ALIGNMENT_SHIFT);  
         cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc = cpu->cd.arm.r[ARM_PC];  
   
903          arm_exception(cpu, ARM_EXCEPTION_SWI);          arm_exception(cpu, ARM_EXCEPTION_SWI);
904  }  }
905  Y(swi)  Y(swi)
906    
907    
908  /*  /*
909     *  und:  Undefined instruction.
910     */
911    X(und)
912    {
913            /*  Synchronize the program counter first:  */
914            cpu->pc &= 0xfffff000;
915            cpu->pc += ic->arg[0];
916            arm_exception(cpu, ARM_EXCEPTION_UND);
917    }
918    Y(und)
919    
920    
921    /*
922   *  swp, swpb:  Swap (word or byte).   *  swp, swpb:  Swap (word or byte).
923   *   *
924   *  arg[0] = ptr to rd   *  arg[0] = ptr to rd
# Line 822  X(swp) Line 929  X(swp)
929  {  {
930          uint32_t addr = reg(ic->arg[2]), data, data2;          uint32_t addr = reg(ic->arg[2]), data, data2;
931          unsigned char d[4];          unsigned char d[4];
932    
933          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
934          uint32_t low_pc = ((size_t)ic - (size_t)          uint32_t low_pc = ((size_t)ic - (size_t)
935              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
936          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
937              << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
         cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc = cpu->cd.arm.r[ARM_PC];  
938    
939          if (!cpu->memory_rw(cpu, cpu->mem, addr, d, sizeof(d), MEM_READ,          if (!cpu->memory_rw(cpu, cpu->mem, addr, d, sizeof(d), MEM_READ,
940              CACHE_DATA)) {              CACHE_DATA)) {
# Line 850  X(swpb) Line 956  X(swpb)
956  {  {
957          uint32_t addr = reg(ic->arg[2]), data;          uint32_t addr = reg(ic->arg[2]), data;
958          unsigned char d[1];          unsigned char d[1];
959    
960          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
961          uint32_t low_pc = ((size_t)ic - (size_t)          uint32_t low_pc = ((size_t)ic - (size_t)
962              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
963          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
964              << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
         cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc = cpu->cd.arm.r[ARM_PC];  
965    
966          if (!cpu->memory_rw(cpu, cpu->mem, addr, d, sizeof(d), MEM_READ,          if (!cpu->memory_rw(cpu, cpu->mem, addr, d, sizeof(d), MEM_READ,
967              CACHE_DATA)) {              CACHE_DATA)) {
# Line 877  Y(swpb) Line 982  Y(swpb)
982    
983  extern void (*arm_load_store_instr[1024])(struct cpu *,  extern void (*arm_load_store_instr[1024])(struct cpu *,
984          struct arm_instr_call *);          struct arm_instr_call *);
985    X(store_w1_word_u1_p0_imm);
986  X(store_w0_byte_u1_p0_imm);  X(store_w0_byte_u1_p0_imm);
987  X(store_w0_word_u1_p0_imm);  X(store_w0_word_u1_p0_imm);
988    X(store_w0_word_u1_p1_imm);
989    X(load_w1_word_u1_p0_imm);
990  X(load_w0_word_u1_p0_imm);  X(load_w0_word_u1_p0_imm);
991  X(load_w0_byte_u1_p1_imm);  X(load_w0_byte_u1_p1_imm);
992  X(load_w0_byte_u1_p1_reg);  X(load_w0_byte_u1_p1_reg);
993    X(load_w1_byte_u1_p1_imm);
994    
995  extern void (*arm_load_store_instr_pc[1024])(struct cpu *,  extern void (*arm_load_store_instr_pc[1024])(struct cpu *,
996          struct arm_instr_call *);          struct arm_instr_call *);
# Line 893  extern void (*arm_load_store_instr_3_pc[ Line 1002  extern void (*arm_load_store_instr_3_pc[
1002          struct arm_instr_call *);          struct arm_instr_call *);
1003    
1004  extern uint32_t (*arm_r[8192])(struct cpu *, struct arm_instr_call *);  extern uint32_t (*arm_r[8192])(struct cpu *, struct arm_instr_call *);
1005    extern void arm_r_r3_t0_c0(void);
1006    
1007  extern void (*arm_dpi_instr[2 * 2 * 2 * 16 * 16])(struct cpu *,  extern void (*arm_dpi_instr[2 * 2 * 2 * 16 * 16])(struct cpu *,
1008          struct arm_instr_call *);          struct arm_instr_call *);
1009    extern void (*arm_dpi_instr_regshort[2 * 16 * 16])(struct cpu *,
1010            struct arm_instr_call *);
1011  X(cmps);  X(cmps);
1012    X(teqs);
1013    X(tsts);
1014  X(sub);  X(sub);
1015  X(add);  X(add);
1016  X(subs);  X(subs);
1017    X(eor_regshort);
1018    X(cmps_regshort);
1019    
1020    
1021    #include "cpu_arm_instr_misc.c"
1022    
1023    
1024  /*  /*
# Line 931  X(bdt_load) Line 1049  X(bdt_load)
1049          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
1050          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
1051              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
1052          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) <<          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
1053              ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
         cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc = cpu->cd.arm.r[ARM_PC];  
1054    
1055          if (s_bit) {          if (s_bit) {
1056                  /*  Load to USR registers:  */                  /*  Load to USR registers:  */
# Line 1070  X(bdt_load) Line 1186  X(bdt_load)
1186                          arm_save_register_bank(cpu);                          arm_save_register_bank(cpu);
1187    
1188                  cpu->cd.arm.cpsr = new_cpsr;                  cpu->cd.arm.cpsr = new_cpsr;
1189                    cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
1190    
1191                  if (switch_register_banks)                  if (switch_register_banks)
1192                          arm_load_register_bank(cpu);                          arm_load_register_bank(cpu);
# Line 1077  X(bdt_load) Line 1194  X(bdt_load)
1194    
1195          /*  NOTE: Special case: Loading the PC  */          /*  NOTE: Special case: Loading the PC  */
1196          if (iw & 0x8000) {          if (iw & 0x8000) {
1197                  cpu->cd.arm.r[ARM_PC] &= ~3;                  cpu->pc = cpu->cd.arm.r[ARM_PC] & 0xfffffffc;
                 cpu->pc = cpu->cd.arm.r[ARM_PC];  
1198                  if (cpu->machine->show_trace_tree)                  if (cpu->machine->show_trace_tree)
1199                          cpu_functioncall_trace_return(cpu);                          cpu_functioncall_trace_return(cpu);
1200                  /*  TODO: There is no need to update the                  /*  TODO: There is no need to update the
# Line 1119  X(bdt_store) Line 1235  X(bdt_store)
1235          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
1236          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
1237              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
1238          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) <<          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
1239              ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
         cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc = cpu->cd.arm.r[ARM_PC];  
1240    
1241          for (i=(u_bit? 0 : 15); i>=0 && i<=15; i+=(u_bit? 1 : -1)) {          for (i=(u_bit? 0 : 15); i>=0 && i<=15; i+=(u_bit? 1 : -1)) {
1242                  if (!((iw >> i) & 1)) {                  if (!((iw >> i) & 1)) {
# Line 1151  X(bdt_store) Line 1265  X(bdt_store)
1265                          }                          }
1266                  }                  }
1267    
1268                    /*  NOTE/TODO: 8 vs 12 on some ARMs  */
1269                  if (i == ARM_PC)                  if (i == ARM_PC)
1270                          value += 12;    /*  NOTE/TODO: 8 on some ARMs  */                          value = cpu->pc + 12;
1271    
1272                  if (p_bit) {                  if (p_bit) {
1273                          if (u_bit)                          if (u_bit)
# Line 1210  Y(bdt_store) Line 1325  Y(bdt_store)
1325    
1326    
1327  /*  Various load/store multiple instructions:  */  /*  Various load/store multiple instructions:  */
1328  #include "tmp_arm_multi.c"  extern uint32_t *multi_opcode[256];
1329    extern void (**multi_opcode_f[256])(struct cpu *, struct arm_instr_call *);
1330    X(multi_0x08b15018);
1331    X(multi_0x08ac000c__ge);
1332    X(multi_0x08a05018);
1333    
1334    
1335  /*****************************************************************************/  /*****************************************************************************/
1336    
1337    
1338  /*  /*
  *  fill_loop_test:  
  *  
  *  A byte-fill loop. Fills at most one page at a time. If the page was not  
  *  in the host_store table, then the original sequence (beginning with  
  *  cmps rZ,#0) is executed instead.  
  *  
  *  L: cmps rZ,#0               ic[0]  
  *     strb rX,[rY],#1          ic[1]  
  *     sub  rZ,rZ,#1            ic[2]  
  *     bgt  L                   ic[3]  
  *  
  *  A maximum of 4 pages are filled before returning.  
  */  
 X(fill_loop_test)  
 {  
         int max_pages_left = 4;  
         uint32_t addr, a, n, ofs, maxlen;  
         uint32_t *rzp = (uint32_t *)(size_t)ic[0].arg[0];  
         unsigned char *page;  
   
 restart_loop:  
         addr = reg(ic[1].arg[0]);  
         page = cpu->cd.arm.host_store[addr >> 12];  
         if (page == NULL) {  
                 instr(cmps)(cpu, ic);  
                 return;  
         }  
   
         n = reg(rzp) + 1;  
         ofs = addr & 0xfff;  
         maxlen = 4096 - ofs;  
         if (n > maxlen)  
                 n = maxlen;  
   
         /*  printf("x = %x, n = %i\n", reg(ic[1].arg[2]), n);  */  
         memset(page + ofs, reg(ic[1].arg[2]), n);  
   
         reg(ic[1].arg[0]) = addr + n;  
   
         reg(rzp) -= n;  
         cpu->n_translated_instrs += (4 * n);  
   
         a = reg(rzp);  
   
         cpu->cd.arm.cpsr &=  
             ~(ARM_FLAG_Z | ARM_FLAG_N | ARM_FLAG_V | ARM_FLAG_C);  
         if (a != 0)  
                 cpu->cd.arm.cpsr |= ARM_FLAG_C;  
         else  
                 cpu->cd.arm.cpsr |= ARM_FLAG_Z;  
         if ((int32_t)a < 0)  
                 cpu->cd.arm.cpsr |= ARM_FLAG_N;  
   
         if (max_pages_left-- > 0 && (int32_t)a > 0)  
                 goto restart_loop;  
   
         cpu->n_translated_instrs --;  
   
         if ((int32_t)a > 0)  
                 cpu->cd.arm.next_ic = ic;  
         else  
                 cpu->cd.arm.next_ic = &ic[4];  
 }  
   
   
 /*  
  *  fill_loop_test2:  
  *  
  *  A word-fill loop. Fills at most one page at a time. If the page was not  
  *  in the host_store table, then the original sequence (beginning with  
  *  cmps rZ,#0) is executed instead.  
  *  
  *      L: str     rX,[rY],#4           ic[0]  
  *         subs    rZ,rZ,#4             ic[1]  
  *         bgt     L                    ic[2]  
  *  
  *  A maximum of 5 pages are filled before returning.  
  */  
 X(fill_loop_test2)  
 {  
         int max_pages_left = 5;  
         unsigned char x1,x2,x3,x4;  
         uint32_t addr, a, n, x, ofs, maxlen;  
         uint32_t *rzp = (uint32_t *)(size_t)ic[1].arg[0];  
         unsigned char *page;  
   
         x = reg(ic[0].arg[2]);  
         x1 = x; x2 = x >> 8; x3 = x >> 16; x4 = x >> 24;  
         if (x1 != x2 || x1 != x3 || x1 != x4) {  
                 instr(store_w0_word_u1_p0_imm)(cpu, ic);  
                 return;  
         }  
   
 restart_loop:  
         addr = reg(ic[0].arg[0]);  
         page = cpu->cd.arm.host_store[addr >> 12];  
         if (page == NULL || (addr & 3) != 0) {  
                 instr(store_w0_word_u1_p0_imm)(cpu, ic);  
                 return;  
         }  
   
         /*  printf("addr = 0x%08x, page = %p\n", addr, page);  
             printf("*rzp = 0x%08x\n", reg(rzp));  */  
   
         n = reg(rzp) / 4;  
         if (n == 0)  
                 n++;  
         /*  n = nr of _words_  */  
         ofs = addr & 0xfff;  
         maxlen = 4096 - ofs;  
         if (n*4 > maxlen)  
                 n = maxlen / 4;  
   
         /*  printf("x = %x, n = %i\n", x1, n);  */  
         memset(page + ofs, x1, n * 4);  
   
         reg(ic[0].arg[0]) = addr + n * 4;  
   
         reg(rzp) -= (n * 4);  
         cpu->n_translated_instrs += (3 * n);  
   
         a = reg(rzp);  
   
         cpu->cd.arm.cpsr &=  
             ~(ARM_FLAG_Z | ARM_FLAG_N | ARM_FLAG_V | ARM_FLAG_C);  
         if (a != 0)  
                 cpu->cd.arm.cpsr |= ARM_FLAG_C;  
         else  
                 cpu->cd.arm.cpsr |= ARM_FLAG_Z;  
         if ((int32_t)a < 0)  
                 cpu->cd.arm.cpsr |= ARM_FLAG_N;  
   
         if (max_pages_left-- > 0 && (int32_t)a > 0)  
                 goto restart_loop;  
   
         cpu->n_translated_instrs --;  
   
         if ((int32_t)a > 0)  
                 cpu->cd.arm.next_ic = ic;  
         else  
                 cpu->cd.arm.next_ic = &ic[3];  
 }  
   
   
 /*  
1339   *  netbsd_memset:   *  netbsd_memset:
1340   *   *
1341   *  The core of a NetBSD/arm memset.   *  The core of a NetBSD/arm memset.
# Line 1381  X(netbsd_memset) Line 1355  X(netbsd_memset)
1355    
1356                  instr(subs)(cpu, ic);                  instr(subs)(cpu, ic);
1357    
1358                  if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) !=                  if (((cpu->cd.arm.flags & ARM_F_N)?1:0) !=
1359                      ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0)) {                      ((cpu->cd.arm.flags & ARM_F_V)?1:0)) {
1360                          cpu->n_translated_instrs += 16;                          cpu->n_translated_instrs += 16;
1361                          /*  Skip the store multiples:  */                          /*  Skip the store multiples:  */
1362                          cpu->cd.arm.next_ic = &ic[17];                          cpu->cd.arm.next_ic = &ic[17];
# Line 1411  X(netbsd_memset) Line 1385  X(netbsd_memset)
1385    
1386                  /*  Branch back if greater:  */                  /*  Branch back if greater:  */
1387                  cpu->n_translated_instrs += 1;                  cpu->n_translated_instrs += 1;
1388          } while (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) ==          } while (((cpu->cd.arm.flags & ARM_F_N)?1:0) ==
1389              ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0) &&              ((cpu->cd.arm.flags & ARM_F_V)?1:0) &&
1390              !(cpu->cd.arm.cpsr & ARM_FLAG_Z));              !(cpu->cd.arm.flags & ARM_F_Z));
1391    
1392          /*  Continue at the instruction after the bgt:  */          /*  Continue at the instruction after the bgt:  */
1393          cpu->cd.arm.next_ic = &ic[18];          cpu->cd.arm.next_ic = &ic[18];
# Line 1471  X(netbsd_memcpy) Line 1445  X(netbsd_memcpy)
1445    
1446                  /*  Loop while greater or equal:  */                  /*  Loop while greater or equal:  */
1447                  cpu->n_translated_instrs ++;                  cpu->n_translated_instrs ++;
1448          } while (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) ==          } while (((cpu->cd.arm.flags & ARM_F_N)?1:0) ==
1449              ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0));              ((cpu->cd.arm.flags & ARM_F_V)?1:0));
1450    
1451          /*  Continue at the instruction after the bge:  */          /*  Continue at the instruction after the bge:  */
1452          cpu->cd.arm.next_ic = &ic[6];          cpu->cd.arm.next_ic = &ic[6];
# Line 1494  X(netbsd_cacheclean) Line 1468  X(netbsd_cacheclean)
1468  {  {
1469          uint32_t r1 = cpu->cd.arm.r[1];          uint32_t r1 = cpu->cd.arm.r[1];
1470          cpu->n_translated_instrs += ((r1 >> 5) * 3);          cpu->n_translated_instrs += ((r1 >> 5) * 3);
1471            cpu->cd.arm.r[0] += r1;
1472            cpu->cd.arm.r[1] = 0;
1473          cpu->cd.arm.next_ic = &ic[4];          cpu->cd.arm.next_ic = &ic[4];
1474  }  }
1475    
# Line 1545  X(netbsd_scanc) Line 1521  X(netbsd_scanc)
1521          cpu->cd.arm.r[3] = page[t & 0xfff];          cpu->cd.arm.r[3] = page[t & 0xfff];
1522    
1523          t = cpu->cd.arm.r[3] & cpu->cd.arm.r[ARM_IP];          t = cpu->cd.arm.r[3] & cpu->cd.arm.r[ARM_IP];
1524          cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N);          cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1525          if (t == 0)          if (t == 0)
1526                  cpu->cd.arm.cpsr |= ARM_FLAG_Z;                  cpu->cd.arm.flags |= ARM_F_Z;
1527    
1528          cpu->n_translated_instrs += 2;          cpu->n_translated_instrs += 2;
1529          cpu->cd.arm.next_ic = &ic[3];          cpu->cd.arm.next_ic = &ic[3];
1530  }  }
1531    
1532    
1533    /*
1534     *  strlen:
1535     *
1536     *  S: e5f03001   ldrb  rY,[rX,#1]!
1537     *     e3530000   cmps  rY,#0
1538     *     1afffffc   bne   S
1539     */
1540    X(strlen)
1541    {
1542            unsigned int n_loops = 0;
1543            uint32_t rY, rX = reg(ic[0].arg[0]);
1544            unsigned char *p;
1545    
1546            do {
1547                    rX ++;
1548                    p = cpu->cd.arm.host_load[rX >> 12];
1549                    if (p == NULL) {
1550                            cpu->n_translated_instrs += (n_loops * 3);
1551                            instr(load_w1_byte_u1_p1_imm)(cpu, ic);
1552                            return;
1553                    }
1554    
1555                    rY = reg(ic[0].arg[2]) = p[rX & 0xfff]; /*  load  */
1556                    reg(ic[0].arg[0]) = rX;                 /*  writeback  */
1557                    n_loops ++;
1558    
1559                    /*  Compare rY to zero:  */
1560                    cpu->cd.arm.flags = ARM_F_C;
1561                    if (rY == 0)
1562                            cpu->cd.arm.flags |= ARM_F_Z;
1563            } while (rY != 0);
1564    
1565            cpu->n_translated_instrs += (n_loops * 3) - 1;
1566            cpu->cd.arm.next_ic = &ic[3];
1567    }
1568    
1569    
1570    /*
1571     *  xchg:
1572     *
1573     *  e02YX00X     eor     rX,rY,rX
1574     *  e02XY00Y     eor     rY,rX,rY
1575     *  e02YX00X     eor     rX,rY,rX
1576     */
1577    X(xchg)
1578    {
1579            uint32_t tmp = reg(ic[0].arg[0]);
1580            cpu->n_translated_instrs += 2;
1581            cpu->cd.arm.next_ic = &ic[3];
1582            reg(ic[0].arg[0]) = reg(ic[1].arg[0]);
1583            reg(ic[1].arg[0]) = tmp;
1584    }
1585    
1586    
1587    /*
1588     *  netbsd_copyin:
1589     *
1590     *  e4b0a004     ldrt    sl,[r0],#4
1591     *  e4b0b004     ldrt    fp,[r0],#4
1592     *  e4b06004     ldrt    r6,[r0],#4
1593     *  e4b07004     ldrt    r7,[r0],#4
1594     *  e4b08004     ldrt    r8,[r0],#4
1595     *  e4b09004     ldrt    r9,[r0],#4
1596     */
1597    X(netbsd_copyin)
1598    {
1599            uint32_t r0 = cpu->cd.arm.r[0], ofs = (r0 & 0xffc), index = r0 >> 12;
1600            unsigned char *p = cpu->cd.arm.host_load[index];
1601            uint32_t *p32 = (uint32_t *) p, *q32;
1602            int ok = cpu->cd.arm.is_userpage[index >> 5] & (1 << (index & 31));
1603    
1604            if (ofs > 0x1000 - 6*4 || !ok || p == NULL) {
1605                    instr(load_w1_word_u1_p0_imm)(cpu, ic);
1606                    return;
1607            }
1608            q32 = &cpu->cd.arm.r[6];
1609            ofs >>= 2;
1610            q32[0] = p32[ofs+2];
1611            q32[1] = p32[ofs+3];
1612            q32[2] = p32[ofs+4];
1613            q32[3] = p32[ofs+5];
1614            q32[4] = p32[ofs+0];
1615            q32[5] = p32[ofs+1];
1616            cpu->cd.arm.r[0] = r0 + 24;
1617            cpu->n_translated_instrs += 5;
1618            cpu->cd.arm.next_ic = &ic[6];
1619    }
1620    
1621    
1622    /*
1623     *  netbsd_copyout:
1624     *
1625     *  e4a18004     strt    r8,[r1],#4
1626     *  e4a19004     strt    r9,[r1],#4
1627     *  e4a1a004     strt    sl,[r1],#4
1628     *  e4a1b004     strt    fp,[r1],#4
1629     *  e4a16004     strt    r6,[r1],#4
1630     *  e4a17004     strt    r7,[r1],#4
1631     */
1632    X(netbsd_copyout)
1633    {
1634            uint32_t r1 = cpu->cd.arm.r[1], ofs = (r1 & 0xffc), index = r1 >> 12;
1635            unsigned char *p = cpu->cd.arm.host_store[index];
1636            uint32_t *p32 = (uint32_t *) p, *q32;
1637            int ok = cpu->cd.arm.is_userpage[index >> 5] & (1 << (index & 31));
1638    
1639            if (ofs > 0x1000 - 6*4 || !ok || p == NULL) {
1640                    instr(store_w1_word_u1_p0_imm)(cpu, ic);
1641                    return;
1642            }
1643            q32 = &cpu->cd.arm.r[6];
1644            ofs >>= 2;
1645            p32[ofs  ] = q32[2];
1646            p32[ofs+1] = q32[3];
1647            p32[ofs+2] = q32[4];
1648            p32[ofs+3] = q32[5];
1649            p32[ofs+4] = q32[0];
1650            p32[ofs+5] = q32[1];
1651            cpu->cd.arm.r[1] = r1 + 24;
1652            cpu->n_translated_instrs += 5;
1653            cpu->cd.arm.next_ic = &ic[6];
1654    }
1655    
1656    
1657    /*
1658     *  cmps by 0, followed by beq (inside the same page):
1659     */
1660    X(cmps0_beq_samepage)
1661    {
1662            uint32_t a = reg(ic->arg[0]);
1663            cpu->n_translated_instrs ++;
1664            if (a == 0) {
1665                    cpu->cd.arm.flags = ARM_F_Z | ARM_F_C;
1666            } else {
1667                    /*  Semi-ugly hack which sets the negative-bit if a < 0:  */
1668                    cpu->cd.arm.flags = ARM_F_C | ((a >> 28) & 8);
1669            }
1670            if (a == 0)
1671                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1672            else
1673                    cpu->cd.arm.next_ic = &ic[2];
1674    }
1675    
1676    
1677    /*
1678     *  cmps followed by beq (inside the same page):
1679     */
1680    X(cmps_beq_samepage)
1681    {
1682            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1683            cpu->n_translated_instrs ++;
1684            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1685            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1686                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1687                    cpu->cd.arm.flags |= ARM_F_V;
1688            if (c == 0) {
1689                    cpu->cd.arm.flags |= ARM_F_Z;
1690                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1691            } else {
1692                    cpu->cd.arm.next_ic = &ic[2];
1693                    if (c & 0x80000000)
1694                            cpu->cd.arm.flags |= ARM_F_N;
1695            }
1696    }
1697    
1698    
1699    /*
1700     *  cmps followed by beq (not the same page):
1701     */
1702    X(cmps_0_beq)
1703    {
1704            uint32_t a = reg(ic->arg[0]);
1705            cpu->n_translated_instrs ++;
1706            if (a == 0) {
1707                    cpu->cd.arm.flags = ARM_F_Z | ARM_F_C;
1708                    cpu->pc = (uint32_t)(((uint32_t)cpu->pc & 0xfffff000)
1709                        + (int32_t)ic[1].arg[0]);
1710                    quick_pc_to_pointers(cpu);
1711            } else {
1712                    /*  Semi-ugly hack which sets the negative-bit if a < 0:  */
1713                    cpu->cd.arm.flags = ARM_F_C | ((a >> 28) & 8);
1714                    cpu->cd.arm.next_ic = &ic[2];
1715            }
1716    }
1717    X(cmps_pos_beq)
1718    {
1719            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1720            cpu->n_translated_instrs ++;
1721            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1722            if ((int32_t)a < 0 && (int32_t)c >= 0)
1723                    cpu->cd.arm.flags |= ARM_F_V;
1724            if (c == 0) {
1725                    cpu->cd.arm.flags |= ARM_F_Z;
1726                    cpu->pc = (uint32_t)(((uint32_t)cpu->pc & 0xfffff000)
1727                        + (int32_t)ic[1].arg[0]);
1728                    quick_pc_to_pointers(cpu);
1729            } else {
1730                    cpu->cd.arm.next_ic = &ic[2];
1731                    if (c & 0x80000000)
1732                            cpu->cd.arm.flags |= ARM_F_N;
1733            }
1734    }
1735    X(cmps_neg_beq)
1736    {
1737            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1738            cpu->n_translated_instrs ++;
1739            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1740            if ((int32_t)a >= 0 && (int32_t)c < 0)
1741                    cpu->cd.arm.flags |= ARM_F_V;
1742            if (c == 0) {
1743                    cpu->cd.arm.flags |= ARM_F_Z;
1744                    cpu->pc = (uint32_t)(((uint32_t)cpu->pc & 0xfffff000)
1745                        + (int32_t)ic[1].arg[0]);
1746                    quick_pc_to_pointers(cpu);
1747            } else {
1748                    cpu->cd.arm.next_ic = &ic[2];
1749                    if (c & 0x80000000)
1750                            cpu->cd.arm.flags |= ARM_F_N;
1751            }
1752    }
1753    
1754    
1755    /*
1756     *  cmps by 0, followed by bne (inside the same page):
1757     */
1758    X(cmps0_bne_samepage)
1759    {
1760            uint32_t a = reg(ic->arg[0]);
1761            cpu->n_translated_instrs ++;
1762            if (a == 0) {
1763                    cpu->cd.arm.flags = ARM_F_Z | ARM_F_C;
1764            } else {
1765                    /*  Semi-ugly hack which sets the negative-bit if a < 0:  */
1766                    cpu->cd.arm.flags = ARM_F_C | ((a >> 28) & 8);
1767            }
1768            if (a == 0)
1769                    cpu->cd.arm.next_ic = &ic[2];
1770            else
1771                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1772    }
1773    
1774    
1775    /*
1776     *  cmps followed by bne (inside the same page):
1777     */
1778    X(cmps_bne_samepage)
1779    {
1780            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1781            cpu->n_translated_instrs ++;
1782            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1783            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1784                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1785                    cpu->cd.arm.flags |= ARM_F_V;
1786            if (c == 0) {
1787                    cpu->cd.arm.flags |= ARM_F_Z;
1788                    cpu->cd.arm.next_ic = &ic[2];
1789            } else {
1790                    if (c & 0x80000000)
1791                            cpu->cd.arm.flags |= ARM_F_N;
1792                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1793            }
1794    }
1795    
1796    
1797    /*
1798     *  cmps followed by bcc (inside the same page):
1799     */
1800    X(cmps_bcc_samepage)
1801    {
1802            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1803            cpu->n_translated_instrs ++;
1804            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1805            if (c & 0x80000000)
1806                    cpu->cd.arm.flags |= ARM_F_N;
1807            else if (c == 0)
1808                    cpu->cd.arm.flags |= ARM_F_Z;
1809            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1810                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1811                    cpu->cd.arm.flags |= ARM_F_V;
1812            if (a >= b)
1813                    cpu->cd.arm.next_ic = &ic[2];
1814            else
1815                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1816    }
1817    
1818    
1819    /*
1820     *  cmps (reg) followed by bcc (inside the same page):
1821     */
1822    X(cmps_reg_bcc_samepage)
1823    {
1824            uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = a - b;
1825            cpu->n_translated_instrs ++;
1826            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1827            if (c & 0x80000000)
1828                    cpu->cd.arm.flags |= ARM_F_N;
1829            else if (c == 0)
1830                    cpu->cd.arm.flags |= ARM_F_Z;
1831            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1832                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1833                    cpu->cd.arm.flags |= ARM_F_V;
1834            if (a >= b)
1835                    cpu->cd.arm.next_ic = &ic[2];
1836            else
1837                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1838    }
1839    
1840    
1841    /*
1842     *  cmps followed by bhi (inside the same page):
1843     */
1844    X(cmps_bhi_samepage)
1845    {
1846            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1847            cpu->n_translated_instrs ++;
1848            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1849            if (c & 0x80000000)
1850                    cpu->cd.arm.flags |= ARM_F_N;
1851            else if (c == 0)
1852                    cpu->cd.arm.flags |= ARM_F_Z;
1853            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1854                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1855                    cpu->cd.arm.flags |= ARM_F_V;
1856            if (a > b)
1857                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1858            else
1859                    cpu->cd.arm.next_ic = &ic[2];
1860    }
1861    
1862    
1863    /*
1864     *  cmps (reg) followed by bhi (inside the same page):
1865     */
1866    X(cmps_reg_bhi_samepage)
1867    {
1868            uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = a - b;
1869            cpu->n_translated_instrs ++;
1870            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1871            if (c & 0x80000000)
1872                    cpu->cd.arm.flags |= ARM_F_N;
1873            else if (c == 0)
1874                    cpu->cd.arm.flags |= ARM_F_Z;
1875            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1876                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1877                    cpu->cd.arm.flags |= ARM_F_V;
1878            if (a > b)
1879                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1880            else
1881                    cpu->cd.arm.next_ic = &ic[2];
1882    }
1883    
1884    
1885    /*
1886     *  cmps followed by bgt (inside the same page):
1887     */
1888    X(cmps_bgt_samepage)
1889    {
1890            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1891            cpu->n_translated_instrs ++;
1892            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1893            if (c & 0x80000000)
1894                    cpu->cd.arm.flags |= ARM_F_N;
1895            else if (c == 0)
1896                    cpu->cd.arm.flags |= ARM_F_Z;
1897            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1898                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1899                    cpu->cd.arm.flags |= ARM_F_V;
1900            if ((int32_t)a > (int32_t)b)
1901                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1902            else
1903                    cpu->cd.arm.next_ic = &ic[2];
1904    }
1905    
1906    
1907    /*
1908     *  cmps followed by ble (inside the same page):
1909     */
1910    X(cmps_ble_samepage)
1911    {
1912            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1913            cpu->n_translated_instrs ++;
1914            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1915            if (c & 0x80000000)
1916                    cpu->cd.arm.flags |= ARM_F_N;
1917            else if (c == 0)
1918                    cpu->cd.arm.flags |= ARM_F_Z;
1919            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1920                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1921                    cpu->cd.arm.flags |= ARM_F_V;
1922            if ((int32_t)a <= (int32_t)b)
1923                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1924            else
1925                    cpu->cd.arm.next_ic = &ic[2];
1926    }
1927    
1928    
1929    /*
1930     *  teqs followed by beq (inside the same page):
1931     */
1932    X(teqs_beq_samepage)
1933    {
1934            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a ^ b;
1935            cpu->n_translated_instrs ++;
1936            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1937            if (c == 0) {
1938                    cpu->cd.arm.flags |= ARM_F_Z;
1939                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
1940                        ic[1].arg[0];
1941            } else {
1942                    if (c & 0x80000000)
1943                            cpu->cd.arm.flags |= ARM_F_N;
1944                    cpu->cd.arm.next_ic = &ic[2];
1945            }
1946    }
1947    
1948    
1949    /*
1950     *  tsts followed by beq (inside the same page):
1951     *  (arg[1] must not have its highest bit set))
1952     */
1953    X(tsts_lo_beq_samepage)
1954    {
1955            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a & b;
1956            cpu->n_translated_instrs ++;
1957            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1958            if (c == 0)
1959                    cpu->cd.arm.flags |= ARM_F_Z;
1960            if (c == 0)
1961                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
1962                        ic[1].arg[0];
1963            else
1964                    cpu->cd.arm.next_ic = &ic[2];
1965    }
1966    
1967    
1968    /*
1969     *  teqs followed by bne (inside the same page):
1970     */
1971    X(teqs_bne_samepage)
1972    {
1973            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a ^ b;
1974            cpu->n_translated_instrs ++;
1975            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1976            if (c == 0) {
1977                    cpu->cd.arm.flags |= ARM_F_Z;
1978            } else {
1979                    if (c & 0x80000000)
1980                            cpu->cd.arm.flags |= ARM_F_N;
1981            }
1982            if (c == 0)
1983                    cpu->cd.arm.next_ic = &ic[2];
1984            else
1985                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
1986                        ic[1].arg[0];
1987    }
1988    
1989    
1990    /*
1991     *  tsts followed by bne (inside the same page):
1992     *  (arg[1] must not have its highest bit set))
1993     */
1994    X(tsts_lo_bne_samepage)
1995    {
1996            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a & b;
1997            cpu->n_translated_instrs ++;
1998            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1999            if (c == 0)
2000                    cpu->cd.arm.flags |= ARM_F_Z;
2001            if (c == 0)
2002                    cpu->cd.arm.next_ic = &ic[2];
2003            else
2004                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
2005                        ic[1].arg[0];
2006    }
2007    
2008    
2009  /*****************************************************************************/  /*****************************************************************************/
2010    
2011    
2012  X(end_of_page)  X(end_of_page)
2013  {  {
2014          /*  Update the PC:  (offset 0, but on the next page)  */          /*  Update the PC:  (offset 0, but on the next page)  */
2015          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
2016              << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (ARM_IC_ENTRIES_PER_PAGE << ARM_INSTR_ALIGNMENT_SHIFT);
         cpu->cd.arm.r[ARM_PC] += (ARM_IC_ENTRIES_PER_PAGE  
             << ARM_INSTR_ALIGNMENT_SHIFT);  
         cpu->pc = cpu->cd.arm.r[ARM_PC];  
2017    
2018          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
2019          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
# Line 1578  X(end_of_page) Line 2027  X(end_of_page)
2027    
2028    
2029  /*  /*
2030   *  arm_combine_netbsd_memset():   *  Combine: netbsd_memset():
2031   *   *
2032   *  Check for the core of a NetBSD/arm memset; large memsets use a sequence   *  Check for the core of a NetBSD/arm memset; large memsets use a sequence
2033   *  of 16 store-multiple instructions, each storing 2 registers at a time.   *  of 16 store-multiple instructions, each storing 2 registers at a time.
2034   */   */
2035  void arm_combine_netbsd_memset(struct cpu *cpu, struct arm_instr_call *ic,  void COMBINE(netbsd_memset)(struct cpu *cpu,
2036          int low_addr)          struct arm_instr_call *ic, int low_addr)
2037  {  {
2038    #ifdef HOST_LITTLE_ENDIAN
2039          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2040              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
2041    
# Line 1602  void arm_combine_netbsd_memset(struct cp Line 2052  void arm_combine_netbsd_memset(struct cp
2052                          combined;                          combined;
2053                  }                  }
2054          }          }
2055    #endif
2056  }  }
2057    
2058    
2059  /*  /*
2060   *  arm_combine_netbsd_memcpy():   *  Combine: netbsd_memcpy():
2061   *   *
2062   *  Check for the core of a NetBSD/arm memcpy; large memcpys use a   *  Check for the core of a NetBSD/arm memcpy; large memcpys use a
2063   *  sequence of ldmia instructions.   *  sequence of ldmia instructions.
2064   */   */
2065  void arm_combine_netbsd_memcpy(struct cpu *cpu, struct arm_instr_call *ic,  void COMBINE(netbsd_memcpy)(struct cpu *cpu, struct arm_instr_call *ic,
2066          int low_addr)          int low_addr)
2067  {  {
2068    #ifdef HOST_LITTLE_ENDIAN
2069          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2070              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
2071    
# Line 1630  void arm_combine_netbsd_memcpy(struct cp Line 2082  void arm_combine_netbsd_memcpy(struct cp
2082                          combined;                          combined;
2083                  }                  }
2084          }          }
2085    #endif
2086  }  }
2087    
2088    
2089  /*  /*
2090   *  arm_combine_netbsd_cacheclean():   *  Combine: netbsd_cacheclean():
2091   *   *
2092   *  Check for the core of a NetBSD/arm cache clean. (There are two variants.)   *  Check for the core of a NetBSD/arm cache clean. (There are two variants.)
2093   */   */
2094  void arm_combine_netbsd_cacheclean(struct cpu *cpu, struct arm_instr_call *ic,  void COMBINE(netbsd_cacheclean)(struct cpu *cpu,
2095          int low_addr)          struct arm_instr_call *ic, int low_addr)
2096  {  {
2097          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2098              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
# Line 1658  void arm_combine_netbsd_cacheclean(struc Line 2111  void arm_combine_netbsd_cacheclean(struc
2111    
2112    
2113  /*  /*
2114   *  arm_combine_netbsd_cacheclean2():   *  Combine: netbsd_cacheclean2():
2115   *   *
2116   *  Check for the core of a NetBSD/arm cache clean. (Second variant.)   *  Check for the core of a NetBSD/arm cache clean. (Second variant.)
2117   */   */
2118  void arm_combine_netbsd_cacheclean2(struct cpu *cpu, struct arm_instr_call *ic,  void COMBINE(netbsd_cacheclean2)(struct cpu *cpu,
2119          int low_addr)          struct arm_instr_call *ic, int low_addr)
2120  {  {
2121          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2122              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
# Line 1683  void arm_combine_netbsd_cacheclean2(stru Line 2136  void arm_combine_netbsd_cacheclean2(stru
2136    
2137    
2138  /*  /*
2139   *  arm_combine_netbsd_scanc():   *  Combine: netbsd_scanc():
2140   */   */
2141  void arm_combine_netbsd_scanc(struct cpu *cpu, struct arm_instr_call *ic,  void COMBINE(netbsd_scanc)(struct cpu *cpu,
2142          int low_addr)          struct arm_instr_call *ic, int low_addr)
2143  {  {
2144          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2145              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
2146    
2147          if (n_back >= 2) {          if (n_back < 2)
2148                  if (ic[-2].f == instr(load_w0_byte_u1_p1_imm) &&                  return;
2149                      ic[-1].f == instr(load_w0_byte_u1_p1_reg)) {  
2150                          ic[-2].f = instr(netbsd_scanc);          if (ic[-2].f == instr(load_w0_byte_u1_p1_imm) &&
2151                          combined;              ic[-2].arg[0] == (size_t)(&cpu->cd.arm.r[1]) &&
2152                  }              ic[-2].arg[1] == 0 &&
2153                ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[3]) &&
2154                ic[-1].f == instr(load_w0_byte_u1_p1_reg) &&
2155                ic[-1].arg[0] == (size_t)(&cpu->cd.arm.r[2]) &&
2156                ic[-1].arg[1] == (size_t)arm_r_r3_t0_c0 &&
2157                ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[3])) {
2158                    ic[-2].f = instr(netbsd_scanc);
2159                    combined;
2160          }          }
2161  }  }
2162    
2163    
2164  /*  /*
2165   *  arm_combine_test2():   *  Combine: strlen():
2166   */   */
2167  void arm_combine_test2(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)  void COMBINE(strlen)(struct cpu *cpu,
2168            struct arm_instr_call *ic, int low_addr)
2169  {  {
2170          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2171              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
2172    
2173          if (n_back >= 2) {          if (n_back < 2)
2174                  if (ic[-2].f == instr(store_w0_word_u1_p0_imm) &&                  return;
2175                      ic[-2].arg[1] == 4 &&  
2176                      ic[-1].f == instr(subs) &&          if (ic[-2].f == instr(load_w1_byte_u1_p1_imm) &&
2177                      ic[-1].arg[0] == ic[-1].arg[2] && ic[-1].arg[1] == 4 &&              ic[-2].arg[1] == 1 &&
2178                      ic[ 0].f == instr(b_samepage__gt) &&              ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[3]) &&
2179                      ic[ 0].arg[0] == (size_t)&ic[-2]) {              ic[-1].f == instr(cmps) &&
2180                          ic[-2].f = instr(fill_loop_test2);              ic[-1].arg[0] == (size_t)(&cpu->cd.arm.r[3]) &&
2181  printf("YO test2\n");              ic[-1].arg[1] == 0) {
2182                          combined;                  ic[-2].f = instr(strlen);
2183                  }                  combined;
2184          }          }
2185  }  }
2186    
2187    
2188  #if 0  /*
2189          /*  TODO: This is another test hack.  */   *  Combine: xchg():
2190     */
2191    void COMBINE(xchg)(struct cpu *cpu,
2192            struct arm_instr_call *ic, int low_addr)
2193    {
2194            int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2195                & (ARM_IC_ENTRIES_PER_PAGE-1);
2196            size_t a, b;
2197    
2198          if (n_back >= 3) {          if (n_back < 2)
2199                  if (ic[-3].f == instr(cmps) &&                  return;
2200                      ic[-3].arg[0] == ic[-1].arg[0] &&  
2201                      ic[-3].arg[1] == 0 &&          a = ic[-2].arg[0]; b = ic[-1].arg[0];
2202                      ic[-2].f == instr(store_w0_byte_u1_p0_imm) &&  
2203                      ic[-2].arg[1] == 1 &&          if (ic[-2].f == instr(eor_regshort) &&
2204                      ic[-1].f == instr(sub) &&              ic[-1].f == instr(eor_regshort) &&
2205                      ic[-1].arg[0] == ic[-1].arg[2] && ic[-1].arg[1] == 1 &&              ic[-2].arg[0] == a && ic[-2].arg[1] == b && ic[-2].arg[2] == b &&
2206                      ic[ 0].f == instr(b_samepage__gt) &&              ic[-1].arg[0] == b && ic[-1].arg[1] == a && ic[-1].arg[2] == a &&
2207                      ic[ 0].arg[0] == (size_t)&ic[-3]) {              ic[ 0].arg[0] == a && ic[ 0].arg[1] == b && ic[ 0].arg[2] == b) {
2208                          ic[-3].f = instr(fill_loop_test);                  ic[-2].f = instr(xchg);
2209                    combined;
2210            }
2211    }
2212    
2213    
2214    /*
2215     *  Combine: netbsd_copyin():
2216     */
2217    void COMBINE(netbsd_copyin)(struct cpu *cpu,
2218            struct arm_instr_call *ic, int low_addr)
2219    {
2220    #ifdef HOST_LITTLE_ENDIAN
2221            int i, n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2222                & (ARM_IC_ENTRIES_PER_PAGE-1);
2223    
2224            if (n_back < 5)
2225                    return;
2226    
2227            for (i=-5; i<0; i++) {
2228                    if (ic[i].f != instr(load_w1_word_u1_p0_imm) ||
2229                        ic[i].arg[0] != (size_t)(&cpu->cd.arm.r[0]) ||
2230                        ic[i].arg[1] != 4)
2231                            return;
2232            }
2233    
2234            if (ic[-5].arg[2] == (size_t)(&cpu->cd.arm.r[10]) &&
2235                ic[-4].arg[2] == (size_t)(&cpu->cd.arm.r[11]) &&
2236                ic[-3].arg[2] == (size_t)(&cpu->cd.arm.r[6]) &&
2237                ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[7]) &&
2238                ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[8])) {
2239                    ic[-5].f = instr(netbsd_copyin);
2240                    combined;
2241            }
2242    #endif
2243    }
2244    
2245    
2246    /*
2247     *  Combine: netbsd_copyout():
2248     */
2249    void COMBINE(netbsd_copyout)(struct cpu *cpu,
2250            struct arm_instr_call *ic, int low_addr)
2251    {
2252    #ifdef HOST_LITTLE_ENDIAN
2253            int i, n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2254                & (ARM_IC_ENTRIES_PER_PAGE-1);
2255    
2256            if (n_back < 5)
2257                    return;
2258    
2259            for (i=-5; i<0; i++) {
2260                    if (ic[i].f != instr(store_w1_word_u1_p0_imm) ||
2261                        ic[i].arg[0] != (size_t)(&cpu->cd.arm.r[1]) ||
2262                        ic[i].arg[1] != 4)
2263                            return;
2264            }
2265    
2266            if (ic[-5].arg[2] == (size_t)(&cpu->cd.arm.r[8]) &&
2267                ic[-4].arg[2] == (size_t)(&cpu->cd.arm.r[9]) &&
2268                ic[-3].arg[2] == (size_t)(&cpu->cd.arm.r[10]) &&
2269                ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[11]) &&
2270                ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[6])) {
2271                    ic[-5].f = instr(netbsd_copyout);
2272                    combined;
2273            }
2274    #endif
2275    }
2276    
2277    
2278    /*
2279     *  Combine: cmps_b():
2280     */
2281    void COMBINE(cmps_b)(struct cpu *cpu,
2282            struct arm_instr_call *ic, int low_addr)
2283    {
2284            int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2285                & (ARM_IC_ENTRIES_PER_PAGE-1);
2286            if (n_back < 1)
2287                    return;
2288            if (ic[0].f == instr(b__eq)) {
2289                    if (ic[-1].f == instr(cmps)) {
2290                            if (ic[-1].arg[1] == 0)
2291                                    ic[-1].f = instr(cmps_0_beq);
2292                            else if (ic[-1].arg[1] & 0x80000000)
2293                                    ic[-1].f = instr(cmps_neg_beq);
2294                            else
2295                                    ic[-1].f = instr(cmps_pos_beq);
2296                          combined;                          combined;
2297                  }                  }
2298                    return;
2299          }          }
2300          /*  TODO: Combine forward as well  */          if (ic[0].f == instr(b_samepage__eq)) {
2301  #endif                  if (ic[-1].f == instr(cmps)) {
2302                            if (ic[-1].arg[1] == 0)
2303                                    ic[-1].f = instr(cmps0_beq_samepage);
2304                            else
2305                                    ic[-1].f = instr(cmps_beq_samepage);
2306                            combined;
2307                    }
2308                    if (ic[-1].f == instr(tsts) &&
2309                        !(ic[-1].arg[1] & 0x80000000)) {
2310                            ic[-1].f = instr(tsts_lo_beq_samepage);
2311                            combined;
2312                    }
2313                    if (ic[-1].f == instr(teqs)) {
2314                            ic[-1].f = instr(teqs_beq_samepage);
2315                            combined;
2316                    }
2317                    return;
2318            }
2319            if (ic[0].f == instr(b_samepage__ne)) {
2320                    if (ic[-1].f == instr(cmps)) {
2321                            if (ic[-1].arg[1] == 0)
2322                                    ic[-1].f = instr(cmps0_bne_samepage);
2323                            else
2324                                    ic[-1].f = instr(cmps_bne_samepage);
2325                            combined;
2326                    }
2327                    if (ic[-1].f == instr(tsts) &&
2328                        !(ic[-1].arg[1] & 0x80000000)) {
2329                            ic[-1].f = instr(tsts_lo_bne_samepage);
2330                            combined;
2331                    }
2332                    if (ic[-1].f == instr(teqs)) {
2333                            ic[-1].f = instr(teqs_bne_samepage);
2334                            combined;
2335                    }
2336                    return;
2337            }
2338            if (ic[0].f == instr(b_samepage__cc)) {
2339                    if (ic[-1].f == instr(cmps)) {
2340                            ic[-1].f = instr(cmps_bcc_samepage);
2341                            combined;
2342                    }
2343                    if (ic[-1].f == instr(cmps_regshort)) {
2344                            ic[-1].f = instr(cmps_reg_bcc_samepage);
2345                            combined;
2346                    }
2347                    return;
2348            }
2349            if (ic[0].f == instr(b_samepage__hi)) {
2350                    if (ic[-1].f == instr(cmps)) {
2351                            ic[-1].f = instr(cmps_bhi_samepage);
2352                            combined;
2353                    }
2354                    if (ic[-1].f == instr(cmps_regshort)) {
2355                            ic[-1].f = instr(cmps_reg_bhi_samepage);
2356                            combined;
2357                    }
2358                    return;
2359            }
2360            if (ic[0].f == instr(b_samepage__gt)) {
2361                    if (ic[-1].f == instr(cmps)) {
2362                            ic[-1].f = instr(cmps_bgt_samepage);
2363                            combined;
2364                    }
2365                    return;
2366            }
2367            if (ic[0].f == instr(b_samepage__le)) {
2368                    if (ic[-1].f == instr(cmps)) {
2369                            ic[-1].f = instr(cmps_ble_samepage);
2370                            combined;
2371                    }
2372                    return;
2373            }
2374    }
2375    
2376    
2377    /*****************************************************************************/
2378    
2379    
2380    static void arm_switch_clear(struct arm_instr_call *ic, int rd,
2381            int condition_code)
2382    {
2383            switch (rd) {
2384            case  0: ic->f = cond_instr(clear_r0); break;
2385            case  1: ic->f = cond_instr(clear_r1); break;
2386            case  2: ic->f = cond_instr(clear_r2); break;
2387            case  3: ic->f = cond_instr(clear_r3); break;
2388            case  4: ic->f = cond_instr(clear_r4); break;
2389            case  5: ic->f = cond_instr(clear_r5); break;
2390            case  6: ic->f = cond_instr(clear_r6); break;
2391            case  7: ic->f = cond_instr(clear_r7); break;
2392            case  8: ic->f = cond_instr(clear_r8); break;
2393            case  9: ic->f = cond_instr(clear_r9); break;
2394            case 10: ic->f = cond_instr(clear_r10); break;
2395            case 11: ic->f = cond_instr(clear_r11); break;
2396            case 12: ic->f = cond_instr(clear_r12); break;
2397            case 13: ic->f = cond_instr(clear_r13); break;
2398            case 14: ic->f = cond_instr(clear_r14); break;
2399            }
2400    }
2401    
2402    
2403    static void arm_switch_mov1(struct arm_instr_call *ic, int rd,
2404            int condition_code)
2405    {
2406            switch (rd) {
2407            case  0: ic->f = cond_instr(mov1_r0); break;
2408            case  1: ic->f = cond_instr(mov1_r1); break;
2409            case  2: ic->f = cond_instr(mov1_r2); break;
2410            case  3: ic->f = cond_instr(mov1_r3); break;
2411            case  4: ic->f = cond_instr(mov1_r4); break;
2412            case  5: ic->f = cond_instr(mov1_r5); break;
2413            case  6: ic->f = cond_instr(mov1_r6); break;
2414            case  7: ic->f = cond_instr(mov1_r7); break;
2415            case  8: ic->f = cond_instr(mov1_r8); break;
2416            case  9: ic->f = cond_instr(mov1_r9); break;
2417            case 10: ic->f = cond_instr(mov1_r10); break;
2418            case 11: ic->f = cond_instr(mov1_r11); break;
2419            case 12: ic->f = cond_instr(mov1_r12); break;
2420            case 13: ic->f = cond_instr(mov1_r13); break;
2421            case 14: ic->f = cond_instr(mov1_r14); break;
2422            }
2423    }
2424    
2425    
2426    static void arm_switch_add1(struct arm_instr_call *ic, int rd,
2427            int condition_code)
2428    {
2429            switch (rd) {
2430            case  0: ic->f = cond_instr(add1_r0); break;
2431            case  1: ic->f = cond_instr(add1_r1); break;
2432            case  2: ic->f = cond_instr(add1_r2); break;
2433            case  3: ic->f = cond_instr(add1_r3); break;
2434            case  4: ic->f = cond_instr(add1_r4); break;
2435            case  5: ic->f = cond_instr(add1_r5); break;
2436            case  6: ic->f = cond_instr(add1_r6); break;
2437            case  7: ic->f = cond_instr(add1_r7); break;
2438            case  8: ic->f = cond_instr(add1_r8); break;
2439            case  9: ic->f = cond_instr(add1_r9); break;
2440            case 10: ic->f = cond_instr(add1_r10); break;
2441            case 11: ic->f = cond_instr(add1_r11); break;
2442            case 12: ic->f = cond_instr(add1_r12); break;
2443            case 13: ic->f = cond_instr(add1_r13); break;
2444            case 14: ic->f = cond_instr(add1_r14); break;
2445            }
2446    }
2447    
2448    
2449  /*****************************************************************************/  /*****************************************************************************/
# Line 1762  X(to_be_translated) Line 2463  X(to_be_translated)
2463          unsigned char *page;          unsigned char *page;
2464          unsigned char ib[4];          unsigned char ib[4];
2465          int condition_code, main_opcode, secondary_opcode, s_bit, rn, rd, r8;          int condition_code, main_opcode, secondary_opcode, s_bit, rn, rd, r8;
2466          int p_bit, u_bit, b_bit, w_bit, l_bit, regform, rm, c, t, any_pc_reg;          int p_bit, u_bit, w_bit, l_bit, regform, rm, c, t, any_pc_reg;
2467          void (*samepage_function)(struct cpu *, struct arm_instr_call *);          void (*samepage_function)(struct cpu *, struct arm_instr_call *);
2468    
2469          /*  Figure out the address of the instruction:  */          /*  Figure out the address of the instruction:  */
2470          low_pc = ((size_t)ic - (size_t)cpu->cd.arm.cur_ic_page)          low_pc = ((size_t)ic - (size_t)cpu->cd.arm.cur_ic_page)
2471              / sizeof(struct arm_instr_call);              / sizeof(struct arm_instr_call);
2472          addr = cpu->cd.arm.r[ARM_PC] & ~((ARM_IC_ENTRIES_PER_PAGE-1) <<          addr = cpu->pc & ~((ARM_IC_ENTRIES_PER_PAGE-1) <<
2473              ARM_INSTR_ALIGNMENT_SHIFT);              ARM_INSTR_ALIGNMENT_SHIFT);
2474          addr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          addr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
2475          cpu->pc = cpu->cd.arm.r[ARM_PC] = addr;          cpu->pc = addr;
2476          addr &= ~((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);          addr &= ~((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);
2477    
2478          /*  Read the instruction word from memory:  */          /*  Read the instruction word from memory:  */
2479          page = cpu->cd.arm.host_load[addr >> 12];          page = cpu->cd.arm.host_load[addr >> 12];
2480          if (page != NULL) {          if (page != NULL) {
2481                  /*  fatal("TRANSLATION HIT!\n");  */                  /*  fatal("TRANSLATION HIT! 0x%08x\n", addr);  */
2482                  memcpy(ib, page + (addr & 0xfff), sizeof(ib));                  memcpy(ib, page + (addr & 0xfff), sizeof(ib));
2483          } else {          } else {
2484                  /*  fatal("TRANSLATION MISS!\n");  */                  /*  fatal("TRANSLATION MISS! 0x%08x\n", addr);  */
2485                  if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],                  if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],
2486                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
2487                          fatal("to_be_translated(): "                          fatal("to_be_translated(): "
# Line 1805  X(to_be_translated) Line 2506  X(to_be_translated)
2506          condition_code = iword >> 28;          condition_code = iword >> 28;
2507          main_opcode = (iword >> 24) & 15;          main_opcode = (iword >> 24) & 15;
2508          secondary_opcode = (iword >> 21) & 15;          secondary_opcode = (iword >> 21) & 15;
2509          u_bit = (iword >> 23) & 1;          u_bit = iword & 0x00800000;
2510          b_bit = (iword >> 22) & 1;          w_bit = iword & 0x00200000;
2511          w_bit = (iword >> 21) & 1;          s_bit = l_bit = iword & 0x00100000;
         s_bit = l_bit = (iword >> 20) & 1;  
2512          rn    = (iword >> 16) & 15;          rn    = (iword >> 16) & 15;
2513          rd    = (iword >> 12) & 15;          rd    = (iword >> 12) & 15;
2514          r8    = (iword >> 8) & 15;          r8    = (iword >> 8) & 15;
# Line 1873  X(to_be_translated) Line 2573  X(to_be_translated)
2573                          ic->arg[0] = iword;                          ic->arg[0] = iword;
2574                          break;                          break;
2575                  }                  }
2576                    if ((iword & 0x0f900ff0) == 0x01000050) {
2577                            fatal("TODO: q{,d}{add,sub}\n");
2578                            goto bad;
2579                    }
2580                  if ((iword & 0x0ff000d0) == 0x01200010) {                  if ((iword & 0x0ff000d0) == 0x01200010) {
2581                          /*  bx or blx  */                          /*  bx or blx  */
2582                          if (iword & 0x20)                          if (iword & 0x20)
# Line 1897  X(to_be_translated) Line 2601  X(to_be_translated)
2601                          ic->arg[2] = (size_t)(&cpu->cd.arm.r[rn]);                          ic->arg[2] = (size_t)(&cpu->cd.arm.r[rn]);
2602                          break;                          break;
2603                  }                  }
2604                    if ((iword & 0x0fff0ff0) == 0x016f0f10) {
2605                            ic->f = cond_instr(clz);
2606                            ic->arg[0] = (size_t)(&cpu->cd.arm.r[rm]);
2607                            ic->arg[1] = (size_t)(&cpu->cd.arm.r[rd]);
2608                            break;
2609                    }
2610                    if ((iword & 0x0ff00090) == 0x01000080) {
2611                            /*  TODO: smlaXX  */
2612                            goto bad;
2613                    }
2614                    if ((iword & 0x0ff00090) == 0x01400080) {
2615                            /*  TODO: smlalY  */
2616                            goto bad;
2617                    }
2618                    if ((iword & 0x0ff000b0) == 0x01200080) {
2619                            /*  TODO: smlawY  */
2620                            goto bad;
2621                    }
2622                    if ((iword & 0x0ff0f090) == 0x01600080) {
2623                            /*  smulXY (16-bit * 16-bit => 32-bit)  */
2624                            switch (iword & 0x60) {
2625                            case 0x00: ic->f = cond_instr(smulbb); break;
2626                            case 0x20: ic->f = cond_instr(smultb); break;
2627                            case 0x40: ic->f = cond_instr(smulbt); break;
2628                            default:   ic->f = cond_instr(smultt); break;
2629                            }
2630                            ic->arg[0] = (size_t)(&cpu->cd.arm.r[rm]);
2631                            ic->arg[1] = (size_t)(&cpu->cd.arm.r[r8]);
2632                            ic->arg[2] = (size_t)(&cpu->cd.arm.r[rn]); /*  Rd  */
2633                            break;
2634                    }
2635                    if ((iword & 0x0ff0f0b0) == 0x012000a0) {
2636                            /*  TODO: smulwY  */
2637                            goto bad;
2638                    }
2639                  if ((iword & 0x0fb0fff0) == 0x0120f000 ||                  if ((iword & 0x0fb0fff0) == 0x0120f000 ||
2640                      (iword & 0x0fb0f000) == 0x0320f000) {                      (iword & 0x0fb0f000) == 0x0320f000) {
2641                          /*  msr: move to [S|C]PSR from a register or                          /*  msr: move to [S|C]PSR from a register or
2642                              immediate value  */                              immediate value  */
                         if (rm == ARM_PC) {  
                                 fatal("msr PC?\n");  
                                 goto bad;  
                         }  
2643                          if (iword & 0x02000000) {                          if (iword & 0x02000000) {
2644                                  if (iword & 0x00400000)                                  if (iword & 0x00400000)
2645                                          ic->f = cond_instr(msr_imm_spsr);                                          ic->f = cond_instr(msr_imm_spsr);
2646                                  else                                  else
2647                                          ic->f = cond_instr(msr_imm);                                          ic->f = cond_instr(msr_imm);
2648                          } else {                          } else {
2649                                    if (rm == ARM_PC) {
2650                                            fatal("msr PC?\n");
2651                                            goto bad;
2652                                    }
2653                                  if (iword & 0x00400000)                                  if (iword & 0x00400000)
2654                                          ic->f = cond_instr(msr_spsr);                                          ic->f = cond_instr(msr_spsr);
2655                                  else                                  else
# Line 1992  X(to_be_translated) Line 2731  X(to_be_translated)
2731                          break;                          break;
2732                  }                  }
2733    
2734                  /*  "mov reg,reg":  */                  /*  "mov reg,reg" or "mov reg,pc":  */
2735                  if ((iword & 0x0fff0ff0) == 0x01a00000 &&                  if ((iword & 0x0fff0ff0) == 0x01a00000 && rd != ARM_PC) {
2736                      (iword&15) != ARM_PC && rd != ARM_PC) {                          if (rm != ARM_PC) {
2737                          ic->f = cond_instr(mov_reg_reg);                                  ic->f = cond_instr(mov_reg_reg);
2738                          ic->arg[0] = (size_t)(&cpu->cd.arm.r[iword & 15]);                                  ic->arg[0] = (size_t)(&cpu->cd.arm.r[rm]);
2739                            } else {
2740                                    ic->f = cond_instr(mov_reg_pc);
2741                                    ic->arg[0] = (addr & 0xfff) + 8;
2742                            }
2743                          ic->arg[1] = (size_t)(&cpu->cd.arm.r[rd]);                          ic->arg[1] = (size_t)(&cpu->cd.arm.r[rd]);
2744                          break;                          break;
2745                  }                  }
2746    
2747                  /*  "mov reg,#0":  */                  /*  "mov reg,#0":  */
2748                  if ((iword & 0x0fff0fff) == 0x03a03000 && rd != ARM_PC) {                  if ((iword & 0x0fff0fff) == 0x03a00000 && rd != ARM_PC) {
2749                          switch (rd) {                          arm_switch_clear(ic, rd, condition_code);
                         case  0: ic->f = cond_instr(clear_r0); break;  
                         case  1: ic->f = cond_instr(clear_r1); break;  
                         case  2: ic->f = cond_instr(clear_r2); break;  
                         case  3: ic->f = cond_instr(clear_r3); break;  
                         case  4: ic->f = cond_instr(clear_r4); break;  
                         case  5: ic->f = cond_instr(clear_r5); break;  
                         case  6: ic->f = cond_instr(clear_r6); break;  
                         case  7: ic->f = cond_instr(clear_r7); break;  
                         case  8: ic->f = cond_instr(clear_r8); break;  
                         case  9: ic->f = cond_instr(clear_r9); break;  
                         case 10: ic->f = cond_instr(clear_r10); break;  
                         case 11: ic->f = cond_instr(clear_r11); break;  
                         case 12: ic->f = cond_instr(clear_r12); break;  
                         case 13: ic->f = cond_instr(clear_r13); break;  
                         case 14: ic->f = cond_instr(clear_r14); break;  
                         }  
2750                          break;                          break;
2751                  }                  }
2752    
2753                  /*  "mov reg,#1":  */                  /*  "mov reg,#1":  */
2754                  if ((iword & 0x0fff0fff) == 0x03a03001 && rd != ARM_PC) {                  if ((iword & 0x0fff0fff) == 0x03a00001 && rd != ARM_PC) {
2755                          switch (rd) {                          arm_switch_mov1(ic, rd, condition_code);
2756                          case  0: ic->f = cond_instr(mov1_r0); break;                          break;
2757                          case  1: ic->f = cond_instr(mov1_r1); break;                  }
2758                          case  2: ic->f = cond_instr(mov1_r2); break;  
2759                          case  3: ic->f = cond_instr(mov1_r3); break;                  /*  "add reg,reg,#1":  */
2760                          case  4: ic->f = cond_instr(mov1_r4); break;                  if ((iword & 0x0ff00fff) == 0x02800001 && rd != ARM_PC
2761                          case  5: ic->f = cond_instr(mov1_r5); break;                      && rn == rd) {
2762                          case  6: ic->f = cond_instr(mov1_r6); break;                          arm_switch_add1(ic, rd, condition_code);
                         case  7: ic->f = cond_instr(mov1_r7); break;  
                         case  8: ic->f = cond_instr(mov1_r8); break;  
                         case  9: ic->f = cond_instr(mov1_r9); break;  
                         case 10: ic->f = cond_instr(mov1_r10); break;  
                         case 11: ic->f = cond_instr(mov1_r11); break;  
                         case 12: ic->f = cond_instr(mov1_r12); break;  
                         case 13: ic->f = cond_instr(mov1_r13); break;  
                         case 14: ic->f = cond_instr(mov1_r14); break;  
                         }  
2763                          break;                          break;
2764                  }                  }
2765    
# Line 2072  X(to_be_translated) Line 2790  X(to_be_translated)
2790                          ic->arg[1] = imm;                          ic->arg[1] = imm;
2791                  }                  }
2792    
2793                    /*  mvn #imm ==> mov #~imm  */
2794                    if (secondary_opcode == 0xf && !regform) {
2795                            secondary_opcode = 0xd;
2796                            ic->arg[1] = ~ic->arg[1];
2797                    }
2798    
2799                  ic->arg[0] = (size_t)(&cpu->cd.arm.r[rn]);                  ic->arg[0] = (size_t)(&cpu->cd.arm.r[rn]);
2800                  ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);                  ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);
2801                  any_pc_reg = 0;                  any_pc_reg = 0;
2802                  if (rn == ARM_PC || rd == ARM_PC)                  if (rn == ARM_PC || rd == ARM_PC)
2803                          any_pc_reg = 1;                          any_pc_reg = 1;
2804    
2805                  ic->f = arm_dpi_instr[condition_code +                  if (!any_pc_reg && regform && (iword & 0xfff) < ARM_PC) {
2806                      16 * secondary_opcode + (s_bit? 256 : 0) +                          ic->arg[1] = (size_t)(&cpu->cd.arm.r[rm]);
2807                      (any_pc_reg? 512 : 0) + (regform? 1024 : 0)];                          ic->f = arm_dpi_instr_regshort[condition_code +
2808                                16 * secondary_opcode + (s_bit? 256 : 0)];
2809                    } else
2810                            ic->f = arm_dpi_instr[condition_code +
2811                                16 * secondary_opcode + (s_bit? 256 : 0) +
2812                                (any_pc_reg? 512 : 0) + (regform? 1024 : 0)];
2813    
2814                    if (ic->f == instr(eor_regshort))
2815                            cpu->cd.arm.combination_check = COMBINE(xchg);
2816                  if (iword == 0xe113000c)                  if (iword == 0xe113000c)
2817                          cpu->combination_check = arm_combine_netbsd_scanc;                          cpu->cd.arm.combination_check = COMBINE(netbsd_scanc);
2818                  break;                  break;
2819    
2820          case 0x4:       /*  Load and store...  */          case 0x4:       /*  Load and store...  */
# Line 2112  X(to_be_translated) Line 2843  X(to_be_translated)
2843                          fatal("Not a Load/store TODO\n");                          fatal("Not a Load/store TODO\n");
2844                          goto bad;                          goto bad;
2845                  }                  }
2846                    /*  Special case: pc-relative load within the same page:  */
2847                    if (rn == ARM_PC && rd != ARM_PC && main_opcode < 6) {
2848                            int ofs = (addr & 0xfff) + 8, max = 0xffc;
2849                            int b_bit = iword & 0x00400000;
2850                            if (b_bit)
2851                                    max = 0xfff;
2852                            if (u_bit)
2853                                    ofs += (iword & 0xfff);
2854                            else
2855                                    ofs -= (iword & 0xfff);
2856                            /*  NOTE/TODO: This assumes 4KB pages,
2857                                it will not work with 1KB pages.  */
2858                            if (ofs >= 0 && ofs <= max) {
2859                                    unsigned char *p;
2860                                    unsigned char c[4];
2861                                    int len = b_bit? 1 : 4;
2862                                    uint32_t x, a = (addr & 0xfffff000) | ofs;
2863                                    /*  ic->f = cond_instr(mov);  */
2864                                    ic->f = arm_dpi_instr[condition_code + 16*0xd];
2865                                    ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);
2866                                    p = cpu->cd.arm.host_load[a >> 12];
2867                                    if (p != NULL) {
2868                                            memcpy(c, p + (a & 0xfff), len);
2869                                    } else {
2870                                            if (!cpu->memory_rw(cpu, cpu->mem, a,
2871                                                c, len, MEM_READ, CACHE_DATA)) {
2872                                                    fatal("to_be_translated(): "
2873                                                        "read failed X: TODO\n");
2874                                                    goto bad;
2875                                            }
2876                                    }
2877                                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2878                                            x = c[0] + (c[1]<<8) +
2879                                                (c[2]<<16) + (c[3]<<24);
2880                                    else
2881                                            x = c[3] + (c[2]<<8) +
2882                                                (c[1]<<16) + (c[0]<<24);
2883                                    if (b_bit)
2884                                            x = c[0];
2885                                    ic->arg[1] = x;
2886                            }
2887                    }
2888                    if (iword == 0xe4b09004)
2889                            cpu->cd.arm.combination_check = COMBINE(netbsd_copyin);
2890                    if (iword == 0xe4a17004)
2891                            cpu->cd.arm.combination_check = COMBINE(netbsd_copyout);
2892                  break;                  break;
2893    
2894          case 0x8:       /*  Multiple load/store...  (Block data transfer)  */          case 0x8:       /*  Multiple load/store...  (Block data transfer)  */
# Line 2162  X(to_be_translated) Line 2939  X(to_be_translated)
2939                  if (main_opcode == 0x0a) {                  if (main_opcode == 0x0a) {
2940                          ic->f = cond_instr(b);                          ic->f = cond_instr(b);
2941                          samepage_function = cond_instr(b_samepage);                          samepage_function = cond_instr(b_samepage);
                         /*  if (iword == 0xcafffffc)  
                                 cpu->combination_check = arm_combine_test2;  */  
2942                          if (iword == 0xcaffffed)                          if (iword == 0xcaffffed)
2943                                  cpu->combination_check =                                  cpu->cd.arm.combination_check =
2944                                      arm_combine_netbsd_memset;                                      COMBINE(netbsd_memset);
2945                          if (iword == 0xaafffff9)                          if (iword == 0xaafffff9)
2946                                  cpu->combination_check =                                  cpu->cd.arm.combination_check =
2947                                      arm_combine_netbsd_memcpy;                                      COMBINE(netbsd_memcpy);
2948                  } else {                  } else {
2949                          if (cpu->machine->show_trace_tree) {                          if (cpu->machine->show_trace_tree) {
2950                                  ic->f = cond_instr(bl_trace);                                  ic->f = cond_instr(bl_trace);
# Line 2181  X(to_be_translated) Line 2956  X(to_be_translated)
2956                          }                          }
2957                  }                  }
2958    
2959                    /*  arg 1 = offset of current instruction  */
2960                    /*  arg 2 = offset of the following instruction  */
2961                    ic->arg[1] = addr & 0xffc;
2962                    ic->arg[2] = (addr & 0xffc) + 4;
2963    
2964                  ic->arg[0] = (iword & 0x00ffffff) << 2;                  ic->arg[0] = (iword & 0x00ffffff) << 2;
2965                  /*  Sign-extend:  */                  /*  Sign-extend:  */
2966                  if (ic->arg[0] & 0x02000000)                  if (ic->arg[0] & 0x02000000)
# Line 2190  X(to_be_translated) Line 2970  X(to_be_translated)
2970                   */                   */
2971                  ic->arg[0] = (int32_t)(ic->arg[0] + 8);                  ic->arg[0] = (int32_t)(ic->arg[0] + 8);
2972    
2973                  /*  Special case: branch within the same page:  */                  /*
2974                     *  Special case: branch within the same page:
2975                     *
2976                     *  arg[0] = addr of the arm_instr_call of the target
2977                     *  arg[1] = addr of the next arm_instr_call.
2978                     */
2979                  {                  {
2980                          uint32_t mask_within_page =                          uint32_t mask_within_page =
2981                              ((ARM_IC_ENTRIES_PER_PAGE-1) <<                              ((ARM_IC_ENTRIES_PER_PAGE-1) <<
# Line 2205  X(to_be_translated) Line 2990  X(to_be_translated)
2990                                      cpu->cd.arm.cur_ic_page +                                      cpu->cd.arm.cur_ic_page +
2991                                      ((new_pc & mask_within_page) >>                                      ((new_pc & mask_within_page) >>
2992                                      ARM_INSTR_ALIGNMENT_SHIFT));                                      ARM_INSTR_ALIGNMENT_SHIFT));
2993                                    ic->arg[1] = (size_t) (
2994                                        cpu->cd.arm.cur_ic_page +
2995                                        (((addr & mask_within_page) + 4) >>
2996                                        ARM_INSTR_ALIGNMENT_SHIFT));
2997                            } else if (main_opcode == 0x0a) {
2998                                    /*  Special hack for a plain "b":  */
2999                                    ic->arg[0] += ic->arg[1];
3000                          }                          }
3001                  }                  }
3002    
3003  #if 0                  if (main_opcode == 0xa && (condition_code <= 1
3004                  /*  Hm. This doesn't really increase performance.  */                      || condition_code == 3 || condition_code == 8
3005                        || condition_code == 12 || condition_code == 13))
3006                            cpu->cd.arm.combination_check = COMBINE(cmps_b);
3007    
3008                    if (iword == 0x1afffffc)
3009                            cpu->cd.arm.combination_check = COMBINE(strlen);
3010    
3011                    /*  Hm. Does this really increase performance?  */
3012                  if (iword == 0x8afffffa)                  if (iword == 0x8afffffa)
3013                          cpu->combination_check = arm_combine_netbsd_cacheclean2;                          cpu->cd.arm.combination_check =
3014                                COMBINE(netbsd_cacheclean2);
3015                    break;
3016    
3017            case 0xc:
3018            case 0xd:
3019                    /*
3020                     *  xxxx1100 0100nnnn ddddcccc oooommmm    MCRR c,op,Rd,Rn,CRm
3021                     *  xxxx1100 0101nnnn ddddcccc oooommmm    MRRC c,op,Rd,Rn,CRm
3022                     */
3023                    if ((iword & 0x0fe00fff) == 0x0c400000) {
3024                            /*  Special case: mar/mra DSP instructions  */
3025                            fatal("TODO: mar/mra DSP instructions!\n");
3026                            /*  Perhaps these are actually identical to MCRR/MRRC */
3027                            goto bad;
3028                    }
3029    
3030                    if ((iword & 0x0fe00000) == 0x0c400000) {
3031                            fatal("MCRR/MRRC: TODO\n");
3032                            goto bad;
3033                    }
3034    
3035                    /*
3036                     *  TODO: LDC/STC
3037                     *
3038                     *  For now, treat as Undefined instructions. This causes e.g.
3039                     *  Linux/ARM to emulate these instructions (floating point).
3040                     */
3041    #if 0
3042                    ic->f = cond_instr(und);
3043                    ic->arg[0] = addr & 0xfff;
3044    #else
3045                    fatal("LDC/STC: TODO\n");
3046                    goto bad;
3047  #endif  #endif
3048                  break;                  break;
3049    
3050          case 0xe:          case 0xe:
3051                    if ((iword & 0x0ff00ff0) == 0x0e200010) {
3052                            /*  Special case: mia* DSP instructions  */
3053                            /*  See Intel's 27343601.pdf, page 16-20  */
3054                            fatal("TODO: mia* DSP instructions!\n");
3055                            goto bad;
3056                    }
3057                  if (iword & 0x10) {                  if (iword & 0x10) {
3058                          /*  xxxx1110 oooLNNNN ddddpppp qqq1MMMM  MCR/MRC  */                          /*  xxxx1110 oooLNNNN ddddpppp qqq1MMMM  MCR/MRC  */
3059                          ic->arg[0] = iword;                          ic->arg[0] = iword;
# Line 2226  X(to_be_translated) Line 3064  X(to_be_translated)
3064                          ic->f = cond_instr(cdp);                          ic->f = cond_instr(cdp);
3065                  }                  }
3066                  if (iword == 0xee070f9a)                  if (iword == 0xee070f9a)
3067                          cpu->combination_check = arm_combine_netbsd_cacheclean;                          cpu->cd.arm.combination_check =
3068                                COMBINE(netbsd_cacheclean);
3069                  break;                  break;
3070    
3071          case 0xf:          case 0xf:
3072                  /*  SWI:  */                  /*  SWI:  */
3073                  /*  Default handler:  */                  /*  Default handler:  */
3074                  ic->f = cond_instr(swi);                  ic->f = cond_instr(swi);
3075                  if (iword == 0xef8c64be) {                  ic->arg[0] = addr & 0xfff;
3076                    if (iword == 0xef8c64eb) {
3077                            /*  Hack for rebooting a machine:  */
3078                            ic->f = instr(reboot);
3079                    } else if (iword == 0xef8c64be) {
3080                          /*  Hack for openfirmware prom emulation:  */                          /*  Hack for openfirmware prom emulation:  */
3081                          ic->f = instr(openfirmware);                          ic->f = instr(openfirmware);
3082                  } else if (cpu->machine->userland_emul != NULL) {                  } else if (cpu->machine->userland_emul != NULL) {

Legend:
Removed from v.18  
changed lines
  Added in v.24

  ViewVC Help
Powered by ViewVC 1.1.26