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

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

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

revision 18 by dpavlin, Mon Oct 8 16:19:11 2007 UTC revision 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2006  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_arm_instr.c,v 1.39 2005/10/27 14:01:13 debug Exp $   *  $Id: cpu_arm_instr.c,v 1.60 2006/02/09 22:40:27 debug Exp $
29   *   *
30   *  ARM instructions.   *  ARM instructions.
31   *   *
# Line 36  Line 36 
36   */   */
37    
38    
 #include "arm_quick_pc_to_pointers.h"  
   
39  /*  #define GATHER_BDT_STATISTICS  */  /*  #define GATHER_BDT_STATISTICS  */
40    
41    
# Line 125  static void update_bdt_statistics(uint32 Line 123  static void update_bdt_statistics(uint32
123   *  functions, otherwise they will simply call the X function.   *  functions, otherwise they will simply call the X function.
124   */   */
125    
126    uint8_t condition_hi[16] = { 0,0,1,1, 0,0,0,0, 0,0,1,1, 0,0,0,0 };
127    uint8_t condition_ge[16] = { 1,0,1,0, 1,0,1,0, 0,1,0,1, 0,1,0,1 };
128    uint8_t condition_gt[16] = { 1,0,1,0, 0,0,0,0, 0,1,0,1, 0,0,0,0 };
129    
130  #define Y(n) void arm_instr_ ## n ## __eq(struct cpu *cpu,              \  #define Y(n) void arm_instr_ ## n ## __eq(struct cpu *cpu,              \
131                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
132          {  if (cpu->cd.arm.cpsr & ARM_FLAG_Z)                           \          {  if (cpu->cd.arm.flags & ARM_F_Z)                             \
133                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
134          void arm_instr_ ## n ## __ne(struct cpu *cpu,                   \          void arm_instr_ ## n ## __ne(struct cpu *cpu,                   \
135                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
136          {  if (!(cpu->cd.arm.cpsr & ARM_FLAG_Z))                        \          {  if (!(cpu->cd.arm.flags & ARM_F_Z))                          \
137                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
138          void arm_instr_ ## n ## __cs(struct cpu *cpu,                   \          void arm_instr_ ## n ## __cs(struct cpu *cpu,                   \
139                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
140          {  if (cpu->cd.arm.cpsr & ARM_FLAG_C)                           \          {  if (cpu->cd.arm.flags & ARM_F_C)                             \
141                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
142          void arm_instr_ ## n ## __cc(struct cpu *cpu,                   \          void arm_instr_ ## n ## __cc(struct cpu *cpu,                   \
143                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
144          {  if (!(cpu->cd.arm.cpsr & ARM_FLAG_C))                        \          {  if (!(cpu->cd.arm.flags & ARM_F_C))                          \
145                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
146          void arm_instr_ ## n ## __mi(struct cpu *cpu,                   \          void arm_instr_ ## n ## __mi(struct cpu *cpu,                   \
147                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
148          {  if (cpu->cd.arm.cpsr & ARM_FLAG_N)                           \          {  if (cpu->cd.arm.flags & ARM_F_N)                             \
149                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
150          void arm_instr_ ## n ## __pl(struct cpu *cpu,                   \          void arm_instr_ ## n ## __pl(struct cpu *cpu,                   \
151                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
152          {  if (!(cpu->cd.arm.cpsr & ARM_FLAG_N))                        \          {  if (!(cpu->cd.arm.flags & ARM_F_N))                          \
153                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
154          void arm_instr_ ## n ## __vs(struct cpu *cpu,                   \          void arm_instr_ ## n ## __vs(struct cpu *cpu,                   \
155                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
156          {  if (cpu->cd.arm.cpsr & ARM_FLAG_V)                           \          {  if (cpu->cd.arm.flags & ARM_F_V)                             \
157                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
158          void arm_instr_ ## n ## __vc(struct cpu *cpu,                   \          void arm_instr_ ## n ## __vc(struct cpu *cpu,                   \
159                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
160          {  if (!(cpu->cd.arm.cpsr & ARM_FLAG_V))                        \          {  if (!(cpu->cd.arm.flags & ARM_F_V))                          \
161                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
162          void arm_instr_ ## n ## __hi(struct cpu *cpu,                   \          void arm_instr_ ## n ## __hi(struct cpu *cpu,                   \
163                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
164          {  if (cpu->cd.arm.cpsr & ARM_FLAG_C &&                         \          {  if (condition_hi[cpu->cd.arm.flags])                         \
                 !(cpu->cd.arm.cpsr & ARM_FLAG_Z))                       \  
165                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
166          void arm_instr_ ## n ## __ls(struct cpu *cpu,                   \          void arm_instr_ ## n ## __ls(struct cpu *cpu,                   \
167                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
168          {  if (cpu->cd.arm.cpsr & ARM_FLAG_Z ||                         \          {  if (!condition_hi[cpu->cd.arm.flags])                        \
                 !(cpu->cd.arm.cpsr & ARM_FLAG_C))                       \  
169                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
170          void arm_instr_ ## n ## __ge(struct cpu *cpu,                   \          void arm_instr_ ## n ## __ge(struct cpu *cpu,                   \
171                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
172          {  if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) ==                 \          {  if (condition_ge[cpu->cd.arm.flags])                         \
                 ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0))                  \  
173                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
174          void arm_instr_ ## n ## __lt(struct cpu *cpu,                   \          void arm_instr_ ## n ## __lt(struct cpu *cpu,                   \
175                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
176          {  if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) !=                 \          {  if (!condition_ge[cpu->cd.arm.flags])                        \
                 ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0))                  \  
177                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
178          void arm_instr_ ## n ## __gt(struct cpu *cpu,                   \          void arm_instr_ ## n ## __gt(struct cpu *cpu,                   \
179                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
180          {  if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) ==                 \          {  if (condition_gt[cpu->cd.arm.flags])                         \
                 ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0) &&                \  
                 !(cpu->cd.arm.cpsr & ARM_FLAG_Z))                       \  
181                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
182          void arm_instr_ ## n ## __le(struct cpu *cpu,                   \          void arm_instr_ ## n ## __le(struct cpu *cpu,                   \
183                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
184          {  if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) !=                 \          {  if (!condition_gt[cpu->cd.arm.flags])                        \
                 ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0) ||                \  
                 (cpu->cd.arm.cpsr & ARM_FLAG_Z))                        \  
185                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
186          void (*arm_cond_instr_ ## n  [16])(struct cpu *,                \          void (*arm_cond_instr_ ## n  [16])(struct cpu *,                \
187                          struct arm_instr_call *) = {                    \                          struct arm_instr_call *) = {                    \
# Line 215  X(invalid) { Line 209  X(invalid) {
209          uint32_t low_pc;          uint32_t low_pc;
210          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
211              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
212          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
213              << ARM_INSTR_ALIGNMENT_SHIFT);              << ARM_INSTR_ALIGNMENT_SHIFT);
214          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];  
215    
216          fatal("Invalid ARM instruction: pc=0x%08x\n", (int)cpu->pc);          fatal("Invalid ARM instruction: pc=0x%08x\n", (int)cpu->pc);
217    
# Line 236  X(invalid) { Line 229  X(invalid) {
229   */   */
230  X(b)  X(b)
231  {  {
232          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];  
233    
234          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
235          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
# Line 257  Y(b) Line 241  Y(b)
241   *  b_samepage:  Branch (to within the same translated page)   *  b_samepage:  Branch (to within the same translated page)
242   *   *
243   *  arg[0] = pointer to new arm_instr_call   *  arg[0] = pointer to new arm_instr_call
244     *  arg[1] = pointer to the next instruction.
245     *
246     *  NOTE: This instruction is manually inlined.
247   */   */
248  X(b_samepage)  X(b_samepage) {
 {  
249          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
250  }  }
251  Y(b_samepage)  X(b_samepage__eq) {
252            cpu->cd.arm.next_ic = (struct arm_instr_call *)
253                ic->arg[cpu->cd.arm.flags & ARM_F_Z? 0 : 1];
254    }
255    X(b_samepage__ne) {
256            cpu->cd.arm.next_ic = (struct arm_instr_call *)
257                ic->arg[cpu->cd.arm.flags & ARM_F_Z? 1 : 0];
258    }
259    X(b_samepage__cs) {
260            cpu->cd.arm.next_ic = (struct arm_instr_call *)
261                ic->arg[cpu->cd.arm.flags & ARM_F_C? 0 : 1];
262    }
263    X(b_samepage__cc) {
264            cpu->cd.arm.next_ic = (struct arm_instr_call *)
265                ic->arg[cpu->cd.arm.flags & ARM_F_C? 1 : 0];
266    }
267    X(b_samepage__mi) {
268            cpu->cd.arm.next_ic = (struct arm_instr_call *)
269                ic->arg[cpu->cd.arm.flags & ARM_F_N? 0 : 1];
270    }
271    X(b_samepage__pl) {
272            cpu->cd.arm.next_ic = (struct arm_instr_call *)
273                ic->arg[cpu->cd.arm.flags & ARM_F_N? 1 : 0];
274    }
275    X(b_samepage__vs) {
276            cpu->cd.arm.next_ic = (struct arm_instr_call *)
277                ic->arg[cpu->cd.arm.flags & ARM_F_V? 0 : 1];
278    }
279    X(b_samepage__vc) {
280            cpu->cd.arm.next_ic = (struct arm_instr_call *)
281                ic->arg[cpu->cd.arm.flags & ARM_F_V? 1 : 0];
282    }
283    X(b_samepage__hi) {
284            cpu->cd.arm.next_ic = (condition_hi[cpu->cd.arm.flags])?
285                (struct arm_instr_call *) ic->arg[0] :
286                (struct arm_instr_call *) ic->arg[1];
287    }
288    X(b_samepage__ls) {
289            cpu->cd.arm.next_ic = (struct arm_instr_call *)
290                ic->arg[condition_hi[cpu->cd.arm.flags]];
291    }
292    X(b_samepage__ge) {
293            cpu->cd.arm.next_ic = (condition_ge[cpu->cd.arm.flags])?
294                (struct arm_instr_call *) ic->arg[0] :
295                (struct arm_instr_call *) ic->arg[1];
296    }
297    X(b_samepage__lt) {
298            cpu->cd.arm.next_ic = (struct arm_instr_call *)
299                ic->arg[condition_ge[cpu->cd.arm.flags]];
300    }
301    X(b_samepage__gt) {
302            cpu->cd.arm.next_ic = (condition_gt[cpu->cd.arm.flags])?
303                (struct arm_instr_call *) ic->arg[0] :
304                (struct arm_instr_call *) ic->arg[1];
305    }
306    X(b_samepage__le) {
307            cpu->cd.arm.next_ic = (struct arm_instr_call *)
308                ic->arg[condition_gt[cpu->cd.arm.flags]];
309    }
310    void (*arm_cond_instr_b_samepage[16])(struct cpu *,
311            struct arm_instr_call *) = {
312            arm_instr_b_samepage__eq, arm_instr_b_samepage__ne,
313            arm_instr_b_samepage__cs, arm_instr_b_samepage__cc,
314            arm_instr_b_samepage__mi, arm_instr_b_samepage__pl,
315            arm_instr_b_samepage__vs, arm_instr_b_samepage__vc,
316            arm_instr_b_samepage__hi, arm_instr_b_samepage__ls,
317            arm_instr_b_samepage__ge, arm_instr_b_samepage__lt,
318            arm_instr_b_samepage__gt, arm_instr_b_samepage__le,
319            arm_instr_b_samepage, arm_instr_nop };
320    
321    
322  /*  /*
# Line 272  Y(b_samepage) Line 326  Y(b_samepage)
326   */   */
327  X(bx)  X(bx)
328  {  {
329          cpu->pc = cpu->cd.arm.r[ARM_PC] = reg(ic->arg[0]);          cpu->pc = reg(ic->arg[0]);
330          if (cpu->pc & 1) {          if (cpu->pc & 1) {
331                  fatal("thumb: TODO\n");                  fatal("thumb: TODO\n");
332                  exit(1);                  exit(1);
# Line 292  Y(bx) Line 346  Y(bx)
346   */   */
347  X(bx_trace)  X(bx_trace)
348  {  {
349          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
350          if (cpu->pc & 1) {          if (cpu->pc & 1) {
351                  fatal("thumb: TODO\n");                  fatal("thumb: TODO\n");
352                  exit(1);                  exit(1);
# Line 314  Y(bx_trace) Line 368  Y(bx_trace)
368   */   */
369  X(bl)  X(bl)
370  {  {
371          uint32_t lr, low_pc;          uint32_t pc = ((uint32_t)cpu->pc & 0xfffff000) + (int32_t)ic->arg[1];
372            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;  
373    
374          /*  Calculate new PC from this instruction + arg[0]  */          /*  Calculate new PC from this instruction + arg[0]  */
375          cpu->pc = cpu->cd.arm.r[ARM_PC] = lr - 4 + (int32_t)ic->arg[0];          cpu->pc = pc + (int32_t)ic->arg[0];
376    
377          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
378          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
# Line 342  Y(bl) Line 387  Y(bl)
387   */   */
388  X(blx)  X(blx)
389  {  {
390          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:  */  
391          cpu->cd.arm.r[ARM_LR] = lr;          cpu->cd.arm.r[ARM_LR] = lr;
392            cpu->pc = reg(ic->arg[0]);
         cpu->pc = cpu->cd.arm.r[ARM_PC] = reg(ic->arg[0]);  
393          if (cpu->pc & 1) {          if (cpu->pc & 1) {
394                  fatal("thumb: TODO\n");                  fatal("thumb: TODO\n");
395                  exit(1);                  exit(1);
# Line 374  Y(blx) Line 409  Y(blx)
409   */   */
410  X(bl_trace)  X(bl_trace)
411  {  {
412          uint32_t lr, low_pc;          uint32_t pc = ((uint32_t)cpu->pc & 0xfffff000) + (int32_t)ic->arg[1];
413            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;  
414    
415          /*  Calculate new PC from this instruction + arg[0]  */          /*  Calculate new PC from this instruction + arg[0]  */
416          cpu->pc = cpu->cd.arm.r[ARM_PC] = lr - 4 + (int32_t)ic->arg[0];          cpu->pc = pc + (int32_t)ic->arg[0];
417    
418          cpu_functioncall_trace(cpu, cpu->pc);          cpu_functioncall_trace(cpu, cpu->pc);
419    
# Line 404  Y(bl_trace) Line 430  Y(bl_trace)
430   */   */
431  X(bl_samepage)  X(bl_samepage)
432  {  {
433          uint32_t lr, low_pc;          cpu->cd.arm.r[ARM_LR] =
434                ((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:  */  
435          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
436  }  }
437  Y(bl_samepage)  Y(bl_samepage)
# Line 429  Y(bl_samepage) Line 444  Y(bl_samepage)
444   */   */
445  X(bl_samepage_trace)  X(bl_samepage_trace)
446  {  {
447          uint32_t tmp_pc, lr, low_pc;          uint32_t low_pc, lr = (cpu->pc & 0xfffff000) + 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);  
448    
449          /*  Link:  */          /*  Link and branch:  */
450          cpu->cd.arm.r[ARM_LR] = lr;          cpu->cd.arm.r[ARM_LR] = lr;
   
         /*  Branch:  */  
451          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
452    
453            /*  Synchronize the program counter:  */
454          low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)          low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)
455              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
456          tmp_pc = cpu->cd.arm.r[ARM_PC];          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
         tmp_pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)  
457              << ARM_INSTR_ALIGNMENT_SHIFT);              << ARM_INSTR_ALIGNMENT_SHIFT);
458          tmp_pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
459          cpu_functioncall_trace(cpu, tmp_pc);  
460            /*  ... and show trace:  */
461            cpu_functioncall_trace(cpu, cpu->pc);
462  }  }
463  Y(bl_samepage_trace)  Y(bl_samepage_trace)
464    
465    
466  #include "cpu_arm_instr_misc.c"  /*
467     *  clz: Count leading zeroes.
468     *
469     *  arg[0] = ptr to rm
470     *  arg[1] = ptr to rd
471     */
472    X(clz)
473    {
474            uint32_t rm = reg(ic->arg[0]);
475            int i = 32, n = 0, j;
476            while (i>0) {
477                    if (rm & 0xff000000) {
478                            for (j=0; j<8; j++) {
479                                    if (rm & 0x80000000)
480                                            break;
481                                    n ++;
482                                    rm <<= 1;
483                            }
484                            break;
485                    } else {
486                            rm <<= 8;
487                            i -= 8;
488                            n += 8;
489                    }
490            }
491            reg(ic->arg[1]) = n;
492    }
493    Y(clz)
494    
495    
496  /*  /*
# Line 474  X(muls) Line 509  X(muls)
509  {  {
510          uint32_t result;          uint32_t result;
511          result = reg(ic->arg[1]) * reg(ic->arg[2]);          result = reg(ic->arg[1]) * reg(ic->arg[2]);
512          cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N);          cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
513          if (result == 0)          if (result == 0)
514                  cpu->cd.arm.cpsr |= ARM_FLAG_Z;                  cpu->cd.arm.flags |= ARM_F_Z;
515          if (result & 0x80000000)          if (result & 0x80000000)
516                  cpu->cd.arm.cpsr |= ARM_FLAG_N;                  cpu->cd.arm.flags |= ARM_F_N;
517          reg(ic->arg[0]) = result;          reg(ic->arg[0]) = result;
518  }  }
519  Y(muls)  Y(muls)
# Line 509  X(mlas) Line 544  X(mlas)
544          rs = (iw >> 8) & 15;  rm = iw & 15;          rs = (iw >> 8) & 15;  rm = iw & 15;
545          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]
546              + cpu->cd.arm.r[rn];              + cpu->cd.arm.r[rn];
547          cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N);          cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
548          if (cpu->cd.arm.r[rd] == 0)          if (cpu->cd.arm.r[rd] == 0)
549                  cpu->cd.arm.cpsr |= ARM_FLAG_Z;                  cpu->cd.arm.flags |= ARM_F_Z;
550          if (cpu->cd.arm.r[rd] & 0x80000000)          if (cpu->cd.arm.r[rd] & 0x80000000)
551                  cpu->cd.arm.cpsr |= ARM_FLAG_N;                  cpu->cd.arm.flags |= ARM_F_N;
552  }  }
553  Y(mlas)  Y(mlas)
554    
# Line 528  X(mull) Line 563  X(mull)
563          /*  xxxx0000 1UAShhhh llllssss 1001mmmm  */          /*  xxxx0000 1UAShhhh llllssss 1001mmmm  */
564          uint32_t iw; uint64_t tmp; int u_bit, a_bit;          uint32_t iw; uint64_t tmp; int u_bit, a_bit;
565          iw = ic->arg[0];          iw = ic->arg[0];
566          u_bit = (iw >> 22) & 1; a_bit = (iw >> 21) & 1;          u_bit = iw & 0x00400000; a_bit = iw & 0x00200000;
567          tmp = cpu->cd.arm.r[iw & 15];          tmp = cpu->cd.arm.r[iw & 15];
568          if (u_bit)          if (u_bit)
569                  tmp = (int64_t)(int32_t)tmp                  tmp = (int64_t)(int32_t)tmp
# Line 550  Y(mull) Line 585  Y(mull)
585    
586    
587  /*  /*
588     *  smulXY:  16-bit * 16-bit multiplication (32-bit result)
589     *
590     *  arg[0] = ptr to rm
591     *  arg[1] = ptr to rs
592     *  arg[2] = ptr to rd
593     */
594    X(smulbb)
595    {
596            reg(ic->arg[2]) = (int32_t)(int16_t)reg(ic->arg[0]) *
597                (int32_t)(int16_t)reg(ic->arg[1]);
598    }
599    Y(smulbb)
600    X(smultb)
601    {
602            reg(ic->arg[2]) = (int32_t)(int16_t)(reg(ic->arg[0]) >> 16) *
603                (int32_t)(int16_t)reg(ic->arg[1]);
604    }
605    Y(smultb)
606    X(smulbt)
607    {
608            reg(ic->arg[2]) = (int32_t)(int16_t)reg(ic->arg[0]) *
609                (int32_t)(int16_t)(reg(ic->arg[1]) >> 16);
610    }
611    Y(smulbt)
612    X(smultt)
613    {
614            reg(ic->arg[2]) = (int32_t)(int16_t)(reg(ic->arg[0]) >> 16) *
615                (int32_t)(int16_t)(reg(ic->arg[1]) >> 16);
616    }
617    Y(smultt)
618    
619    
620    /*
621   *  mov_reg_reg:  Move a register to another.   *  mov_reg_reg:  Move a register to another.
622   *   *
623   *  arg[0] = ptr to source register   *  arg[0] = ptr to source register
# Line 563  Y(mov_reg_reg) Line 631  Y(mov_reg_reg)
631    
632    
633  /*  /*
634     *  mov_reg_pc:  Move the PC register to a normal register.
635     *
636     *  arg[0] = offset compared to start of current page + 8
637     *  arg[1] = ptr to destination register
638     */
639    X(mov_reg_pc)
640    {
641            reg(ic->arg[1]) = ((uint32_t)cpu->pc&0xfffff000) + (int32_t)ic->arg[0];
642    }
643    Y(mov_reg_pc)
644    
645    
646    /*
647   *  ret_trace:  "mov pc,lr" with trace enabled   *  ret_trace:  "mov pc,lr" with trace enabled
648   *  ret:  "mov pc,lr" without trace enabled   *  ret:  "mov pc,lr" without trace enabled
649   *   *
# Line 571  Y(mov_reg_reg) Line 652  Y(mov_reg_reg)
652  X(ret_trace)  X(ret_trace)
653  {  {
654          uint32_t old_pc, mask_within_page;          uint32_t old_pc, mask_within_page;
655          old_pc = cpu->cd.arm.r[ARM_PC];          old_pc = cpu->pc;
656          mask_within_page = ((ARM_IC_ENTRIES_PER_PAGE-1)          mask_within_page = ((ARM_IC_ENTRIES_PER_PAGE-1)
657              << ARM_INSTR_ALIGNMENT_SHIFT) |              << ARM_INSTR_ALIGNMENT_SHIFT) |
658              ((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);              ((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);
659    
660          /*  Update the PC register:  */          /*  Update the PC register:  */
661          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
662    
663          cpu_functioncall_trace_return(cpu);          cpu_functioncall_trace_return(cpu);
664    
# Line 596  X(ret_trace) Line 677  X(ret_trace)
677  Y(ret_trace)  Y(ret_trace)
678  X(ret)  X(ret)
679  {  {
680          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
681          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
682  }  }
683  Y(ret)  Y(ret)
# Line 620  X(msr_imm) Line 701  X(msr_imm)
701              (ic->arg[0] & ARM_FLAG_MODE));              (ic->arg[0] & ARM_FLAG_MODE));
702          uint32_t new_value = ic->arg[0];          uint32_t new_value = ic->arg[0];
703    
704            cpu->cd.arm.cpsr &= 0x0fffffff;
705            cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
706    
707          if (switch_register_banks)          if (switch_register_banks)
708                  arm_save_register_bank(cpu);                  arm_save_register_bank(cpu);
709    
710          cpu->cd.arm.cpsr &= ~mask;          cpu->cd.arm.cpsr &= ~mask;
711          cpu->cd.arm.cpsr |= (new_value & mask);          cpu->cd.arm.cpsr |= (new_value & mask);
712    
713            cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
714    
715          if (switch_register_banks)          if (switch_register_banks)
716                  arm_load_register_bank(cpu);                  arm_load_register_bank(cpu);
717  }  }
# Line 667  X(msr_imm_spsr) Line 753  X(msr_imm_spsr)
753          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
754          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)
755              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
756          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
757              << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
758          cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          old_pc = cpu->pc;
759          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);  
760  }  }
761                  exit(1);                  exit(1);
762          }          }
# Line 692  Y(msr_spsr) Line 777  Y(msr_spsr)
777   */   */
778  X(mrs)  X(mrs)
779  {  {
780            cpu->cd.arm.cpsr &= 0x0fffffff;
781            cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
782          reg(ic->arg[0]) = cpu->cd.arm.cpsr;          reg(ic->arg[0]) = cpu->cd.arm.cpsr;
783  }  }
784  Y(mrs)  Y(mrs)
785    
786    
787  /*  /*
788   *  mrs: Move from status/flag register to a normal register.   *  mrs: Move from saved status/flag register to a normal register.
789   *   *
790   *  arg[0] = pointer to rd   *  arg[0] = pointer to rd
791   */   */
# Line 727  Y(mrs_spsr) Line 814  Y(mrs_spsr)
814   *  arg[0] = copy of the instruction word   *  arg[0] = copy of the instruction word
815   */   */
816  X(mcr_mrc) {  X(mcr_mrc) {
817          uint32_t low_pc;          uint32_t low_pc = ((size_t)ic - (size_t)
         low_pc = ((size_t)ic - (size_t)  
818              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
819          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
820              << 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];  
821          arm_mcr_mrc(cpu, ic->arg[0]);          arm_mcr_mrc(cpu, ic->arg[0]);
822  }  }
823  Y(mcr_mrc)  Y(mcr_mrc)
824  X(cdp) {  X(cdp) {
825          uint32_t low_pc;          uint32_t low_pc = ((size_t)ic - (size_t)
         low_pc = ((size_t)ic - (size_t)  
826              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
827          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
828              << 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];  
829          arm_cdp(cpu, ic->arg[0]);          arm_cdp(cpu, ic->arg[0]);
830  }  }
831  Y(cdp)  Y(cdp)
# Line 755  Y(cdp) Line 836  Y(cdp)
836   */   */
837  X(openfirmware)  X(openfirmware)
838  {  {
839            /*  TODO: sync pc?  */
840          of_emul(cpu);          of_emul(cpu);
841          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
842          if (cpu->machine->show_trace_tree)          if (cpu->machine->show_trace_tree)
843                  cpu_functioncall_trace_return(cpu);                  cpu_functioncall_trace_return(cpu);
844          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
# Line 764  X(openfirmware) Line 846  X(openfirmware)
846    
847    
848  /*  /*
849     *  reboot:
850     */
851    X(reboot)
852    {
853            cpu->running = 0;
854            cpu->running_translated = 0;
855            cpu->n_translated_instrs --;
856            cpu->cd.arm.next_ic = &nothing_call;
857    }
858    
859    
860    /*
861   *  swi_useremul: Syscall.   *  swi_useremul: Syscall.
862   *   *
863   *  arg[0] = swi number   *  arg[0] = swi number
# Line 773  X(swi_useremul) Line 867  X(swi_useremul)
867          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
868          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)
869              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
870          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
871              << ARM_INSTR_ALIGNMENT_SHIFT);              << ARM_INSTR_ALIGNMENT_SHIFT);
872          cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
873          old_pc = cpu->pc = cpu->cd.arm.r[ARM_PC];          old_pc = cpu->pc;
874    
875          useremul_syscall(cpu, ic->arg[0]);          useremul_syscall(cpu, ic->arg[0]);
876    
# Line 798  Y(swi_useremul) Line 892  Y(swi_useremul)
892   */   */
893  X(swi)  X(swi)
894  {  {
895          /*  Synchronize the program counter:  */          /*  Synchronize the program counter first:  */
896          uint32_t low_pc = ((size_t)ic - (size_t)          cpu->pc &= 0xfffff000;
897              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];  
   
898          arm_exception(cpu, ARM_EXCEPTION_SWI);          arm_exception(cpu, ARM_EXCEPTION_SWI);
899  }  }
900  Y(swi)  Y(swi)
901    
902    
903  /*  /*
904     *  und:  Undefined instruction.
905     */
906    X(und)
907    {
908            /*  Synchronize the program counter first:  */
909            cpu->pc &= 0xfffff000;
910            cpu->pc += ic->arg[0];
911            arm_exception(cpu, ARM_EXCEPTION_UND);
912    }
913    Y(und)
914    
915    
916    /*
917   *  swp, swpb:  Swap (word or byte).   *  swp, swpb:  Swap (word or byte).
918   *   *
919   *  arg[0] = ptr to rd   *  arg[0] = ptr to rd
# Line 822  X(swp) Line 924  X(swp)
924  {  {
925          uint32_t addr = reg(ic->arg[2]), data, data2;          uint32_t addr = reg(ic->arg[2]), data, data2;
926          unsigned char d[4];          unsigned char d[4];
927    
928          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
929          uint32_t low_pc = ((size_t)ic - (size_t)          uint32_t low_pc = ((size_t)ic - (size_t)
930              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
931          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
932              << 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];  
933    
934          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,
935              CACHE_DATA)) {              CACHE_DATA)) {
# Line 850  X(swpb) Line 951  X(swpb)
951  {  {
952          uint32_t addr = reg(ic->arg[2]), data;          uint32_t addr = reg(ic->arg[2]), data;
953          unsigned char d[1];          unsigned char d[1];
954    
955          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
956          uint32_t low_pc = ((size_t)ic - (size_t)          uint32_t low_pc = ((size_t)ic - (size_t)
957              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
958          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
959              << 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];  
960    
961          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,
962              CACHE_DATA)) {              CACHE_DATA)) {
# Line 877  Y(swpb) Line 977  Y(swpb)
977    
978  extern void (*arm_load_store_instr[1024])(struct cpu *,  extern void (*arm_load_store_instr[1024])(struct cpu *,
979          struct arm_instr_call *);          struct arm_instr_call *);
980    X(store_w1_word_u1_p0_imm);
981  X(store_w0_byte_u1_p0_imm);  X(store_w0_byte_u1_p0_imm);
982  X(store_w0_word_u1_p0_imm);  X(store_w0_word_u1_p0_imm);
983    X(store_w0_word_u1_p1_imm);
984    X(load_w1_word_u1_p0_imm);
985  X(load_w0_word_u1_p0_imm);  X(load_w0_word_u1_p0_imm);
986  X(load_w0_byte_u1_p1_imm);  X(load_w0_byte_u1_p1_imm);
987  X(load_w0_byte_u1_p1_reg);  X(load_w0_byte_u1_p1_reg);
988    X(load_w1_byte_u1_p1_imm);
989    
990  extern void (*arm_load_store_instr_pc[1024])(struct cpu *,  extern void (*arm_load_store_instr_pc[1024])(struct cpu *,
991          struct arm_instr_call *);          struct arm_instr_call *);
# Line 893  extern void (*arm_load_store_instr_3_pc[ Line 997  extern void (*arm_load_store_instr_3_pc[
997          struct arm_instr_call *);          struct arm_instr_call *);
998    
999  extern uint32_t (*arm_r[8192])(struct cpu *, struct arm_instr_call *);  extern uint32_t (*arm_r[8192])(struct cpu *, struct arm_instr_call *);
1000    extern void arm_r_r3_t0_c0(void);
1001    
1002  extern void (*arm_dpi_instr[2 * 2 * 2 * 16 * 16])(struct cpu *,  extern void (*arm_dpi_instr[2 * 2 * 2 * 16 * 16])(struct cpu *,
1003          struct arm_instr_call *);          struct arm_instr_call *);
1004    extern void (*arm_dpi_instr_regshort[2 * 16 * 16])(struct cpu *,
1005            struct arm_instr_call *);
1006  X(cmps);  X(cmps);
1007    X(teqs);
1008    X(tsts);
1009  X(sub);  X(sub);
1010  X(add);  X(add);
1011  X(subs);  X(subs);
1012    X(eor_regshort);
1013    X(cmps_regshort);
1014    
1015    
1016    #include "cpu_arm_instr_misc.c"
1017    
1018    
1019  /*  /*
1020   *  bdt_load:  Block Data Transfer, Load   *  bdt_load:  Block Data Transfer, Load
# Line 931  X(bdt_load) Line 1044  X(bdt_load)
1044          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
1045          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
1046              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
1047          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) <<          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
1048              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];  
1049    
1050          if (s_bit) {          if (s_bit) {
1051                  /*  Load to USR registers:  */                  /*  Load to USR registers:  */
# Line 1070  X(bdt_load) Line 1181  X(bdt_load)
1181                          arm_save_register_bank(cpu);                          arm_save_register_bank(cpu);
1182    
1183                  cpu->cd.arm.cpsr = new_cpsr;                  cpu->cd.arm.cpsr = new_cpsr;
1184                    cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
1185    
1186                  if (switch_register_banks)                  if (switch_register_banks)
1187                          arm_load_register_bank(cpu);                          arm_load_register_bank(cpu);
# Line 1077  X(bdt_load) Line 1189  X(bdt_load)
1189    
1190          /*  NOTE: Special case: Loading the PC  */          /*  NOTE: Special case: Loading the PC  */
1191          if (iw & 0x8000) {          if (iw & 0x8000) {
1192                  cpu->cd.arm.r[ARM_PC] &= ~3;                  cpu->pc = cpu->cd.arm.r[ARM_PC] & 0xfffffffc;
                 cpu->pc = cpu->cd.arm.r[ARM_PC];  
1193                  if (cpu->machine->show_trace_tree)                  if (cpu->machine->show_trace_tree)
1194                          cpu_functioncall_trace_return(cpu);                          cpu_functioncall_trace_return(cpu);
1195                  /*  TODO: There is no need to update the                  /*  TODO: There is no need to update the
# Line 1119  X(bdt_store) Line 1230  X(bdt_store)
1230          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
1231          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
1232              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
1233          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) <<          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
1234              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];  
1235    
1236          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)) {
1237                  if (!((iw >> i) & 1)) {                  if (!((iw >> i) & 1)) {
# Line 1151  X(bdt_store) Line 1260  X(bdt_store)
1260                          }                          }
1261                  }                  }
1262    
1263                    /*  NOTE/TODO: 8 vs 12 on some ARMs  */
1264                  if (i == ARM_PC)                  if (i == ARM_PC)
1265                          value += 12;    /*  NOTE/TODO: 8 on some ARMs  */                          value = cpu->pc + 12;
1266    
1267                  if (p_bit) {                  if (p_bit) {
1268                          if (u_bit)                          if (u_bit)
# Line 1210  Y(bdt_store) Line 1320  Y(bdt_store)
1320    
1321    
1322  /*  Various load/store multiple instructions:  */  /*  Various load/store multiple instructions:  */
1323  #include "tmp_arm_multi.c"  uint32_t *multi_opcode[256];
1324    void (**multi_opcode_f[256])(struct cpu *, struct arm_instr_call *);
1325    X(multi_0x08b15018);
1326    X(multi_0x08ac000c__ge);
1327    X(multi_0x08a05018);
1328    
1329    
1330  /*****************************************************************************/  /*****************************************************************************/
1331    
1332    
1333  /*  /*
  *  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];  
 }  
   
   
 /*  
1334   *  netbsd_memset:   *  netbsd_memset:
1335   *   *
1336   *  The core of a NetBSD/arm memset.   *  The core of a NetBSD/arm memset.
# Line 1381  X(netbsd_memset) Line 1350  X(netbsd_memset)
1350    
1351                  instr(subs)(cpu, ic);                  instr(subs)(cpu, ic);
1352    
1353                  if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) !=                  if (((cpu->cd.arm.flags & ARM_F_N)?1:0) !=
1354                      ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0)) {                      ((cpu->cd.arm.flags & ARM_F_V)?1:0)) {
1355                          cpu->n_translated_instrs += 16;                          cpu->n_translated_instrs += 16;
1356                          /*  Skip the store multiples:  */                          /*  Skip the store multiples:  */
1357                          cpu->cd.arm.next_ic = &ic[17];                          cpu->cd.arm.next_ic = &ic[17];
# Line 1411  X(netbsd_memset) Line 1380  X(netbsd_memset)
1380    
1381                  /*  Branch back if greater:  */                  /*  Branch back if greater:  */
1382                  cpu->n_translated_instrs += 1;                  cpu->n_translated_instrs += 1;
1383          } while (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) ==          } while (((cpu->cd.arm.flags & ARM_F_N)?1:0) ==
1384              ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0) &&              ((cpu->cd.arm.flags & ARM_F_V)?1:0) &&
1385              !(cpu->cd.arm.cpsr & ARM_FLAG_Z));              !(cpu->cd.arm.flags & ARM_F_Z));
1386    
1387          /*  Continue at the instruction after the bgt:  */          /*  Continue at the instruction after the bgt:  */
1388          cpu->cd.arm.next_ic = &ic[18];          cpu->cd.arm.next_ic = &ic[18];
# Line 1471  X(netbsd_memcpy) Line 1440  X(netbsd_memcpy)
1440    
1441                  /*  Loop while greater or equal:  */                  /*  Loop while greater or equal:  */
1442                  cpu->n_translated_instrs ++;                  cpu->n_translated_instrs ++;
1443          } while (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) ==          } while (((cpu->cd.arm.flags & ARM_F_N)?1:0) ==
1444              ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0));              ((cpu->cd.arm.flags & ARM_F_V)?1:0));
1445    
1446          /*  Continue at the instruction after the bge:  */          /*  Continue at the instruction after the bge:  */
1447          cpu->cd.arm.next_ic = &ic[6];          cpu->cd.arm.next_ic = &ic[6];
# Line 1494  X(netbsd_cacheclean) Line 1463  X(netbsd_cacheclean)
1463  {  {
1464          uint32_t r1 = cpu->cd.arm.r[1];          uint32_t r1 = cpu->cd.arm.r[1];
1465          cpu->n_translated_instrs += ((r1 >> 5) * 3);          cpu->n_translated_instrs += ((r1 >> 5) * 3);
1466            cpu->cd.arm.r[0] += r1;
1467            cpu->cd.arm.r[1] = 0;
1468          cpu->cd.arm.next_ic = &ic[4];          cpu->cd.arm.next_ic = &ic[4];
1469  }  }
1470    
# Line 1545  X(netbsd_scanc) Line 1516  X(netbsd_scanc)
1516          cpu->cd.arm.r[3] = page[t & 0xfff];          cpu->cd.arm.r[3] = page[t & 0xfff];
1517    
1518          t = cpu->cd.arm.r[3] & cpu->cd.arm.r[ARM_IP];          t = cpu->cd.arm.r[3] & cpu->cd.arm.r[ARM_IP];
1519          cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N);          cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1520          if (t == 0)          if (t == 0)
1521                  cpu->cd.arm.cpsr |= ARM_FLAG_Z;                  cpu->cd.arm.flags |= ARM_F_Z;
1522    
1523            cpu->n_translated_instrs += 2;
1524            cpu->cd.arm.next_ic = &ic[3];
1525    }
1526    
1527    
1528    /*
1529     *  strlen:
1530     *
1531     *  S: e5f03001   ldrb  rY,[rX,#1]!
1532     *     e3530000   cmps  rY,#0
1533     *     1afffffc   bne   S
1534     */
1535    X(strlen)
1536    {
1537            unsigned int n_loops = 0;
1538            uint32_t rY, rX = reg(ic[0].arg[0]);
1539            unsigned char *p;
1540    
1541            do {
1542                    rX ++;
1543                    p = cpu->cd.arm.host_load[rX >> 12];
1544                    if (p == NULL) {
1545                            cpu->n_translated_instrs += (n_loops * 3);
1546                            instr(load_w1_byte_u1_p1_imm)(cpu, ic);
1547                            return;
1548                    }
1549    
1550                    rY = reg(ic[0].arg[2]) = p[rX & 0xfff]; /*  load  */
1551                    reg(ic[0].arg[0]) = rX;                 /*  writeback  */
1552                    n_loops ++;
1553    
1554                    /*  Compare rY to zero:  */
1555                    cpu->cd.arm.flags = ARM_F_C;
1556                    if (rY == 0)
1557                            cpu->cd.arm.flags |= ARM_F_Z;
1558            } while (rY != 0);
1559    
1560            cpu->n_translated_instrs += (n_loops * 3) - 1;
1561            cpu->cd.arm.next_ic = &ic[3];
1562    }
1563    
1564    
1565    /*
1566     *  xchg:
1567     *
1568     *  e02YX00X     eor     rX,rY,rX
1569     *  e02XY00Y     eor     rY,rX,rY
1570     *  e02YX00X     eor     rX,rY,rX
1571     */
1572    X(xchg)
1573    {
1574            uint32_t tmp = reg(ic[0].arg[0]);
1575          cpu->n_translated_instrs += 2;          cpu->n_translated_instrs += 2;
1576          cpu->cd.arm.next_ic = &ic[3];          cpu->cd.arm.next_ic = &ic[3];
1577            reg(ic[0].arg[0]) = reg(ic[1].arg[0]);
1578            reg(ic[1].arg[0]) = tmp;
1579    }
1580    
1581    
1582    /*
1583     *  netbsd_copyin:
1584     *
1585     *  e4b0a004     ldrt    sl,[r0],#4
1586     *  e4b0b004     ldrt    fp,[r0],#4
1587     *  e4b06004     ldrt    r6,[r0],#4
1588     *  e4b07004     ldrt    r7,[r0],#4
1589     *  e4b08004     ldrt    r8,[r0],#4
1590     *  e4b09004     ldrt    r9,[r0],#4
1591     */
1592    X(netbsd_copyin)
1593    {
1594            uint32_t r0 = cpu->cd.arm.r[0], ofs = (r0 & 0xffc), index = r0 >> 12;
1595            unsigned char *p = cpu->cd.arm.host_load[index];
1596            uint32_t *p32 = (uint32_t *) p, *q32;
1597            int ok = cpu->cd.arm.is_userpage[index >> 5] & (1 << (index & 31));
1598    
1599            if (ofs > 0x1000 - 6*4 || !ok || p == NULL) {
1600                    instr(load_w1_word_u1_p0_imm)(cpu, ic);
1601                    return;
1602            }
1603            q32 = &cpu->cd.arm.r[6];
1604            ofs >>= 2;
1605            q32[0] = p32[ofs+2];
1606            q32[1] = p32[ofs+3];
1607            q32[2] = p32[ofs+4];
1608            q32[3] = p32[ofs+5];
1609            q32[4] = p32[ofs+0];
1610            q32[5] = p32[ofs+1];
1611            cpu->cd.arm.r[0] = r0 + 24;
1612            cpu->n_translated_instrs += 5;
1613            cpu->cd.arm.next_ic = &ic[6];
1614    }
1615    
1616    
1617    /*
1618     *  netbsd_copyout:
1619     *
1620     *  e4a18004     strt    r8,[r1],#4
1621     *  e4a19004     strt    r9,[r1],#4
1622     *  e4a1a004     strt    sl,[r1],#4
1623     *  e4a1b004     strt    fp,[r1],#4
1624     *  e4a16004     strt    r6,[r1],#4
1625     *  e4a17004     strt    r7,[r1],#4
1626     */
1627    X(netbsd_copyout)
1628    {
1629            uint32_t r1 = cpu->cd.arm.r[1], ofs = (r1 & 0xffc), index = r1 >> 12;
1630            unsigned char *p = cpu->cd.arm.host_store[index];
1631            uint32_t *p32 = (uint32_t *) p, *q32;
1632            int ok = cpu->cd.arm.is_userpage[index >> 5] & (1 << (index & 31));
1633    
1634            if (ofs > 0x1000 - 6*4 || !ok || p == NULL) {
1635                    instr(store_w1_word_u1_p0_imm)(cpu, ic);
1636                    return;
1637            }
1638            q32 = &cpu->cd.arm.r[6];
1639            ofs >>= 2;
1640            p32[ofs  ] = q32[2];
1641            p32[ofs+1] = q32[3];
1642            p32[ofs+2] = q32[4];
1643            p32[ofs+3] = q32[5];
1644            p32[ofs+4] = q32[0];
1645            p32[ofs+5] = q32[1];
1646            cpu->cd.arm.r[1] = r1 + 24;
1647            cpu->n_translated_instrs += 5;
1648            cpu->cd.arm.next_ic = &ic[6];
1649    }
1650    
1651    
1652    /*
1653     *  cmps by 0, followed by beq (inside the same page):
1654     */
1655    X(cmps0_beq_samepage)
1656    {
1657            uint32_t a = reg(ic->arg[0]);
1658            cpu->n_translated_instrs ++;
1659            if (a == 0) {
1660                    cpu->cd.arm.flags = ARM_F_Z | ARM_F_C;
1661            } else {
1662                    /*  Semi-ugly hack which sets the negative-bit if a < 0:  */
1663                    cpu->cd.arm.flags = ARM_F_C | ((a >> 28) & 8);
1664            }
1665            if (a == 0)
1666                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1667            else
1668                    cpu->cd.arm.next_ic = &ic[2];
1669    }
1670    
1671    
1672    /*
1673     *  cmps followed by beq (inside the same page):
1674     */
1675    X(cmps_beq_samepage)
1676    {
1677            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1678            cpu->n_translated_instrs ++;
1679            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1680            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1681                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1682                    cpu->cd.arm.flags |= ARM_F_V;
1683            if (c == 0) {
1684                    cpu->cd.arm.flags |= ARM_F_Z;
1685                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1686            } else {
1687                    cpu->cd.arm.next_ic = &ic[2];
1688                    if (c & 0x80000000)
1689                            cpu->cd.arm.flags |= ARM_F_N;
1690            }
1691    }
1692    
1693    
1694    /*
1695     *  cmps followed by beq (not the same page):
1696     */
1697    X(cmps_0_beq)
1698    {
1699            uint32_t a = reg(ic->arg[0]);
1700            cpu->n_translated_instrs ++;
1701            if (a == 0) {
1702                    cpu->cd.arm.flags = ARM_F_Z | ARM_F_C;
1703                    cpu->pc = (uint32_t)(((uint32_t)cpu->pc & 0xfffff000)
1704                        + (int32_t)ic[1].arg[0]);
1705                    quick_pc_to_pointers(cpu);
1706            } else {
1707                    /*  Semi-ugly hack which sets the negative-bit if a < 0:  */
1708                    cpu->cd.arm.flags = ARM_F_C | ((a >> 28) & 8);
1709                    cpu->cd.arm.next_ic = &ic[2];
1710            }
1711    }
1712    X(cmps_pos_beq)
1713    {
1714            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1715            cpu->n_translated_instrs ++;
1716            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1717            if ((int32_t)a < 0 && (int32_t)c >= 0)
1718                    cpu->cd.arm.flags |= ARM_F_V;
1719            if (c == 0) {
1720                    cpu->cd.arm.flags |= ARM_F_Z;
1721                    cpu->pc = (uint32_t)(((uint32_t)cpu->pc & 0xfffff000)
1722                        + (int32_t)ic[1].arg[0]);
1723                    quick_pc_to_pointers(cpu);
1724            } else {
1725                    cpu->cd.arm.next_ic = &ic[2];
1726                    if (c & 0x80000000)
1727                            cpu->cd.arm.flags |= ARM_F_N;
1728            }
1729    }
1730    X(cmps_neg_beq)
1731    {
1732            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1733            cpu->n_translated_instrs ++;
1734            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1735            if ((int32_t)a >= 0 && (int32_t)c < 0)
1736                    cpu->cd.arm.flags |= ARM_F_V;
1737            if (c == 0) {
1738                    cpu->cd.arm.flags |= ARM_F_Z;
1739                    cpu->pc = (uint32_t)(((uint32_t)cpu->pc & 0xfffff000)
1740                        + (int32_t)ic[1].arg[0]);
1741                    quick_pc_to_pointers(cpu);
1742            } else {
1743                    cpu->cd.arm.next_ic = &ic[2];
1744                    if (c & 0x80000000)
1745                            cpu->cd.arm.flags |= ARM_F_N;
1746            }
1747    }
1748    
1749    
1750    /*
1751     *  cmps by 0, followed by bne (inside the same page):
1752     */
1753    X(cmps0_bne_samepage)
1754    {
1755            uint32_t a = reg(ic->arg[0]);
1756            cpu->n_translated_instrs ++;
1757            if (a == 0) {
1758                    cpu->cd.arm.flags = ARM_F_Z | ARM_F_C;
1759            } else {
1760                    /*  Semi-ugly hack which sets the negative-bit if a < 0:  */
1761                    cpu->cd.arm.flags = ARM_F_C | ((a >> 28) & 8);
1762            }
1763            if (a == 0)
1764                    cpu->cd.arm.next_ic = &ic[2];
1765            else
1766                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1767    }
1768    
1769    
1770    /*
1771     *  cmps followed by bne (inside the same page):
1772     */
1773    X(cmps_bne_samepage)
1774    {
1775            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1776            cpu->n_translated_instrs ++;
1777            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1778            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1779                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1780                    cpu->cd.arm.flags |= ARM_F_V;
1781            if (c == 0) {
1782                    cpu->cd.arm.flags |= ARM_F_Z;
1783                    cpu->cd.arm.next_ic = &ic[2];
1784            } else {
1785                    if (c & 0x80000000)
1786                            cpu->cd.arm.flags |= ARM_F_N;
1787                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1788            }
1789    }
1790    
1791    
1792    /*
1793     *  cmps followed by bcc (inside the same page):
1794     */
1795    X(cmps_bcc_samepage)
1796    {
1797            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1798            cpu->n_translated_instrs ++;
1799            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1800            if (c & 0x80000000)
1801                    cpu->cd.arm.flags |= ARM_F_N;
1802            else if (c == 0)
1803                    cpu->cd.arm.flags |= ARM_F_Z;
1804            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1805                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1806                    cpu->cd.arm.flags |= ARM_F_V;
1807            if (a >= b)
1808                    cpu->cd.arm.next_ic = &ic[2];
1809            else
1810                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1811    }
1812    
1813    
1814    /*
1815     *  cmps (reg) followed by bcc (inside the same page):
1816     */
1817    X(cmps_reg_bcc_samepage)
1818    {
1819            uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = a - b;
1820            cpu->n_translated_instrs ++;
1821            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1822            if (c & 0x80000000)
1823                    cpu->cd.arm.flags |= ARM_F_N;
1824            else if (c == 0)
1825                    cpu->cd.arm.flags |= ARM_F_Z;
1826            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1827                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1828                    cpu->cd.arm.flags |= ARM_F_V;
1829            if (a >= b)
1830                    cpu->cd.arm.next_ic = &ic[2];
1831            else
1832                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1833    }
1834    
1835    
1836    /*
1837     *  cmps followed by bhi (inside the same page):
1838     */
1839    X(cmps_bhi_samepage)
1840    {
1841            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1842            cpu->n_translated_instrs ++;
1843            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1844            if (c & 0x80000000)
1845                    cpu->cd.arm.flags |= ARM_F_N;
1846            else if (c == 0)
1847                    cpu->cd.arm.flags |= ARM_F_Z;
1848            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1849                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1850                    cpu->cd.arm.flags |= ARM_F_V;
1851            if (a > b)
1852                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1853            else
1854                    cpu->cd.arm.next_ic = &ic[2];
1855    }
1856    
1857    
1858    /*
1859     *  cmps (reg) followed by bhi (inside the same page):
1860     */
1861    X(cmps_reg_bhi_samepage)
1862    {
1863            uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = a - b;
1864            cpu->n_translated_instrs ++;
1865            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1866            if (c & 0x80000000)
1867                    cpu->cd.arm.flags |= ARM_F_N;
1868            else if (c == 0)
1869                    cpu->cd.arm.flags |= ARM_F_Z;
1870            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1871                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1872                    cpu->cd.arm.flags |= ARM_F_V;
1873            if (a > b)
1874                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1875            else
1876                    cpu->cd.arm.next_ic = &ic[2];
1877    }
1878    
1879    
1880    /*
1881     *  cmps followed by bgt (inside the same page):
1882     */
1883    X(cmps_bgt_samepage)
1884    {
1885            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1886            cpu->n_translated_instrs ++;
1887            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1888            if (c & 0x80000000)
1889                    cpu->cd.arm.flags |= ARM_F_N;
1890            else if (c == 0)
1891                    cpu->cd.arm.flags |= ARM_F_Z;
1892            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1893                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1894                    cpu->cd.arm.flags |= ARM_F_V;
1895            if ((int32_t)a > (int32_t)b)
1896                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1897            else
1898                    cpu->cd.arm.next_ic = &ic[2];
1899    }
1900    
1901    
1902    /*
1903     *  cmps followed by ble (inside the same page):
1904     */
1905    X(cmps_ble_samepage)
1906    {
1907            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1908            cpu->n_translated_instrs ++;
1909            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1910            if (c & 0x80000000)
1911                    cpu->cd.arm.flags |= ARM_F_N;
1912            else if (c == 0)
1913                    cpu->cd.arm.flags |= ARM_F_Z;
1914            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1915                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1916                    cpu->cd.arm.flags |= ARM_F_V;
1917            if ((int32_t)a <= (int32_t)b)
1918                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1919            else
1920                    cpu->cd.arm.next_ic = &ic[2];
1921    }
1922    
1923    
1924    /*
1925     *  teqs followed by beq (inside the same page):
1926     */
1927    X(teqs_beq_samepage)
1928    {
1929            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a ^ b;
1930            cpu->n_translated_instrs ++;
1931            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1932            if (c == 0) {
1933                    cpu->cd.arm.flags |= ARM_F_Z;
1934                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
1935                        ic[1].arg[0];
1936            } else {
1937                    if (c & 0x80000000)
1938                            cpu->cd.arm.flags |= ARM_F_N;
1939                    cpu->cd.arm.next_ic = &ic[2];
1940            }
1941    }
1942    
1943    
1944    /*
1945     *  tsts followed by beq (inside the same page):
1946     *  (arg[1] must not have its highest bit set))
1947     */
1948    X(tsts_lo_beq_samepage)
1949    {
1950            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a & b;
1951            cpu->n_translated_instrs ++;
1952            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1953            if (c == 0)
1954                    cpu->cd.arm.flags |= ARM_F_Z;
1955            if (c == 0)
1956                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
1957                        ic[1].arg[0];
1958            else
1959                    cpu->cd.arm.next_ic = &ic[2];
1960    }
1961    
1962    
1963    /*
1964     *  teqs followed by bne (inside the same page):
1965     */
1966    X(teqs_bne_samepage)
1967    {
1968            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a ^ b;
1969            cpu->n_translated_instrs ++;
1970            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1971            if (c == 0) {
1972                    cpu->cd.arm.flags |= ARM_F_Z;
1973            } else {
1974                    if (c & 0x80000000)
1975                            cpu->cd.arm.flags |= ARM_F_N;
1976            }
1977            if (c == 0)
1978                    cpu->cd.arm.next_ic = &ic[2];
1979            else
1980                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
1981                        ic[1].arg[0];
1982    }
1983    
1984    
1985    /*
1986     *  tsts followed by bne (inside the same page):
1987     *  (arg[1] must not have its highest bit set))
1988     */
1989    X(tsts_lo_bne_samepage)
1990    {
1991            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a & b;
1992            cpu->n_translated_instrs ++;
1993            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1994            if (c == 0)
1995                    cpu->cd.arm.flags |= ARM_F_Z;
1996            if (c == 0)
1997                    cpu->cd.arm.next_ic = &ic[2];
1998            else
1999                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
2000                        ic[1].arg[0];
2001  }  }
2002    
2003    
# Line 1560  X(netbsd_scanc) Line 2007  X(netbsd_scanc)
2007  X(end_of_page)  X(end_of_page)
2008  {  {
2009          /*  Update the PC:  (offset 0, but on the next page)  */          /*  Update the PC:  (offset 0, but on the next page)  */
2010          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
2011              << 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];  
2012    
2013          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
2014          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
# Line 1578  X(end_of_page) Line 2022  X(end_of_page)
2022    
2023    
2024  /*  /*
2025   *  arm_combine_netbsd_memset():   *  Combine: netbsd_memset():
2026   *   *
2027   *  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
2028   *  of 16 store-multiple instructions, each storing 2 registers at a time.   *  of 16 store-multiple instructions, each storing 2 registers at a time.
2029   */   */
2030  void arm_combine_netbsd_memset(struct cpu *cpu, struct arm_instr_call *ic,  void COMBINE(netbsd_memset)(struct cpu *cpu,
2031          int low_addr)          struct arm_instr_call *ic, int low_addr)
2032  {  {
2033    #ifdef HOST_LITTLE_ENDIAN
2034          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2035              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
2036    
# Line 1602  void arm_combine_netbsd_memset(struct cp Line 2047  void arm_combine_netbsd_memset(struct cp
2047                          combined;                          combined;
2048                  }                  }
2049          }          }
2050    #endif
2051  }  }
2052    
2053    
2054  /*  /*
2055   *  arm_combine_netbsd_memcpy():   *  Combine: netbsd_memcpy():
2056   *   *
2057   *  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
2058   *  sequence of ldmia instructions.   *  sequence of ldmia instructions.
2059   */   */
2060  void arm_combine_netbsd_memcpy(struct cpu *cpu, struct arm_instr_call *ic,  void COMBINE(netbsd_memcpy)(struct cpu *cpu, struct arm_instr_call *ic,
2061          int low_addr)          int low_addr)
2062  {  {
2063    #ifdef HOST_LITTLE_ENDIAN
2064          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2065              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
2066    
# Line 1630  void arm_combine_netbsd_memcpy(struct cp Line 2077  void arm_combine_netbsd_memcpy(struct cp
2077                          combined;                          combined;
2078                  }                  }
2079          }          }
2080    #endif
2081  }  }
2082    
2083    
2084  /*  /*
2085   *  arm_combine_netbsd_cacheclean():   *  Combine: netbsd_cacheclean():
2086   *   *
2087   *  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.)
2088   */   */
2089  void arm_combine_netbsd_cacheclean(struct cpu *cpu, struct arm_instr_call *ic,  void COMBINE(netbsd_cacheclean)(struct cpu *cpu,
2090          int low_addr)          struct arm_instr_call *ic, int low_addr)
2091  {  {
2092          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2093              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
# Line 1658  void arm_combine_netbsd_cacheclean(struc Line 2106  void arm_combine_netbsd_cacheclean(struc
2106    
2107    
2108  /*  /*
2109   *  arm_combine_netbsd_cacheclean2():   *  Combine: netbsd_cacheclean2():
2110   *   *
2111   *  Check for the core of a NetBSD/arm cache clean. (Second variant.)   *  Check for the core of a NetBSD/arm cache clean. (Second variant.)
2112   */   */
2113  void arm_combine_netbsd_cacheclean2(struct cpu *cpu, struct arm_instr_call *ic,  void COMBINE(netbsd_cacheclean2)(struct cpu *cpu,
2114          int low_addr)          struct arm_instr_call *ic, int low_addr)
2115  {  {
2116          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2117              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
# Line 1683  void arm_combine_netbsd_cacheclean2(stru Line 2131  void arm_combine_netbsd_cacheclean2(stru
2131    
2132    
2133  /*  /*
2134   *  arm_combine_netbsd_scanc():   *  Combine: netbsd_scanc():
2135   */   */
2136  void arm_combine_netbsd_scanc(struct cpu *cpu, struct arm_instr_call *ic,  void COMBINE(netbsd_scanc)(struct cpu *cpu,
2137          int low_addr)          struct arm_instr_call *ic, int low_addr)
2138  {  {
2139          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2140              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
2141    
2142          if (n_back >= 2) {          if (n_back < 2)
2143                  if (ic[-2].f == instr(load_w0_byte_u1_p1_imm) &&                  return;
2144                      ic[-1].f == instr(load_w0_byte_u1_p1_reg)) {  
2145                          ic[-2].f = instr(netbsd_scanc);          if (ic[-2].f == instr(load_w0_byte_u1_p1_imm) &&
2146                          combined;              ic[-2].arg[0] == (size_t)(&cpu->cd.arm.r[1]) &&
2147                  }              ic[-2].arg[1] == 0 &&
2148                ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[3]) &&
2149                ic[-1].f == instr(load_w0_byte_u1_p1_reg) &&
2150                ic[-1].arg[0] == (size_t)(&cpu->cd.arm.r[2]) &&
2151                ic[-1].arg[1] == (size_t)arm_r_r3_t0_c0 &&
2152                ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[3])) {
2153                    ic[-2].f = instr(netbsd_scanc);
2154                    combined;
2155          }          }
2156  }  }
2157    
2158    
2159  /*  /*
2160   *  arm_combine_test2():   *  Combine: strlen():
2161   */   */
2162  void arm_combine_test2(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)  void COMBINE(strlen)(struct cpu *cpu,
2163            struct arm_instr_call *ic, int low_addr)
2164  {  {
2165          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2166              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
2167    
2168          if (n_back >= 2) {          if (n_back < 2)
2169                  if (ic[-2].f == instr(store_w0_word_u1_p0_imm) &&                  return;
2170                      ic[-2].arg[1] == 4 &&  
2171                      ic[-1].f == instr(subs) &&          if (ic[-2].f == instr(load_w1_byte_u1_p1_imm) &&
2172                      ic[-1].arg[0] == ic[-1].arg[2] && ic[-1].arg[1] == 4 &&              ic[-2].arg[1] == 1 &&
2173                      ic[ 0].f == instr(b_samepage__gt) &&              ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[3]) &&
2174                      ic[ 0].arg[0] == (size_t)&ic[-2]) {              ic[-1].f == instr(cmps) &&
2175                          ic[-2].f = instr(fill_loop_test2);              ic[-1].arg[0] == (size_t)(&cpu->cd.arm.r[3]) &&
2176  printf("YO test2\n");              ic[-1].arg[1] == 0) {
2177                          combined;                  ic[-2].f = instr(strlen);
2178                  }                  combined;
2179          }          }
2180  }  }
2181    
2182    
2183  #if 0  /*
2184          /*  TODO: This is another test hack.  */   *  Combine: xchg():
2185     */
2186    void COMBINE(xchg)(struct cpu *cpu,
2187            struct arm_instr_call *ic, int low_addr)
2188    {
2189            int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2190                & (ARM_IC_ENTRIES_PER_PAGE-1);
2191            size_t a, b;
2192    
2193          if (n_back >= 3) {          if (n_back < 2)
2194                  if (ic[-3].f == instr(cmps) &&                  return;
2195                      ic[-3].arg[0] == ic[-1].arg[0] &&  
2196                      ic[-3].arg[1] == 0 &&          a = ic[-2].arg[0]; b = ic[-1].arg[0];
2197                      ic[-2].f == instr(store_w0_byte_u1_p0_imm) &&  
2198                      ic[-2].arg[1] == 1 &&          if (ic[-2].f == instr(eor_regshort) &&
2199                      ic[-1].f == instr(sub) &&              ic[-1].f == instr(eor_regshort) &&
2200                      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 &&
2201                      ic[ 0].f == instr(b_samepage__gt) &&              ic[-1].arg[0] == b && ic[-1].arg[1] == a && ic[-1].arg[2] == a &&
2202                      ic[ 0].arg[0] == (size_t)&ic[-3]) {              ic[ 0].arg[0] == a && ic[ 0].arg[1] == b && ic[ 0].arg[2] == b) {
2203                          ic[-3].f = instr(fill_loop_test);                  ic[-2].f = instr(xchg);
2204                    combined;
2205            }
2206    }
2207    
2208    
2209    /*
2210     *  Combine: netbsd_copyin():
2211     */
2212    void COMBINE(netbsd_copyin)(struct cpu *cpu,
2213            struct arm_instr_call *ic, int low_addr)
2214    {
2215    #ifdef HOST_LITTLE_ENDIAN
2216            int i, n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2217                & (ARM_IC_ENTRIES_PER_PAGE-1);
2218    
2219            if (n_back < 5)
2220                    return;
2221    
2222            for (i=-5; i<0; i++) {
2223                    if (ic[i].f != instr(load_w1_word_u1_p0_imm) ||
2224                        ic[i].arg[0] != (size_t)(&cpu->cd.arm.r[0]) ||
2225                        ic[i].arg[1] != 4)
2226                            return;
2227            }
2228    
2229            if (ic[-5].arg[2] == (size_t)(&cpu->cd.arm.r[10]) &&
2230                ic[-4].arg[2] == (size_t)(&cpu->cd.arm.r[11]) &&
2231                ic[-3].arg[2] == (size_t)(&cpu->cd.arm.r[6]) &&
2232                ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[7]) &&
2233                ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[8])) {
2234                    ic[-5].f = instr(netbsd_copyin);
2235                    combined;
2236            }
2237    #endif
2238    }
2239    
2240    
2241    /*
2242     *  Combine: netbsd_copyout():
2243     */
2244    void COMBINE(netbsd_copyout)(struct cpu *cpu,
2245            struct arm_instr_call *ic, int low_addr)
2246    {
2247    #ifdef HOST_LITTLE_ENDIAN
2248            int i, n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2249                & (ARM_IC_ENTRIES_PER_PAGE-1);
2250    
2251            if (n_back < 5)
2252                    return;
2253    
2254            for (i=-5; i<0; i++) {
2255                    if (ic[i].f != instr(store_w1_word_u1_p0_imm) ||
2256                        ic[i].arg[0] != (size_t)(&cpu->cd.arm.r[1]) ||
2257                        ic[i].arg[1] != 4)
2258                            return;
2259            }
2260    
2261            if (ic[-5].arg[2] == (size_t)(&cpu->cd.arm.r[8]) &&
2262                ic[-4].arg[2] == (size_t)(&cpu->cd.arm.r[9]) &&
2263                ic[-3].arg[2] == (size_t)(&cpu->cd.arm.r[10]) &&
2264                ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[11]) &&
2265                ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[6])) {
2266                    ic[-5].f = instr(netbsd_copyout);
2267                    combined;
2268            }
2269    #endif
2270    }
2271    
2272    
2273    /*
2274     *  Combine: cmps_b():
2275     */
2276    void COMBINE(cmps_b)(struct cpu *cpu,
2277            struct arm_instr_call *ic, int low_addr)
2278    {
2279            int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2280                & (ARM_IC_ENTRIES_PER_PAGE-1);
2281            if (n_back < 1)
2282                    return;
2283            if (ic[0].f == instr(b__eq)) {
2284                    if (ic[-1].f == instr(cmps)) {
2285                            if (ic[-1].arg[1] == 0)
2286                                    ic[-1].f = instr(cmps_0_beq);
2287                            else if (ic[-1].arg[1] & 0x80000000)
2288                                    ic[-1].f = instr(cmps_neg_beq);
2289                            else
2290                                    ic[-1].f = instr(cmps_pos_beq);
2291                          combined;                          combined;
2292                  }                  }
2293                    return;
2294          }          }
2295          /*  TODO: Combine forward as well  */          if (ic[0].f == instr(b_samepage__eq)) {
2296  #endif                  if (ic[-1].f == instr(cmps)) {
2297                            if (ic[-1].arg[1] == 0)
2298                                    ic[-1].f = instr(cmps0_beq_samepage);
2299                            else
2300                                    ic[-1].f = instr(cmps_beq_samepage);
2301                            combined;
2302                    }
2303                    if (ic[-1].f == instr(tsts) &&
2304                        !(ic[-1].arg[1] & 0x80000000)) {
2305                            ic[-1].f = instr(tsts_lo_beq_samepage);
2306                            combined;
2307                    }
2308                    if (ic[-1].f == instr(teqs)) {
2309                            ic[-1].f = instr(teqs_beq_samepage);
2310                            combined;
2311                    }
2312                    return;
2313            }
2314            if (ic[0].f == instr(b_samepage__ne)) {
2315                    if (ic[-1].f == instr(cmps)) {
2316                            if (ic[-1].arg[1] == 0)
2317                                    ic[-1].f = instr(cmps0_bne_samepage);
2318                            else
2319                                    ic[-1].f = instr(cmps_bne_samepage);
2320                            combined;
2321                    }
2322                    if (ic[-1].f == instr(tsts) &&
2323                        !(ic[-1].arg[1] & 0x80000000)) {
2324                            ic[-1].f = instr(tsts_lo_bne_samepage);
2325                            combined;
2326                    }
2327                    if (ic[-1].f == instr(teqs)) {
2328                            ic[-1].f = instr(teqs_bne_samepage);
2329                            combined;
2330                    }
2331                    return;
2332            }
2333            if (ic[0].f == instr(b_samepage__cc)) {
2334                    if (ic[-1].f == instr(cmps)) {
2335                            ic[-1].f = instr(cmps_bcc_samepage);
2336                            combined;
2337                    }
2338                    if (ic[-1].f == instr(cmps_regshort)) {
2339                            ic[-1].f = instr(cmps_reg_bcc_samepage);
2340                            combined;
2341                    }
2342                    return;
2343            }
2344            if (ic[0].f == instr(b_samepage__hi)) {
2345                    if (ic[-1].f == instr(cmps)) {
2346                            ic[-1].f = instr(cmps_bhi_samepage);
2347                            combined;
2348                    }
2349                    if (ic[-1].f == instr(cmps_regshort)) {
2350                            ic[-1].f = instr(cmps_reg_bhi_samepage);
2351                            combined;
2352                    }
2353                    return;
2354            }
2355            if (ic[0].f == instr(b_samepage__gt)) {
2356                    if (ic[-1].f == instr(cmps)) {
2357                            ic[-1].f = instr(cmps_bgt_samepage);
2358                            combined;
2359                    }
2360                    return;
2361            }
2362            if (ic[0].f == instr(b_samepage__le)) {
2363                    if (ic[-1].f == instr(cmps)) {
2364                            ic[-1].f = instr(cmps_ble_samepage);
2365                            combined;
2366                    }
2367                    return;
2368            }
2369    }
2370    
2371    
2372    /*****************************************************************************/
2373    
2374    
2375    static void arm_switch_clear(struct arm_instr_call *ic, int rd,
2376            int condition_code)
2377    {
2378            switch (rd) {
2379            case  0: ic->f = cond_instr(clear_r0); break;
2380            case  1: ic->f = cond_instr(clear_r1); break;
2381            case  2: ic->f = cond_instr(clear_r2); break;
2382            case  3: ic->f = cond_instr(clear_r3); break;
2383            case  4: ic->f = cond_instr(clear_r4); break;
2384            case  5: ic->f = cond_instr(clear_r5); break;
2385            case  6: ic->f = cond_instr(clear_r6); break;
2386            case  7: ic->f = cond_instr(clear_r7); break;
2387            case  8: ic->f = cond_instr(clear_r8); break;
2388            case  9: ic->f = cond_instr(clear_r9); break;
2389            case 10: ic->f = cond_instr(clear_r10); break;
2390            case 11: ic->f = cond_instr(clear_r11); break;
2391            case 12: ic->f = cond_instr(clear_r12); break;
2392            case 13: ic->f = cond_instr(clear_r13); break;
2393            case 14: ic->f = cond_instr(clear_r14); break;
2394            }
2395    }
2396    
2397    
2398    static void arm_switch_mov1(struct arm_instr_call *ic, int rd,
2399            int condition_code)
2400    {
2401            switch (rd) {
2402            case  0: ic->f = cond_instr(mov1_r0); break;
2403            case  1: ic->f = cond_instr(mov1_r1); break;
2404            case  2: ic->f = cond_instr(mov1_r2); break;
2405            case  3: ic->f = cond_instr(mov1_r3); break;
2406            case  4: ic->f = cond_instr(mov1_r4); break;
2407            case  5: ic->f = cond_instr(mov1_r5); break;
2408            case  6: ic->f = cond_instr(mov1_r6); break;
2409            case  7: ic->f = cond_instr(mov1_r7); break;
2410            case  8: ic->f = cond_instr(mov1_r8); break;
2411            case  9: ic->f = cond_instr(mov1_r9); break;
2412            case 10: ic->f = cond_instr(mov1_r10); break;
2413            case 11: ic->f = cond_instr(mov1_r11); break;
2414            case 12: ic->f = cond_instr(mov1_r12); break;
2415            case 13: ic->f = cond_instr(mov1_r13); break;
2416            case 14: ic->f = cond_instr(mov1_r14); break;
2417            }
2418    }
2419    
2420    
2421    static void arm_switch_add1(struct arm_instr_call *ic, int rd,
2422            int condition_code)
2423    {
2424            switch (rd) {
2425            case  0: ic->f = cond_instr(add1_r0); break;
2426            case  1: ic->f = cond_instr(add1_r1); break;
2427            case  2: ic->f = cond_instr(add1_r2); break;
2428            case  3: ic->f = cond_instr(add1_r3); break;
2429            case  4: ic->f = cond_instr(add1_r4); break;
2430            case  5: ic->f = cond_instr(add1_r5); break;
2431            case  6: ic->f = cond_instr(add1_r6); break;
2432            case  7: ic->f = cond_instr(add1_r7); break;
2433            case  8: ic->f = cond_instr(add1_r8); break;
2434            case  9: ic->f = cond_instr(add1_r9); break;
2435            case 10: ic->f = cond_instr(add1_r10); break;
2436            case 11: ic->f = cond_instr(add1_r11); break;
2437            case 12: ic->f = cond_instr(add1_r12); break;
2438            case 13: ic->f = cond_instr(add1_r13); break;
2439            case 14: ic->f = cond_instr(add1_r14); break;
2440            }
2441    }
2442    
2443    
2444  /*****************************************************************************/  /*****************************************************************************/
# Line 1759  printf("YO test2\n"); Line 2455  printf("YO test2\n");
2455  X(to_be_translated)  X(to_be_translated)
2456  {  {
2457          uint32_t addr, low_pc, iword, imm = 0;          uint32_t addr, low_pc, iword, imm = 0;
2458    #ifdef DYNTRANS_BACKEND
2459            int simple = 0;
2460    #endif
2461          unsigned char *page;          unsigned char *page;
2462          unsigned char ib[4];          unsigned char ib[4];
2463          int condition_code, main_opcode, secondary_opcode, s_bit, rn, rd, r8;          int condition_code, main_opcode, secondary_opcode, s_bit, rn, rd, r8;
2464          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;
2465          void (*samepage_function)(struct cpu *, struct arm_instr_call *);          void (*samepage_function)(struct cpu *, struct arm_instr_call *);
2466    
2467          /*  Figure out the address of the instruction:  */          /*  Figure out the address of the instruction:  */
2468          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)
2469              / sizeof(struct arm_instr_call);              / sizeof(struct arm_instr_call);
2470          addr = cpu->cd.arm.r[ARM_PC] & ~((ARM_IC_ENTRIES_PER_PAGE-1) <<          addr = cpu->pc & ~((ARM_IC_ENTRIES_PER_PAGE-1) <<
2471              ARM_INSTR_ALIGNMENT_SHIFT);              ARM_INSTR_ALIGNMENT_SHIFT);
2472          addr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          addr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
2473          cpu->pc = cpu->cd.arm.r[ARM_PC] = addr;          cpu->pc = addr;
2474          addr &= ~((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);          addr &= ~((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);
2475    
2476          /*  Read the instruction word from memory:  */          /*  Read the instruction word from memory:  */
2477          page = cpu->cd.arm.host_load[addr >> 12];          page = cpu->cd.arm.host_load[addr >> 12];
2478          if (page != NULL) {          if (page != NULL) {
2479                  /*  fatal("TRANSLATION HIT!\n");  */                  /*  fatal("TRANSLATION HIT! 0x%08x\n", addr);  */
2480                  memcpy(ib, page + (addr & 0xfff), sizeof(ib));                  memcpy(ib, page + (addr & 0xfff), sizeof(ib));
2481          } else {          } else {
2482                  /*  fatal("TRANSLATION MISS!\n");  */                  /*  fatal("TRANSLATION MISS! 0x%08x\n", addr);  */
2483                  if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],                  if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],
2484                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
2485                          fatal("to_be_translated(): "                          fatal("to_be_translated(): "
# Line 1805  X(to_be_translated) Line 2504  X(to_be_translated)
2504          condition_code = iword >> 28;          condition_code = iword >> 28;
2505          main_opcode = (iword >> 24) & 15;          main_opcode = (iword >> 24) & 15;
2506          secondary_opcode = (iword >> 21) & 15;          secondary_opcode = (iword >> 21) & 15;
2507          u_bit = (iword >> 23) & 1;          u_bit = iword & 0x00800000;
2508          b_bit = (iword >> 22) & 1;          w_bit = iword & 0x00200000;
2509          w_bit = (iword >> 21) & 1;          s_bit = l_bit = iword & 0x00100000;
         s_bit = l_bit = (iword >> 20) & 1;  
2510          rn    = (iword >> 16) & 15;          rn    = (iword >> 16) & 15;
2511          rd    = (iword >> 12) & 15;          rd    = (iword >> 12) & 15;
2512          r8    = (iword >> 8) & 15;          r8    = (iword >> 8) & 15;
# Line 1873  X(to_be_translated) Line 2571  X(to_be_translated)
2571                          ic->arg[0] = iword;                          ic->arg[0] = iword;
2572                          break;                          break;
2573                  }                  }
2574                    if ((iword & 0x0f900ff0) == 0x01000050) {
2575                            fatal("TODO: q{,d}{add,sub}\n");
2576                            goto bad;
2577                    }
2578                  if ((iword & 0x0ff000d0) == 0x01200010) {                  if ((iword & 0x0ff000d0) == 0x01200010) {
2579                          /*  bx or blx  */                          /*  bx or blx  */
2580                          if (iword & 0x20)                          if (iword & 0x20)
# Line 1897  X(to_be_translated) Line 2599  X(to_be_translated)
2599                          ic->arg[2] = (size_t)(&cpu->cd.arm.r[rn]);                          ic->arg[2] = (size_t)(&cpu->cd.arm.r[rn]);
2600                          break;                          break;
2601                  }                  }
2602                    if ((iword & 0x0fff0ff0) == 0x016f0f10) {
2603                            ic->f = cond_instr(clz);
2604                            ic->arg[0] = (size_t)(&cpu->cd.arm.r[rm]);
2605                            ic->arg[1] = (size_t)(&cpu->cd.arm.r[rd]);
2606                            break;
2607                    }
2608                    if ((iword & 0x0ff00090) == 0x01000080) {
2609                            /*  TODO: smlaXX  */
2610                            goto bad;
2611                    }
2612                    if ((iword & 0x0ff00090) == 0x01400080) {
2613                            /*  TODO: smlalY  */
2614                            goto bad;
2615                    }
2616                    if ((iword & 0x0ff000b0) == 0x01200080) {
2617                            /*  TODO: smlawY  */
2618                            goto bad;
2619                    }
2620                    if ((iword & 0x0ff0f090) == 0x01600080) {
2621                            /*  smulXY (16-bit * 16-bit => 32-bit)  */
2622                            switch (iword & 0x60) {
2623                            case 0x00: ic->f = cond_instr(smulbb); break;
2624                            case 0x20: ic->f = cond_instr(smultb); break;
2625                            case 0x40: ic->f = cond_instr(smulbt); break;
2626                            default:   ic->f = cond_instr(smultt); break;
2627                            }
2628                            ic->arg[0] = (size_t)(&cpu->cd.arm.r[rm]);
2629                            ic->arg[1] = (size_t)(&cpu->cd.arm.r[r8]);
2630                            ic->arg[2] = (size_t)(&cpu->cd.arm.r[rn]); /*  Rd  */
2631                            break;
2632                    }
2633                    if ((iword & 0x0ff0f0b0) == 0x012000a0) {
2634                            /*  TODO: smulwY  */
2635                            goto bad;
2636                    }
2637                  if ((iword & 0x0fb0fff0) == 0x0120f000 ||                  if ((iword & 0x0fb0fff0) == 0x0120f000 ||
2638                      (iword & 0x0fb0f000) == 0x0320f000) {                      (iword & 0x0fb0f000) == 0x0320f000) {
2639                          /*  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 2729  X(to_be_translated)
2729                          break;                          break;
2730                  }                  }
2731    
2732                  /*  "mov reg,reg":  */                  /*  "mov reg,reg" or "mov reg,pc":  */
2733                  if ((iword & 0x0fff0ff0) == 0x01a00000 &&                  if ((iword & 0x0fff0ff0) == 0x01a00000 && rd != ARM_PC) {
2734                      (iword&15) != ARM_PC && rd != ARM_PC) {                          if (rm != ARM_PC) {
2735                          ic->f = cond_instr(mov_reg_reg);                                  ic->f = cond_instr(mov_reg_reg);
2736                          ic->arg[0] = (size_t)(&cpu->cd.arm.r[iword & 15]);                                  ic->arg[0] = (size_t)(&cpu->cd.arm.r[rm]);
2737                            } else {
2738                                    ic->f = cond_instr(mov_reg_pc);
2739                                    ic->arg[0] = (addr & 0xfff) + 8;
2740                            }
2741                          ic->arg[1] = (size_t)(&cpu->cd.arm.r[rd]);                          ic->arg[1] = (size_t)(&cpu->cd.arm.r[rd]);
2742                          break;                          break;
2743                  }                  }
2744    
2745                  /*  "mov reg,#0":  */                  /*  "mov reg,#0":  */
2746                  if ((iword & 0x0fff0fff) == 0x03a03000 && rd != ARM_PC) {                  if ((iword & 0x0fff0fff) == 0x03a00000 && rd != ARM_PC) {
2747                          switch (rd) {                          arm_switch_clear(ic, rd, condition_code);
2748                          case  0: ic->f = cond_instr(clear_r0); break;  #ifdef DYNTRANS_BACKEND
2749                          case  1: ic->f = cond_instr(clear_r1); break;  simple = 1;
2750                          case  2: ic->f = cond_instr(clear_r2); break;  #endif
                         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;  
                         }  
2751                          break;                          break;
2752                  }                  }
2753    
2754                  /*  "mov reg,#1":  */                  /*  "mov reg,#1":  */
2755                  if ((iword & 0x0fff0fff) == 0x03a03001 && rd != ARM_PC) {                  if ((iword & 0x0fff0fff) == 0x03a00001 && rd != ARM_PC) {
2756                          switch (rd) {                          arm_switch_mov1(ic, rd, condition_code);
2757                          case  0: ic->f = cond_instr(mov1_r0); break;  #ifdef DYNTRANS_BACKEND
2758                          case  1: ic->f = cond_instr(mov1_r1); break;  simple = 1;
2759                          case  2: ic->f = cond_instr(mov1_r2); break;  #endif
2760                          case  3: ic->f = cond_instr(mov1_r3); break;                          break;
2761                          case  4: ic->f = cond_instr(mov1_r4); break;                  }
2762                          case  5: ic->f = cond_instr(mov1_r5); break;  
2763                          case  6: ic->f = cond_instr(mov1_r6); break;                  /*  "add reg,reg,#1":  */
2764                          case  7: ic->f = cond_instr(mov1_r7); break;                  if ((iword & 0x0ff00fff) == 0x02800001 && rd != ARM_PC
2765                          case  8: ic->f = cond_instr(mov1_r8); break;                      && rn == rd) {
2766                          case  9: ic->f = cond_instr(mov1_r9); break;                          arm_switch_add1(ic, rd, condition_code);
2767                          case 10: ic->f = cond_instr(mov1_r10); break;  #ifdef DYNTRANS_BACKEND
2768                          case 11: ic->f = cond_instr(mov1_r11); break;  simple = 1;
2769                          case 12: ic->f = cond_instr(mov1_r12); break;  #endif
                         case 13: ic->f = cond_instr(mov1_r13); break;  
                         case 14: ic->f = cond_instr(mov1_r14); break;  
                         }  
2770                          break;                          break;
2771                  }                  }
2772    
# Line 2072  X(to_be_translated) Line 2797  X(to_be_translated)
2797                          ic->arg[1] = imm;                          ic->arg[1] = imm;
2798                  }                  }
2799    
2800                    /*  mvn #imm ==> mov #~imm  */
2801                    if (secondary_opcode == 0xf && !regform) {
2802                            secondary_opcode = 0xd;
2803                            ic->arg[1] = ~ic->arg[1];
2804                    }
2805    
2806                  ic->arg[0] = (size_t)(&cpu->cd.arm.r[rn]);                  ic->arg[0] = (size_t)(&cpu->cd.arm.r[rn]);
2807                  ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);                  ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);
2808                  any_pc_reg = 0;                  any_pc_reg = 0;
2809                  if (rn == ARM_PC || rd == ARM_PC)                  if (rn == ARM_PC || rd == ARM_PC)
2810                          any_pc_reg = 1;                          any_pc_reg = 1;
2811    
2812                  ic->f = arm_dpi_instr[condition_code +                  if (!any_pc_reg && regform && (iword & 0xfff) < ARM_PC) {
2813                      16 * secondary_opcode + (s_bit? 256 : 0) +                          ic->arg[1] = (size_t)(&cpu->cd.arm.r[rm]);
2814                      (any_pc_reg? 512 : 0) + (regform? 1024 : 0)];                          ic->f = arm_dpi_instr_regshort[condition_code +
2815                                16 * secondary_opcode + (s_bit? 256 : 0)];
2816                    } else
2817                            ic->f = arm_dpi_instr[condition_code +
2818                                16 * secondary_opcode + (s_bit? 256 : 0) +
2819                                (any_pc_reg? 512 : 0) + (regform? 1024 : 0)];
2820    
2821                    if (ic->f == instr(eor_regshort))
2822                            cpu->cd.arm.combination_check = COMBINE(xchg);
2823                  if (iword == 0xe113000c)                  if (iword == 0xe113000c)
2824                          cpu->combination_check = arm_combine_netbsd_scanc;                          cpu->cd.arm.combination_check = COMBINE(netbsd_scanc);
2825                  break;                  break;
2826    
2827          case 0x4:       /*  Load and store...  */          case 0x4:       /*  Load and store...  */
# Line 2112  X(to_be_translated) Line 2850  X(to_be_translated)
2850                          fatal("Not a Load/store TODO\n");                          fatal("Not a Load/store TODO\n");
2851                          goto bad;                          goto bad;
2852                  }                  }
2853                    /*  Special case: pc-relative load within the same page:  */
2854                    if (rn == ARM_PC && rd != ARM_PC && main_opcode < 6) {
2855                            int ofs = (addr & 0xfff) + 8, max = 0xffc;
2856                            int b_bit = iword & 0x00400000;
2857                            if (b_bit)
2858                                    max = 0xfff;
2859                            if (u_bit)
2860                                    ofs += (iword & 0xfff);
2861                            else
2862                                    ofs -= (iword & 0xfff);
2863                            /*  NOTE/TODO: This assumes 4KB pages,
2864                                it will not work with 1KB pages.  */
2865                            if (ofs >= 0 && ofs <= max) {
2866                                    unsigned char *p;
2867                                    unsigned char c[4];
2868                                    int len = b_bit? 1 : 4;
2869                                    uint32_t x, a = (addr & 0xfffff000) | ofs;
2870                                    /*  ic->f = cond_instr(mov);  */
2871                                    ic->f = arm_dpi_instr[condition_code + 16*0xd];
2872                                    ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);
2873                                    p = cpu->cd.arm.host_load[a >> 12];
2874                                    if (p != NULL) {
2875                                            memcpy(c, p + (a & 0xfff), len);
2876                                    } else {
2877                                            if (!cpu->memory_rw(cpu, cpu->mem, a,
2878                                                c, len, MEM_READ, CACHE_DATA)) {
2879                                                    fatal("to_be_translated(): "
2880                                                        "read failed X: TODO\n");
2881                                                    goto bad;
2882                                            }
2883                                    }
2884                                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2885                                            x = c[0] + (c[1]<<8) +
2886                                                (c[2]<<16) + (c[3]<<24);
2887                                    else
2888                                            x = c[3] + (c[2]<<8) +
2889                                                (c[1]<<16) + (c[0]<<24);
2890                                    if (b_bit)
2891                                            x = c[0];
2892                                    ic->arg[1] = x;
2893                            }
2894                    }
2895                    if (iword == 0xe4b09004)
2896                            cpu->cd.arm.combination_check = COMBINE(netbsd_copyin);
2897                    if (iword == 0xe4a17004)
2898                            cpu->cd.arm.combination_check = COMBINE(netbsd_copyout);
2899                  break;                  break;
2900    
2901          case 0x8:       /*  Multiple load/store...  (Block data transfer)  */          case 0x8:       /*  Multiple load/store...  (Block data transfer)  */
# Line 2162  X(to_be_translated) Line 2946  X(to_be_translated)
2946                  if (main_opcode == 0x0a) {                  if (main_opcode == 0x0a) {
2947                          ic->f = cond_instr(b);                          ic->f = cond_instr(b);
2948                          samepage_function = cond_instr(b_samepage);                          samepage_function = cond_instr(b_samepage);
                         /*  if (iword == 0xcafffffc)  
                                 cpu->combination_check = arm_combine_test2;  */  
2949                          if (iword == 0xcaffffed)                          if (iword == 0xcaffffed)
2950                                  cpu->combination_check =                                  cpu->cd.arm.combination_check =
2951                                      arm_combine_netbsd_memset;                                      COMBINE(netbsd_memset);
2952                          if (iword == 0xaafffff9)                          if (iword == 0xaafffff9)
2953                                  cpu->combination_check =                                  cpu->cd.arm.combination_check =
2954                                      arm_combine_netbsd_memcpy;                                      COMBINE(netbsd_memcpy);
2955                  } else {                  } else {
2956                          if (cpu->machine->show_trace_tree) {                          if (cpu->machine->show_trace_tree) {
2957                                  ic->f = cond_instr(bl_trace);                                  ic->f = cond_instr(bl_trace);
# Line 2181  X(to_be_translated) Line 2963  X(to_be_translated)
2963                          }                          }
2964                  }                  }
2965    
2966                    /*  arg 1 = offset of current instruction  */
2967                    /*  arg 2 = offset of the following instruction  */
2968                    ic->arg[1] = addr & 0xffc;
2969                    ic->arg[2] = (addr & 0xffc) + 4;
2970    
2971                  ic->arg[0] = (iword & 0x00ffffff) << 2;                  ic->arg[0] = (iword & 0x00ffffff) << 2;
2972                  /*  Sign-extend:  */                  /*  Sign-extend:  */
2973                  if (ic->arg[0] & 0x02000000)                  if (ic->arg[0] & 0x02000000)
# Line 2190  X(to_be_translated) Line 2977  X(to_be_translated)
2977                   */                   */
2978                  ic->arg[0] = (int32_t)(ic->arg[0] + 8);                  ic->arg[0] = (int32_t)(ic->arg[0] + 8);
2979    
2980                  /*  Special case: branch within the same page:  */                  /*
2981                     *  Special case: branch within the same page:
2982                     *
2983                     *  arg[0] = addr of the arm_instr_call of the target
2984                     *  arg[1] = addr of the next arm_instr_call.
2985                     */
2986                  {                  {
2987                          uint32_t mask_within_page =                          uint32_t mask_within_page =
2988                              ((ARM_IC_ENTRIES_PER_PAGE-1) <<                              ((ARM_IC_ENTRIES_PER_PAGE-1) <<
# Line 2205  X(to_be_translated) Line 2997  X(to_be_translated)
2997                                      cpu->cd.arm.cur_ic_page +                                      cpu->cd.arm.cur_ic_page +
2998                                      ((new_pc & mask_within_page) >>                                      ((new_pc & mask_within_page) >>
2999                                      ARM_INSTR_ALIGNMENT_SHIFT));                                      ARM_INSTR_ALIGNMENT_SHIFT));
3000                                    ic->arg[1] = (size_t) (
3001                                        cpu->cd.arm.cur_ic_page +
3002                                        (((addr & mask_within_page) + 4) >>
3003                                        ARM_INSTR_ALIGNMENT_SHIFT));
3004                            } else if (main_opcode == 0x0a) {
3005                                    /*  Special hack for a plain "b":  */
3006                                    ic->arg[0] += ic->arg[1];
3007                          }                          }
3008                  }                  }
3009    
3010  #if 0                  if (main_opcode == 0xa && (condition_code <= 1
3011                  /*  Hm. This doesn't really increase performance.  */                      || condition_code == 3 || condition_code == 8
3012                        || condition_code == 12 || condition_code == 13))
3013                            cpu->cd.arm.combination_check = COMBINE(cmps_b);
3014    
3015                    if (iword == 0x1afffffc)
3016                            cpu->cd.arm.combination_check = COMBINE(strlen);
3017    
3018                    /*  Hm. Does this really increase performance?  */
3019                  if (iword == 0x8afffffa)                  if (iword == 0x8afffffa)
3020                          cpu->combination_check = arm_combine_netbsd_cacheclean2;                          cpu->cd.arm.combination_check =
3021                                COMBINE(netbsd_cacheclean2);
3022                    break;
3023    
3024            case 0xc:
3025            case 0xd:
3026                    /*
3027                     *  xxxx1100 0100nnnn ddddcccc oooommmm    MCRR c,op,Rd,Rn,CRm
3028                     *  xxxx1100 0101nnnn ddddcccc oooommmm    MRRC c,op,Rd,Rn,CRm
3029                     */
3030                    if ((iword & 0x0fe00fff) == 0x0c400000) {
3031                            /*  Special case: mar/mra DSP instructions  */
3032                            fatal("TODO: mar/mra DSP instructions!\n");
3033                            /*  Perhaps these are actually identical to MCRR/MRRC */
3034                            goto bad;
3035                    }
3036    
3037                    if ((iword & 0x0fe00000) == 0x0c400000) {
3038                            fatal("MCRR/MRRC: TODO\n");
3039                            goto bad;
3040                    }
3041    
3042                    /*
3043                     *  TODO: LDC/STC
3044                     *
3045                     *  For now, treat as Undefined instructions. This causes e.g.
3046                     *  Linux/ARM to emulate these instructions (floating point).
3047                     */
3048    #if 0
3049                    ic->f = cond_instr(und);
3050                    ic->arg[0] = addr & 0xfff;
3051    #else
3052                    fatal("LDC/STC: TODO\n");
3053                    goto bad;
3054  #endif  #endif
3055                  break;                  break;
3056    
3057          case 0xe:          case 0xe:
3058                    if ((iword & 0x0ff00ff0) == 0x0e200010) {
3059                            /*  Special case: mia* DSP instructions  */
3060                            /*  See Intel's 27343601.pdf, page 16-20  */
3061                            fatal("TODO: mia* DSP instructions!\n");
3062                            goto bad;
3063                    }
3064                  if (iword & 0x10) {                  if (iword & 0x10) {
3065                          /*  xxxx1110 oooLNNNN ddddpppp qqq1MMMM  MCR/MRC  */                          /*  xxxx1110 oooLNNNN ddddpppp qqq1MMMM  MCR/MRC  */
3066                          ic->arg[0] = iword;                          ic->arg[0] = iword;
# Line 2226  X(to_be_translated) Line 3071  X(to_be_translated)
3071                          ic->f = cond_instr(cdp);                          ic->f = cond_instr(cdp);
3072                  }                  }
3073                  if (iword == 0xee070f9a)                  if (iword == 0xee070f9a)
3074                          cpu->combination_check = arm_combine_netbsd_cacheclean;                          cpu->cd.arm.combination_check =
3075                                COMBINE(netbsd_cacheclean);
3076                  break;                  break;
3077    
3078          case 0xf:          case 0xf:
3079                  /*  SWI:  */                  /*  SWI:  */
3080                  /*  Default handler:  */                  /*  Default handler:  */
3081                  ic->f = cond_instr(swi);                  ic->f = cond_instr(swi);
3082                  if (iword == 0xef8c64be) {                  ic->arg[0] = addr & 0xfff;
3083                    if (iword == 0xef8c64eb) {
3084                            /*  Hack for rebooting a machine:  */
3085                            ic->f = instr(reboot);
3086                    } else if (iword == 0xef8c64be) {
3087                          /*  Hack for openfirmware prom emulation:  */                          /*  Hack for openfirmware prom emulation:  */
3088                          ic->f = instr(openfirmware);                          ic->f = instr(openfirmware);
3089                  } else if (cpu->machine->userland_emul != NULL) {                  } else if (cpu->machine->userland_emul != NULL) {

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

  ViewVC Help
Powered by ViewVC 1.1.26