/[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 16 by dpavlin, Mon Oct 8 16:19:01 2007 UTC revision 30 by dpavlin, Mon Oct 8 16:20:40 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.29 2005/10/11 03:31:28 debug Exp $   *  $Id: cpu_arm_instr.c,v 1.68 2006/08/11 17:43:30 debug Exp $
29   *   *
30   *  ARM instructions.   *  ARM instructions.
31   *   *
# Line 36  Line 36 
36   */   */
37    
38    
39    /*  #define GATHER_BDT_STATISTICS  */
40    
41    
42    #ifdef GATHER_BDT_STATISTICS
43    /*
44     *  update_bdt_statistics():
45     *
46     *  Gathers statistics about load/store multiple instructions.
47     *
48     *  NOTE/TODO: Perhaps it would be more memory efficient to swap the high
49     *  and low parts of the instruction word, so that the lllllll bits become
50     *  the high bits; this would cause fewer host pages to be used. Anyway, the
51     *  current implementation works on hosts with lots of RAM.
52     *
53     *  The resulting file, bdt_statistics.txt, should then be processed like
54     *  this to give a new cpu_arm_multi.txt:
55     *
56     *  uniq -c bdt_statistics.txt|sort -nr|head -256|cut -f 2 > cpu_arm_multi.txt
57     */
58    static void update_bdt_statistics(uint32_t iw)
59    {
60            static FILE *f = NULL;
61            static long long *counts;
62            static char *counts_used;
63            static long long n = 0;
64    
65            if (f == NULL) {
66                    size_t s = (1 << 24) * sizeof(long long);
67                    f = fopen("bdt_statistics.txt", "w");
68                    if (f == NULL) {
69                            fprintf(stderr, "update_bdt_statistics(): :-(\n");
70                            exit(1);
71                    }
72                    counts = zeroed_alloc(s);
73                    counts_used = zeroed_alloc(65536);
74            }
75    
76            /*  Drop the s-bit: xxxx100P USWLnnnn llllllll llllllll  */
77            iw = ((iw & 0x01800000) >> 1) | (iw & 0x003fffff);
78    
79            counts_used[iw & 0xffff] = 1;
80            counts[iw] ++;
81    
82            n ++;
83            if ((n % 500000) == 0) {
84                    int i;
85                    long long j;
86                    fatal("[ update_bdt_statistics(): n = %lli ]\n", (long long) n);
87                    fseek(f, 0, SEEK_SET);
88                    for (i=0; i<0x1000000; i++)
89                            if (counts_used[i & 0xffff] && counts[i] != 0) {
90                                    /*  Recreate the opcode:  */
91                                    uint32_t opcode = ((i & 0x00c00000) << 1)
92                                        | (i & 0x003fffff) | 0x08000000;
93                                    for (j=0; j<counts[i]; j++)
94                                            fprintf(f, "0x%08x\n", opcode);
95                            }
96                    fflush(f);
97            }
98    }
99    #endif
100    
101    
102    /*****************************************************************************/
103    
104    
105  /*  /*
106   *  Helper definitions:   *  Helper definitions:
107   *   *
# Line 51  Line 117 
117   *  condition code. (The NV condition code is not included, and the AL code   *  condition code. (The NV condition code is not included, and the AL code
118   *  uses the main foo function.)  Y also defines an array with pointers to   *  uses the main foo function.)  Y also defines an array with pointers to
119   *  all of these functions.   *  all of these functions.
120     *
121     *  If the compiler is good enough (i.e. allows long enough code sequences
122     *  to be inlined), then the Y functions will be compiled as full (inlined)
123     *  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 135  Line 201 
201    
202    
203  /*  /*
  *  nop:  Do nothing.  
204   *  invalid:  Invalid instructions end up here.   *  invalid:  Invalid instructions end up here.
205   */   */
 X(nop) { }  
206  X(invalid) {  X(invalid) {
207          uint32_t low_pc;          uint32_t low_pc;
208          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
209              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
210          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
211              << ARM_INSTR_ALIGNMENT_SHIFT);              << ARM_INSTR_ALIGNMENT_SHIFT);
212          cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
         cpu->pc = cpu->cd.arm.r[ARM_PC];  
213    
214          fatal("Invalid ARM instruction: pc=0x%08x\n", (int)cpu->pc);          fatal("FATAL ERROR: An internal error occured in the ARM"
215                " dyntrans code. Please contact the author with detailed"
216                " repro steps on how to trigger this bug. pc = 0x%08"PRIx32"\n",
217                (uint32_t)cpu->pc);
218    
         cpu->running = 0;  
         cpu->running_translated = 0;  
         cpu->n_translated_instrs --;  
219          cpu->cd.arm.next_ic = &nothing_call;          cpu->cd.arm.next_ic = &nothing_call;
220  }  }
221    
222    
223  /*  /*
224     *  nop:  Do nothing.
225     */
226    X(nop)
227    {
228    }
229    
230    
231    /*
232   *  b:  Branch (to a different translated page)   *  b:  Branch (to a different translated page)
233   *   *
234   *  arg[0] = relative offset   *  arg[0] = relative offset
235   */   */
236  X(b)  X(b)
237  {  {
238          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];  
239    
240          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
241          arm_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
242  }  }
243  Y(b)  Y(b)
244    
# Line 185  Y(b) Line 247  Y(b)
247   *  b_samepage:  Branch (to within the same translated page)   *  b_samepage:  Branch (to within the same translated page)
248   *   *
249   *  arg[0] = pointer to new arm_instr_call   *  arg[0] = pointer to new arm_instr_call
250     *  arg[1] = pointer to the next instruction.
251     *
252     *  NOTE: This instruction is manually inlined.
253   */   */
254  X(b_samepage)  X(b_samepage) {
 {  
255          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
256  }  }
257  Y(b_samepage)  X(b_samepage__eq) {
258            cpu->cd.arm.next_ic = (struct arm_instr_call *)
259                ic->arg[cpu->cd.arm.flags & ARM_F_Z? 0 : 1];
260    }
261    X(b_samepage__ne) {
262            cpu->cd.arm.next_ic = (struct arm_instr_call *)
263                ic->arg[cpu->cd.arm.flags & ARM_F_Z? 1 : 0];
264    }
265    X(b_samepage__cs) {
266            cpu->cd.arm.next_ic = (struct arm_instr_call *)
267                ic->arg[cpu->cd.arm.flags & ARM_F_C? 0 : 1];
268    }
269    X(b_samepage__cc) {
270            cpu->cd.arm.next_ic = (struct arm_instr_call *)
271                ic->arg[cpu->cd.arm.flags & ARM_F_C? 1 : 0];
272    }
273    X(b_samepage__mi) {
274            cpu->cd.arm.next_ic = (struct arm_instr_call *)
275                ic->arg[cpu->cd.arm.flags & ARM_F_N? 0 : 1];
276    }
277    X(b_samepage__pl) {
278            cpu->cd.arm.next_ic = (struct arm_instr_call *)
279                ic->arg[cpu->cd.arm.flags & ARM_F_N? 1 : 0];
280    }
281    X(b_samepage__vs) {
282            cpu->cd.arm.next_ic = (struct arm_instr_call *)
283                ic->arg[cpu->cd.arm.flags & ARM_F_V? 0 : 1];
284    }
285    X(b_samepage__vc) {
286            cpu->cd.arm.next_ic = (struct arm_instr_call *)
287                ic->arg[cpu->cd.arm.flags & ARM_F_V? 1 : 0];
288    }
289    X(b_samepage__hi) {
290            cpu->cd.arm.next_ic = (condition_hi[cpu->cd.arm.flags])?
291                (struct arm_instr_call *) ic->arg[0] :
292                (struct arm_instr_call *) ic->arg[1];
293    }
294    X(b_samepage__ls) {
295            cpu->cd.arm.next_ic = (struct arm_instr_call *)
296                ic->arg[condition_hi[cpu->cd.arm.flags]];
297    }
298    X(b_samepage__ge) {
299            cpu->cd.arm.next_ic = (condition_ge[cpu->cd.arm.flags])?
300                (struct arm_instr_call *) ic->arg[0] :
301                (struct arm_instr_call *) ic->arg[1];
302    }
303    X(b_samepage__lt) {
304            cpu->cd.arm.next_ic = (struct arm_instr_call *)
305                ic->arg[condition_ge[cpu->cd.arm.flags]];
306    }
307    X(b_samepage__gt) {
308            cpu->cd.arm.next_ic = (condition_gt[cpu->cd.arm.flags])?
309                (struct arm_instr_call *) ic->arg[0] :
310                (struct arm_instr_call *) ic->arg[1];
311    }
312    X(b_samepage__le) {
313            cpu->cd.arm.next_ic = (struct arm_instr_call *)
314                ic->arg[condition_gt[cpu->cd.arm.flags]];
315    }
316    void (*arm_cond_instr_b_samepage[16])(struct cpu *,
317            struct arm_instr_call *) = {
318            arm_instr_b_samepage__eq, arm_instr_b_samepage__ne,
319            arm_instr_b_samepage__cs, arm_instr_b_samepage__cc,
320            arm_instr_b_samepage__mi, arm_instr_b_samepage__pl,
321            arm_instr_b_samepage__vs, arm_instr_b_samepage__vc,
322            arm_instr_b_samepage__hi, arm_instr_b_samepage__ls,
323            arm_instr_b_samepage__ge, arm_instr_b_samepage__lt,
324            arm_instr_b_samepage__gt, arm_instr_b_samepage__le,
325            arm_instr_b_samepage, arm_instr_nop };
326    
327    
328  /*  /*
# Line 200  Y(b_samepage) Line 332  Y(b_samepage)
332   */   */
333  X(bx)  X(bx)
334  {  {
335          cpu->pc = cpu->cd.arm.r[ARM_PC] = reg(ic->arg[0]);          cpu->pc = reg(ic->arg[0]);
336          if (cpu->pc & 1) {          if (cpu->pc & 1) {
337                  fatal("thumb: TODO\n");                  fatal("thumb: TODO\n");
338                  exit(1);                  exit(1);
# Line 208  X(bx) Line 340  X(bx)
340          cpu->pc &= ~3;          cpu->pc &= ~3;
341    
342          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
343          arm_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
344  }  }
345  Y(bx)  Y(bx)
346    
# Line 220  Y(bx) Line 352  Y(bx)
352   */   */
353  X(bx_trace)  X(bx_trace)
354  {  {
355          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
356          if (cpu->pc & 1) {          if (cpu->pc & 1) {
357                  fatal("thumb: TODO\n");                  fatal("thumb: TODO\n");
358                  exit(1);                  exit(1);
# Line 230  X(bx_trace) Line 362  X(bx_trace)
362          cpu_functioncall_trace_return(cpu);          cpu_functioncall_trace_return(cpu);
363    
364          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
365          arm_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
366  }  }
367  Y(bx_trace)  Y(bx_trace)
368    
# Line 242  Y(bx_trace) Line 374  Y(bx_trace)
374   */   */
375  X(bl)  X(bl)
376  {  {
377          uint32_t lr, low_pc;          uint32_t pc = ((uint32_t)cpu->pc & 0xfffff000) + (int32_t)ic->arg[1];
378            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;  
379    
380          /*  Calculate new PC from this instruction + arg[0]  */          /*  Calculate new PC from this instruction + arg[0]  */
381          cpu->pc = cpu->cd.arm.r[ARM_PC] = lr - 4 + (int32_t)ic->arg[0];          cpu->pc = pc + (int32_t)ic->arg[0];
382    
383          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
384          arm_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
385  }  }
386  Y(bl)  Y(bl)
387    
# Line 270  Y(bl) Line 393  Y(bl)
393   */   */
394  X(blx)  X(blx)
395  {  {
396          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:  */  
397          cpu->cd.arm.r[ARM_LR] = lr;          cpu->cd.arm.r[ARM_LR] = lr;
398            cpu->pc = reg(ic->arg[0]);
         cpu->pc = cpu->cd.arm.r[ARM_PC] = reg(ic->arg[0]);  
399          if (cpu->pc & 1) {          if (cpu->pc & 1) {
400                  fatal("thumb: TODO\n");                  fatal("thumb: TODO\n");
401                  exit(1);                  exit(1);
# Line 290  X(blx) Line 403  X(blx)
403          cpu->pc &= ~3;          cpu->pc &= ~3;
404    
405          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
406          arm_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
407  }  }
408  Y(blx)  Y(blx)
409    
# Line 302  Y(blx) Line 415  Y(blx)
415   */   */
416  X(bl_trace)  X(bl_trace)
417  {  {
418          uint32_t lr, low_pc;          uint32_t pc = ((uint32_t)cpu->pc & 0xfffff000) + (int32_t)ic->arg[1];
419            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;  
420    
421          /*  Calculate new PC from this instruction + arg[0]  */          /*  Calculate new PC from this instruction + arg[0]  */
422          cpu->pc = cpu->cd.arm.r[ARM_PC] = lr - 4 + (int32_t)ic->arg[0];          cpu->pc = pc + (int32_t)ic->arg[0];
423    
424          cpu_functioncall_trace(cpu, cpu->pc);          cpu_functioncall_trace(cpu, cpu->pc);
425    
426          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
427          arm_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
428  }  }
429  Y(bl_trace)  Y(bl_trace)
430    
# Line 332  Y(bl_trace) Line 436  Y(bl_trace)
436   */   */
437  X(bl_samepage)  X(bl_samepage)
438  {  {
439          uint32_t lr, low_pc;          cpu->cd.arm.r[ARM_LR] =
440                ((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:  */  
441          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
442  }  }
443  Y(bl_samepage)  Y(bl_samepage)
# Line 357  Y(bl_samepage) Line 450  Y(bl_samepage)
450   */   */
451  X(bl_samepage_trace)  X(bl_samepage_trace)
452  {  {
453          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);  
454    
455          /*  Link:  */          /*  Link and branch:  */
456          cpu->cd.arm.r[ARM_LR] = lr;          cpu->cd.arm.r[ARM_LR] = lr;
   
         /*  Branch:  */  
457          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
458    
459            /*  Synchronize the program counter:  */
460          low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)          low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)
461              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
462          tmp_pc = cpu->cd.arm.r[ARM_PC];          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
         tmp_pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)  
463              << ARM_INSTR_ALIGNMENT_SHIFT);              << ARM_INSTR_ALIGNMENT_SHIFT);
464          tmp_pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
465          cpu_functioncall_trace(cpu, tmp_pc);  
466            /*  ... and show trace:  */
467            cpu_functioncall_trace(cpu, cpu->pc);
468  }  }
469  Y(bl_samepage_trace)  Y(bl_samepage_trace)
470    
471    
472  /*  /*
473     *  clz: Count leading zeroes.
474     *
475     *  arg[0] = ptr to rm
476     *  arg[1] = ptr to rd
477     */
478    X(clz)
479    {
480            uint32_t rm = reg(ic->arg[0]);
481            int i = 32, n = 0, j;
482            while (i>0) {
483                    if (rm & 0xff000000) {
484                            for (j=0; j<8; j++) {
485                                    if (rm & 0x80000000)
486                                            break;
487                                    n ++;
488                                    rm <<= 1;
489                            }
490                            break;
491                    } else {
492                            rm <<= 8;
493                            i -= 8;
494                            n += 8;
495                    }
496            }
497            reg(ic->arg[1]) = n;
498    }
499    Y(clz)
500    
501    
502    /*
503   *  mul: Multiplication   *  mul: Multiplication
504   *   *
505   *  arg[0] = ptr to rd   *  arg[0] = ptr to rd
# Line 397  X(mul) Line 513  X(mul)
513  Y(mul)  Y(mul)
514  X(muls)  X(muls)
515  {  {
516          uint32_t result = reg(ic->arg[1]) * reg(ic->arg[2]);          uint32_t result;
517          cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N);          result = reg(ic->arg[1]) * reg(ic->arg[2]);
518            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
519          if (result == 0)          if (result == 0)
520                  cpu->cd.arm.cpsr |= ARM_FLAG_Z;                  cpu->cd.arm.flags |= ARM_F_Z;
521          if (result & 0x80000000)          if (result & 0x80000000)
522                  cpu->cd.arm.cpsr |= ARM_FLAG_N;                  cpu->cd.arm.flags |= ARM_F_N;
523          reg(ic->arg[0]) = result;          reg(ic->arg[0]) = result;
524  }  }
525  Y(muls)  Y(muls)
# Line 417  X(mla) Line 534  X(mla)
534  {  {
535          /*  xxxx0000 00ASdddd nnnnssss 1001mmmm (Rd,Rm,Rs[,Rn])  */          /*  xxxx0000 00ASdddd nnnnssss 1001mmmm (Rd,Rm,Rs[,Rn])  */
536          uint32_t iw = ic->arg[0];          uint32_t iw = ic->arg[0];
537          int rd = (iw >> 16) & 15, rn = (iw >> 12) & 15,          int rd, rs, rn, rm;
538              rs = (iw >> 8) & 15,  rm = iw & 15;          rd = (iw >> 16) & 15; rn = (iw >> 12) & 15,
539            rs = (iw >> 8) & 15;  rm = iw & 15;
540          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]
541              + cpu->cd.arm.r[rn];              + cpu->cd.arm.r[rn];
542  }  }
# Line 427  X(mlas) Line 545  X(mlas)
545  {  {
546          /*  xxxx0000 00ASdddd nnnnssss 1001mmmm (Rd,Rm,Rs[,Rn])  */          /*  xxxx0000 00ASdddd nnnnssss 1001mmmm (Rd,Rm,Rs[,Rn])  */
547          uint32_t iw = ic->arg[0];          uint32_t iw = ic->arg[0];
548          int rd = (iw >> 16) & 15, rn = (iw >> 12) & 15,          int rd, rs, rn, rm;
549              rs = (iw >> 8) & 15,  rm = iw & 15;          rd = (iw >> 16) & 15; rn = (iw >> 12) & 15,
550            rs = (iw >> 8) & 15;  rm = iw & 15;
551          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]
552              + cpu->cd.arm.r[rn];              + cpu->cd.arm.r[rn];
553          cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N);          cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
554          if (cpu->cd.arm.r[rd] == 0)          if (cpu->cd.arm.r[rd] == 0)
555                  cpu->cd.arm.cpsr |= ARM_FLAG_Z;                  cpu->cd.arm.flags |= ARM_F_Z;
556          if (cpu->cd.arm.r[rd] & 0x80000000)          if (cpu->cd.arm.r[rd] & 0x80000000)
557                  cpu->cd.arm.cpsr |= ARM_FLAG_N;                  cpu->cd.arm.flags |= ARM_F_N;
558  }  }
559  Y(mlas)  Y(mlas)
560    
# Line 448  Y(mlas) Line 567  Y(mlas)
567  X(mull)  X(mull)
568  {  {
569          /*  xxxx0000 1UAShhhh llllssss 1001mmmm  */          /*  xxxx0000 1UAShhhh llllssss 1001mmmm  */
570          uint32_t iw = ic->arg[0];          uint32_t iw; uint64_t tmp; int u_bit, a_bit;
571          int u_bit = (iw >> 22) & 1, a_bit = (iw >> 21) & 1;          iw = ic->arg[0];
572          uint64_t tmp = cpu->cd.arm.r[iw & 15];          u_bit = iw & 0x00400000; a_bit = iw & 0x00200000;
573            tmp = cpu->cd.arm.r[iw & 15];
574          if (u_bit)          if (u_bit)
575                  tmp = (int64_t)(int32_t)tmp                  tmp = (int64_t)(int32_t)tmp
576                      * (int64_t)(int32_t)cpu->cd.arm.r[(iw >> 8) & 15];                      * (int64_t)(int32_t)cpu->cd.arm.r[(iw >> 8) & 15];
# Line 471  Y(mull) Line 591  Y(mull)
591    
592    
593  /*  /*
594     *  smulXY:  16-bit * 16-bit multiplication (32-bit result)
595     *
596     *  arg[0] = ptr to rm
597     *  arg[1] = ptr to rs
598     *  arg[2] = ptr to rd
599     */
600    X(smulbb)
601    {
602            reg(ic->arg[2]) = (int32_t)(int16_t)reg(ic->arg[0]) *
603                (int32_t)(int16_t)reg(ic->arg[1]);
604    }
605    Y(smulbb)
606    X(smultb)
607    {
608            reg(ic->arg[2]) = (int32_t)(int16_t)(reg(ic->arg[0]) >> 16) *
609                (int32_t)(int16_t)reg(ic->arg[1]);
610    }
611    Y(smultb)
612    X(smulbt)
613    {
614            reg(ic->arg[2]) = (int32_t)(int16_t)reg(ic->arg[0]) *
615                (int32_t)(int16_t)(reg(ic->arg[1]) >> 16);
616    }
617    Y(smulbt)
618    X(smultt)
619    {
620            reg(ic->arg[2]) = (int32_t)(int16_t)(reg(ic->arg[0]) >> 16) *
621                (int32_t)(int16_t)(reg(ic->arg[1]) >> 16);
622    }
623    Y(smultt)
624    
625    
626    /*
627   *  mov_reg_reg:  Move a register to another.   *  mov_reg_reg:  Move a register to another.
628   *   *
629   *  arg[0] = ptr to source register   *  arg[0] = ptr to source register
# Line 484  Y(mov_reg_reg) Line 637  Y(mov_reg_reg)
637    
638    
639  /*  /*
640     *  mov_reg_pc:  Move the PC register to a normal register.
641     *
642     *  arg[0] = offset compared to start of current page + 8
643     *  arg[1] = ptr to destination register
644     */
645    X(mov_reg_pc)
646    {
647            reg(ic->arg[1]) = ((uint32_t)cpu->pc&0xfffff000) + (int32_t)ic->arg[0];
648    }
649    Y(mov_reg_pc)
650    
651    
652    /*
653   *  ret_trace:  "mov pc,lr" with trace enabled   *  ret_trace:  "mov pc,lr" with trace enabled
654     *  ret:  "mov pc,lr" without trace enabled
655   *   *
656   *  arg[0] = ignored   *  arg[0] = ignored
657   */   */
658  X(ret_trace)  X(ret_trace)
659  {  {
660          uint32_t old_pc = cpu->cd.arm.r[ARM_PC];          uint32_t old_pc, mask_within_page;
661          uint32_t mask_within_page = ((ARM_IC_ENTRIES_PER_PAGE-1)          old_pc = cpu->pc;
662            mask_within_page = ((ARM_IC_ENTRIES_PER_PAGE-1)
663              << ARM_INSTR_ALIGNMENT_SHIFT) |              << ARM_INSTR_ALIGNMENT_SHIFT) |
664              ((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);              ((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);
665    
666          /*  Update the PC register:  */          /*  Update the PC register:  */
667          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
668    
669          cpu_functioncall_trace_return(cpu);          cpu_functioncall_trace_return(cpu);
670    
# Line 509  X(ret_trace) Line 677  X(ret_trace)
677                      ((cpu->pc & mask_within_page) >> ARM_INSTR_ALIGNMENT_SHIFT);                      ((cpu->pc & mask_within_page) >> ARM_INSTR_ALIGNMENT_SHIFT);
678          } else {          } else {
679                  /*  Find the new physical page and update pointers:  */                  /*  Find the new physical page and update pointers:  */
680                  arm_pc_to_pointers(cpu);                  quick_pc_to_pointers(cpu);
681          }          }
682  }  }
683  Y(ret_trace)  Y(ret_trace)
684    X(ret)
685    {
686            cpu->pc = cpu->cd.arm.r[ARM_LR];
687            quick_pc_to_pointers(cpu);
688    }
689    Y(ret)
690    
691    
692  /*  /*
# Line 533  X(msr_imm) Line 707  X(msr_imm)
707              (ic->arg[0] & ARM_FLAG_MODE));              (ic->arg[0] & ARM_FLAG_MODE));
708          uint32_t new_value = ic->arg[0];          uint32_t new_value = ic->arg[0];
709    
710            cpu->cd.arm.cpsr &= 0x0fffffff;
711            cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
712    
713          if (switch_register_banks)          if (switch_register_banks)
714                  arm_save_register_bank(cpu);                  arm_save_register_bank(cpu);
715    
716          cpu->cd.arm.cpsr &= ~mask;          cpu->cd.arm.cpsr &= ~mask;
717          cpu->cd.arm.cpsr |= (new_value & mask);          cpu->cd.arm.cpsr |= (new_value & mask);
718    
719            cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
720    
721          if (switch_register_banks)          if (switch_register_banks)
722                  arm_load_register_bank(cpu);                  arm_load_register_bank(cpu);
723  }  }
# Line 580  X(msr_imm_spsr) Line 759  X(msr_imm_spsr)
759          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
760          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)
761              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
762          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
763              << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
764          cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          old_pc = cpu->pc;
765          old_pc = cpu->pc = cpu->cd.arm.r[ARM_PC];          printf("msr_spsr: old pc = 0x%08"PRIx32"\n", old_pc);
 printf("msr_spsr: old pc = 0x%08x\n", old_pc);  
766  }  }
767                  exit(1);                  exit(1);
768          }          }
# Line 605  Y(msr_spsr) Line 783  Y(msr_spsr)
783   */   */
784  X(mrs)  X(mrs)
785  {  {
786            cpu->cd.arm.cpsr &= 0x0fffffff;
787            cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
788          reg(ic->arg[0]) = cpu->cd.arm.cpsr;          reg(ic->arg[0]) = cpu->cd.arm.cpsr;
789  }  }
790  Y(mrs)  Y(mrs)
791    
792    
793  /*  /*
794   *  mrs: Move from status/flag register to a normal register.   *  mrs: Move from saved status/flag register to a normal register.
795   *   *
796   *  arg[0] = pointer to rd   *  arg[0] = pointer to rd
797   */   */
# Line 640  Y(mrs_spsr) Line 820  Y(mrs_spsr)
820   *  arg[0] = copy of the instruction word   *  arg[0] = copy of the instruction word
821   */   */
822  X(mcr_mrc) {  X(mcr_mrc) {
823          uint32_t low_pc;          uint32_t low_pc = ((size_t)ic - (size_t)
         low_pc = ((size_t)ic - (size_t)  
824              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
825          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
826              << 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];  
827          arm_mcr_mrc(cpu, ic->arg[0]);          arm_mcr_mrc(cpu, ic->arg[0]);
828  }  }
829  Y(mcr_mrc)  Y(mcr_mrc)
830  X(cdp) {  X(cdp) {
831          uint32_t low_pc;          uint32_t low_pc = ((size_t)ic - (size_t)
         low_pc = ((size_t)ic - (size_t)  
832              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
833          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
834              << 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];  
835          arm_cdp(cpu, ic->arg[0]);          arm_cdp(cpu, ic->arg[0]);
836  }  }
837  Y(cdp)  Y(cdp)
# Line 668  Y(cdp) Line 842  Y(cdp)
842   */   */
843  X(openfirmware)  X(openfirmware)
844  {  {
845            /*  TODO: sync pc?  */
846          of_emul(cpu);          of_emul(cpu);
847          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
848          if (cpu->machine->show_trace_tree)          if (cpu->machine->show_trace_tree)
849                  cpu_functioncall_trace_return(cpu);                  cpu_functioncall_trace_return(cpu);
850          arm_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
851    }
852    
853    
854    /*
855     *  reboot:
856     */
857    X(reboot)
858    {
859            cpu->running = 0;
860            cpu->n_translated_instrs --;
861            cpu->cd.arm.next_ic = &nothing_call;
862  }  }
863    
864    
# Line 686  X(swi_useremul) Line 872  X(swi_useremul)
872          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
873          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)
874              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
875          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
876              << ARM_INSTR_ALIGNMENT_SHIFT);              << ARM_INSTR_ALIGNMENT_SHIFT);
877          cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
878          old_pc = cpu->pc = cpu->cd.arm.r[ARM_PC];          old_pc = cpu->pc;
879    
880          useremul_syscall(cpu, ic->arg[0]);          useremul_syscall(cpu, ic->arg[0]);
881    
882          if (!cpu->running) {          if (!cpu->running) {
                 cpu->running_translated = 0;  
883                  cpu->n_translated_instrs --;                  cpu->n_translated_instrs --;
884                  cpu->cd.arm.next_ic = &nothing_call;                  cpu->cd.arm.next_ic = &nothing_call;
885          } else if (cpu->pc != old_pc) {          } else if (cpu->pc != old_pc) {
886                  /*  PC was changed by the SWI call. Find the new physical                  /*  PC was changed by the SWI call. Find the new physical
887                      page and update the translation pointers:  */                      page and update the translation pointers:  */
888                  arm_pc_to_pointers(cpu);                  quick_pc_to_pointers(cpu);
889          }          }
890  }  }
891  Y(swi_useremul)  Y(swi_useremul)
# Line 711  Y(swi_useremul) Line 896  Y(swi_useremul)
896   */   */
897  X(swi)  X(swi)
898  {  {
899          /*  Synchronize the program counter:  */          /*  Synchronize the program counter first:  */
900          uint32_t low_pc = ((size_t)ic - (size_t)          cpu->pc &= 0xfffff000;
901              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];  
   
902          arm_exception(cpu, ARM_EXCEPTION_SWI);          arm_exception(cpu, ARM_EXCEPTION_SWI);
903  }  }
904  Y(swi)  Y(swi)
905    
906    
907  /*  /*
908     *  und:  Undefined instruction.
909     */
910    X(und)
911    {
912            /*  Synchronize the program counter first:  */
913            cpu->pc &= 0xfffff000;
914            cpu->pc += ic->arg[0];
915            arm_exception(cpu, ARM_EXCEPTION_UND);
916    }
917    Y(und)
918    
919    
920    /*
921   *  swp, swpb:  Swap (word or byte).   *  swp, swpb:  Swap (word or byte).
922   *   *
923   *  arg[0] = ptr to rd   *  arg[0] = ptr to rd
# Line 735  X(swp) Line 928  X(swp)
928  {  {
929          uint32_t addr = reg(ic->arg[2]), data, data2;          uint32_t addr = reg(ic->arg[2]), data, data2;
930          unsigned char d[4];          unsigned char d[4];
931    
932          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
933          uint32_t low_pc = ((size_t)ic - (size_t)          uint32_t low_pc = ((size_t)ic - (size_t)
934              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
935          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
936              << 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];  
937    
938          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,
939              CACHE_DATA)) {              CACHE_DATA)) {
# Line 763  X(swpb) Line 955  X(swpb)
955  {  {
956          uint32_t addr = reg(ic->arg[2]), data;          uint32_t addr = reg(ic->arg[2]), data;
957          unsigned char d[1];          unsigned char d[1];
958    
959          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
960          uint32_t low_pc = ((size_t)ic - (size_t)          uint32_t low_pc = ((size_t)ic - (size_t)
961              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
962          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
963              << 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];  
964    
965          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,
966              CACHE_DATA)) {              CACHE_DATA)) {
# Line 790  Y(swpb) Line 981  Y(swpb)
981    
982  extern void (*arm_load_store_instr[1024])(struct cpu *,  extern void (*arm_load_store_instr[1024])(struct cpu *,
983          struct arm_instr_call *);          struct arm_instr_call *);
984    X(store_w1_word_u1_p0_imm);
985  X(store_w0_byte_u1_p0_imm);  X(store_w0_byte_u1_p0_imm);
986  X(store_w0_word_u1_p0_imm);  X(store_w0_word_u1_p0_imm);
987    X(store_w0_word_u1_p1_imm);
988    X(load_w1_word_u1_p0_imm);
989    X(load_w0_word_u1_p0_imm);
990    X(load_w0_byte_u1_p1_imm);
991    X(load_w0_byte_u1_p1_reg);
992    X(load_w1_byte_u1_p1_imm);
993    
994  extern void (*arm_load_store_instr_pc[1024])(struct cpu *,  extern void (*arm_load_store_instr_pc[1024])(struct cpu *,
995          struct arm_instr_call *);          struct arm_instr_call *);
# Line 803  extern void (*arm_load_store_instr_3_pc[ Line 1001  extern void (*arm_load_store_instr_3_pc[
1001          struct arm_instr_call *);          struct arm_instr_call *);
1002    
1003  extern uint32_t (*arm_r[8192])(struct cpu *, struct arm_instr_call *);  extern uint32_t (*arm_r[8192])(struct cpu *, struct arm_instr_call *);
1004    extern void arm_r_r3_t0_c0(void);
1005    
1006  extern void (*arm_dpi_instr[2 * 2 * 2 * 16 * 16])(struct cpu *,  extern void (*arm_dpi_instr[2 * 2 * 2 * 16 * 16])(struct cpu *,
1007          struct arm_instr_call *);          struct arm_instr_call *);
1008    extern void (*arm_dpi_instr_regshort[2 * 16 * 16])(struct cpu *,
1009            struct arm_instr_call *);
1010  X(cmps);  X(cmps);
1011    X(teqs);
1012    X(tsts);
1013  X(sub);  X(sub);
1014    X(add);
1015  X(subs);  X(subs);
1016    X(eor_regshort);
1017    X(cmps_regshort);
1018    
1019    
1020    #include "cpu_arm_instr_misc.c"
1021    
1022    
1023  /*  /*
1024   *  bdt_load:  Block Data Transfer, Load   *  bdt_load:  Block Data Transfer, Load
# Line 832  X(bdt_load) Line 1040  X(bdt_load)
1040          int i, return_flag = 0;          int i, return_flag = 0;
1041          uint32_t new_values[16];          uint32_t new_values[16];
1042    
1043    #ifdef GATHER_BDT_STATISTICS
1044            if (!s_bit)
1045                    update_bdt_statistics(iw);
1046    #endif
1047    
1048          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
1049          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
1050              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
1051          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) <<          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
1052              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];  
1053    
1054          if (s_bit) {          if (s_bit) {
1055                  /*  Load to USR registers:  */                  /*  Load to USR registers:  */
# Line 974  X(bdt_load) Line 1185  X(bdt_load)
1185                          arm_save_register_bank(cpu);                          arm_save_register_bank(cpu);
1186    
1187                  cpu->cd.arm.cpsr = new_cpsr;                  cpu->cd.arm.cpsr = new_cpsr;
1188                    cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
1189    
1190                  if (switch_register_banks)                  if (switch_register_banks)
1191                          arm_load_register_bank(cpu);                          arm_load_register_bank(cpu);
# Line 981  X(bdt_load) Line 1193  X(bdt_load)
1193    
1194          /*  NOTE: Special case: Loading the PC  */          /*  NOTE: Special case: Loading the PC  */
1195          if (iw & 0x8000) {          if (iw & 0x8000) {
1196                  cpu->cd.arm.r[ARM_PC] &= ~3;                  cpu->pc = cpu->cd.arm.r[ARM_PC] & 0xfffffffc;
                 cpu->pc = cpu->cd.arm.r[ARM_PC];  
1197                  if (cpu->machine->show_trace_tree)                  if (cpu->machine->show_trace_tree)
1198                          cpu_functioncall_trace_return(cpu);                          cpu_functioncall_trace_return(cpu);
1199                  /*  TODO: There is no need to update the                  /*  TODO: There is no need to update the
# Line 990  X(bdt_load) Line 1201  X(bdt_load)
1201                      same page!  */                      same page!  */
1202                  /*  Find the new physical page and update the                  /*  Find the new physical page and update the
1203                      translation pointers:  */                      translation pointers:  */
1204                  arm_pc_to_pointers(cpu);                  quick_pc_to_pointers(cpu);
1205          }          }
1206  }  }
1207  Y(bdt_load)  Y(bdt_load)
# Line 1015  X(bdt_store) Line 1226  X(bdt_store)
1226          int w_bit = iw & 0x00200000;          int w_bit = iw & 0x00200000;
1227          int i;          int i;
1228    
1229    #ifdef GATHER_BDT_STATISTICS
1230            if (!s_bit)
1231                    update_bdt_statistics(iw);
1232    #endif
1233    
1234          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
1235          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
1236              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
1237          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) <<          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
1238              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];  
1239    
1240          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)) {
1241                  if (!((iw >> i) & 1)) {                  if (!((iw >> i) & 1)) {
# Line 1050  X(bdt_store) Line 1264  X(bdt_store)
1264                          }                          }
1265                  }                  }
1266    
1267                    /*  NOTE/TODO: 8 vs 12 on some ARMs  */
1268                  if (i == ARM_PC)                  if (i == ARM_PC)
1269                          value += 12;    /*  NOTE/TODO: 8 on some ARMs  */                          value = cpu->pc + 12;
1270    
1271                  if (p_bit) {                  if (p_bit) {
1272                          if (u_bit)                          if (u_bit)
# Line 1108  X(bdt_store) Line 1323  X(bdt_store)
1323  Y(bdt_store)  Y(bdt_store)
1324    
1325    
1326    /*  Various load/store multiple instructions:  */
1327    extern uint32_t *multi_opcode[256];
1328    extern void (**multi_opcode_f[256])(struct cpu *, struct arm_instr_call *);
1329    X(multi_0x08b15018);
1330    X(multi_0x08ac000c__ge);
1331    X(multi_0x08a05018);
1332    
1333    
1334  /*****************************************************************************/  /*****************************************************************************/
1335    
1336    
1337  /*  /*
1338   *  fill_loop_test:   *  netbsd_memset:
1339   *   *
1340   *  A byte-fill loop. Fills at most one page at a time. If the page was not   *  The core of a NetBSD/arm memset.
  *  in the host_store table, then the original sequence (beginning with  
  *  cmps rZ,#0) is executed instead.  
1341   *   *
1342   *  L: cmps rZ,#0               ic[0]   *  f01bc420:  e25XX080     subs    rX,rX,#0x80
1343   *     strb rX,[rY],#1          ic[1]   *  f01bc424:  a8ac000c     stmgeia ip!,{r2,r3}   (16 of these)
1344   *     sub  rZ,rZ,#1            ic[2]   *  ..
1345   *     bgt  L                   ic[3]   *  f01bc464:  caffffed     bgt     0xf01bc420      <memset+0x38>
  *  
  *  A maximum of 4 pages are filled before returning.  
1346   */   */
1347  X(fill_loop_test)  X(netbsd_memset)
1348  {  {
         int max_pages_left = 4;  
         uint32_t addr, a, n, ofs, maxlen;  
         uint32_t *rzp = (uint32_t *)(size_t)ic[0].arg[0];  
1349          unsigned char *page;          unsigned char *page;
1350            uint32_t addr;
1351    
1352            do {
1353                    addr = cpu->cd.arm.r[ARM_IP];
1354    
1355                    instr(subs)(cpu, ic);
1356    
1357                    if (((cpu->cd.arm.flags & ARM_F_N)?1:0) !=
1358                        ((cpu->cd.arm.flags & ARM_F_V)?1:0)) {
1359                            cpu->n_translated_instrs += 16;
1360                            /*  Skip the store multiples:  */
1361                            cpu->cd.arm.next_ic = &ic[17];
1362                            return;
1363                    }
1364    
1365                    /*  Crossing a page boundary? Then continue non-combined.  */
1366                    if ((addr & 0xfff) + 128 > 0x1000)
1367                            return;
1368    
1369                    /*  R2/R3 non-zero? Not allowed here.  */
1370                    if (cpu->cd.arm.r[2] != 0 || cpu->cd.arm.r[3] != 0)
1371                            return;
1372    
1373                    /*  printf("addr = 0x%08x\n", addr);  */
1374    
1375                    page = cpu->cd.arm.host_store[addr >> 12];
1376                    /*  No page translation? Continue non-combined.  */
1377                    if (page == NULL)
1378                            return;
1379    
1380                    /*  Clear:  */
1381                    memset(page + (addr & 0xfff), 0, 128);
1382                    cpu->cd.arm.r[ARM_IP] = addr + 128;
1383                    cpu->n_translated_instrs += 16;
1384    
1385                    /*  Branch back if greater:  */
1386                    cpu->n_translated_instrs += 1;
1387            } while (((cpu->cd.arm.flags & ARM_F_N)?1:0) ==
1388                ((cpu->cd.arm.flags & ARM_F_V)?1:0) &&
1389                !(cpu->cd.arm.flags & ARM_F_Z));
1390    
1391            /*  Continue at the instruction after the bgt:  */
1392            cpu->cd.arm.next_ic = &ic[18];
1393    }
1394    
1395    
1396    /*
1397     *  netbsd_memcpy:
1398     *
1399     *  The core of a NetBSD/arm memcpy.
1400     *
1401     *  f01bc530:  e8b15018     ldmia   r1!,{r3,r4,ip,lr}
1402     *  f01bc534:  e8a05018     stmia   r0!,{r3,r4,ip,lr}
1403     *  f01bc538:  e8b15018     ldmia   r1!,{r3,r4,ip,lr}
1404     *  f01bc53c:  e8a05018     stmia   r0!,{r3,r4,ip,lr}
1405     *  f01bc540:  e2522020     subs    r2,r2,#0x20
1406     *  f01bc544:  aafffff9     bge     0xf01bc530
1407     */
1408    X(netbsd_memcpy)
1409    {
1410            unsigned char *page_0, *page_1;
1411            uint32_t addr_r0, addr_r1;
1412    
1413            do {
1414                    addr_r0 = cpu->cd.arm.r[0];
1415                    addr_r1 = cpu->cd.arm.r[1];
1416    
1417                    /*  printf("addr_r0 = %08x  r1 = %08x\n", addr_r0, addr_r1);  */
1418    
1419                    /*  Crossing a page boundary? Then continue non-combined.  */
1420                    if ((addr_r0 & 0xfff) + 32 > 0x1000 ||
1421                        (addr_r1 & 0xfff) + 32 > 0x1000) {
1422                            instr(multi_0x08b15018)(cpu, ic);
1423                            return;
1424                    }
1425    
1426                    page_0 = cpu->cd.arm.host_store[addr_r0 >> 12];
1427                    page_1 = cpu->cd.arm.host_store[addr_r1 >> 12];
1428    
1429                    /*  No page translations? Continue non-combined.  */
1430                    if (page_0 == NULL || page_1 == NULL) {
1431                            instr(multi_0x08b15018)(cpu, ic);
1432                            return;
1433                    }
1434    
1435                    memcpy(page_0 + (addr_r0 & 0xfff),
1436                        page_1 + (addr_r1 & 0xfff), 32);
1437                    cpu->cd.arm.r[0] = addr_r0 + 32;
1438                    cpu->cd.arm.r[1] = addr_r1 + 32;
1439    
1440                    cpu->n_translated_instrs += 4;
1441    
1442                    instr(subs)(cpu, ic + 4);
1443                    cpu->n_translated_instrs ++;
1444    
1445                    /*  Loop while greater or equal:  */
1446                    cpu->n_translated_instrs ++;
1447            } while (((cpu->cd.arm.flags & ARM_F_N)?1:0) ==
1448                ((cpu->cd.arm.flags & ARM_F_V)?1:0));
1449    
1450            /*  Continue at the instruction after the bge:  */
1451            cpu->cd.arm.next_ic = &ic[6];
1452            cpu->n_translated_instrs --;
1453    }
1454    
1455    
1456    /*
1457     *  netbsd_cacheclean:
1458     *
1459     *  The core of a NetBSD/arm cache clean routine, variant 1:
1460     *
1461     *  f015f88c:  e4902020     ldr     r2,[r0],#32
1462     *  f015f890:  e2511020     subs    r1,r1,#0x20
1463     *  f015f894:  1afffffc     bne     0xf015f88c
1464     *  f015f898:  ee070f9a     mcr     15,0,r0,cr7,cr10,4
1465     */
1466    X(netbsd_cacheclean)
1467    {
1468            uint32_t r1 = cpu->cd.arm.r[1];
1469            cpu->n_translated_instrs += ((r1 >> 5) * 3);
1470            cpu->cd.arm.r[0] += r1;
1471            cpu->cd.arm.r[1] = 0;
1472            cpu->cd.arm.next_ic = &ic[4];
1473    }
1474    
1475    
1476    /*
1477     *  netbsd_cacheclean2:
1478     *
1479     *  The core of a NetBSD/arm cache clean routine, variant 2:
1480     *
1481     *  f015f93c:  ee070f3a     mcr     15,0,r0,cr7,cr10,1
1482     *  f015f940:  ee070f36     mcr     15,0,r0,cr7,cr6,1
1483     *  f015f944:  e2800020     add     r0,r0,#0x20
1484     *  f015f948:  e2511020     subs    r1,r1,#0x20
1485     *  f015f94c:  8afffffa     bhi     0xf015f93c
1486     */
1487    X(netbsd_cacheclean2)
1488    {
1489            cpu->n_translated_instrs += ((cpu->cd.arm.r[1] >> 5) * 5) - 1;
1490            cpu->cd.arm.next_ic = &ic[5];
1491    }
1492    
1493    
1494    /*
1495     *  netbsd_scanc:
1496     *
1497     *  f01bccbc:  e5d13000     ldrb    r3,[r1]
1498     *  f01bccc0:  e7d23003     ldrb    r3,[r2,r3]
1499     *  f01bccc4:  e113000c     tsts    r3,ip
1500     */
1501    X(netbsd_scanc)
1502    {
1503            unsigned char *page = cpu->cd.arm.host_load[cpu->cd.arm.r[1] >> 12];
1504            uint32_t t;
1505    
 restart_loop:  
         addr = reg(ic[1].arg[0]);  
         page = cpu->cd.arm.host_store[addr >> 12];  
1506          if (page == NULL) {          if (page == NULL) {
1507                  instr(cmps)(cpu, ic);                  instr(load_w0_byte_u1_p1_imm)(cpu, ic);
1508                  return;                  return;
1509          }          }
1510    
1511          n = reg(rzp) + 1;          t = page[cpu->cd.arm.r[1] & 0xfff];
1512          ofs = addr & 0xfff;          t += cpu->cd.arm.r[2];
1513          maxlen = 4096 - ofs;          page = cpu->cd.arm.host_load[t >> 12];
         if (n > maxlen)  
                 n = maxlen;  
1514    
1515          /*  printf("x = %x, n = %i\n", reg(ic[1].arg[2]), n);  */          if (page == NULL) {
1516          memset(page + ofs, reg(ic[1].arg[2]), n);                  instr(load_w0_byte_u1_p1_imm)(cpu, ic);
1517                    return;
1518            }
1519    
1520          reg(ic[1].arg[0]) = addr + n;          cpu->cd.arm.r[3] = page[t & 0xfff];
1521    
1522          reg(rzp) -= n;          t = cpu->cd.arm.r[3] & cpu->cd.arm.r[ARM_IP];
1523          cpu->n_translated_instrs += (4 * n);          cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1524            if (t == 0)
1525                    cpu->cd.arm.flags |= ARM_F_Z;
1526    
1527          a = reg(rzp);          cpu->n_translated_instrs += 2;
1528            cpu->cd.arm.next_ic = &ic[3];
1529    }
1530    
         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;  
1531    
1532          if (max_pages_left-- > 0 && (int32_t)a > 0)  /*
1533                  goto restart_loop;   *  strlen:
1534     *
1535     *  S: e5f03001   ldrb  rY,[rX,#1]!
1536     *     e3530000   cmps  rY,#0
1537     *     1afffffc   bne   S
1538     */
1539    X(strlen)
1540    {
1541            unsigned int n_loops = 0;
1542            uint32_t rY, rX = reg(ic[0].arg[0]);
1543            unsigned char *p;
1544    
1545            do {
1546                    rX ++;
1547                    p = cpu->cd.arm.host_load[rX >> 12];
1548                    if (p == NULL) {
1549                            cpu->n_translated_instrs += (n_loops * 3);
1550                            instr(load_w1_byte_u1_p1_imm)(cpu, ic);
1551                            return;
1552                    }
1553    
1554          cpu->n_translated_instrs --;                  rY = reg(ic[0].arg[2]) = p[rX & 0xfff]; /*  load  */
1555                    reg(ic[0].arg[0]) = rX;                 /*  writeback  */
1556                    n_loops ++;
1557    
1558          if ((int32_t)a > 0)                  /*  Compare rY to zero:  */
1559                  cpu->cd.arm.next_ic = ic;                  cpu->cd.arm.flags = ARM_F_C;
1560          else                  if (rY == 0)
1561                  cpu->cd.arm.next_ic = &ic[4];                          cpu->cd.arm.flags |= ARM_F_Z;
1562            } while (rY != 0);
1563    
1564            cpu->n_translated_instrs += (n_loops * 3) - 1;
1565            cpu->cd.arm.next_ic = &ic[3];
1566  }  }
1567    
1568    
1569  /*  /*
1570   *  fill_loop_test2:   *  xchg:
1571   *   *
1572   *  A word-fill loop. Fills at most one page at a time. If the page was not   *  e02YX00X     eor     rX,rY,rX
1573   *  in the host_store table, then the original sequence (beginning with   *  e02XY00Y     eor     rY,rX,rY
1574   *  cmps rZ,#0) is executed instead.   *  e02YX00X     eor     rX,rY,rX
1575   *   */
1576   *      L: str     rX,[rY],#4           ic[0]  X(xchg)
1577   *         subs    rZ,rZ,#4             ic[1]  {
1578   *         bgt     L                    ic[2]          uint32_t tmp = reg(ic[0].arg[0]);
1579            cpu->n_translated_instrs += 2;
1580            cpu->cd.arm.next_ic = &ic[3];
1581            reg(ic[0].arg[0]) = reg(ic[1].arg[0]);
1582            reg(ic[1].arg[0]) = tmp;
1583    }
1584    
1585    
1586    /*
1587     *  netbsd_copyin:
1588   *   *
1589   *  A maximum of 5 pages are filled before returning.   *  e4b0a004     ldrt    sl,[r0],#4
1590     *  e4b0b004     ldrt    fp,[r0],#4
1591     *  e4b06004     ldrt    r6,[r0],#4
1592     *  e4b07004     ldrt    r7,[r0],#4
1593     *  e4b08004     ldrt    r8,[r0],#4
1594     *  e4b09004     ldrt    r9,[r0],#4
1595   */   */
1596  X(fill_loop_test2)  X(netbsd_copyin)
1597  {  {
1598          int max_pages_left = 5;          uint32_t r0 = cpu->cd.arm.r[0], ofs = (r0 & 0xffc), index = r0 >> 12;
1599          unsigned char x1,x2,x3,x4;          unsigned char *p = cpu->cd.arm.host_load[index];
1600          uint32_t addr, a, n, x, ofs, maxlen;          uint32_t *p32 = (uint32_t *) p, *q32;
1601          uint32_t *rzp = (uint32_t *)(size_t)ic[1].arg[0];          int ok = cpu->cd.arm.is_userpage[index >> 5] & (1 << (index & 31));
         unsigned char *page;  
1602    
1603          x = reg(ic[0].arg[2]);          if (ofs > 0x1000 - 6*4 || !ok || p == NULL) {
1604          x1 = x; x2 = x >> 8; x3 = x >> 16; x4 = x >> 24;                  instr(load_w1_word_u1_p0_imm)(cpu, ic);
         if (x1 != x2 || x1 != x3 || x1 != x4) {  
                 instr(store_w0_word_u1_p0_imm)(cpu, ic);  
1605                  return;                  return;
1606          }          }
1607            q32 = &cpu->cd.arm.r[6];
1608            ofs >>= 2;
1609            q32[0] = p32[ofs+2];
1610            q32[1] = p32[ofs+3];
1611            q32[2] = p32[ofs+4];
1612            q32[3] = p32[ofs+5];
1613            q32[4] = p32[ofs+0];
1614            q32[5] = p32[ofs+1];
1615            cpu->cd.arm.r[0] = r0 + 24;
1616            cpu->n_translated_instrs += 5;
1617            cpu->cd.arm.next_ic = &ic[6];
1618    }
1619    
1620  restart_loop:  
1621          addr = reg(ic[0].arg[0]);  /*
1622          page = cpu->cd.arm.host_store[addr >> 12];   *  netbsd_copyout:
1623          if (page == NULL || (addr & 3) != 0) {   *
1624                  instr(store_w0_word_u1_p0_imm)(cpu, ic);   *  e4a18004     strt    r8,[r1],#4
1625     *  e4a19004     strt    r9,[r1],#4
1626     *  e4a1a004     strt    sl,[r1],#4
1627     *  e4a1b004     strt    fp,[r1],#4
1628     *  e4a16004     strt    r6,[r1],#4
1629     *  e4a17004     strt    r7,[r1],#4
1630     */
1631    X(netbsd_copyout)
1632    {
1633            uint32_t r1 = cpu->cd.arm.r[1], ofs = (r1 & 0xffc), index = r1 >> 12;
1634            unsigned char *p = cpu->cd.arm.host_store[index];
1635            uint32_t *p32 = (uint32_t *) p, *q32;
1636            int ok = cpu->cd.arm.is_userpage[index >> 5] & (1 << (index & 31));
1637    
1638            if (ofs > 0x1000 - 6*4 || !ok || p == NULL) {
1639                    instr(store_w1_word_u1_p0_imm)(cpu, ic);
1640                  return;                  return;
1641          }          }
1642            q32 = &cpu->cd.arm.r[6];
1643            ofs >>= 2;
1644            p32[ofs  ] = q32[2];
1645            p32[ofs+1] = q32[3];
1646            p32[ofs+2] = q32[4];
1647            p32[ofs+3] = q32[5];
1648            p32[ofs+4] = q32[0];
1649            p32[ofs+5] = q32[1];
1650            cpu->cd.arm.r[1] = r1 + 24;
1651            cpu->n_translated_instrs += 5;
1652            cpu->cd.arm.next_ic = &ic[6];
1653    }
1654    
         /*  printf("addr = 0x%08x, page = %p\n", addr, page);  
             printf("*rzp = 0x%08x\n", reg(rzp));  */  
1655    
1656          n = reg(rzp) / 4;  /*
1657          if (n == 0)   *  cmps by 0, followed by beq (inside the same page):
1658                  n++;   */
1659          /*  n = nr of _words_  */  X(cmps0_beq_samepage)
1660          ofs = addr & 0xfff;  {
1661          maxlen = 4096 - ofs;          uint32_t a = reg(ic->arg[0]);
1662          if (n*4 > maxlen)          cpu->n_translated_instrs ++;
1663                  n = maxlen / 4;          if (a == 0) {
1664                    cpu->cd.arm.flags = ARM_F_Z | ARM_F_C;
1665            } else {
1666                    /*  Semi-ugly hack which sets the negative-bit if a < 0:  */
1667                    cpu->cd.arm.flags = ARM_F_C | ((a >> 28) & 8);
1668            }
1669            if (a == 0)
1670                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1671            else
1672                    cpu->cd.arm.next_ic = &ic[2];
1673    }
1674    
         /*  printf("x = %x, n = %i\n", x1, n);  */  
         memset(page + ofs, x1, n * 4);  
1675    
1676          reg(ic[0].arg[0]) = addr + n * 4;  /*
1677     *  cmps followed by beq (inside the same page):
1678     */
1679    X(cmps_beq_samepage)
1680    {
1681            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1682            cpu->n_translated_instrs ++;
1683            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1684            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1685                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1686                    cpu->cd.arm.flags |= ARM_F_V;
1687            if (c == 0) {
1688                    cpu->cd.arm.flags |= ARM_F_Z;
1689                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1690            } else {
1691                    cpu->cd.arm.next_ic = &ic[2];
1692                    if (c & 0x80000000)
1693                            cpu->cd.arm.flags |= ARM_F_N;
1694            }
1695    }
1696    
1697    
1698          reg(rzp) -= (n * 4);  /*
1699          cpu->n_translated_instrs += (3 * n);   *  cmps followed by beq (not the same page):
1700     */
1701    X(cmps_0_beq)
1702    {
1703            uint32_t a = reg(ic->arg[0]);
1704            cpu->n_translated_instrs ++;
1705            if (a == 0) {
1706                    cpu->cd.arm.flags = ARM_F_Z | ARM_F_C;
1707                    cpu->pc = (uint32_t)(((uint32_t)cpu->pc & 0xfffff000)
1708                        + (int32_t)ic[1].arg[0]);
1709                    quick_pc_to_pointers(cpu);
1710            } else {
1711                    /*  Semi-ugly hack which sets the negative-bit if a < 0:  */
1712                    cpu->cd.arm.flags = ARM_F_C | ((a >> 28) & 8);
1713                    cpu->cd.arm.next_ic = &ic[2];
1714            }
1715    }
1716    X(cmps_pos_beq)
1717    {
1718            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1719            cpu->n_translated_instrs ++;
1720            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1721            if ((int32_t)a < 0 && (int32_t)c >= 0)
1722                    cpu->cd.arm.flags |= ARM_F_V;
1723            if (c == 0) {
1724                    cpu->cd.arm.flags |= ARM_F_Z;
1725                    cpu->pc = (uint32_t)(((uint32_t)cpu->pc & 0xfffff000)
1726                        + (int32_t)ic[1].arg[0]);
1727                    quick_pc_to_pointers(cpu);
1728            } else {
1729                    cpu->cd.arm.next_ic = &ic[2];
1730                    if (c & 0x80000000)
1731                            cpu->cd.arm.flags |= ARM_F_N;
1732            }
1733    }
1734    X(cmps_neg_beq)
1735    {
1736            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1737            cpu->n_translated_instrs ++;
1738            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1739            if ((int32_t)a >= 0 && (int32_t)c < 0)
1740                    cpu->cd.arm.flags |= ARM_F_V;
1741            if (c == 0) {
1742                    cpu->cd.arm.flags |= ARM_F_Z;
1743                    cpu->pc = (uint32_t)(((uint32_t)cpu->pc & 0xfffff000)
1744                        + (int32_t)ic[1].arg[0]);
1745                    quick_pc_to_pointers(cpu);
1746            } else {
1747                    cpu->cd.arm.next_ic = &ic[2];
1748                    if (c & 0x80000000)
1749                            cpu->cd.arm.flags |= ARM_F_N;
1750            }
1751    }
1752    
         a = reg(rzp);  
1753    
1754          cpu->cd.arm.cpsr &=  /*
1755              ~(ARM_FLAG_Z | ARM_FLAG_N | ARM_FLAG_V | ARM_FLAG_C);   *  cmps by 0, followed by bne (inside the same page):
1756          if (a != 0)   */
1757                  cpu->cd.arm.cpsr |= ARM_FLAG_C;  X(cmps0_bne_samepage)
1758    {
1759            uint32_t a = reg(ic->arg[0]);
1760            cpu->n_translated_instrs ++;
1761            if (a == 0) {
1762                    cpu->cd.arm.flags = ARM_F_Z | ARM_F_C;
1763            } else {
1764                    /*  Semi-ugly hack which sets the negative-bit if a < 0:  */
1765                    cpu->cd.arm.flags = ARM_F_C | ((a >> 28) & 8);
1766            }
1767            if (a == 0)
1768                    cpu->cd.arm.next_ic = &ic[2];
1769          else          else
1770                  cpu->cd.arm.cpsr |= ARM_FLAG_Z;                  cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1771          if ((int32_t)a < 0)  }
                 cpu->cd.arm.cpsr |= ARM_FLAG_N;  
1772    
         if (max_pages_left-- > 0 && (int32_t)a > 0)  
                 goto restart_loop;  
1773    
1774          cpu->n_translated_instrs --;  /*
1775     *  cmps followed by bne (inside the same page):
1776     */
1777    X(cmps_bne_samepage)
1778    {
1779            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1780            cpu->n_translated_instrs ++;
1781            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1782            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1783                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1784                    cpu->cd.arm.flags |= ARM_F_V;
1785            if (c == 0) {
1786                    cpu->cd.arm.flags |= ARM_F_Z;
1787                    cpu->cd.arm.next_ic = &ic[2];
1788            } else {
1789                    if (c & 0x80000000)
1790                            cpu->cd.arm.flags |= ARM_F_N;
1791                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1792            }
1793    }
1794    
1795    
1796    /*
1797     *  cmps followed by bcc (inside the same page):
1798     */
1799    X(cmps_bcc_samepage)
1800    {
1801            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1802            cpu->n_translated_instrs ++;
1803            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1804            if (c & 0x80000000)
1805                    cpu->cd.arm.flags |= ARM_F_N;
1806            else if (c == 0)
1807                    cpu->cd.arm.flags |= ARM_F_Z;
1808            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1809                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1810                    cpu->cd.arm.flags |= ARM_F_V;
1811            if (a >= b)
1812                    cpu->cd.arm.next_ic = &ic[2];
1813            else
1814                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1815    }
1816    
1817    
1818    /*
1819     *  cmps (reg) followed by bcc (inside the same page):
1820     */
1821    X(cmps_reg_bcc_samepage)
1822    {
1823            uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = a - b;
1824            cpu->n_translated_instrs ++;
1825            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1826            if (c & 0x80000000)
1827                    cpu->cd.arm.flags |= ARM_F_N;
1828            else if (c == 0)
1829                    cpu->cd.arm.flags |= ARM_F_Z;
1830            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1831                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1832                    cpu->cd.arm.flags |= ARM_F_V;
1833            if (a >= b)
1834                    cpu->cd.arm.next_ic = &ic[2];
1835            else
1836                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1837    }
1838    
1839    
1840    /*
1841     *  cmps followed by bhi (inside the same page):
1842     */
1843    X(cmps_bhi_samepage)
1844    {
1845            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1846            cpu->n_translated_instrs ++;
1847            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1848            if (c & 0x80000000)
1849                    cpu->cd.arm.flags |= ARM_F_N;
1850            else if (c == 0)
1851                    cpu->cd.arm.flags |= ARM_F_Z;
1852            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1853                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1854                    cpu->cd.arm.flags |= ARM_F_V;
1855            if (a > b)
1856                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1857            else
1858                    cpu->cd.arm.next_ic = &ic[2];
1859    }
1860    
1861    
1862    /*
1863     *  cmps (reg) followed by bhi (inside the same page):
1864     */
1865    X(cmps_reg_bhi_samepage)
1866    {
1867            uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = a - b;
1868            cpu->n_translated_instrs ++;
1869            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1870            if (c & 0x80000000)
1871                    cpu->cd.arm.flags |= ARM_F_N;
1872            else if (c == 0)
1873                    cpu->cd.arm.flags |= ARM_F_Z;
1874            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1875                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1876                    cpu->cd.arm.flags |= ARM_F_V;
1877            if (a > b)
1878                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1879            else
1880                    cpu->cd.arm.next_ic = &ic[2];
1881    }
1882    
1883    
1884    /*
1885     *  cmps followed by bgt (inside the same page):
1886     */
1887    X(cmps_bgt_samepage)
1888    {
1889            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1890            cpu->n_translated_instrs ++;
1891            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1892            if (c & 0x80000000)
1893                    cpu->cd.arm.flags |= ARM_F_N;
1894            else if (c == 0)
1895                    cpu->cd.arm.flags |= ARM_F_Z;
1896            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1897                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1898                    cpu->cd.arm.flags |= ARM_F_V;
1899            if ((int32_t)a > (int32_t)b)
1900                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1901            else
1902                    cpu->cd.arm.next_ic = &ic[2];
1903    }
1904    
1905    
1906          if ((int32_t)a > 0)  /*
1907                  cpu->cd.arm.next_ic = ic;   *  cmps followed by ble (inside the same page):
1908     */
1909    X(cmps_ble_samepage)
1910    {
1911            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1912            cpu->n_translated_instrs ++;
1913            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1914            if (c & 0x80000000)
1915                    cpu->cd.arm.flags |= ARM_F_N;
1916            else if (c == 0)
1917                    cpu->cd.arm.flags |= ARM_F_Z;
1918            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1919                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1920                    cpu->cd.arm.flags |= ARM_F_V;
1921            if ((int32_t)a <= (int32_t)b)
1922                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1923          else          else
1924                  cpu->cd.arm.next_ic = &ic[3];                  cpu->cd.arm.next_ic = &ic[2];
1925    }
1926    
1927    
1928    /*
1929     *  teqs followed by beq (inside the same page):
1930     */
1931    X(teqs_beq_samepage)
1932    {
1933            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a ^ b;
1934            cpu->n_translated_instrs ++;
1935            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1936            if (c == 0) {
1937                    cpu->cd.arm.flags |= ARM_F_Z;
1938                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
1939                        ic[1].arg[0];
1940            } else {
1941                    if (c & 0x80000000)
1942                            cpu->cd.arm.flags |= ARM_F_N;
1943                    cpu->cd.arm.next_ic = &ic[2];
1944            }
1945    }
1946    
1947    
1948    /*
1949     *  tsts followed by beq (inside the same page):
1950     *  (arg[1] must not have its highest bit set))
1951     */
1952    X(tsts_lo_beq_samepage)
1953    {
1954            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a & b;
1955            cpu->n_translated_instrs ++;
1956            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1957            if (c == 0)
1958                    cpu->cd.arm.flags |= ARM_F_Z;
1959            if (c == 0)
1960                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
1961                        ic[1].arg[0];
1962            else
1963                    cpu->cd.arm.next_ic = &ic[2];
1964    }
1965    
1966    
1967    /*
1968     *  teqs followed by bne (inside the same page):
1969     */
1970    X(teqs_bne_samepage)
1971    {
1972            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a ^ b;
1973            cpu->n_translated_instrs ++;
1974            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1975            if (c == 0) {
1976                    cpu->cd.arm.flags |= ARM_F_Z;
1977            } else {
1978                    if (c & 0x80000000)
1979                            cpu->cd.arm.flags |= ARM_F_N;
1980            }
1981            if (c == 0)
1982                    cpu->cd.arm.next_ic = &ic[2];
1983            else
1984                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
1985                        ic[1].arg[0];
1986    }
1987    
1988    
1989    /*
1990     *  tsts followed by bne (inside the same page):
1991     *  (arg[1] must not have its highest bit set))
1992     */
1993    X(tsts_lo_bne_samepage)
1994    {
1995            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a & b;
1996            cpu->n_translated_instrs ++;
1997            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1998            if (c == 0)
1999                    cpu->cd.arm.flags |= ARM_F_Z;
2000            if (c == 0)
2001                    cpu->cd.arm.next_ic = &ic[2];
2002            else
2003                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
2004                        ic[1].arg[0];
2005  }  }
2006    
2007    
# Line 1262  restart_loop: Line 2011  restart_loop:
2011  X(end_of_page)  X(end_of_page)
2012  {  {
2013          /*  Update the PC:  (offset 0, but on the next page)  */          /*  Update the PC:  (offset 0, but on the next page)  */
2014          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
2015              << 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];  
2016    
2017          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
2018          arm_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
2019    
2020          /*  end_of_page doesn't count as an executed instruction:  */          /*  end_of_page doesn't count as an executed instruction:  */
2021          cpu->n_translated_instrs --;          cpu->n_translated_instrs --;
# Line 1280  X(end_of_page) Line 2026  X(end_of_page)
2026    
2027    
2028  /*  /*
2029   *  arm_combine_instructions():   *  Combine: netbsd_memset():
2030   *   *
2031   *  Combine two or more instructions, if possible, into a single function call.   *  Check for the core of a NetBSD/arm memset; large memsets use a sequence
2032     *  of 16 store-multiple instructions, each storing 2 registers at a time.
2033   */   */
2034  void arm_combine_instructions(struct cpu *cpu, struct arm_instr_call *ic,  void COMBINE(netbsd_memset)(struct cpu *cpu,
2035          uint32_t addr)          struct arm_instr_call *ic, int low_addr)
2036  {  {
2037          int n_back;  #ifdef HOST_LITTLE_ENDIAN
2038          n_back = (addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2039              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
2040    
2041          if (n_back >= 2) {          if (n_back >= 17) {
2042                  if (ic[-2].f == instr(store_w0_word_u1_p0_imm) &&                  int i;
2043                      ic[-2].arg[1] == 4 &&                  for (i=-16; i<=-1; i++)
2044                      ic[-1].f == instr(subs) &&                          if (ic[i].f != instr(multi_0x08ac000c__ge))
2045                      ic[-1].arg[0] == ic[-1].arg[2] && ic[-1].arg[1] == 4 &&                                  return;
2046                    if (ic[-17].f == instr(subs) &&
2047                        ic[-17].arg[0]==ic[-17].arg[2] && ic[-17].arg[1] == 128 &&
2048                      ic[ 0].f == instr(b_samepage__gt) &&                      ic[ 0].f == instr(b_samepage__gt) &&
2049                      ic[ 0].arg[0] == (size_t)&ic[-2]) {                      ic[ 0].arg[0] == (size_t)&ic[-17]) {
2050                          ic[-2].f = instr(fill_loop_test2);                          ic[-17].f = instr(netbsd_memset);
2051                          combined;                  }
2052            }
2053    #endif
2054    }
2055    
2056    
2057    /*
2058     *  Combine: netbsd_memcpy():
2059     *
2060     *  Check for the core of a NetBSD/arm memcpy; large memcpys use a
2061     *  sequence of ldmia instructions.
2062     */
2063    void COMBINE(netbsd_memcpy)(struct cpu *cpu, struct arm_instr_call *ic,
2064            int low_addr)
2065    {
2066    #ifdef HOST_LITTLE_ENDIAN
2067            int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2068                & (ARM_IC_ENTRIES_PER_PAGE-1);
2069    
2070            if (n_back >= 5) {
2071                    if (ic[-5].f==instr(multi_0x08b15018) &&
2072                        ic[-4].f==instr(multi_0x08a05018) &&
2073                        ic[-3].f==instr(multi_0x08b15018) &&
2074                        ic[-2].f==instr(multi_0x08a05018) &&
2075                        ic[-1].f == instr(subs) &&
2076                        ic[-1].arg[0]==ic[-1].arg[2] && ic[-1].arg[1] == 0x20 &&
2077                        ic[ 0].f == instr(b_samepage__ge) &&
2078                        ic[ 0].arg[0] == (size_t)&ic[-5]) {
2079                            ic[-5].f = instr(netbsd_memcpy);
2080                  }                  }
2081          }          }
2082    #endif
2083    }
2084    
2085    
2086    /*
2087     *  Combine: netbsd_cacheclean():
2088     *
2089     *  Check for the core of a NetBSD/arm cache clean. (There are two variants.)
2090     */
2091    void COMBINE(netbsd_cacheclean)(struct cpu *cpu,
2092            struct arm_instr_call *ic, int low_addr)
2093    {
2094            int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2095                & (ARM_IC_ENTRIES_PER_PAGE-1);
2096    
2097          if (n_back >= 3) {          if (n_back >= 3) {
2098                  if (ic[-3].f == instr(cmps) &&                  if (ic[-3].f==instr(load_w0_word_u1_p0_imm) &&
2099                      ic[-3].arg[0] == ic[-1].arg[0] &&                      ic[-2].f == instr(subs) &&
2100                      ic[-3].arg[1] == 0 &&                      ic[-2].arg[0]==ic[-2].arg[2] && ic[-2].arg[1] == 0x20 &&
2101                      ic[-2].f == instr(store_w0_byte_u1_p0_imm) &&                      ic[-1].f == instr(b_samepage__ne) &&
2102                      ic[-2].arg[1] == 1 &&                      ic[-1].arg[0] == (size_t)&ic[-3]) {
2103                      ic[-1].f == instr(sub) &&                          ic[-3].f = instr(netbsd_cacheclean);
2104                      ic[-1].arg[0] == ic[-1].arg[2] && ic[-1].arg[1] == 1 &&                  }
2105                      ic[ 0].f == instr(b_samepage__gt) &&          }
2106                      ic[ 0].arg[0] == (size_t)&ic[-3]) {  }
2107                          ic[-3].f = instr(fill_loop_test);  
2108                          combined;  
2109    /*
2110     *  Combine: netbsd_cacheclean2():
2111     *
2112     *  Check for the core of a NetBSD/arm cache clean. (Second variant.)
2113     */
2114    void COMBINE(netbsd_cacheclean2)(struct cpu *cpu,
2115            struct arm_instr_call *ic, int low_addr)
2116    {
2117            int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2118                & (ARM_IC_ENTRIES_PER_PAGE-1);
2119    
2120            if (n_back >= 4) {
2121                    if (ic[-4].f == instr(mcr_mrc) && ic[-4].arg[0] == 0xee070f3a &&
2122                        ic[-3].f == instr(mcr_mrc) && ic[-3].arg[0] == 0xee070f36 &&
2123                        ic[-2].f == instr(add) &&
2124                        ic[-2].arg[0]==ic[-2].arg[2] && ic[-2].arg[1] == 0x20 &&
2125                        ic[-1].f == instr(subs) &&
2126                        ic[-1].arg[0]==ic[-1].arg[2] && ic[-1].arg[1] == 0x20) {
2127                            ic[-4].f = instr(netbsd_cacheclean2);
2128                    }
2129            }
2130    }
2131    
2132    
2133    /*
2134     *  Combine: netbsd_scanc():
2135     */
2136    void COMBINE(netbsd_scanc)(struct cpu *cpu,
2137            struct arm_instr_call *ic, int low_addr)
2138    {
2139            int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2140                & (ARM_IC_ENTRIES_PER_PAGE-1);
2141    
2142            if (n_back < 2)
2143                    return;
2144    
2145            if (ic[-2].f == instr(load_w0_byte_u1_p1_imm) &&
2146                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            }
2155    }
2156    
2157    
2158    /*
2159     *  Combine: strlen():
2160     */
2161    void COMBINE(strlen)(struct cpu *cpu,
2162            struct arm_instr_call *ic, int low_addr)
2163    {
2164            int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2165                & (ARM_IC_ENTRIES_PER_PAGE-1);
2166    
2167            if (n_back < 2)
2168                    return;
2169    
2170            if (ic[-2].f == instr(load_w1_byte_u1_p1_imm) &&
2171                ic[-2].arg[1] == 1 &&
2172                ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[3]) &&
2173                ic[-1].f == instr(cmps) &&
2174                ic[-1].arg[0] == (size_t)(&cpu->cd.arm.r[3]) &&
2175                ic[-1].arg[1] == 0) {
2176                    ic[-2].f = instr(strlen);
2177            }
2178    }
2179    
2180    
2181    /*
2182     *  Combine: xchg():
2183     */
2184    void COMBINE(xchg)(struct cpu *cpu,
2185            struct arm_instr_call *ic, int low_addr)
2186    {
2187            int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2188                & (ARM_IC_ENTRIES_PER_PAGE-1);
2189            size_t a, b;
2190    
2191            if (n_back < 2)
2192                    return;
2193    
2194            a = ic[-2].arg[0]; b = ic[-1].arg[0];
2195    
2196            if (ic[-2].f == instr(eor_regshort) &&
2197                ic[-1].f == instr(eor_regshort) &&
2198                ic[-2].arg[0] == a && ic[-2].arg[1] == b && ic[-2].arg[2] == b &&
2199                ic[-1].arg[0] == b && ic[-1].arg[1] == a && ic[-1].arg[2] == a &&
2200                ic[ 0].arg[0] == a && ic[ 0].arg[1] == b && ic[ 0].arg[2] == b) {
2201                    ic[-2].f = instr(xchg);
2202            }
2203    }
2204    
2205    
2206    /*
2207     *  Combine: netbsd_copyin():
2208     */
2209    void COMBINE(netbsd_copyin)(struct cpu *cpu,
2210            struct arm_instr_call *ic, int low_addr)
2211    {
2212    #ifdef HOST_LITTLE_ENDIAN
2213            int i, n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2214                & (ARM_IC_ENTRIES_PER_PAGE-1);
2215    
2216            if (n_back < 5)
2217                    return;
2218    
2219            for (i=-5; i<0; i++) {
2220                    if (ic[i].f != instr(load_w1_word_u1_p0_imm) ||
2221                        ic[i].arg[0] != (size_t)(&cpu->cd.arm.r[0]) ||
2222                        ic[i].arg[1] != 4)
2223                            return;
2224            }
2225    
2226            if (ic[-5].arg[2] == (size_t)(&cpu->cd.arm.r[10]) &&
2227                ic[-4].arg[2] == (size_t)(&cpu->cd.arm.r[11]) &&
2228                ic[-3].arg[2] == (size_t)(&cpu->cd.arm.r[6]) &&
2229                ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[7]) &&
2230                ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[8])) {
2231                    ic[-5].f = instr(netbsd_copyin);
2232            }
2233    #endif
2234    }
2235    
2236    
2237    /*
2238     *  Combine: netbsd_copyout():
2239     */
2240    void COMBINE(netbsd_copyout)(struct cpu *cpu,
2241            struct arm_instr_call *ic, int low_addr)
2242    {
2243    #ifdef HOST_LITTLE_ENDIAN
2244            int i, n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2245                & (ARM_IC_ENTRIES_PER_PAGE-1);
2246    
2247            if (n_back < 5)
2248                    return;
2249    
2250            for (i=-5; i<0; i++) {
2251                    if (ic[i].f != instr(store_w1_word_u1_p0_imm) ||
2252                        ic[i].arg[0] != (size_t)(&cpu->cd.arm.r[1]) ||
2253                        ic[i].arg[1] != 4)
2254                            return;
2255            }
2256    
2257            if (ic[-5].arg[2] == (size_t)(&cpu->cd.arm.r[8]) &&
2258                ic[-4].arg[2] == (size_t)(&cpu->cd.arm.r[9]) &&
2259                ic[-3].arg[2] == (size_t)(&cpu->cd.arm.r[10]) &&
2260                ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[11]) &&
2261                ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[6])) {
2262                    ic[-5].f = instr(netbsd_copyout);
2263            }
2264    #endif
2265    }
2266    
2267    
2268    /*
2269     *  Combine: cmps_b():
2270     */
2271    void COMBINE(cmps_b)(struct cpu *cpu,
2272            struct arm_instr_call *ic, int low_addr)
2273    {
2274            int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2275                & (ARM_IC_ENTRIES_PER_PAGE-1);
2276            if (n_back < 1)
2277                    return;
2278            if (ic[0].f == instr(b__eq)) {
2279                    if (ic[-1].f == instr(cmps)) {
2280                            if (ic[-1].arg[1] == 0)
2281                                    ic[-1].f = instr(cmps_0_beq);
2282                            else if (ic[-1].arg[1] & 0x80000000)
2283                                    ic[-1].f = instr(cmps_neg_beq);
2284                            else
2285                                    ic[-1].f = instr(cmps_pos_beq);
2286                  }                  }
2287                    return;
2288          }          }
2289            if (ic[0].f == instr(b_samepage__eq)) {
2290                    if (ic[-1].f == instr(cmps)) {
2291                            if (ic[-1].arg[1] == 0)
2292                                    ic[-1].f = instr(cmps0_beq_samepage);
2293                            else
2294                                    ic[-1].f = instr(cmps_beq_samepage);
2295                    }
2296                    if (ic[-1].f == instr(tsts) &&
2297                        !(ic[-1].arg[1] & 0x80000000)) {
2298                            ic[-1].f = instr(tsts_lo_beq_samepage);
2299                    }
2300                    if (ic[-1].f == instr(teqs)) {
2301                            ic[-1].f = instr(teqs_beq_samepage);
2302                    }
2303                    return;
2304            }
2305            if (ic[0].f == instr(b_samepage__ne)) {
2306                    if (ic[-1].f == instr(cmps)) {
2307                            if (ic[-1].arg[1] == 0)
2308                                    ic[-1].f = instr(cmps0_bne_samepage);
2309                            else
2310                                    ic[-1].f = instr(cmps_bne_samepage);
2311                    }
2312                    if (ic[-1].f == instr(tsts) &&
2313                        !(ic[-1].arg[1] & 0x80000000)) {
2314                            ic[-1].f = instr(tsts_lo_bne_samepage);
2315                    }
2316                    if (ic[-1].f == instr(teqs)) {
2317                            ic[-1].f = instr(teqs_bne_samepage);
2318                    }
2319                    return;
2320            }
2321            if (ic[0].f == instr(b_samepage__cc)) {
2322                    if (ic[-1].f == instr(cmps)) {
2323                            ic[-1].f = instr(cmps_bcc_samepage);
2324                    }
2325                    if (ic[-1].f == instr(cmps_regshort)) {
2326                            ic[-1].f = instr(cmps_reg_bcc_samepage);
2327                    }
2328                    return;
2329            }
2330            if (ic[0].f == instr(b_samepage__hi)) {
2331                    if (ic[-1].f == instr(cmps)) {
2332                            ic[-1].f = instr(cmps_bhi_samepage);
2333                    }
2334                    if (ic[-1].f == instr(cmps_regshort)) {
2335                            ic[-1].f = instr(cmps_reg_bhi_samepage);
2336                    }
2337                    return;
2338            }
2339            if (ic[0].f == instr(b_samepage__gt)) {
2340                    if (ic[-1].f == instr(cmps)) {
2341                            ic[-1].f = instr(cmps_bgt_samepage);
2342                    }
2343                    return;
2344            }
2345            if (ic[0].f == instr(b_samepage__le)) {
2346                    if (ic[-1].f == instr(cmps)) {
2347                            ic[-1].f = instr(cmps_ble_samepage);
2348                    }
2349                    return;
2350            }
2351    }
2352    
2353          /*  TODO: Combine forward as well  */  
2354    /*****************************************************************************/
2355    
2356    
2357    static void arm_switch_clear(struct arm_instr_call *ic, int rd,
2358            int condition_code)
2359    {
2360            switch (rd) {
2361            case  0: ic->f = cond_instr(clear_r0); break;
2362            case  1: ic->f = cond_instr(clear_r1); break;
2363            case  2: ic->f = cond_instr(clear_r2); break;
2364            case  3: ic->f = cond_instr(clear_r3); break;
2365            case  4: ic->f = cond_instr(clear_r4); break;
2366            case  5: ic->f = cond_instr(clear_r5); break;
2367            case  6: ic->f = cond_instr(clear_r6); break;
2368            case  7: ic->f = cond_instr(clear_r7); break;
2369            case  8: ic->f = cond_instr(clear_r8); break;
2370            case  9: ic->f = cond_instr(clear_r9); break;
2371            case 10: ic->f = cond_instr(clear_r10); break;
2372            case 11: ic->f = cond_instr(clear_r11); break;
2373            case 12: ic->f = cond_instr(clear_r12); break;
2374            case 13: ic->f = cond_instr(clear_r13); break;
2375            case 14: ic->f = cond_instr(clear_r14); break;
2376            }
2377    }
2378    
2379    
2380    static void arm_switch_mov1(struct arm_instr_call *ic, int rd,
2381            int condition_code)
2382    {
2383            switch (rd) {
2384            case  0: ic->f = cond_instr(mov1_r0); break;
2385            case  1: ic->f = cond_instr(mov1_r1); break;
2386            case  2: ic->f = cond_instr(mov1_r2); break;
2387            case  3: ic->f = cond_instr(mov1_r3); break;
2388            case  4: ic->f = cond_instr(mov1_r4); break;
2389            case  5: ic->f = cond_instr(mov1_r5); break;
2390            case  6: ic->f = cond_instr(mov1_r6); break;
2391            case  7: ic->f = cond_instr(mov1_r7); break;
2392            case  8: ic->f = cond_instr(mov1_r8); break;
2393            case  9: ic->f = cond_instr(mov1_r9); break;
2394            case 10: ic->f = cond_instr(mov1_r10); break;
2395            case 11: ic->f = cond_instr(mov1_r11); break;
2396            case 12: ic->f = cond_instr(mov1_r12); break;
2397            case 13: ic->f = cond_instr(mov1_r13); break;
2398            case 14: ic->f = cond_instr(mov1_r14); break;
2399            }
2400    }
2401    
2402    
2403    static void arm_switch_add1(struct arm_instr_call *ic, int rd,
2404            int condition_code)
2405    {
2406            switch (rd) {
2407            case  0: ic->f = cond_instr(add1_r0); break;
2408            case  1: ic->f = cond_instr(add1_r1); break;
2409            case  2: ic->f = cond_instr(add1_r2); break;
2410            case  3: ic->f = cond_instr(add1_r3); break;
2411            case  4: ic->f = cond_instr(add1_r4); break;
2412            case  5: ic->f = cond_instr(add1_r5); break;
2413            case  6: ic->f = cond_instr(add1_r6); break;
2414            case  7: ic->f = cond_instr(add1_r7); break;
2415            case  8: ic->f = cond_instr(add1_r8); break;
2416            case  9: ic->f = cond_instr(add1_r9); break;
2417            case 10: ic->f = cond_instr(add1_r10); break;
2418            case 11: ic->f = cond_instr(add1_r11); break;
2419            case 12: ic->f = cond_instr(add1_r12); break;
2420            case 13: ic->f = cond_instr(add1_r13); break;
2421            case 14: ic->f = cond_instr(add1_r14); break;
2422            }
2423  }  }
2424    
2425    
# Line 1339  X(to_be_translated) Line 2440  X(to_be_translated)
2440          unsigned char *page;          unsigned char *page;
2441          unsigned char ib[4];          unsigned char ib[4];
2442          int condition_code, main_opcode, secondary_opcode, s_bit, rn, rd, r8;          int condition_code, main_opcode, secondary_opcode, s_bit, rn, rd, r8;
2443          int p_bit, u_bit, b_bit, w_bit, l_bit, regform, rm, c, t;          int p_bit, u_bit, w_bit, l_bit, regform, rm, c, t, any_pc_reg;
         int any_pc_reg;  
