/[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 19 by dpavlin, Mon Oct 8 16:19:11 2007 UTC revision 20 by dpavlin, Mon Oct 8 16:19:23 2007 UTC
# 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.54 2005/11/19 18:53:07 debug Exp $
29   *   *
30   *  ARM instructions.   *  ARM instructions.
31   *   *
# Line 125  static void update_bdt_statistics(uint32 Line 125  static void update_bdt_statistics(uint32
125   *  functions, otherwise they will simply call the X function.   *  functions, otherwise they will simply call the X function.
126   */   */
127    
128    uint8_t condition_hi[16] = { 0,0,1,1, 0,0,0,0, 0,0,1,1, 0,0,0,0 };
129    uint8_t condition_ge[16] = { 1,0,1,0, 1,0,1,0, 0,1,0,1, 0,1,0,1 };
130    uint8_t condition_gt[16] = { 1,0,1,0, 0,0,0,0, 0,1,0,1, 0,0,0,0 };
131    
132  #define Y(n) void arm_instr_ ## n ## __eq(struct cpu *cpu,              \  #define Y(n) void arm_instr_ ## n ## __eq(struct cpu *cpu,              \
133                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
134          {  if (cpu->cd.arm.cpsr & ARM_FLAG_Z)                           \          {  if (cpu->cd.arm.flags & ARM_F_Z)                             \
135                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
136          void arm_instr_ ## n ## __ne(struct cpu *cpu,                   \          void arm_instr_ ## n ## __ne(struct cpu *cpu,                   \
137                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
138          {  if (!(cpu->cd.arm.cpsr & ARM_FLAG_Z))                        \          {  if (!(cpu->cd.arm.flags & ARM_F_Z))                          \
139                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
140          void arm_instr_ ## n ## __cs(struct cpu *cpu,                   \          void arm_instr_ ## n ## __cs(struct cpu *cpu,                   \
141                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
142          {  if (cpu->cd.arm.cpsr & ARM_FLAG_C)                           \          {  if (cpu->cd.arm.flags & ARM_F_C)                             \
143                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
144          void arm_instr_ ## n ## __cc(struct cpu *cpu,                   \          void arm_instr_ ## n ## __cc(struct cpu *cpu,                   \
145                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
146          {  if (!(cpu->cd.arm.cpsr & ARM_FLAG_C))                        \          {  if (!(cpu->cd.arm.flags & ARM_F_C))                          \
147                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
148          void arm_instr_ ## n ## __mi(struct cpu *cpu,                   \          void arm_instr_ ## n ## __mi(struct cpu *cpu,                   \
149                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
150          {  if (cpu->cd.arm.cpsr & ARM_FLAG_N)                           \          {  if (cpu->cd.arm.flags & ARM_F_N)                             \
151                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
152          void arm_instr_ ## n ## __pl(struct cpu *cpu,                   \          void arm_instr_ ## n ## __pl(struct cpu *cpu,                   \
153                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
154          {  if (!(cpu->cd.arm.cpsr & ARM_FLAG_N))                        \          {  if (!(cpu->cd.arm.flags & ARM_F_N))                          \
155                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
156          void arm_instr_ ## n ## __vs(struct cpu *cpu,                   \          void arm_instr_ ## n ## __vs(struct cpu *cpu,                   \
157                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
158          {  if (cpu->cd.arm.cpsr & ARM_FLAG_V)                           \          {  if (cpu->cd.arm.flags & ARM_F_V)                             \
159                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
160          void arm_instr_ ## n ## __vc(struct cpu *cpu,                   \          void arm_instr_ ## n ## __vc(struct cpu *cpu,                   \
161                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
162          {  if (!(cpu->cd.arm.cpsr & ARM_FLAG_V))                        \          {  if (!(cpu->cd.arm.flags & ARM_F_V))                          \
163                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
164          void arm_instr_ ## n ## __hi(struct cpu *cpu,                   \          void arm_instr_ ## n ## __hi(struct cpu *cpu,                   \
165                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
166          {  if (cpu->cd.arm.cpsr & ARM_FLAG_C &&                         \          {  if (condition_hi[cpu->cd.arm.flags])                         \
                 !(cpu->cd.arm.cpsr & ARM_FLAG_Z))                       \  
167                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
168          void arm_instr_ ## n ## __ls(struct cpu *cpu,                   \          void arm_instr_ ## n ## __ls(struct cpu *cpu,                   \
169                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
170          {  if (cpu->cd.arm.cpsr & ARM_FLAG_Z ||                         \          {  if (!condition_hi[cpu->cd.arm.flags])                        \
                 !(cpu->cd.arm.cpsr & ARM_FLAG_C))                       \  
171                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
172          void arm_instr_ ## n ## __ge(struct cpu *cpu,                   \          void arm_instr_ ## n ## __ge(struct cpu *cpu,                   \
173                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
174          {  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))                  \  
175                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
176          void arm_instr_ ## n ## __lt(struct cpu *cpu,                   \          void arm_instr_ ## n ## __lt(struct cpu *cpu,                   \
177                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
178          {  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))                  \  
179                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
180          void arm_instr_ ## n ## __gt(struct cpu *cpu,                   \          void arm_instr_ ## n ## __gt(struct cpu *cpu,                   \
181                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
182          {  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))                       \  
183                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
184          void arm_instr_ ## n ## __le(struct cpu *cpu,                   \          void arm_instr_ ## n ## __le(struct cpu *cpu,                   \
185                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
186          {  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))                        \  
187                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
188          void (*arm_cond_instr_ ## n  [16])(struct cpu *,                \          void (*arm_cond_instr_ ## n  [16])(struct cpu *,                \
189                          struct arm_instr_call *) = {                    \                          struct arm_instr_call *) = {                    \
# Line 215  X(invalid) { Line 211  X(invalid) {
211          uint32_t low_pc;          uint32_t low_pc;
212          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
213              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
214          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
215              << ARM_INSTR_ALIGNMENT_SHIFT);              << ARM_INSTR_ALIGNMENT_SHIFT);
216          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];  
217    
218          fatal("Invalid ARM instruction: pc=0x%08x\n", (int)cpu->pc);          fatal("Invalid ARM instruction: pc=0x%08x\n", (int)cpu->pc);
219    
# Line 236  X(invalid) { Line 231  X(invalid) {
231   */   */
232  X(b)  X(b)
233  {  {
234          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];  
235    
236          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
237          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
# Line 257  Y(b) Line 243  Y(b)
243   *  b_samepage:  Branch (to within the same translated page)   *  b_samepage:  Branch (to within the same translated page)
244   *   *
245   *  arg[0] = pointer to new arm_instr_call   *  arg[0] = pointer to new arm_instr_call
246     *  arg[1] = pointer to the next instruction.
247     *
248     *  NOTE: This instruction is manually inlined.
249   */   */
250  X(b_samepage)  X(b_samepage) {
 {  
251          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
252  }  }
253  Y(b_samepage)  X(b_samepage__eq) {
254            cpu->cd.arm.next_ic = (struct arm_instr_call *)
255                ic->arg[cpu->cd.arm.flags & ARM_F_Z? 0 : 1];
256    }
257    X(b_samepage__ne) {
258            cpu->cd.arm.next_ic = (struct arm_instr_call *)
259                ic->arg[cpu->cd.arm.flags & ARM_F_Z? 1 : 0];
260    }
261    X(b_samepage__cs) {
262            cpu->cd.arm.next_ic = (struct arm_instr_call *)
263                ic->arg[cpu->cd.arm.flags & ARM_F_C? 0 : 1];
264    }
265    X(b_samepage__cc) {
266            cpu->cd.arm.next_ic = (struct arm_instr_call *)
267                ic->arg[cpu->cd.arm.flags & ARM_F_C? 1 : 0];
268    }
269    X(b_samepage__mi) {
270            cpu->cd.arm.next_ic = (struct arm_instr_call *)
271                ic->arg[cpu->cd.arm.flags & ARM_F_N? 0 : 1];
272    }
273    X(b_samepage__pl) {
274            cpu->cd.arm.next_ic = (struct arm_instr_call *)
275                ic->arg[cpu->cd.arm.flags & ARM_F_N? 1 : 0];
276    }
277    X(b_samepage__vs) {
278            cpu->cd.arm.next_ic = (struct arm_instr_call *)
279                ic->arg[cpu->cd.arm.flags & ARM_F_V? 0 : 1];
280    }
281    X(b_samepage__vc) {
282            cpu->cd.arm.next_ic = (struct arm_instr_call *)
283                ic->arg[cpu->cd.arm.flags & ARM_F_V? 1 : 0];
284    }
285    X(b_samepage__hi) {
286            cpu->cd.arm.next_ic = (condition_hi[cpu->cd.arm.flags])?
287                (struct arm_instr_call *) ic->arg[0] :
288                (struct arm_instr_call *) ic->arg[1];
289    }
290    X(b_samepage__ls) {
291            cpu->cd.arm.next_ic = (struct arm_instr_call *)
292                ic->arg[condition_hi[cpu->cd.arm.flags]];
293    }
294    X(b_samepage__ge) {
295            cpu->cd.arm.next_ic = (condition_ge[cpu->cd.arm.flags])?
296                (struct arm_instr_call *) ic->arg[0] :
297                (struct arm_instr_call *) ic->arg[1];
298    }
299    X(b_samepage__lt) {
300            cpu->cd.arm.next_ic = (struct arm_instr_call *)
301                ic->arg[condition_ge[cpu->cd.arm.flags]];
302    }
303    X(b_samepage__gt) {
304            cpu->cd.arm.next_ic = (condition_gt[cpu->cd.arm.flags])?
305                (struct arm_instr_call *) ic->arg[0] :
306                (struct arm_instr_call *) ic->arg[1];
307    }
308    X(b_samepage__le) {
309            cpu->cd.arm.next_ic = (struct arm_instr_call *)
310                ic->arg[condition_gt[cpu->cd.arm.flags]];
311    }
312    void (*arm_cond_instr_b_samepage[16])(struct cpu *,
313            struct arm_instr_call *) = {
314            arm_instr_b_samepage__eq, arm_instr_b_samepage__ne,
315            arm_instr_b_samepage__cs, arm_instr_b_samepage__cc,
316            arm_instr_b_samepage__mi, arm_instr_b_samepage__pl,
317            arm_instr_b_samepage__vs, arm_instr_b_samepage__vc,
318            arm_instr_b_samepage__hi, arm_instr_b_samepage__ls,
319            arm_instr_b_samepage__ge, arm_instr_b_samepage__lt,
320            arm_instr_b_samepage__gt, arm_instr_b_samepage__le,
321            arm_instr_b_samepage, arm_instr_nop };
322    
323    
324  /*  /*
# Line 272  Y(b_samepage) Line 328  Y(b_samepage)
328   */   */
329  X(bx)  X(bx)
330  {  {
331          cpu->pc = cpu->cd.arm.r[ARM_PC] = reg(ic->arg[0]);          cpu->pc = reg(ic->arg[0]);
332          if (cpu->pc & 1) {          if (cpu->pc & 1) {
333                  fatal("thumb: TODO\n");                  fatal("thumb: TODO\n");
334                  exit(1);                  exit(1);
# Line 292  Y(bx) Line 348  Y(bx)
348   */   */
349  X(bx_trace)  X(bx_trace)
350  {  {
351          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
352          if (cpu->pc & 1) {          if (cpu->pc & 1) {
353                  fatal("thumb: TODO\n");                  fatal("thumb: TODO\n");
354                  exit(1);                  exit(1);
# Line 314  Y(bx_trace) Line 370  Y(bx_trace)
370   */   */
371  X(bl)  X(bl)
372  {  {
373          uint32_t lr, low_pc;          uint32_t pc = ((uint32_t)cpu->pc & 0xfffff000) + (int32_t)ic->arg[1];
374            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;  
375    
376          /*  Calculate new PC from this instruction + arg[0]  */          /*  Calculate new PC from this instruction + arg[0]  */
377          cpu->pc = cpu->cd.arm.r[ARM_PC] = lr - 4 + (int32_t)ic->arg[0];          cpu->pc = pc + (int32_t)ic->arg[0];
378    
379          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
380          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
# Line 342  Y(bl) Line 389  Y(bl)
389   */   */
390  X(blx)  X(blx)
391  {  {
392          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:  */  
393          cpu->cd.arm.r[ARM_LR] = lr;          cpu->cd.arm.r[ARM_LR] = lr;
394            cpu->pc = reg(ic->arg[0]);
         cpu->pc = cpu->cd.arm.r[ARM_PC] = reg(ic->arg[0]);  
395          if (cpu->pc & 1) {          if (cpu->pc & 1) {
396                  fatal("thumb: TODO\n");                  fatal("thumb: TODO\n");
397                  exit(1);                  exit(1);
# Line 374  Y(blx) Line 411  Y(blx)
411   */   */
412  X(bl_trace)  X(bl_trace)
413  {  {
414          uint32_t lr, low_pc;          uint32_t pc = ((uint32_t)cpu->pc & 0xfffff000) + (int32_t)ic->arg[1];
415            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;  
416    
417          /*  Calculate new PC from this instruction + arg[0]  */          /*  Calculate new PC from this instruction + arg[0]  */
418          cpu->pc = cpu->cd.arm.r[ARM_PC] = lr - 4 + (int32_t)ic->arg[0];          cpu->pc = pc + (int32_t)ic->arg[0];
419    
420          cpu_functioncall_trace(cpu, cpu->pc);          cpu_functioncall_trace(cpu, cpu->pc);
421    
# Line 404  Y(bl_trace) Line 432  Y(bl_trace)
432   */   */
433  X(bl_samepage)  X(bl_samepage)
434  {  {
435          uint32_t lr, low_pc;          cpu->cd.arm.r[ARM_LR] =
436                ((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:  */  
437          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
438  }  }
439  Y(bl_samepage)  Y(bl_samepage)
# Line 429  Y(bl_samepage) Line 446  Y(bl_samepage)
446   */   */
447  X(bl_samepage_trace)  X(bl_samepage_trace)
448  {  {
449          uint32_t tmp_pc, lr, low_pc;          uint32_t low_pc, lr = (cpu->pc & 0xfffff000) + ic->arg[2];
450    
451          /*  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:  */  
452          cpu->cd.arm.r[ARM_LR] = lr;          cpu->cd.arm.r[ARM_LR] = lr;
   
         /*  Branch:  */  
453          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
454    
455            /*  Synchronize the program counter:  */
456          low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)          low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)
457              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
458          tmp_pc = cpu->cd.arm.r[ARM_PC];          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
         tmp_pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)  
459              << ARM_INSTR_ALIGNMENT_SHIFT);              << ARM_INSTR_ALIGNMENT_SHIFT);
460          tmp_pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
461          cpu_functioncall_trace(cpu, tmp_pc);  
462            /*  ... and show trace:  */
463            cpu_functioncall_trace(cpu, cpu->pc);
464  }  }
465  Y(bl_samepage_trace)  Y(bl_samepage_trace)
466    
467    
468  #include "cpu_arm_instr_misc.c"  /*
469     *  clz: Count leading zeroes.
470     *
471     *  arg[0] = ptr to rm
472     *  arg[1] = ptr to rd
473     */
474    X(clz)
475    {
476            uint32_t rm = reg(ic->arg[0]);
477            int i = 32, n = 0, j;
478            while (i>0) {
479                    if (rm & 0xff000000) {
480                            for (j=0; j<8; j++) {
481                                    if (rm & 0x80000000)
482                                            break;
483                                    n ++;
484                                    rm <<= 1;
485                            }
486                            break;
487                    } else {
488                            rm <<= 8;
489                            i -= 8;
490                            n += 8;
491                    }
492            }
493            reg(ic->arg[1]) = n;
494    }
495    Y(clz)
496    
497    
498  /*  /*
# Line 474  X(muls) Line 511  X(muls)
511  {  {
512          uint32_t result;          uint32_t result;
513          result = reg(ic->arg[1]) * reg(ic->arg[2]);          result = reg(ic->arg[1]) * reg(ic->arg[2]);
514          cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N);          cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
515          if (result == 0)          if (result == 0)
516                  cpu->cd.arm.cpsr |= ARM_FLAG_Z;                  cpu->cd.arm.flags |= ARM_F_Z;
517          if (result & 0x80000000)          if (result & 0x80000000)
518                  cpu->cd.arm.cpsr |= ARM_FLAG_N;                  cpu->cd.arm.flags |= ARM_F_N;
519          reg(ic->arg[0]) = result;          reg(ic->arg[0]) = result;
520  }  }
521  Y(muls)  Y(muls)
# Line 509  X(mlas) Line 546  X(mlas)
546          rs = (iw >> 8) & 15;  rm = iw & 15;          rs = (iw >> 8) & 15;  rm = iw & 15;
547          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]
548              + cpu->cd.arm.r[rn];              + cpu->cd.arm.r[rn];
549          cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N);          cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
550          if (cpu->cd.arm.r[rd] == 0)          if (cpu->cd.arm.r[rd] == 0)
551                  cpu->cd.arm.cpsr |= ARM_FLAG_Z;                  cpu->cd.arm.flags |= ARM_F_Z;
552          if (cpu->cd.arm.r[rd] & 0x80000000)          if (cpu->cd.arm.r[rd] & 0x80000000)
553                  cpu->cd.arm.cpsr |= ARM_FLAG_N;                  cpu->cd.arm.flags |= ARM_F_N;
554  }  }
555  Y(mlas)  Y(mlas)
556    
# Line 528  X(mull) Line 565  X(mull)
565          /*  xxxx0000 1UAShhhh llllssss 1001mmmm  */          /*  xxxx0000 1UAShhhh llllssss 1001mmmm  */
566          uint32_t iw; uint64_t tmp; int u_bit, a_bit;          uint32_t iw; uint64_t tmp; int u_bit, a_bit;
567          iw = ic->arg[0];          iw = ic->arg[0];
568          u_bit = (iw >> 22) & 1; a_bit = (iw >> 21) & 1;          u_bit = iw & 0x00400000; a_bit = iw & 0x00200000;
569          tmp = cpu->cd.arm.r[iw & 15];          tmp = cpu->cd.arm.r[iw & 15];
570          if (u_bit)          if (u_bit)
571                  tmp = (int64_t)(int32_t)tmp                  tmp = (int64_t)(int32_t)tmp
# Line 563  Y(mov_reg_reg) Line 600  Y(mov_reg_reg)
600    
601    
602  /*  /*
603     *  mov_reg_pc:  Move the PC register to a normal register.
604     *
605     *  arg[0] = offset compared to start of current page + 8
606     *  arg[1] = ptr to destination register
607     */
608    X(mov_reg_pc)
609    {
610            reg(ic->arg[1]) = ((uint32_t)cpu->pc&0xfffff000) + (int32_t)ic->arg[0];
611    }
612    Y(mov_reg_pc)
613    
614    
615    /*
616   *  ret_trace:  "mov pc,lr" with trace enabled   *  ret_trace:  "mov pc,lr" with trace enabled
617   *  ret:  "mov pc,lr" without trace enabled   *  ret:  "mov pc,lr" without trace enabled
618   *   *
# Line 571  Y(mov_reg_reg) Line 621  Y(mov_reg_reg)
621  X(ret_trace)  X(ret_trace)
622  {  {
623          uint32_t old_pc, mask_within_page;          uint32_t old_pc, mask_within_page;
624          old_pc = cpu->cd.arm.r[ARM_PC];          old_pc = cpu->pc;
625          mask_within_page = ((ARM_IC_ENTRIES_PER_PAGE-1)          mask_within_page = ((ARM_IC_ENTRIES_PER_PAGE-1)
626              << ARM_INSTR_ALIGNMENT_SHIFT) |              << ARM_INSTR_ALIGNMENT_SHIFT) |
627              ((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);              ((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);
628    
629          /*  Update the PC register:  */          /*  Update the PC register:  */
630          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
631    
632          cpu_functioncall_trace_return(cpu);          cpu_functioncall_trace_return(cpu);
633    
# Line 596  X(ret_trace) Line 646  X(ret_trace)
646  Y(ret_trace)  Y(ret_trace)
647  X(ret)  X(ret)
648  {  {
649          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
650          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
651  }  }
652  Y(ret)  Y(ret)
# Line 620  X(msr_imm) Line 670  X(msr_imm)
670              (ic->arg[0] & ARM_FLAG_MODE));              (ic->arg[0] & ARM_FLAG_MODE));
671          uint32_t new_value = ic->arg[0];          uint32_t new_value = ic->arg[0];
672    
673            cpu->cd.arm.cpsr &= 0x0fffffff;
674            cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
675    
676          if (switch_register_banks)          if (switch_register_banks)
677                  arm_save_register_bank(cpu);                  arm_save_register_bank(cpu);
678    
679          cpu->cd.arm.cpsr &= ~mask;          cpu->cd.arm.cpsr &= ~mask;
680          cpu->cd.arm.cpsr |= (new_value & mask);          cpu->cd.arm.cpsr |= (new_value & mask);
681    
682            cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
683    
684          if (switch_register_banks)          if (switch_register_banks)
685                  arm_load_register_bank(cpu);                  arm_load_register_bank(cpu);
686  }  }
# Line 667  X(msr_imm_spsr) Line 722  X(msr_imm_spsr)
722          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
723          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)
724              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
725          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
726              << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
727          cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          old_pc = cpu->pc;
728          old_pc = cpu->pc = cpu->cd.arm.r[ARM_PC];          printf("msr_spsr: old pc = 0x%08x\n", old_pc);
 printf("msr_spsr: old pc = 0x%08x\n", old_pc);  
729  }  }
730                  exit(1);                  exit(1);
731          }          }
# Line 692  Y(msr_spsr) Line 746  Y(msr_spsr)
746   */   */
747  X(mrs)  X(mrs)
748  {  {
749            cpu->cd.arm.cpsr &= 0x0fffffff;
750            cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
751          reg(ic->arg[0]) = cpu->cd.arm.cpsr;          reg(ic->arg[0]) = cpu->cd.arm.cpsr;
752  }  }
753  Y(mrs)  Y(mrs)
754    
755    
756  /*  /*
757   *  mrs: Move from status/flag register to a normal register.   *  mrs: Move from saved status/flag register to a normal register.
758   *   *
759   *  arg[0] = pointer to rd   *  arg[0] = pointer to rd
760   */   */
# Line 727  Y(mrs_spsr) Line 783  Y(mrs_spsr)
783   *  arg[0] = copy of the instruction word   *  arg[0] = copy of the instruction word
784   */   */
785  X(mcr_mrc) {  X(mcr_mrc) {
786          uint32_t low_pc;          uint32_t low_pc = ((size_t)ic - (size_t)
         low_pc = ((size_t)ic - (size_t)  
787              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
788          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
789              << 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];  
790          arm_mcr_mrc(cpu, ic->arg[0]);          arm_mcr_mrc(cpu, ic->arg[0]);
791  }  }
792  Y(mcr_mrc)  Y(mcr_mrc)
793  X(cdp) {  X(cdp) {
794          uint32_t low_pc;          uint32_t low_pc = ((size_t)ic - (size_t)
         low_pc = ((size_t)ic - (size_t)  
795              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
796          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
797              << 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];  
798          arm_cdp(cpu, ic->arg[0]);          arm_cdp(cpu, ic->arg[0]);
799  }  }
800  Y(cdp)  Y(cdp)
# Line 755  Y(cdp) Line 805  Y(cdp)
805   */   */
806  X(openfirmware)  X(openfirmware)
807  {  {
808            /*  TODO: sync pc?  */
809          of_emul(cpu);          of_emul(cpu);
810          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
811          if (cpu->machine->show_trace_tree)          if (cpu->machine->show_trace_tree)
812                  cpu_functioncall_trace_return(cpu);                  cpu_functioncall_trace_return(cpu);
813          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
# Line 764  X(openfirmware) Line 815  X(openfirmware)
815    
816    
817  /*  /*
818     *  reboot:
819     */
820    X(reboot)
821    {
822            cpu->running = 0;
823            cpu->running_translated = 0;
824            cpu->n_translated_instrs --;
825            cpu->cd.arm.next_ic = &nothing_call;
826    }
827    
828    
829    /*
830   *  swi_useremul: Syscall.   *  swi_useremul: Syscall.
831   *   *
832   *  arg[0] = swi number   *  arg[0] = swi number
# Line 773  X(swi_useremul) Line 836  X(swi_useremul)
836          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
837          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)
838              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
839          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
840              << ARM_INSTR_ALIGNMENT_SHIFT);              << ARM_INSTR_ALIGNMENT_SHIFT);
841          cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
842          old_pc = cpu->pc = cpu->cd.arm.r[ARM_PC];          old_pc = cpu->pc;
843    
844          useremul_syscall(cpu, ic->arg[0]);          useremul_syscall(cpu, ic->arg[0]);
845    
# Line 798  Y(swi_useremul) Line 861  Y(swi_useremul)
861   */   */
862  X(swi)  X(swi)
863  {  {
864          /*  Synchronize the program counter:  */          /*  Synchronize the program counter first:  */
865          uint32_t low_pc = ((size_t)ic - (size_t)          cpu->pc &= 0xfffff000;
866              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];  
   
867          arm_exception(cpu, ARM_EXCEPTION_SWI);          arm_exception(cpu, ARM_EXCEPTION_SWI);
868  }  }
869  Y(swi)  Y(swi)
870    
871    
872  /*  /*
873     *  und:  Undefined instruction.
874     */
875    X(und)
876    {
877            /*  Synchronize the program counter first:  */
878            cpu->pc &= 0xfffff000;
879            cpu->pc += ic->arg[0];
880            arm_exception(cpu, ARM_EXCEPTION_UND);
881    }
882    Y(und)
883    
884    
885    /*
886   *  swp, swpb:  Swap (word or byte).   *  swp, swpb:  Swap (word or byte).
887   *   *
888   *  arg[0] = ptr to rd   *  arg[0] = ptr to rd
# Line 822  X(swp) Line 893  X(swp)
893  {  {
894          uint32_t addr = reg(ic->arg[2]), data, data2;          uint32_t addr = reg(ic->arg[2]), data, data2;
895          unsigned char d[4];          unsigned char d[4];
896    
897          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
898          uint32_t low_pc = ((size_t)ic - (size_t)          uint32_t low_pc = ((size_t)ic - (size_t)
899              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
900          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
901              << 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];  
902    
903          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,
904              CACHE_DATA)) {              CACHE_DATA)) {
# Line 850  X(swpb) Line 920  X(swpb)
920  {  {
921          uint32_t addr = reg(ic->arg[2]), data;          uint32_t addr = reg(ic->arg[2]), data;
922          unsigned char d[1];          unsigned char d[1];
923    
924          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
925          uint32_t low_pc = ((size_t)ic - (size_t)          uint32_t low_pc = ((size_t)ic - (size_t)
926              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
927          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
928              << 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];  
929    
930          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,
931              CACHE_DATA)) {              CACHE_DATA)) {
# Line 877  Y(swpb) Line 946  Y(swpb)
946    
947  extern void (*arm_load_store_instr[1024])(struct cpu *,  extern void (*arm_load_store_instr[1024])(struct cpu *,
948          struct arm_instr_call *);          struct arm_instr_call *);
949    X(store_w1_word_u1_p0_imm);
950  X(store_w0_byte_u1_p0_imm);  X(store_w0_byte_u1_p0_imm);
951  X(store_w0_word_u1_p0_imm);  X(store_w0_word_u1_p0_imm);
952    X(store_w0_word_u1_p1_imm);
953    X(load_w1_word_u1_p0_imm);
954  X(load_w0_word_u1_p0_imm);  X(load_w0_word_u1_p0_imm);
955  X(load_w0_byte_u1_p1_imm);  X(load_w0_byte_u1_p1_imm);
956  X(load_w0_byte_u1_p1_reg);  X(load_w0_byte_u1_p1_reg);
957    X(load_w1_byte_u1_p1_imm);
958    
959  extern void (*arm_load_store_instr_pc[1024])(struct cpu *,  extern void (*arm_load_store_instr_pc[1024])(struct cpu *,
960          struct arm_instr_call *);          struct arm_instr_call *);
# Line 893  extern void (*arm_load_store_instr_3_pc[ Line 966  extern void (*arm_load_store_instr_3_pc[
966          struct arm_instr_call *);          struct arm_instr_call *);
967    
968  extern uint32_t (*arm_r[8192])(struct cpu *, struct arm_instr_call *);  extern uint32_t (*arm_r[8192])(struct cpu *, struct arm_instr_call *);
969    extern void arm_r_r3_t0_c0(void);
970    
971  extern void (*arm_dpi_instr[2 * 2 * 2 * 16 * 16])(struct cpu *,  extern void (*arm_dpi_instr[2 * 2 * 2 * 16 * 16])(struct cpu *,
972          struct arm_instr_call *);          struct arm_instr_call *);
973    extern void (*arm_dpi_instr_regshort[2 * 16 * 16])(struct cpu *,
974            struct arm_instr_call *);
975  X(cmps);  X(cmps);
976    X(teqs);
977    X(tsts);
978  X(sub);  X(sub);
979  X(add);  X(add);
980  X(subs);  X(subs);
981    X(eor_regshort);
982    X(cmps_regshort);
983    
984    
985    #include "cpu_arm_instr_misc.c"
986    
987    
988  /*  /*
989   *  bdt_load:  Block Data Transfer, Load   *  bdt_load:  Block Data Transfer, Load
# Line 931  X(bdt_load) Line 1013  X(bdt_load)
1013          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
1014          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
1015              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
1016          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) <<          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
1017              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];  
1018    
1019          if (s_bit) {          if (s_bit) {
1020                  /*  Load to USR registers:  */                  /*  Load to USR registers:  */
# Line 1070  X(bdt_load) Line 1150  X(bdt_load)
1150                          arm_save_register_bank(cpu);                          arm_save_register_bank(cpu);
1151    
1152                  cpu->cd.arm.cpsr = new_cpsr;                  cpu->cd.arm.cpsr = new_cpsr;
1153                    cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
1154    
1155                  if (switch_register_banks)                  if (switch_register_banks)
1156                          arm_load_register_bank(cpu);                          arm_load_register_bank(cpu);
# Line 1077  X(bdt_load) Line 1158  X(bdt_load)
1158    
1159          /*  NOTE: Special case: Loading the PC  */          /*  NOTE: Special case: Loading the PC  */
1160          if (iw & 0x8000) {          if (iw & 0x8000) {
1161                  cpu->cd.arm.r[ARM_PC] &= ~3;                  cpu->pc = cpu->cd.arm.r[ARM_PC] & 0xfffffffc;
                 cpu->pc = cpu->cd.arm.r[ARM_PC];  
1162                  if (cpu->machine->show_trace_tree)                  if (cpu->machine->show_trace_tree)
1163                          cpu_functioncall_trace_return(cpu);                          cpu_functioncall_trace_return(cpu);
1164                  /*  TODO: There is no need to update the                  /*  TODO: There is no need to update the
# Line 1119  X(bdt_store) Line 1199  X(bdt_store)
1199          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
1200          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
1201              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
1202          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) <<          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
1203              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];  
1204    
1205          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)) {
1206                  if (!((iw >> i) & 1)) {                  if (!((iw >> i) & 1)) {
# Line 1151  X(bdt_store) Line 1229  X(bdt_store)
1229                          }                          }
1230                  }                  }
1231    
1232                    /*  NOTE/TODO: 8 vs 12 on some ARMs  */
1233                  if (i == ARM_PC)                  if (i == ARM_PC)
1234                          value += 12;    /*  NOTE/TODO: 8 on some ARMs  */                          value = cpu->pc + 12;
1235    
1236                  if (p_bit) {                  if (p_bit) {
1237                          if (u_bit)                          if (u_bit)
# Line 1210  Y(bdt_store) Line 1289  Y(bdt_store)
1289    
1290    
1291  /*  Various load/store multiple instructions:  */  /*  Various load/store multiple instructions:  */
1292  #include "tmp_arm_multi.c"  uint32_t *multi_opcode[256];
1293    void (**multi_opcode_f[256])(struct cpu *, struct arm_instr_call *);
1294    X(multi_0x08b15018);
1295    X(multi_0x08ac000c__ge);
1296    X(multi_0x08a05018);
1297    
1298    
1299  /*****************************************************************************/  /*****************************************************************************/
1300    
1301    
1302  /*  /*
  *  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];  
 }  
   
   
 /*  
1303   *  netbsd_memset:   *  netbsd_memset:
1304   *   *
1305   *  The core of a NetBSD/arm memset.   *  The core of a NetBSD/arm memset.
# Line 1381  X(netbsd_memset) Line 1319  X(netbsd_memset)
1319    
1320                  instr(subs)(cpu, ic);                  instr(subs)(cpu, ic);
1321    
1322                  if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) !=                  if (((cpu->cd.arm.flags & ARM_F_N)?1:0) !=
1323                      ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0)) {                      ((cpu->cd.arm.flags & ARM_F_V)?1:0)) {
1324                          cpu->n_translated_instrs += 16;                          cpu->n_translated_instrs += 16;
1325                          /*  Skip the store multiples:  */                          /*  Skip the store multiples:  */
1326                          cpu->cd.arm.next_ic = &ic[17];                          cpu->cd.arm.next_ic = &ic[17];
# Line 1411  X(netbsd_memset) Line 1349  X(netbsd_memset)
1349    
1350                  /*  Branch back if greater:  */                  /*  Branch back if greater:  */
1351                  cpu->n_translated_instrs += 1;                  cpu->n_translated_instrs += 1;
1352          } while (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) ==          } while (((cpu->cd.arm.flags & ARM_F_N)?1:0) ==
1353              ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0) &&              ((cpu->cd.arm.flags & ARM_F_V)?1:0) &&
1354              !(cpu->cd.arm.cpsr & ARM_FLAG_Z));              !(cpu->cd.arm.flags & ARM_F_Z));
1355    
1356          /*  Continue at the instruction after the bgt:  */          /*  Continue at the instruction after the bgt:  */
1357          cpu->cd.arm.next_ic = &ic[18];          cpu->cd.arm.next_ic = &ic[18];
# Line 1471  X(netbsd_memcpy) Line 1409  X(netbsd_memcpy)
1409    
1410                  /*  Loop while greater or equal:  */                  /*  Loop while greater or equal:  */
1411                  cpu->n_translated_instrs ++;                  cpu->n_translated_instrs ++;
1412          } while (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) ==          } while (((cpu->cd.arm.flags & ARM_F_N)?1:0) ==
1413              ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0));              ((cpu->cd.arm.flags & ARM_F_V)?1:0));
1414    
1415          /*  Continue at the instruction after the bge:  */          /*  Continue at the instruction after the bge:  */
1416          cpu->cd.arm.next_ic = &ic[6];          cpu->cd.arm.next_ic = &ic[6];
# Line 1494  X(netbsd_cacheclean) Line 1432  X(netbsd_cacheclean)
1432  {  {
1433          uint32_t r1 = cpu->cd.arm.r[1];          uint32_t r1 = cpu->cd.arm.r[1];
1434          cpu->n_translated_instrs += ((r1 >> 5) * 3);          cpu->n_translated_instrs += ((r1 >> 5) * 3);
1435            cpu->cd.arm.r[0] += r1;
1436            cpu->cd.arm.r[1] = 0;
1437          cpu->cd.arm.next_ic = &ic[4];          cpu->cd.arm.next_ic = &ic[4];
1438  }  }
1439    
# Line 1545  X(netbsd_scanc) Line 1485  X(netbsd_scanc)
1485          cpu->cd.arm.r[3] = page[t & 0xfff];          cpu->cd.arm.r[3] = page[t & 0xfff];
1486    
1487          t = cpu->cd.arm.r[3] & cpu->cd.arm.r[ARM_IP];          t = cpu->cd.arm.r[3] & cpu->cd.arm.r[ARM_IP];
1488          cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N);          cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1489          if (t == 0)          if (t == 0)
1490                  cpu->cd.arm.cpsr |= ARM_FLAG_Z;                  cpu->cd.arm.flags |= ARM_F_Z;
1491    
1492            cpu->n_translated_instrs += 2;
1493            cpu->cd.arm.next_ic = &ic[3];
1494    }
1495    
1496    
1497    /*
1498     *  strlen:
1499     *
1500     *  S: e5f03001   ldrb  rY,[rX,#1]!
1501     *     e3530000   cmps  rY,#0
1502     *     1afffffc   bne   S
1503     */
1504    X(strlen)
1505    {
1506            unsigned int n_loops = 0;
1507            uint32_t rY, rX = reg(ic[0].arg[0]);
1508            unsigned char *p;
1509    
1510            do {
1511                    rX ++;
1512                    p = cpu->cd.arm.host_load[rX >> 12];
1513                    if (p == NULL) {
1514                            cpu->n_translated_instrs += (n_loops * 3);
1515                            instr(load_w1_byte_u1_p1_imm)(cpu, ic);
1516                            return;
1517                    }
1518    
1519                    rY = reg(ic[0].arg[2]) = p[rX & 0xfff]; /*  load  */
1520                    reg(ic[0].arg[0]) = rX;                 /*  writeback  */
1521                    n_loops ++;
1522    
1523                    /*  Compare rY to zero:  */
1524                    cpu->cd.arm.flags = ARM_F_C;
1525                    if (rY == 0)
1526                            cpu->cd.arm.flags |= ARM_F_Z;
1527            } while (rY != 0);
1528    
1529            cpu->n_translated_instrs += (n_loops * 3) - 1;
1530            cpu->cd.arm.next_ic = &ic[3];
1531    }
1532    
1533    
1534    /*
1535     *  xchg:
1536     *
1537     *  e02YX00X     eor     rX,rY,rX
1538     *  e02XY00Y     eor     rY,rX,rY
1539     *  e02YX00X     eor     rX,rY,rX
1540     */
1541    X(xchg)
1542    {
1543            uint32_t tmp = reg(ic[0].arg[0]);
1544          cpu->n_translated_instrs += 2;          cpu->n_translated_instrs += 2;
1545          cpu->cd.arm.next_ic = &ic[3];          cpu->cd.arm.next_ic = &ic[3];
1546            reg(ic[0].arg[0]) = reg(ic[1].arg[0]);
1547            reg(ic[1].arg[0]) = tmp;
1548    }
1549    
1550    
1551    /*
1552     *  netbsd_copyin:
1553     *
1554     *  e4b0a004     ldrt    sl,[r0],#4
1555     *  e4b0b004     ldrt    fp,[r0],#4
1556     *  e4b06004     ldrt    r6,[r0],#4
1557     *  e4b07004     ldrt    r7,[r0],#4
1558     *  e4b08004     ldrt    r8,[r0],#4
1559     *  e4b09004     ldrt    r9,[r0],#4
1560     */
1561    X(netbsd_copyin)
1562    {
1563            uint32_t r0 = cpu->cd.arm.r[0], ofs = (r0 & 0xffc), index = r0 >> 12;
1564            unsigned char *p = cpu->cd.arm.host_load[index];
1565            uint32_t *p32 = (uint32_t *) p, *q32;
1566            int ok = cpu->cd.arm.is_userpage[index >> 5] & (1 << (index & 31));
1567    
1568            if (ofs > 0x1000 - 6*4 || !ok || p == NULL) {
1569                    instr(load_w1_word_u1_p0_imm)(cpu, ic);
1570                    return;
1571            }
1572            q32 = &cpu->cd.arm.r[6];
1573            ofs >>= 2;
1574            q32[0] = p32[ofs+2];
1575            q32[1] = p32[ofs+3];
1576            q32[2] = p32[ofs+4];
1577            q32[3] = p32[ofs+5];
1578            q32[4] = p32[ofs+0];
1579            q32[5] = p32[ofs+1];
1580            cpu->cd.arm.r[0] = r0 + 24;
1581            cpu->n_translated_instrs += 5;
1582            cpu->cd.arm.next_ic = &ic[6];
1583    }
1584    
1585    
1586    /*
1587     *  netbsd_copyout:
1588     *
1589     *  e4a18004     strt    r8,[r1],#4
1590     *  e4a19004     strt    r9,[r1],#4
1591     *  e4a1a004     strt    sl,[r1],#4
1592     *  e4a1b004     strt    fp,[r1],#4
1593     *  e4a16004     strt    r6,[r1],#4
1594     *  e4a17004     strt    r7,[r1],#4
1595     */
1596    X(netbsd_copyout)
1597    {
1598            uint32_t r1 = cpu->cd.arm.r[1], ofs = (r1 & 0xffc), index = r1 >> 12;
1599            unsigned char *p = cpu->cd.arm.host_store[index];
1600            uint32_t *p32 = (uint32_t *) p, *q32;
1601            int ok = cpu->cd.arm.is_userpage[index >> 5] & (1 << (index & 31));
1602    
1603            if (ofs > 0x1000 - 6*4 || !ok || p == NULL) {
1604                    instr(store_w1_word_u1_p0_imm)(cpu, ic);
1605                    return;
1606            }
1607            q32 = &cpu->cd.arm.r[6];
1608            ofs >>= 2;
1609            p32[ofs  ] = q32[2];
1610            p32[ofs+1] = q32[3];
1611            p32[ofs+2] = q32[4];
1612            p32[ofs+3] = q32[5];
1613            p32[ofs+4] = q32[0];
1614            p32[ofs+5] = q32[1];
1615            cpu->cd.arm.r[1] = r1 + 24;
1616            cpu->n_translated_instrs += 5;
1617            cpu->cd.arm.next_ic = &ic[6];
1618    }
1619    
1620    
1621    /*
1622     *  cmps by 0, followed by beq (inside the same page):
1623     */
1624    X(cmps0_beq_samepage)
1625    {
1626            uint32_t a = reg(ic->arg[0]);
1627            cpu->n_translated_instrs ++;
1628            if (a == 0) {
1629                    cpu->cd.arm.flags = ARM_F_Z | ARM_F_C;
1630            } else {
1631                    /*  Semi-ugly hack which sets the negative-bit if a < 0:  */
1632                    cpu->cd.arm.flags = ARM_F_C | ((a >> 28) & 8);
1633            }
1634            if (a == 0)
1635                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1636            else
1637                    cpu->cd.arm.next_ic = &ic[2];
1638    }
1639    
1640    
1641    /*
1642     *  cmps followed by beq (inside the same page):
1643     */
1644    X(cmps_beq_samepage)
1645    {
1646            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1647            cpu->n_translated_instrs ++;
1648            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1649            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1650                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1651                    cpu->cd.arm.flags |= ARM_F_V;
1652            if (c == 0) {
1653                    cpu->cd.arm.flags |= ARM_F_Z;
1654                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1655            } else {
1656                    cpu->cd.arm.next_ic = &ic[2];
1657                    if (c & 0x80000000)
1658                            cpu->cd.arm.flags |= ARM_F_N;
1659            }
1660    }
1661    
1662    
1663    /*
1664     *  cmps followed by beq (not the same page):
1665     */
1666    X(cmps_0_beq)
1667    {
1668            uint32_t a = reg(ic->arg[0]);
1669            cpu->n_translated_instrs ++;
1670            if (a == 0) {
1671                    cpu->cd.arm.flags = ARM_F_Z | ARM_F_C;
1672                    cpu->pc = (uint32_t)(((uint32_t)cpu->pc & 0xfffff000)
1673                        + (int32_t)ic[1].arg[0]);
1674                    quick_pc_to_pointers(cpu);
1675            } else {
1676                    /*  Semi-ugly hack which sets the negative-bit if a < 0:  */
1677                    cpu->cd.arm.flags = ARM_F_C | ((a >> 28) & 8);
1678                    cpu->cd.arm.next_ic = &ic[2];
1679            }
1680    }
1681    X(cmps_pos_beq)
1682    {
1683            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1684            cpu->n_translated_instrs ++;
1685            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1686            if ((int32_t)a < 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->pc = (uint32_t)(((uint32_t)cpu->pc & 0xfffff000)
1691                        + (int32_t)ic[1].arg[0]);
1692                    quick_pc_to_pointers(cpu);
1693            } else {
1694                    cpu->cd.arm.next_ic = &ic[2];
1695                    if (c & 0x80000000)
1696                            cpu->cd.arm.flags |= ARM_F_N;
1697            }
1698    }
1699    X(cmps_neg_beq)
1700    {
1701            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1702            cpu->n_translated_instrs ++;
1703            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1704            if ((int32_t)a >= 0 && (int32_t)c < 0)
1705                    cpu->cd.arm.flags |= ARM_F_V;
1706            if (c == 0) {
1707                    cpu->cd.arm.flags |= ARM_F_Z;
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                    cpu->cd.arm.next_ic = &ic[2];
1713                    if (c & 0x80000000)
1714                            cpu->cd.arm.flags |= ARM_F_N;
1715            }
1716    }
1717    
1718    
1719    /*
1720     *  cmps by 0, followed by bne (inside the same page):
1721     */
1722    X(cmps0_bne_samepage)
1723    {
1724            uint32_t a = reg(ic->arg[0]);
1725            cpu->n_translated_instrs ++;
1726            if (a == 0) {
1727                    cpu->cd.arm.flags = ARM_F_Z | ARM_F_C;
1728            } else {
1729                    /*  Semi-ugly hack which sets the negative-bit if a < 0:  */
1730                    cpu->cd.arm.flags = ARM_F_C | ((a >> 28) & 8);
1731            }
1732            if (a == 0)
1733                    cpu->cd.arm.next_ic = &ic[2];
1734            else
1735                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1736    }
1737    
1738    
1739    /*
1740     *  cmps followed by bne (inside the same page):
1741     */
1742    X(cmps_bne_samepage)
1743    {
1744            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1745            cpu->n_translated_instrs ++;
1746            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1747            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1748                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1749                    cpu->cd.arm.flags |= ARM_F_V;
1750            if (c == 0) {
1751                    cpu->cd.arm.flags |= ARM_F_Z;
1752                    cpu->cd.arm.next_ic = &ic[2];
1753            } else {
1754                    if (c & 0x80000000)
1755                            cpu->cd.arm.flags |= ARM_F_N;
1756                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1757            }
1758    }
1759    
1760    
1761    /*
1762     *  cmps followed by bcc (inside the same page):
1763     */
1764    X(cmps_bcc_samepage)
1765    {
1766            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1767            cpu->n_translated_instrs ++;
1768            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1769            if (c & 0x80000000)
1770                    cpu->cd.arm.flags |= ARM_F_N;
1771            else if (c == 0)
1772                    cpu->cd.arm.flags |= ARM_F_Z;
1773            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1774                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1775                    cpu->cd.arm.flags |= ARM_F_V;
1776            if (a >= b)
1777                    cpu->cd.arm.next_ic = &ic[2];
1778            else
1779                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1780    }
1781    
1782    
1783    /*
1784     *  cmps (reg) followed by bcc (inside the same page):
1785     */
1786    X(cmps_reg_bcc_samepage)
1787    {
1788            uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = a - b;
1789            cpu->n_translated_instrs ++;
1790            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1791            if (c & 0x80000000)
1792                    cpu->cd.arm.flags |= ARM_F_N;
1793            else if (c == 0)
1794                    cpu->cd.arm.flags |= ARM_F_Z;
1795            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1796                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1797                    cpu->cd.arm.flags |= ARM_F_V;
1798            if (a >= b)
1799                    cpu->cd.arm.next_ic = &ic[2];
1800            else
1801                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1802    }
1803    
1804    
1805    /*
1806     *  cmps followed by bhi (inside the same page):
1807     */
1808    X(cmps_bhi_samepage)
1809    {
1810            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1811            cpu->n_translated_instrs ++;
1812            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1813            if (c & 0x80000000)
1814                    cpu->cd.arm.flags |= ARM_F_N;
1815            else if (c == 0)
1816                    cpu->cd.arm.flags |= ARM_F_Z;
1817            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1818                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1819                    cpu->cd.arm.flags |= ARM_F_V;
1820            if (a > b)
1821                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1822            else
1823                    cpu->cd.arm.next_ic = &ic[2];
1824    }
1825    
1826    
1827    /*
1828     *  cmps (reg) followed by bhi (inside the same page):
1829     */
1830    X(cmps_reg_bhi_samepage)
1831    {
1832            uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = a - b;
1833            cpu->n_translated_instrs ++;
1834            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1835            if (c & 0x80000000)
1836                    cpu->cd.arm.flags |= ARM_F_N;
1837            else if (c == 0)
1838                    cpu->cd.arm.flags |= ARM_F_Z;
1839            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1840                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1841                    cpu->cd.arm.flags |= ARM_F_V;
1842            if (a > b)
1843                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1844            else
1845                    cpu->cd.arm.next_ic = &ic[2];
1846    }
1847    
1848    
1849    /*
1850     *  cmps followed by bgt (inside the same page):
1851     */
1852    X(cmps_bgt_samepage)
1853    {
1854            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1855            cpu->n_translated_instrs ++;
1856            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1857            if (c & 0x80000000)
1858                    cpu->cd.arm.flags |= ARM_F_N;
1859            else if (c == 0)
1860                    cpu->cd.arm.flags |= ARM_F_Z;
1861            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1862                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1863                    cpu->cd.arm.flags |= ARM_F_V;
1864            if ((int32_t)a > (int32_t)b)
1865                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1866            else
1867                    cpu->cd.arm.next_ic = &ic[2];
1868    }
1869    
1870    
1871    /*
1872     *  cmps followed by ble (inside the same page):
1873     */
1874    X(cmps_ble_samepage)
1875    {
1876            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1877            cpu->n_translated_instrs ++;
1878            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1879            if (c & 0x80000000)
1880                    cpu->cd.arm.flags |= ARM_F_N;
1881            else if (c == 0)
1882                    cpu->cd.arm.flags |= ARM_F_Z;
1883            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1884                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1885                    cpu->cd.arm.flags |= ARM_F_V;
1886            if ((int32_t)a <= (int32_t)b)
1887                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1888            else
1889                    cpu->cd.arm.next_ic = &ic[2];
1890    }
1891    
1892    
1893    /*
1894     *  teqs followed by beq (inside the same page):
1895     */
1896    X(teqs_beq_samepage)
1897    {
1898            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a ^ b;
1899            cpu->n_translated_instrs ++;
1900            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1901            if (c == 0) {
1902                    cpu->cd.arm.flags |= ARM_F_Z;
1903                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
1904                        ic[1].arg[0];
1905            } else {
1906                    if (c & 0x80000000)
1907                            cpu->cd.arm.flags |= ARM_F_N;
1908                    cpu->cd.arm.next_ic = &ic[2];
1909            }
1910    }
1911    
1912    
1913    /*
1914     *  tsts followed by beq (inside the same page):
1915     *  (arg[1] must not have its highest bit set))
1916     */
1917    X(tsts_lo_beq_samepage)
1918    {
1919            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a & b;
1920            cpu->n_translated_instrs ++;
1921            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1922            if (c == 0)
1923                    cpu->cd.arm.flags |= ARM_F_Z;
1924            if (c == 0)
1925                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
1926                        ic[1].arg[0];
1927            else
1928                    cpu->cd.arm.next_ic = &ic[2];
1929    }
1930    
1931    
1932    /*
1933     *  teqs followed by bne (inside the same page):
1934     */
1935    X(teqs_bne_samepage)
1936    {
1937            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a ^ b;
1938            cpu->n_translated_instrs ++;
1939            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1940            if (c == 0) {
1941                    cpu->cd.arm.flags |= ARM_F_Z;
1942            } else {
1943                    if (c & 0x80000000)
1944                            cpu->cd.arm.flags |= ARM_F_N;
1945            }
1946            if (c == 0)
1947                    cpu->cd.arm.next_ic = &ic[2];
1948            else
1949                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
1950                        ic[1].arg[0];
1951    }
1952    
1953    
1954    /*
1955     *  tsts followed by bne (inside the same page):
1956     *  (arg[1] must not have its highest bit set))
1957     */
1958    X(tsts_lo_bne_samepage)
1959    {
1960            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a & b;
1961            cpu->n_translated_instrs ++;
1962            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1963            if (c == 0)
1964                    cpu->cd.arm.flags |= ARM_F_Z;
1965            if (c == 0)
1966                    cpu->cd.arm.next_ic = &ic[2];
1967            else
1968                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
1969                        ic[1].arg[0];
1970  }  }
1971    
1972    
# Line 1560  X(netbsd_scanc) Line 1976  X(netbsd_scanc)
1976  X(end_of_page)  X(end_of_page)
1977  {  {
1978          /*  Update the PC:  (offset 0, but on the next page)  */          /*  Update the PC:  (offset 0, but on the next page)  */
1979          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
1980              << 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];  
1981    
1982          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
1983          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
# Line 1583  X(end_of_page) Line 1996  X(end_of_page)
1996   *  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
1997   *  of 16 store-multiple instructions, each storing 2 registers at a time.   *  of 16 store-multiple instructions, each storing 2 registers at a time.
1998   */   */
1999  void arm_combine_netbsd_memset(struct cpu *cpu, struct arm_instr_call *ic,  void arm_combine_netbsd_memset(struct cpu *cpu,
2000          int low_addr)          struct arm_instr_call *ic, int low_addr)
2001  {  {
2002    #ifdef HOST_LITTLE_ENDIAN
2003          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2004              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
2005    
# Line 1602  void arm_combine_netbsd_memset(struct cp Line 2016  void arm_combine_netbsd_memset(struct cp
2016                          combined;                          combined;
2017                  }                  }
2018          }          }
2019    #endif
2020  }  }
2021    
2022    
# Line 1611  void arm_combine_netbsd_memset(struct cp Line 2026  void arm_combine_netbsd_memset(struct cp
2026   *  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
2027   *  sequence of ldmia instructions.   *  sequence of ldmia instructions.
2028   */   */
2029  void arm_combine_netbsd_memcpy(struct cpu *cpu, struct arm_instr_call *ic,  void arm_combine_netbsd_memcpy(struct cpu *cpu,
2030          int low_addr)          struct arm_instr_call *ic, int low_addr)
2031  {  {
2032    #ifdef HOST_LITTLE_ENDIAN
2033          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2034              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
2035    
# Line 1630  void arm_combine_netbsd_memcpy(struct cp Line 2046  void arm_combine_netbsd_memcpy(struct cp
2046                          combined;                          combined;
2047                  }                  }
2048          }          }
2049    #endif
2050  }  }
2051    
2052    
# Line 1638  void arm_combine_netbsd_memcpy(struct cp Line 2055  void arm_combine_netbsd_memcpy(struct cp
2055   *   *
2056   *  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.)
2057   */   */
2058  void arm_combine_netbsd_cacheclean(struct cpu *cpu, struct arm_instr_call *ic,  void arm_combine_netbsd_cacheclean(struct cpu *cpu,
2059          int low_addr)          struct arm_instr_call *ic, int low_addr)
2060  {  {
2061          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2062              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
# Line 1662  void arm_combine_netbsd_cacheclean(struc Line 2079  void arm_combine_netbsd_cacheclean(struc
2079   *   *
2080   *  Check for the core of a NetBSD/arm cache clean. (Second variant.)   *  Check for the core of a NetBSD/arm cache clean. (Second variant.)
2081   */   */
2082  void arm_combine_netbsd_cacheclean2(struct cpu *cpu, struct arm_instr_call *ic,  void arm_combine_netbsd_cacheclean2(struct cpu *cpu,
2083          int low_addr)          struct arm_instr_call *ic, int low_addr)
2084  {  {
2085          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2086              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
# Line 1685  void arm_combine_netbsd_cacheclean2(stru Line 2102  void arm_combine_netbsd_cacheclean2(stru
2102  /*  /*
2103   *  arm_combine_netbsd_scanc():   *  arm_combine_netbsd_scanc():
2104   */   */
2105  void arm_combine_netbsd_scanc(struct cpu *cpu, struct arm_instr_call *ic,  void arm_combine_netbsd_scanc(struct cpu *cpu,
2106          int low_addr)          struct arm_instr_call *ic, int low_addr)
2107  {  {
2108          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2109              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
2110    
2111          if (n_back >= 2) {          if (n_back < 2)
2112                  if (ic[-2].f == instr(load_w0_byte_u1_p1_imm) &&                  return;
2113                      ic[-1].f == instr(load_w0_byte_u1_p1_reg)) {  
2114                          ic[-2].f = instr(netbsd_scanc);          if (ic[-2].f == instr(load_w0_byte_u1_p1_imm) &&
2115                          combined;              ic[-2].arg[0] == (size_t)(&cpu->cd.arm.r[1]) &&
2116                  }              ic[-2].arg[1] == 0 &&
2117                ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[3]) &&
2118                ic[-1].f == instr(load_w0_byte_u1_p1_reg) &&
2119                ic[-1].arg[0] == (size_t)(&cpu->cd.arm.r[2]) &&
2120                ic[-1].arg[1] == (size_t)arm_r_r3_t0_c0 &&
2121                ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[3])) {
2122                    ic[-2].f = instr(netbsd_scanc);
2123                    combined;
2124          }          }
2125  }  }
2126    
2127    
2128  /*  /*
2129   *  arm_combine_test2():   *  arm_combine_strlen():
2130   */   */
2131  void arm_combine_test2(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)  void arm_combine_strlen(struct cpu *cpu,
2132            struct arm_instr_call *ic, int low_addr)
2133  {  {
2134          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2135              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
2136    
2137          if (n_back >= 2) {          if (n_back < 2)
2138                  if (ic[-2].f == instr(store_w0_word_u1_p0_imm) &&                  return;
2139                      ic[-2].arg[1] == 4 &&  
2140                      ic[-1].f == instr(subs) &&          if (ic[-2].f == instr(load_w1_byte_u1_p1_imm) &&
2141                      ic[-1].arg[0] == ic[-1].arg[2] && ic[-1].arg[1] == 4 &&              ic[-2].arg[1] == 1 &&
2142                      ic[ 0].f == instr(b_samepage__gt) &&              ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[3]) &&
2143                      ic[ 0].arg[0] == (size_t)&ic[-2]) {              ic[-1].f == instr(cmps) &&
2144                          ic[-2].f = instr(fill_loop_test2);              ic[-1].arg[0] == (size_t)(&cpu->cd.arm.r[3]) &&
2145  printf("YO test2\n");              ic[-1].arg[1] == 0) {
2146                          combined;                  ic[-2].f = instr(strlen);
2147                  }                  combined;
2148          }          }
2149  }  }
2150    
2151    
2152  #if 0  /*
2153          /*  TODO: This is another test hack.  */   *  arm_combine_xchg():
2154     */
2155    void arm_combine_xchg(struct cpu *cpu,
2156            struct arm_instr_call *ic, int low_addr)
2157    {
2158            int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2159                & (ARM_IC_ENTRIES_PER_PAGE-1);
2160            size_t a, b;
2161    
2162          if (n_back >= 3) {          if (n_back < 2)
2163                  if (ic[-3].f == instr(cmps) &&                  return;
2164                      ic[-3].arg[0] == ic[-1].arg[0] &&  
2165                      ic[-3].arg[1] == 0 &&          a = ic[-2].arg[0]; b = ic[-1].arg[0];
2166                      ic[-2].f == instr(store_w0_byte_u1_p0_imm) &&  
2167                      ic[-2].arg[1] == 1 &&          if (ic[-2].f == instr(eor_regshort) &&
2168                      ic[-1].f == instr(sub) &&              ic[-1].f == instr(eor_regshort) &&
2169                      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 &&
2170                      ic[ 0].f == instr(b_samepage__gt) &&              ic[-1].arg[0] == b && ic[-1].arg[1] == a && ic[-1].arg[2] == a &&
2171                      ic[ 0].arg[0] == (size_t)&ic[-3]) {              ic[ 0].arg[0] == a && ic[ 0].arg[1] == b && ic[ 0].arg[2] == b) {
2172                          ic[-3].f = instr(fill_loop_test);                  ic[-2].f = instr(xchg);
2173                    combined;
2174            }
2175    }
2176    
2177    
2178    /*
2179     *  arm_combine_netbsd_copyin():
2180     */
2181    void arm_combine_netbsd_copyin(struct cpu *cpu,
2182            struct arm_instr_call *ic, int low_addr)
2183    {
2184    #ifdef HOST_LITTLE_ENDIAN
2185            int i, n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2186                & (ARM_IC_ENTRIES_PER_PAGE-1);
2187    
2188            if (n_back < 5)
2189                    return;
2190    
2191            for (i=-5; i<0; i++) {
2192                    if (ic[i].f != instr(load_w1_word_u1_p0_imm) ||
2193                        ic[i].arg[0] != (size_t)(&cpu->cd.arm.r[0]) ||
2194                        ic[i].arg[1] != 4)
2195                            return;
2196            }
2197    
2198            if (ic[-5].arg[2] == (size_t)(&cpu->cd.arm.r[10]) &&
2199                ic[-4].arg[2] == (size_t)(&cpu->cd.arm.r[11]) &&
2200                ic[-3].arg[2] == (size_t)(&cpu->cd.arm.r[6]) &&
2201                ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[7]) &&
2202                ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[8])) {
2203                    ic[-5].f = instr(netbsd_copyin);
2204                    combined;
2205            }
2206    #endif
2207    }
2208    
2209    
2210    /*
2211     *  arm_combine_netbsd_copyout():
2212     */
2213    void arm_combine_netbsd_copyout(struct cpu *cpu,
2214            struct arm_instr_call *ic, int low_addr)
2215    {
2216    #ifdef HOST_LITTLE_ENDIAN
2217            int i, n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2218                & (ARM_IC_ENTRIES_PER_PAGE-1);
2219    
2220            if (n_back < 5)
2221                    return;
2222    
2223            for (i=-5; i<0; i++) {
2224                    if (ic[i].f != instr(store_w1_word_u1_p0_imm) ||
2225                        ic[i].arg[0] != (size_t)(&cpu->cd.arm.r[1]) ||
2226                        ic[i].arg[1] != 4)
2227                            return;
2228            }
2229    
2230            if (ic[-5].arg[2] == (size_t)(&cpu->cd.arm.r[8]) &&
2231                ic[-4].arg[2] == (size_t)(&cpu->cd.arm.r[9]) &&
2232                ic[-3].arg[2] == (size_t)(&cpu->cd.arm.r[10]) &&
2233                ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[11]) &&
2234                ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[6])) {
2235                    ic[-5].f = instr(netbsd_copyout);
2236                    combined;
2237            }
2238    #endif
2239    }
2240    
2241    
2242    /*
2243     *  arm_combine_cmps_b():
2244     */
2245    void arm_combine_cmps_b(struct cpu *cpu,
2246            struct arm_instr_call *ic, int low_addr)
2247    {
2248            int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2249                & (ARM_IC_ENTRIES_PER_PAGE-1);
2250            if (n_back < 1)
2251                    return;
2252            if (ic[0].f == instr(b__eq)) {
2253                    if (ic[-1].f == instr(cmps)) {
2254                            if (ic[-1].arg[1] == 0)
2255                                    ic[-1].f = instr(cmps_0_beq);
2256                            else if (ic[-1].arg[1] & 0x80000000)
2257                                    ic[-1].f = instr(cmps_neg_beq);
2258                            else
2259                                    ic[-1].f = instr(cmps_pos_beq);
2260                          combined;                          combined;
2261                  }                  }
2262                    return;
2263          }          }
2264          /*  TODO: Combine forward as well  */          if (ic[0].f == instr(b_samepage__eq)) {
2265  #endif                  if (ic[-1].f == instr(cmps)) {
2266                            if (ic[-1].arg[1] == 0)
2267                                    ic[-1].f = instr(cmps0_beq_samepage);
2268                            else
2269                                    ic[-1].f = instr(cmps_beq_samepage);
2270                            combined;
2271                    }
2272                    if (ic[-1].f == instr(tsts) &&
2273                        !(ic[-1].arg[1] & 0x80000000)) {
2274                            ic[-1].f = instr(tsts_lo_beq_samepage);
2275                            combined;
2276                    }
2277                    if (ic[-1].f == instr(teqs)) {
2278                            ic[-1].f = instr(teqs_beq_samepage);
2279                            combined;
2280                    }
2281                    return;
2282            }
2283            if (ic[0].f == instr(b_samepage__ne)) {
2284                    if (ic[-1].f == instr(cmps)) {
2285                            if (ic[-1].arg[1] == 0)
2286                                    ic[-1].f = instr(cmps0_bne_samepage);
2287                            else
2288                                    ic[-1].f = instr(cmps_bne_samepage);
2289                            combined;
2290                    }
2291                    if (ic[-1].f == instr(tsts) &&
2292                        !(ic[-1].arg[1] & 0x80000000)) {
2293                            ic[-1].f = instr(tsts_lo_bne_samepage);
2294                            combined;
2295                    }
2296                    if (ic[-1].f == instr(teqs)) {
2297                            ic[-1].f = instr(teqs_bne_samepage);
2298                            combined;
2299                    }
2300                    return;
2301            }
2302            if (ic[0].f == instr(b_samepage__cc)) {
2303                    if (ic[-1].f == instr(cmps)) {
2304                            ic[-1].f = instr(cmps_bcc_samepage);
2305                            combined;
2306                    }
2307                    if (ic[-1].f == instr(cmps_regshort)) {
2308                            ic[-1].f = instr(cmps_reg_bcc_samepage);
2309                            combined;
2310                    }
2311                    return;
2312            }
2313            if (ic[0].f == instr(b_samepage__hi)) {
2314                    if (ic[-1].f == instr(cmps)) {
2315                            ic[-1].f = instr(cmps_bhi_samepage);
2316                            combined;
2317                    }
2318                    if (ic[-1].f == instr(cmps_regshort)) {
2319                            ic[-1].f = instr(cmps_reg_bhi_samepage);
2320                            combined;
2321                    }
2322                    return;
2323            }
2324            if (ic[0].f == instr(b_samepage__gt)) {
2325                    if (ic[-1].f == instr(cmps)) {
2326                            ic[-1].f = instr(cmps_bgt_samepage);
2327                            combined;
2328                    }
2329                    return;
2330            }
2331            if (ic[0].f == instr(b_samepage__le)) {
2332                    if (ic[-1].f == instr(cmps)) {
2333                            ic[-1].f = instr(cmps_ble_samepage);
2334                            combined;
2335                    }
2336                    return;
2337            }
2338    }
2339    
2340    
2341    /*****************************************************************************/
2342    
2343    
2344    static void arm_switch_clear(struct arm_instr_call *ic, int rd,
2345            int condition_code)
2346    {
2347            switch (rd) {
2348            case  0: ic->f = cond_instr(clear_r0); break;
2349            case  1: ic->f = cond_instr(clear_r1); break;
2350            case  2: ic->f = cond_instr(clear_r2); break;
2351            case  3: ic->f = cond_instr(clear_r3); break;
2352            case  4: ic->f = cond_instr(clear_r4); break;
2353            case  5: ic->f = cond_instr(clear_r5); break;
2354            case  6: ic->f = cond_instr(clear_r6); break;
2355            case  7: ic->f = cond_instr(clear_r7); break;
2356            case  8: ic->f = cond_instr(clear_r8); break;
2357            case  9: ic->f = cond_instr(clear_r9); break;
2358            case 10: ic->f = cond_instr(clear_r10); break;
2359            case 11: ic->f = cond_instr(clear_r11); break;
2360            case 12: ic->f = cond_instr(clear_r12); break;
2361            case 13: ic->f = cond_instr(clear_r13); break;
2362            case 14: ic->f = cond_instr(clear_r14); break;
2363            }
2364    }
2365    
2366    
2367    static void arm_switch_mov1(struct arm_instr_call *ic, int rd,
2368            int condition_code)
2369    {
2370            switch (rd) {
2371            case  0: ic->f = cond_instr(mov1_r0); break;
2372            case  1: ic->f = cond_instr(mov1_r1); break;
2373            case  2: ic->f = cond_instr(mov1_r2); break;
2374            case  3: ic->f = cond_instr(mov1_r3); break;
2375            case  4: ic->f = cond_instr(mov1_r4); break;
2376            case  5: ic->f = cond_instr(mov1_r5); break;
2377            case  6: ic->f = cond_instr(mov1_r6); break;
2378            case  7: ic->f = cond_instr(mov1_r7); break;
2379            case  8: ic->f = cond_instr(mov1_r8); break;
2380            case  9: ic->f = cond_instr(mov1_r9); break;
2381            case 10: ic->f = cond_instr(mov1_r10); break;
2382            case 11: ic->f = cond_instr(mov1_r11); break;
2383            case 12: ic->f = cond_instr(mov1_r12); break;
2384            case 13: ic->f = cond_instr(mov1_r13); break;
2385            case 14: ic->f = cond_instr(mov1_r14); break;
2386            }
2387    }
2388    
2389    
2390    static void arm_switch_add1(struct arm_instr_call *ic, int rd,
2391            int condition_code)
2392    {
2393            switch (rd) {
2394            case  0: ic->f = cond_instr(add1_r0); break;
2395            case  1: ic->f = cond_instr(add1_r1); break;
2396            case  2: ic->f = cond_instr(add1_r2); break;
2397            case  3: ic->f = cond_instr(add1_r3); break;
2398            case  4: ic->f = cond_instr(add1_r4); break;
2399            case  5: ic->f = cond_instr(add1_r5); break;
2400            case  6: ic->f = cond_instr(add1_r6); break;
2401            case  7: ic->f = cond_instr(add1_r7); break;
2402            case  8: ic->f = cond_instr(add1_r8); break;
2403            case  9: ic->f = cond_instr(add1_r9); break;
2404            case 10: ic->f = cond_instr(add1_r10); break;
2405            case 11: ic->f = cond_instr(add1_r11); break;
2406            case 12: ic->f = cond_instr(add1_r12); break;
2407            case 13: ic->f = cond_instr(add1_r13); break;
2408            case 14: ic->f = cond_instr(add1_r14); break;
2409            }
2410    }
2411    
2412    
2413  /*****************************************************************************/  /*****************************************************************************/
# Line 1762  X(to_be_translated) Line 2427  X(to_be_translated)
2427          unsigned char *page;          unsigned char *page;
2428          unsigned char ib[4];          unsigned char ib[4];
2429          int condition_code, main_opcode, secondary_opcode, s_bit, rn, rd, r8;          int condition_code, main_opcode, secondary_opcode, s_bit, rn, rd, r8;
2430          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;
2431          void (*samepage_function)(struct cpu *, struct arm_instr_call *);          void (*samepage_function)(struct cpu *, struct arm_instr_call *);
2432    
2433          /*  Figure out the address of the instruction:  */          /*  Figure out the address of the instruction:  */
2434          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)
2435              / sizeof(struct arm_instr_call);              / sizeof(struct arm_instr_call);
2436          addr = cpu->cd.arm.r[ARM_PC] & ~((ARM_IC_ENTRIES_PER_PAGE-1) <<          addr = cpu->pc & ~((ARM_IC_ENTRIES_PER_PAGE-1) <<
2437              ARM_INSTR_ALIGNMENT_SHIFT);              ARM_INSTR_ALIGNMENT_SHIFT);
2438          addr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          addr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
2439          cpu->pc = cpu->cd.arm.r[ARM_PC] = addr;          cpu->pc = addr;
2440          addr &= ~((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);          addr &= ~((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);
2441    
2442          /*  Read the instruction word from memory:  */          /*  Read the instruction word from memory:  */
2443          page = cpu->cd.arm.host_load[addr >> 12];          page = cpu->cd.arm.host_load[addr >> 12];
2444          if (page != NULL) {          if (page != NULL) {
2445                  /*  fatal("TRANSLATION HIT!\n");  */                  /*  fatal("TRANSLATION HIT! 0x%08x\n", addr);  */
2446                  memcpy(ib, page + (addr & 0xfff), sizeof(ib));                  memcpy(ib, page + (addr & 0xfff), sizeof(ib));
2447          } else {          } else {
2448                  /*  fatal("TRANSLATION MISS!\n");  */                  /*  fatal("TRANSLATION MISS! 0x%08x\n", addr);  */
2449                  if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],                  if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],
2450                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
2451                          fatal("to_be_translated(): "                          fatal("to_be_translated(): "
# Line 1805  X(to_be_translated) Line 2470  X(to_be_translated)
2470          condition_code = iword >> 28;          condition_code = iword >> 28;
2471          main_opcode = (iword >> 24) & 15;          main_opcode = (iword >> 24) & 15;
2472          secondary_opcode = (iword >> 21) & 15;          secondary_opcode = (iword >> 21) & 15;
2473          u_bit = (iword >> 23) & 1;          u_bit = iword & 0x00800000;
2474          b_bit = (iword >> 22) & 1;          w_bit = iword & 0x00200000;
2475          w_bit = (iword >> 21) & 1;          s_bit = l_bit = iword & 0x00100000;
         s_bit = l_bit = (iword >> 20) & 1;  
2476          rn    = (iword >> 16) & 15;          rn    = (iword >> 16) & 15;
2477          rd    = (iword >> 12) & 15;          rd    = (iword >> 12) & 15;
2478          r8    = (iword >> 8) & 15;          r8    = (iword >> 8) & 15;
# Line 1873  X(to_be_translated) Line 2537  X(to_be_translated)
2537                          ic->arg[0] = iword;                          ic->arg[0] = iword;
2538                          break;                          break;
2539                  }                  }
2540                    if ((iword & 0x0f900ff0) == 0x01000050) {
2541                            fatal("TODO: q{,d}{add,sub}\n");
2542                            goto bad;
2543                    }
2544                  if ((iword & 0x0ff000d0) == 0x01200010) {                  if ((iword & 0x0ff000d0) == 0x01200010) {
2545                          /*  bx or blx  */                          /*  bx or blx  */
2546                          if (iword & 0x20)                          if (iword & 0x20)
# Line 1897  X(to_be_translated) Line 2565  X(to_be_translated)
2565                          ic->arg[2] = (size_t)(&cpu->cd.arm.r[rn]);                          ic->arg[2] = (size_t)(&cpu->cd.arm.r[rn]);
2566                          break;                          break;
2567                  }                  }
2568                    if ((iword & 0x0fff0ff0) == 0x016f0f10) {
2569                            ic->f = cond_instr(clz);
2570                            ic->arg[0] = (size_t)(&cpu->cd.arm.r[rm]);
2571                            ic->arg[1] = (size_t)(&cpu->cd.arm.r[rd]);
2572                            break;
2573                    }
2574                    if ((iword & 0x0ff00090) == 0x01000080) {
2575                            /*  TODO: smlaXX  */
2576                            goto bad;
2577                    }
2578                    if ((iword & 0x0ff00090) == 0x01400080) {
2579                            /*  TODO: smlalY  */
2580                            goto bad;
2581                    }
2582                    if ((iword & 0x0ff000b0) == 0x01200080) {
2583                            /*  TODO: smlawY  */
2584                            goto bad;
2585                    }
2586                    if ((iword & 0x0ff0f090) == 0x01600080) {
2587                            /*  TODO: smulXY  */
2588                            goto bad;
2589                    }
2590                    if ((iword & 0x0ff0f0b0) == 0x012000a0) {
2591                            /*  TODO: smulwY  */
2592                            goto bad;
2593                    }
2594                  if ((iword & 0x0fb0fff0) == 0x0120f000 ||                  if ((iword & 0x0fb0fff0) == 0x0120f000 ||
2595                      (iword & 0x0fb0f000) == 0x0320f000) {                      (iword & 0x0fb0f000) == 0x0320f000) {
2596                          /*  msr: move to [S|C]PSR from a register or                          /*  msr: move to [S|C]PSR from a register or
# Line 1992  X(to_be_translated) Line 2686  X(to_be_translated)
2686                          break;                          break;
2687                  }                  }
2688    
2689                  /*  "mov reg,reg":  */                  /*  "mov reg,reg" or "mov reg,pc":  */
2690                  if ((iword & 0x0fff0ff0) == 0x01a00000 &&                  if ((iword & 0x0fff0ff0) == 0x01a00000 && rd != ARM_PC) {
2691                      (iword&15) != ARM_PC && rd != ARM_PC) {                          if (rm != ARM_PC) {
2692                          ic->f = cond_instr(mov_reg_reg);                                  ic->f = cond_instr(mov_reg_reg);
2693                          ic->arg[0] = (size_t)(&cpu->cd.arm.r[iword & 15]);                                  ic->arg[0] = (size_t)(&cpu->cd.arm.r[rm]);
2694                            } else {
2695                                    ic->f = cond_instr(mov_reg_pc);
2696                                    ic->arg[0] = (addr & 0xfff) + 8;
2697                            }
2698                          ic->arg[1] = (size_t)(&cpu->cd.arm.r[rd]);                          ic->arg[1] = (size_t)(&cpu->cd.arm.r[rd]);
2699                          break;                          break;
2700                  }                  }
2701    
2702                  /*  "mov reg,#0":  */                  /*  "mov reg,#0":  */
2703                  if ((iword & 0x0fff0fff) == 0x03a03000 && rd != ARM_PC) {                  if ((iword & 0x0fff0fff) == 0x03a00000 && rd != ARM_PC) {
2704                          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;  
                         }  
2705                          break;                          break;
2706                  }                  }
2707    
2708                  /*  "mov reg,#1":  */                  /*  "mov reg,#1":  */
2709                  if ((iword & 0x0fff0fff) == 0x03a03001 && rd != ARM_PC) {                  if ((iword & 0x0fff0fff) == 0x03a00001 && rd != ARM_PC) {
2710                          switch (rd) {                          arm_switch_mov1(ic, rd, condition_code);
2711                          case  0: ic->f = cond_instr(mov1_r0); break;                          break;
2712                          case  1: ic->f = cond_instr(mov1_r1); break;                  }
2713                          case  2: ic->f = cond_instr(mov1_r2); break;  
2714                          case  3: ic->f = cond_instr(mov1_r3); break;                  /*  "add reg,reg,#1":  */
2715                          case  4: ic->f = cond_instr(mov1_r4); break;                  if ((iword & 0x0ff00fff) == 0x02800001 && rd != ARM_PC
2716                          case  5: ic->f = cond_instr(mov1_r5); break;                      && rn == rd) {
2717                          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;  
                         }  
2718                          break;                          break;
2719                  }                  }
2720    
# Line 2072  X(to_be_translated) Line 2745  X(to_be_translated)
2745                          ic->arg[1] = imm;                          ic->arg[1] = imm;
2746                  }                  }
2747    
2748                    /*  mvn #imm ==> mov #~imm  */
2749                    if (secondary_opcode == 0xf && !regform) {
2750                            secondary_opcode = 0xd;
2751                            ic->arg[1] = ~ic->arg[1];
2752                    }
2753    
2754                  ic->arg[0] = (size_t)(&cpu->cd.arm.r[rn]);                  ic->arg[0] = (size_t)(&cpu->cd.arm.r[rn]);
2755                  ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);                  ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);
2756                  any_pc_reg = 0;                  any_pc_reg = 0;
2757                  if (rn == ARM_PC || rd == ARM_PC)                  if (rn == ARM_PC || rd == ARM_PC)
2758                          any_pc_reg = 1;                          any_pc_reg = 1;
2759    
2760                  ic->f = arm_dpi_instr[condition_code +                  if (!any_pc_reg && regform && (iword & 0xfff) < ARM_PC) {
2761                      16 * secondary_opcode + (s_bit? 256 : 0) +                          ic->arg[1] = (size_t)(&cpu->cd.arm.r[rm]);
2762                      (any_pc_reg? 512 : 0) + (regform? 1024 : 0)];                          ic->f = arm_dpi_instr_regshort[condition_code +
2763                                16 * secondary_opcode + (s_bit? 256 : 0)];
2764                    } else
2765                            ic->f = arm_dpi_instr[condition_code +
2766                                16 * secondary_opcode + (s_bit? 256 : 0) +
2767                                (any_pc_reg? 512 : 0) + (regform? 1024 : 0)];
2768    
2769                    if (ic->f == instr(eor_regshort))
2770                            cpu->cd.arm.combination_check = arm_combine_xchg;
2771                  if (iword == 0xe113000c)                  if (iword == 0xe113000c)
2772                          cpu->combination_check = arm_combine_netbsd_scanc;                          cpu->cd.arm.combination_check =
2773                                arm_combine_netbsd_scanc;
2774                  break;                  break;
2775    
2776          case 0x4:       /*  Load and store...  */          case 0x4:       /*  Load and store...  */
# Line 2112  X(to_be_translated) Line 2799  X(to_be_translated)
2799                          fatal("Not a Load/store TODO\n");                          fatal("Not a Load/store TODO\n");
2800                          goto bad;                          goto bad;
2801                  }                  }
2802                    /*  Special case: pc-relative load within the same page:  */
2803                    if (rn == ARM_PC && rd != ARM_PC && main_opcode < 6) {
2804                            int ofs = (addr & 0xfff) + 8, max = 0xffc;
2805                            int b_bit = iword & 0x00400000;
2806                            if (b_bit)
2807                                    max = 0xfff;
2808                            if (u_bit)
2809                                    ofs += (iword & 0xfff);
2810                            else
2811                                    ofs -= (iword & 0xfff);
2812                            /*  NOTE/TODO: This assumes 4KB pages,
2813                                it will not work with 1KB pages.  */
2814                            if (ofs >= 0 && ofs <= max) {
2815                                    unsigned char *p;
2816                                    unsigned char c[4];
2817                                    int len = b_bit? 1 : 4;
2818                                    uint32_t x, a = (addr & 0xfffff000) | ofs;
2819                                    /*  ic->f = cond_instr(mov);  */
2820                                    ic->f = arm_dpi_instr[condition_code + 16*0xd];
2821                                    ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);
2822                                    p = cpu->cd.arm.host_load[a >> 12];
2823                                    if (p != NULL) {
2824                                            memcpy(c, p + (a & 0xfff), len);
2825                                    } else {
2826                                            if (!cpu->memory_rw(cpu, cpu->mem, a,
2827                                                c, len, MEM_READ, CACHE_DATA)) {
2828                                                    fatal("to_be_translated(): "
2829                                                        "read failed X: TODO\n");
2830                                                    goto bad;
2831                                            }
2832                                    }
2833                                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2834                                            x = c[0] + (c[1]<<8) +
2835                                                (c[2]<<16) + (c[3]<<24);
2836                                    else
2837                                            x = c[3] + (c[2]<<8) +
2838                                                (c[1]<<16) + (c[0]<<24);
2839                                    if (b_bit)
2840                                            x = c[0];
2841                                    ic->arg[1] = x;
2842                            }
2843                    }
2844                    if (iword == 0xe4b09004)
2845                            cpu->cd.arm.combination_check =
2846                                arm_combine_netbsd_copyin;
2847                    if (iword == 0xe4a17004)
2848                            cpu->cd.arm.combination_check =
2849                                arm_combine_netbsd_copyout;
2850                  break;                  break;
2851    
2852          case 0x8:       /*  Multiple load/store...  (Block data transfer)  */          case 0x8:       /*  Multiple load/store...  (Block data transfer)  */
# Line 2162  X(to_be_translated) Line 2897  X(to_be_translated)
2897                  if (main_opcode == 0x0a) {                  if (main_opcode == 0x0a) {
2898                          ic->f = cond_instr(b);                          ic->f = cond_instr(b);
2899                          samepage_function = cond_instr(b_samepage);                          samepage_function = cond_instr(b_samepage);
                         /*  if (iword == 0xcafffffc)  
                                 cpu->combination_check = arm_combine_test2;  */  
2900                          if (iword == 0xcaffffed)                          if (iword == 0xcaffffed)
2901                                  cpu->combination_check =                                  cpu->cd.arm.combination_check =
2902                                      arm_combine_netbsd_memset;                                      arm_combine_netbsd_memset;
2903                          if (iword == 0xaafffff9)                          if (iword == 0xaafffff9)
2904                                  cpu->combination_check =                                  cpu->cd.arm.combination_check =
2905                                      arm_combine_netbsd_memcpy;                                      arm_combine_netbsd_memcpy;
2906                  } else {                  } else {
2907                          if (cpu->machine->show_trace_tree) {                          if (cpu->machine->show_trace_tree) {
# Line 2181  X(to_be_translated) Line 2914  X(to_be_translated)
2914                          }                          }
2915                  }                  }
2916    
2917                    /*  arg 1 = offset of current instruction  */
2918                    /*  arg 2 = offset of the following instruction  */
2919                    ic->arg[1] = addr & 0xffc;
2920                    ic->arg[2] = (addr & 0xffc) + 4;
2921    
2922                  ic->arg[0] = (iword & 0x00ffffff) << 2;                  ic->arg[0] = (iword & 0x00ffffff) << 2;
2923                  /*  Sign-extend:  */                  /*  Sign-extend:  */
2924                  if (ic->arg[0] & 0x02000000)                  if (ic->arg[0] & 0x02000000)
# Line 2190  X(to_be_translated) Line 2928  X(to_be_translated)
2928                   */                   */
2929                  ic->arg[0] = (int32_t)(ic->arg[0] + 8);                  ic->arg[0] = (int32_t)(ic->arg[0] + 8);
2930    
2931                  /*  Special case: branch within the same page:  */                  /*
2932                     *  Special case: branch within the same page:
2933                     *
2934                     *  arg[0] = addr of the arm_instr_call of the target
2935                     *  arg[1] = addr of the next arm_instr_call.
2936                     */
2937                  {                  {
2938                          uint32_t mask_within_page =                          uint32_t mask_within_page =
2939                              ((ARM_IC_ENTRIES_PER_PAGE-1) <<                              ((ARM_IC_ENTRIES_PER_PAGE-1) <<
# Line 2205  X(to_be_translated) Line 2948  X(to_be_translated)
2948                                      cpu->cd.arm.cur_ic_page +                                      cpu->cd.arm.cur_ic_page +
2949                                      ((new_pc & mask_within_page) >>                                      ((new_pc & mask_within_page) >>
2950                                      ARM_INSTR_ALIGNMENT_SHIFT));                                      ARM_INSTR_ALIGNMENT_SHIFT));
2951                                    ic->arg[1] = (size_t) (
2952                                        cpu->cd.arm.cur_ic_page +
2953                                        (((addr & mask_within_page) + 4) >>
2954                                        ARM_INSTR_ALIGNMENT_SHIFT));
2955                            } else if (main_opcode == 0x0a) {
2956                                    /*  Special hack for a plain "b":  */
2957                                    ic->arg[0] += ic->arg[1];
2958                          }                          }
2959                  }                  }
2960    
2961  #if 0                  if (main_opcode == 0xa && (condition_code <= 1
2962                  /*  Hm. This doesn't really increase performance.  */                      || condition_code == 3 || condition_code == 8
2963                        || condition_code == 12 || condition_code == 13))
2964                            cpu->cd.arm.combination_check = arm_combine_cmps_b;
2965    
2966                    if (iword == 0x1afffffc)
2967                            cpu->cd.arm.combination_check = arm_combine_strlen;
2968    
2969                    /*  Hm. Does this really increase performance?  */
2970                  if (iword == 0x8afffffa)                  if (iword == 0x8afffffa)
2971                          cpu->combination_check = arm_combine_netbsd_cacheclean2;                          cpu->cd.arm.combination_check =
2972  #endif                              arm_combine_netbsd_cacheclean2;
2973                    break;
2974    
2975            case 0xc:
2976            case 0xd:
2977                    /*
2978                     *  xxxx1100 0100nnnn ddddcccc oooommmm    MCRR c,op,Rd,Rn,CRm
2979                     *  xxxx1100 0101nnnn ddddcccc oooommmm    MRRC c,op,Rd,Rn,CRm
2980                     */
2981                    if ((iword & 0x0fe00000) == 0x0c400000) {
2982                            fatal("MCRR/MRRC: TODO\n");
2983                            goto bad;
2984                    }
2985    
2986                    /*
2987                     *  TODO: LDC/STC
2988                     *
2989                     *  For now, treat as Undefined instructions. This causes e.g.
2990                     *  Linux/ARM to emulate these instructions (floating point).
2991                     */
2992                    ic->f = cond_instr(und);
2993                    ic->arg[0] = addr & 0xfff;
2994                  break;                  break;
2995    
2996          case 0xe:          case 0xe:
# Line 2226  X(to_be_translated) Line 3004  X(to_be_translated)
3004                          ic->f = cond_instr(cdp);                          ic->f = cond_instr(cdp);
3005                  }                  }
3006                  if (iword == 0xee070f9a)                  if (iword == 0xee070f9a)
3007                          cpu->combination_check = arm_combine_netbsd_cacheclean;                          cpu->cd.arm.combination_check =
3008                                arm_combine_netbsd_cacheclean;
3009                  break;                  break;
3010    
3011          case 0xf:          case 0xf:
3012                  /*  SWI:  */                  /*  SWI:  */
3013                  /*  Default handler:  */                  /*  Default handler:  */
3014                  ic->f = cond_instr(swi);                  ic->f = cond_instr(swi);
3015                  if (iword == 0xef8c64be) {                  ic->arg[0] = addr & 0xfff;
3016                    if (iword == 0xef8c64eb) {
3017                            /*  Hack for rebooting a machine:  */
3018                            ic->f = instr(reboot);
3019                    } else if (iword == 0xef8c64be) {
3020                          /*  Hack for openfirmware prom emulation:  */                          /*  Hack for openfirmware prom emulation:  */
3021                          ic->f = instr(openfirmware);                          ic->f = instr(openfirmware);
3022                  } else if (cpu->machine->userland_emul != NULL) {                  } else if (cpu->machine->userland_emul != NULL) {

Legend:
Removed from v.19  
changed lines
  Added in v.20

  ViewVC Help
Powered by ViewVC 1.1.26