2444          void (*samepage_function)(struct cpu *, struct arm_instr_call *);          void (*samepage_function)(struct cpu *, struct arm_instr_call *);
2445    
2446          /*  Figure out the address of the instruction:  */          /*  Figure out the address of the instruction:  */
2447          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)
2448              / sizeof(struct arm_instr_call);              / sizeof(struct arm_instr_call);
2449          addr = cpu->cd.arm.r[ARM_PC] & ~((ARM_IC_ENTRIES_PER_PAGE-1) <<          addr = cpu->pc & ~((ARM_IC_ENTRIES_PER_PAGE-1) <<
2450              ARM_INSTR_ALIGNMENT_SHIFT);              ARM_INSTR_ALIGNMENT_SHIFT);
2451          addr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          addr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
2452          cpu->pc = cpu->cd.arm.r[ARM_PC] = addr;          cpu->pc = addr;
2453          addr &= ~((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);          addr &= ~((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);
2454    
2455          /*  Read the instruction word from memory:  */          /*  Read the instruction word from memory:  */
2456          page = cpu->cd.arm.host_load[addr >> 12];          page = cpu->cd.arm.host_load[addr >> 12];
2457          if (page != NULL) {          if (page != NULL) {
2458                  /*  fatal("TRANSLATION HIT!\n");  */                  /*  fatal("TRANSLATION HIT! 0x%08x\n", addr);  */
2459                  memcpy(ib, page + (addr & 0xfff), sizeof(ib));                  memcpy(ib, page + (addr & 0xfff), sizeof(ib));
2460          } else {          } else {
2461                  /*  fatal("TRANSLATION MISS!\n");  */                  /*  fatal("TRANSLATION MISS! 0x%08x\n", addr);  */
2462                  if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],                  if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],
2463                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
2464                          fatal("to_be_translated(): "                          fatal("to_be_translated(): "
2465                              "read failed: TODO\n");                              "read failed: TODO\n");
2466                          goto bad;                          return;
2467                  }                  }
2468          }          }
2469    
# Line 1383  X(to_be_translated) Line 2483  X(to_be_translated)
2483          condition_code = iword >> 28;          condition_code = iword >> 28;
2484          main_opcode = (iword >> 24) & 15;          main_opcode = (iword >> 24) & 15;
2485          secondary_opcode = (iword >> 21) & 15;          secondary_opcode = (iword >> 21) & 15;
2486          u_bit = (iword >> 23) & 1;          u_bit = iword & 0x00800000;
2487          b_bit = (iword >> 22) & 1;          w_bit = iword & 0x00200000;
2488          w_bit = (iword >> 21) & 1;          s_bit = l_bit = iword & 0x00100000;
         s_bit = l_bit = (iword >> 20) & 1;  
2489          rn    = (iword >> 16) & 15;          rn    = (iword >> 16) & 15;
2490          rd    = (iword >> 12) & 15;          rd    = (iword >> 12) & 15;
2491          r8    = (iword >> 8) & 15;          r8    = (iword >> 8) & 15;
# Line 1451  X(to_be_translated) Line 2550  X(to_be_translated)
2550                          ic->arg[0] = iword;                          ic->arg[0] = iword;
2551                          break;                          break;
2552                  }                  }
2553                    if ((iword & 0x0f900ff0) == 0x01000050) {
2554                            fatal("TODO: q{,d}{add,sub}\n");
2555                            goto bad;
2556                    }
2557                  if ((iword & 0x0ff000d0) == 0x01200010) {                  if ((iword & 0x0ff000d0) == 0x01200010) {
2558                          /*  bx or blx  */                          /*  bx or blx  */
2559                          if (iword & 0x20)                          if (iword & 0x20)
# Line 1475  X(to_be_translated) Line 2578  X(to_be_translated)
2578                          ic->arg[2] = (size_t)(&cpu->cd.arm.r[rn]);                          ic->arg[2] = (size_t)(&cpu->cd.arm.r[rn]);
2579                          break;                          break;
2580                  }                  }
2581                    if ((iword & 0x0fff0ff0) == 0x016f0f10) {
2582                            ic->f = cond_instr(clz);
2583                            ic->arg[0] = (size_t)(&cpu->cd.arm.r[rm]);
2584                            ic->arg[1] = (size_t)(&cpu->cd.arm.r[rd]);
2585                            break;
2586                    }
2587                    if ((iword & 0x0ff00090) == 0x01000080) {
2588                            /*  TODO: smlaXX  */
2589                            goto bad;
2590                    }
2591                    if ((iword & 0x0ff00090) == 0x01400080) {
2592                            /*  TODO: smlalY  */
2593                            goto bad;
2594                    }
2595                    if ((iword & 0x0ff000b0) == 0x01200080) {
2596                            /*  TODO: smlawY  */
2597                            goto bad;
2598                    }
2599                    if ((iword & 0x0ff0f090) == 0x01600080) {
2600                            /*  smulXY (16-bit * 16-bit => 32-bit)  */
2601                            switch (iword & 0x60) {
2602                            case 0x00: ic->f = cond_instr(smulbb); break;
2603                            case 0x20: ic->f = cond_instr(smultb); break;
2604                            case 0x40: ic->f = cond_instr(smulbt); break;
2605                            default:   ic->f = cond_instr(smultt); break;
2606                            }
2607                            ic->arg[0] = (size_t)(&cpu->cd.arm.r[rm]);
2608                            ic->arg[1] = (size_t)(&cpu->cd.arm.r[r8]);
2609                            ic->arg[2] = (size_t)(&cpu->cd.arm.r[rn]); /*  Rd  */
2610                            break;
2611                    }
2612                    if ((iword & 0x0ff0f0b0) == 0x012000a0) {
2613                            /*  TODO: smulwY  */
2614                            goto bad;
2615                    }
2616                  if ((iword & 0x0fb0fff0) == 0x0120f000 ||                  if ((iword & 0x0fb0fff0) == 0x0120f000 ||
2617                      (iword & 0x0fb0f000) == 0x0320f000) {                      (iword & 0x0fb0f000) == 0x0320f000) {
2618                          /*  msr: move to [S|C]PSR from a register or                          /*  msr: move to [S|C]PSR from a register or
2619                              immediate value  */                              immediate value  */
                         if (rm == ARM_PC) {  
                                 fatal("msr PC?\n");  
                                 goto bad;  
                         }  
2620                          if (iword & 0x02000000) {                          if (iword & 0x02000000) {
2621                                  if (iword & 0x00400000)                                  if (iword & 0x00400000)
2622                                          ic->f = cond_instr(msr_imm_spsr);                                          ic->f = cond_instr(msr_imm_spsr);
2623                                  else                                  else
2624                                          ic->f = cond_instr(msr_imm);                                          ic->f = cond_instr(msr_imm);
2625                          } else {                          } else {
2626                                    if (rm == ARM_PC) {
2627                                            fatal("msr PC?\n");
2628                                            goto bad;
2629                                    }
2630                                  if (iword & 0x00400000)                                  if (iword & 0x00400000)
2631                                          ic->f = cond_instr(msr_spsr);                                          ic->f = cond_instr(msr_spsr);
2632                                  else                                  else
# Line 1561  X(to_be_translated) Line 2699  X(to_be_translated)
2699                          goto bad;                          goto bad;
2700                  }                  }
2701    
2702                  /*  "mov pc,lr" with trace enabled:  */                  /*  "mov pc,lr":  */
2703                  if ((iword & 0x0fffffff) == 0x01a0f00e &&                  if ((iword & 0x0fffffff) == 0x01a0f00e) {
2704                      cpu->machine->show_trace_tree) {                          if (cpu->machine->show_trace_tree)
2705                          ic->f = cond_instr(ret_trace);                                  ic->f = cond_instr(ret_trace);
2706                            else
2707                                    ic->f = cond_instr(ret);
2708                          break;                          break;
2709                  }                  }
2710    
2711                  /*  "mov reg,reg":  */                  /*  "mov reg,reg" or "mov reg,pc":  */
2712                  if ((iword & 0x0fff0ff0) == 0x01a00000 &&                  if ((iword & 0x0fff0ff0) == 0x01a00000 && rd != ARM_PC) {
2713                      (iword&15) != ARM_PC && rd != ARM_PC) {                          if (rm != ARM_PC) {
2714                          ic->f = cond_instr(mov_reg_reg);                                  ic->f = cond_instr(mov_reg_reg);
2715                          ic->arg[0] = (size_t)(&cpu->cd.arm.r[iword & 15]);                                  ic->arg[0] = (size_t)(&cpu->cd.arm.r[rm]);
2716                            } else {
2717                                    ic->f = cond_instr(mov_reg_pc);
2718                                    ic->arg[0] = (addr & 0xfff) + 8;
2719                            }
2720                          ic->arg[1] = (size_t)(&cpu->cd.arm.r[rd]);                          ic->arg[1] = (size_t)(&cpu->cd.arm.r[rd]);
2721                          break;                          break;
2722                  }                  }
2723    
2724                    /*  "mov reg,#0":  */
2725                    if ((iword & 0x0fff0fff) == 0x03a00000 && rd != ARM_PC) {
2726                            arm_switch_clear(ic, rd, condition_code);
2727                            break;
2728                    }
2729    
2730                    /*  "mov reg,#1":  */
2731                    if ((iword & 0x0fff0fff) == 0x03a00001 && rd != ARM_PC) {
2732                            arm_switch_mov1(ic, rd, condition_code);
2733                            break;
2734                    }
2735    
2736                    /*  "add reg,reg,#1":  */
2737                    if ((iword & 0x0ff00fff) == 0x02800001 && rd != ARM_PC
2738                        && rn == rd) {
2739                            arm_switch_add1(ic, rd, condition_code);
2740                            break;
2741                    }
2742    
2743                  /*                  /*
2744                   *  Generic Data Processing Instructions:                   *  Generic Data Processing Instructions:
2745                   */                   */
# Line 1604  X(to_be_translated) Line 2767  X(to_be_translated)
2767                          ic->arg[1] = imm;                          ic->arg[1] = imm;
2768                  }                  }
2769    
2770                    /*  mvn #imm ==> mov #~imm  */
2771                    if (secondary_opcode == 0xf && !regform) {
2772                            secondary_opcode = 0xd;
2773                            ic->arg[1] = ~ic->arg[1];
2774                    }
2775    
2776                  ic->arg[0] = (size_t)(&cpu->cd.arm.r[rn]);                  ic->arg[0] = (size_t)(&cpu->cd.arm.r[rn]);
2777                  ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);                  ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);
2778                  any_pc_reg = 0;                  any_pc_reg = 0;
2779                  if (rn == ARM_PC || rd == ARM_PC)                  if (rn == ARM_PC || rd == ARM_PC)
2780                          any_pc_reg = 1;                          any_pc_reg = 1;
2781    
2782                  ic->f = arm_dpi_instr[condition_code +                  if (!any_pc_reg && regform && (iword & 0xfff) < ARM_PC) {
2783                      16 * secondary_opcode + (s_bit? 256 : 0) +                          ic->arg[1] = (size_t)(&cpu->cd.arm.r[rm]);
2784                      (any_pc_reg? 512 : 0) + (regform? 1024 : 0)];                          ic->f = arm_dpi_instr_regshort[condition_code +
2785                                16 * secondary_opcode + (s_bit? 256 : 0)];
2786                    } else
2787                            ic->f = arm_dpi_instr[condition_code +
2788                                16 * secondary_opcode + (s_bit? 256 : 0) +
2789                                (any_pc_reg? 512 : 0) + (regform? 1024 : 0)];
2790    
2791                    if (ic->f == instr(eor_regshort))
2792                            cpu->cd.arm.combination_check = COMBINE(xchg);
2793                    if (iword == 0xe113000c)
2794                            cpu->cd.arm.combination_check = COMBINE(netbsd_scanc);
2795                  break;                  break;
2796    
2797          case 0x4:       /*  Load and store...  */          case 0x4:       /*  Load and store...  */
# Line 1641  X(to_be_translated) Line 2820  X(to_be_translated)
2820                          fatal("Not a Load/store TODO\n");                          fatal("Not a Load/store TODO\n");
2821                          goto bad;                          goto bad;
2822                  }                  }
2823                    /*  Special case: pc-relative load within the same page:  */
2824                    if (rn == ARM_PC && rd != ARM_PC && main_opcode < 6) {
2825                            int ofs = (addr & 0xfff) + 8, max = 0xffc;
2826                            int b_bit = iword & 0x00400000;
2827                            if (b_bit)
2828                                    max = 0xfff;
2829                            if (u_bit)
2830                                    ofs += (iword & 0xfff);
2831                            else
2832                                    ofs -= (iword & 0xfff);
2833                            /*  NOTE/TODO: This assumes 4KB pages,
2834                                it will not work with 1KB pages.  */
2835                            if (ofs >= 0 && ofs <= max) {
2836                                    unsigned char *p;
2837                                    unsigned char c[4];
2838                                    int len = b_bit? 1 : 4;
2839                                    uint32_t x, a = (addr & 0xfffff000) | ofs;
2840                                    /*  ic->f = cond_instr(mov);  */
2841                                    ic->f = arm_dpi_instr[condition_code + 16*0xd];
2842                                    ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);
2843                                    p = cpu->cd.arm.host_load[a >> 12];
2844                                    if (p != NULL) {
2845                                            memcpy(c, p + (a & 0xfff), len);
2846                                    } else {
2847                                            if (!cpu->memory_rw(cpu, cpu->mem, a,
2848                                                c, len, MEM_READ, CACHE_DATA)) {
2849                                                    fatal("to_be_translated(): "
2850                                                        "read failed X: TODO\n");
2851                                                    goto bad;
2852                                            }
2853                                    }
2854                                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2855                                            x = c[0] + (c[1]<<8) +
2856                                                (c[2]<<16) + (c[3]<<24);
2857                                    else
2858                                            x = c[3] + (c[2]<<8) +
2859                                                (c[1]<<16) + (c[0]<<24);
2860                                    if (b_bit)
2861                                            x = c[0];
2862                                    ic->arg[1] = x;
2863                            }
2864                    }
2865                    if (iword == 0xe4b09004)
2866                            cpu->cd.arm.combination_check = COMBINE(netbsd_copyin);
2867                    if (iword == 0xe4a17004)
2868                            cpu->cd.arm.combination_check = COMBINE(netbsd_copyout);
2869                  break;                  break;
2870    
2871          case 0x8:       /*  Multiple load/store...  (Block data transfer)  */          case 0x8:       /*  Multiple load/store...  (Block data transfer)  */
2872          case 0x9:       /*  xxxx100P USWLnnnn llllllll llllllll  */          case 0x9:       /*  xxxx100P USWLnnnn llllllll llllllll  */
2873                    ic->arg[0] = (size_t)(&cpu->cd.arm.r[rn]);
2874                    ic->arg[1] = (size_t)iword;
2875                    /*  Generic case:  */
2876                  if (l_bit)                  if (l_bit)
2877                          ic->f = cond_instr(bdt_load);                          ic->f = cond_instr(bdt_load);
2878                  else                  else
2879                          ic->f = cond_instr(bdt_store);                          ic->f = cond_instr(bdt_store);
2880                  ic->arg[0] = (size_t)(&cpu->cd.arm.r[rn]);  #if defined(HOST_LITTLE_ENDIAN) && !defined(GATHER_BDT_STATISTICS)
2881                  ic->arg[1] = (size_t)iword;                  /*
2882                     *  Check for availability of optimized implementation:
2883                     *  xxxx100P USWLnnnn llllllll llllllll
2884                     *           ^  ^ ^ ^        ^  ^ ^ ^   (0x00950154)
2885                     *  These bits are used to select which list to scan, and then
2886                     *  the list is scanned linearly.
2887                     *
2888                     *  The optimized functions do not support show_trace_tree,
2889                     *  but it's ok to use the unoptimized version in that case.
2890                     */
2891                    if (!cpu->machine->show_trace_tree) {
2892                            int i = 0, j = iword;
2893                            j = ((j & 0x00800000) >> 16) | ((j & 0x00100000) >> 14)
2894                              | ((j & 0x00040000) >> 13) | ((j & 0x00010000) >> 12)
2895                              | ((j & 0x00000100) >>  5) | ((j & 0x00000040) >>  4)
2896                              | ((j & 0x00000010) >>  3) | ((j & 0x00000004) >>  2);
2897                            while (multi_opcode[j][i] != 0) {
2898                                    if ((iword & 0x0fffffff) ==
2899                                        multi_opcode[j][i]) {
2900                                            ic->f = multi_opcode_f[j]
2901                                                [i*16 + condition_code];
2902                                            break;
2903                                    }
2904                                    i ++;
2905                            }
2906                    }
2907    #endif
2908                  if (rn == ARM_PC) {                  if (rn == ARM_PC) {
2909                          fatal("TODO: bdt with PC as base\n");                          fatal("TODO: bdt with PC as base\n");
2910                          goto bad;                          goto bad;
# Line 1662  X(to_be_translated) Line 2916  X(to_be_translated)
2916                  if (main_opcode == 0x0a) {                  if (main_opcode == 0x0a) {
2917                          ic->f = cond_instr(b);                          ic->f = cond_instr(b);
2918                          samepage_function = cond_instr(b_samepage);                          samepage_function = cond_instr(b_samepage);
2919                            if (iword == 0xcaffffed)
2920                                    cpu->cd.arm.combination_check =
2921                                        COMBINE(netbsd_memset);
2922                            if (iword == 0xaafffff9)
2923                                    cpu->cd.arm.combination_check =
2924                                        COMBINE(netbsd_memcpy);
2925                  } else {                  } else {
2926                          if (cpu->machine->show_trace_tree) {                          if (cpu->machine->show_trace_tree) {
2927                                  ic->f = cond_instr(bl_trace);                                  ic->f = cond_instr(bl_trace);
# Line 1673  X(to_be_translated) Line 2933  X(to_be_translated)
2933                          }                          }
2934                  }                  }
2935    
2936                    /*  arg 1 = offset of current instruction  */
2937                    /*  arg 2 = offset of the following instruction  */
2938                    ic->arg[1] = addr & 0xffc;
2939                    ic->arg[2] = (addr & 0xffc) + 4;
2940    
2941                  ic->arg[0] = (iword & 0x00ffffff) << 2;                  ic->arg[0] = (iword & 0x00ffffff) << 2;
2942                  /*  Sign-extend:  */                  /*  Sign-extend:  */
2943                  if (ic->arg[0] & 0x02000000)                  if (ic->arg[0] & 0x02000000)
# Line 1682  X(to_be_translated) Line 2947  X(to_be_translated)
2947                   */                   */
2948                  ic->arg[0] = (int32_t)(ic->arg[0] + 8);                  ic->arg[0] = (int32_t)(ic->arg[0] + 8);
2949    
2950                  /*  Special case: branch within the same page:  */                  /*
2951                     *  Special case: branch within the same page:
2952                     *
2953                     *  arg[0] = addr of the arm_instr_call of the target
2954                     *  arg[1] = addr of the next arm_instr_call.
2955                     */
2956                  {                  {
2957                          uint32_t mask_within_page =                          uint32_t mask_within_page =
2958                              ((ARM_IC_ENTRIES_PER_PAGE-1) <<                              ((ARM_IC_ENTRIES_PER_PAGE-1) <<
# Line 1697  X(to_be_translated) Line 2967  X(to_be_translated)
2967                                      cpu->cd.arm.cur_ic_page +                                      cpu->cd.arm.cur_ic_page +
2968                                      ((new_pc & mask_within_page) >>                                      ((new_pc & mask_within_page) >>
2969                                      ARM_INSTR_ALIGNMENT_SHIFT));                                      ARM_INSTR_ALIGNMENT_SHIFT));
2970                                    ic->arg[1] = (size_t) (
2971                                        cpu->cd.arm.cur_ic_page +
2972                                        (((addr & mask_within_page) + 4) >>
2973                                        ARM_INSTR_ALIGNMENT_SHIFT));
2974                            } else if (main_opcode == 0x0a) {
2975                                    /*  Special hack for a plain "b":  */
2976                                    ic->arg[0] += ic->arg[1];
2977                          }                          }
2978                  }                  }
2979    
2980                    if (main_opcode == 0xa && (condition_code <= 1
2981                        || condition_code == 3 || condition_code == 8
2982                        || condition_code == 12 || condition_code == 13))
2983                            cpu->cd.arm.combination_check = COMBINE(cmps_b);
2984    
2985                    if (iword == 0x1afffffc)
2986                            cpu->cd.arm.combination_check = COMBINE(strlen);
2987    
2988                    /*  Hm. Does this really increase performance?  */
2989                    if (iword == 0x8afffffa)
2990                            cpu->cd.arm.combination_check =
2991                                COMBINE(netbsd_cacheclean2);
2992                    break;
2993    
2994            case 0xc:
2995            case 0xd:
2996                    /*
2997                     *  xxxx1100 0100nnnn ddddcccc oooommmm    MCRR c,op,Rd,Rn,CRm
2998                     *  xxxx1100 0101nnnn ddddcccc oooommmm    MRRC c,op,Rd,Rn,CRm
2999                     */
3000                    if ((iword & 0x0fe00fff) == 0x0c400000) {
3001                            /*  Special case: mar/mra DSP instructions  */
3002                            fatal("TODO: mar/mra DSP instructions!\n");
3003                            /*  Perhaps these are actually identical to MCRR/MRRC */
3004                            goto bad;
3005                    }
3006    
3007                    if ((iword & 0x0fe00000) == 0x0c400000) {
3008                            fatal("MCRR/MRRC: TODO\n");
3009                            goto bad;
3010                    }
3011    
3012                    /*
3013                     *  TODO: LDC/STC
3014                     *
3015                     *  For now, treat as Undefined instructions. This causes e.g.
3016                     *  Linux/ARM to emulate these instructions (floating point).
3017                     */
3018    #if 0
3019                    ic->f = cond_instr(und);
3020                    ic->arg[0] = addr & 0xfff;
3021    #else
3022                    fatal("LDC/STC: TODO\n");
3023                    goto bad;
3024    #endif
3025                  break;                  break;
3026    
3027          case 0xe:          case 0xe:
3028                    if ((iword & 0x0ff00ff0) == 0x0e200010) {
3029                            /*  Special case: mia* DSP instructions  */
3030                            /*  See Intel's 27343601.pdf, page 16-20  */
3031                            fatal("TODO: mia* DSP instructions!\n");
3032                            goto bad;
3033                    }
3034                  if (iword & 0x10) {                  if (iword & 0x10) {
3035                          /*  xxxx1110 oooLNNNN ddddpppp qqq1MMMM  MCR/MRC  */                          /*  xxxx1110 oooLNNNN ddddpppp qqq1MMMM  MCR/MRC  */
3036                          ic->arg[0] = iword;                          ic->arg[0] = iword;
# Line 1711  X(to_be_translated) Line 3040  X(to_be_translated)
3040                          ic->arg[0] = iword;                          ic->arg[0] = iword;
3041                          ic->f = cond_instr(cdp);                          ic->f = cond_instr(cdp);
3042                  }                  }
3043                    if (iword == 0xee070f9a)
3044                            cpu->cd.arm.combination_check =
3045                                COMBINE(netbsd_cacheclean);
3046                  break;                  break;
3047    
3048          case 0xf:          case 0xf:
3049                  /*  SWI:  */                  /*  SWI:  */
3050                  /*  Default handler:  */                  /*  Default handler:  */
3051                  ic->f = cond_instr(swi);                  ic->f = cond_instr(swi);
3052                  if (iword == 0xef8c64be) {                  ic->arg[0] = addr & 0xfff;
3053                    if (iword == 0xef8c64eb) {
3054                            /*  Hack for rebooting a machine:  */
3055                            ic->f = instr(reboot);
3056                    } else if (iword == 0xef8c64be) {
3057                          /*  Hack for openfirmware prom emulation:  */                          /*  Hack for openfirmware prom emulation:  */
3058                          ic->f = instr(openfirmware);                          ic->f = instr(openfirmware);
3059                  } else if (cpu->machine->userland_emul != NULL) {                  } else if (cpu->machine->userland_emul != NULL) {

Legend:
Removed from v.16  
changed lines
  Added in v.30

  ViewVC Help
Powered by ViewVC 1.1.26