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

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

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

revision 18 by dpavlin, Mon Oct 8 16:19:11 2007 UTC revision 32 by dpavlin, Mon Oct 8 16:20:58 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2006  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_arm_instr.c,v 1.39 2005/10/27 14:01:13 debug Exp $   *  $Id: cpu_arm_instr.c,v 1.69 2006/09/09 09:04:32 debug Exp $
29   *   *
30   *  ARM instructions.   *  ARM instructions.
31   *   *
# Line 33  Line 33 
33   *  (If no instruction was executed, then it should be decreased. If, say, 4   *  (If no instruction was executed, then it should be decreased. If, say, 4
34   *  instructions were combined into one function and executed, then it should   *  instructions were combined into one function and executed, then it should
35   *  be increased by 3.)   *  be increased by 3.)
36     *
37     *  Note: cpu->pc is prefered over r[ARM_PC]. r[ARM_PC] is only used in a
38     *        few places, and should always be kept in synch with the real
39     *        program counter.
40   */   */
41    
42    
 #include "arm_quick_pc_to_pointers.h"  
   
43  /*  #define GATHER_BDT_STATISTICS  */  /*  #define GATHER_BDT_STATISTICS  */
44    
45    
# Line 125  static void update_bdt_statistics(uint32 Line 127  static void update_bdt_statistics(uint32
127   *  functions, otherwise they will simply call the X function.   *  functions, otherwise they will simply call the X function.
128   */   */
129    
130    uint8_t condition_hi[16] = { 0,0,1,1, 0,0,0,0, 0,0,1,1, 0,0,0,0 };
131    uint8_t condition_ge[16] = { 1,0,1,0, 1,0,1,0, 0,1,0,1, 0,1,0,1 };
132    uint8_t condition_gt[16] = { 1,0,1,0, 0,0,0,0, 0,1,0,1, 0,0,0,0 };
133    
134  #define Y(n) void arm_instr_ ## n ## __eq(struct cpu *cpu,              \  #define Y(n) void arm_instr_ ## n ## __eq(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 ## __ne(struct cpu *cpu,                   \          void arm_instr_ ## n ## __ne(struct cpu *cpu,                   \
139                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
140          {  if (!(cpu->cd.arm.cpsr & ARM_FLAG_Z))                        \          {  if (!(cpu->cd.arm.flags & ARM_F_Z))                          \
141                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
142          void arm_instr_ ## n ## __cs(struct cpu *cpu,                   \          void arm_instr_ ## n ## __cs(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 ## __cc(struct cpu *cpu,                   \          void arm_instr_ ## n ## __cc(struct cpu *cpu,                   \
147                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
148          {  if (!(cpu->cd.arm.cpsr & ARM_FLAG_C))                        \          {  if (!(cpu->cd.arm.flags & ARM_F_C))                          \
149                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
150          void arm_instr_ ## n ## __mi(struct cpu *cpu,                   \          void arm_instr_ ## n ## __mi(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 ## __pl(struct cpu *cpu,                   \          void arm_instr_ ## n ## __pl(struct cpu *cpu,                   \
155                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
156          {  if (!(cpu->cd.arm.cpsr & ARM_FLAG_N))                        \          {  if (!(cpu->cd.arm.flags & ARM_F_N))                          \
157                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
158          void arm_instr_ ## n ## __vs(struct cpu *cpu,                   \          void arm_instr_ ## n ## __vs(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 ## __vc(struct cpu *cpu,                   \          void arm_instr_ ## n ## __vc(struct cpu *cpu,                   \
163                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
164          {  if (!(cpu->cd.arm.cpsr & ARM_FLAG_V))                        \          {  if (!(cpu->cd.arm.flags & ARM_F_V))                          \
165                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
166          void arm_instr_ ## n ## __hi(struct cpu *cpu,                   \          void arm_instr_ ## n ## __hi(struct cpu *cpu,                   \
167                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
168          {  if (cpu->cd.arm.cpsr & ARM_FLAG_C &&                         \          {  if (condition_hi[cpu->cd.arm.flags])                         \
                 !(cpu->cd.arm.cpsr & ARM_FLAG_Z))                       \  
169                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
170          void arm_instr_ ## n ## __ls(struct cpu *cpu,                   \          void arm_instr_ ## n ## __ls(struct cpu *cpu,                   \
171                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
172          {  if (cpu->cd.arm.cpsr & ARM_FLAG_Z ||                         \          {  if (!condition_hi[cpu->cd.arm.flags])                        \
                 !(cpu->cd.arm.cpsr & ARM_FLAG_C))                       \  
173                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
174          void arm_instr_ ## n ## __ge(struct cpu *cpu,                   \          void arm_instr_ ## n ## __ge(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 ## __lt(struct cpu *cpu,                   \          void arm_instr_ ## n ## __lt(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_ge[cpu->cd.arm.flags])                        \
                 ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0))                  \  
181                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
182          void arm_instr_ ## n ## __gt(struct cpu *cpu,                   \          void arm_instr_ ## n ## __gt(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_instr_ ## n ## __le(struct cpu *cpu,                   \          void arm_instr_ ## n ## __le(struct cpu *cpu,                   \
187                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
188          {  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))                        \  
189                  arm_instr_ ## n (cpu, ic);              }               \                  arm_instr_ ## n (cpu, ic);              }               \
190          void (*arm_cond_instr_ ## n  [16])(struct cpu *,                \          void (*arm_cond_instr_ ## n  [16])(struct cpu *,                \
191                          struct arm_instr_call *) = {                    \                          struct arm_instr_call *) = {                    \
# Line 207  static void update_bdt_statistics(uint32 Line 205  static void update_bdt_statistics(uint32
205    
206    
207  /*  /*
  *  nop:  Do nothing.  
208   *  invalid:  Invalid instructions end up here.   *  invalid:  Invalid instructions end up here.
209   */   */
 X(nop) { }  
210  X(invalid) {  X(invalid) {
211          uint32_t low_pc;          uint32_t low_pc;
212          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
213              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
214          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
215              << ARM_INSTR_ALIGNMENT_SHIFT);              << ARM_INSTR_ALIGNMENT_SHIFT);
216          cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
         cpu->pc = cpu->cd.arm.r[ARM_PC];  
217    
218          fatal("Invalid ARM instruction: pc=0x%08x\n", (int)cpu->pc);          fatal("FATAL ERROR: An internal error occured in the ARM"
219                " dyntrans code. Please contact the author with detailed"
220                " repro steps on how to trigger this bug. pc = 0x%08"PRIx32"\n",
221                (uint32_t)cpu->pc);
222    
         cpu->running = 0;  
         cpu->running_translated = 0;  
         cpu->n_translated_instrs --;  
223          cpu->cd.arm.next_ic = &nothing_call;          cpu->cd.arm.next_ic = &nothing_call;
224  }  }
225    
226    
227  /*  /*
228     *  nop:  Do nothing.
229     */
230    X(nop)
231    {
232    }
233    
234    
235    /*
236   *  b:  Branch (to a different translated page)   *  b:  Branch (to a different translated page)
237   *   *
238   *  arg[0] = relative offset   *  arg[0] = relative offset
239   */   */
240  X(b)  X(b)
241  {  {
242          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];  
243    
244          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
245          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
# Line 257  Y(b) Line 251  Y(b)
251   *  b_samepage:  Branch (to within the same translated page)   *  b_samepage:  Branch (to within the same translated page)
252   *   *
253   *  arg[0] = pointer to new arm_instr_call   *  arg[0] = pointer to new arm_instr_call
254     *  arg[1] = pointer to the next instruction.
255     *
256     *  NOTE: This instruction is manually inlined.
257   */   */
258  X(b_samepage)  X(b_samepage) {
 {  
259          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
260  }  }
261  Y(b_samepage)  X(b_samepage__eq) {
262            cpu->cd.arm.next_ic = (struct arm_instr_call *)
263                ic->arg[cpu->cd.arm.flags & ARM_F_Z? 0 : 1];
264    }
265    X(b_samepage__ne) {
266            cpu->cd.arm.next_ic = (struct arm_instr_call *)
267                ic->arg[cpu->cd.arm.flags & ARM_F_Z? 1 : 0];
268    }
269    X(b_samepage__cs) {
270            cpu->cd.arm.next_ic = (struct arm_instr_call *)
271                ic->arg[cpu->cd.arm.flags & ARM_F_C? 0 : 1];
272    }
273    X(b_samepage__cc) {
274            cpu->cd.arm.next_ic = (struct arm_instr_call *)
275                ic->arg[cpu->cd.arm.flags & ARM_F_C? 1 : 0];
276    }
277    X(b_samepage__mi) {
278            cpu->cd.arm.next_ic = (struct arm_instr_call *)
279                ic->arg[cpu->cd.arm.flags & ARM_F_N? 0 : 1];
280    }
281    X(b_samepage__pl) {
282            cpu->cd.arm.next_ic = (struct arm_instr_call *)
283                ic->arg[cpu->cd.arm.flags & ARM_F_N? 1 : 0];
284    }
285    X(b_samepage__vs) {
286            cpu->cd.arm.next_ic = (struct arm_instr_call *)
287                ic->arg[cpu->cd.arm.flags & ARM_F_V? 0 : 1];
288    }
289    X(b_samepage__vc) {
290            cpu->cd.arm.next_ic = (struct arm_instr_call *)
291                ic->arg[cpu->cd.arm.flags & ARM_F_V? 1 : 0];
292    }
293    X(b_samepage__hi) {
294            cpu->cd.arm.next_ic = (condition_hi[cpu->cd.arm.flags])?
295                (struct arm_instr_call *) ic->arg[0] :
296                (struct arm_instr_call *) ic->arg[1];
297    }
298    X(b_samepage__ls) {
299            cpu->cd.arm.next_ic = (struct arm_instr_call *)
300                ic->arg[condition_hi[cpu->cd.arm.flags]];
301    }
302    X(b_samepage__ge) {
303            cpu->cd.arm.next_ic = (condition_ge[cpu->cd.arm.flags])?
304                (struct arm_instr_call *) ic->arg[0] :
305                (struct arm_instr_call *) ic->arg[1];
306    }
307    X(b_samepage__lt) {
308            cpu->cd.arm.next_ic = (struct arm_instr_call *)
309                ic->arg[condition_ge[cpu->cd.arm.flags]];
310    }
311    X(b_samepage__gt) {
312            cpu->cd.arm.next_ic = (condition_gt[cpu->cd.arm.flags])?
313                (struct arm_instr_call *) ic->arg[0] :
314                (struct arm_instr_call *) ic->arg[1];
315    }
316    X(b_samepage__le) {
317            cpu->cd.arm.next_ic = (struct arm_instr_call *)
318                ic->arg[condition_gt[cpu->cd.arm.flags]];
319    }
320    void (*arm_cond_instr_b_samepage[16])(struct cpu *,
321            struct arm_instr_call *) = {
322            arm_instr_b_samepage__eq, arm_instr_b_samepage__ne,
323            arm_instr_b_samepage__cs, arm_instr_b_samepage__cc,
324            arm_instr_b_samepage__mi, arm_instr_b_samepage__pl,
325            arm_instr_b_samepage__vs, arm_instr_b_samepage__vc,
326            arm_instr_b_samepage__hi, arm_instr_b_samepage__ls,
327            arm_instr_b_samepage__ge, arm_instr_b_samepage__lt,
328            arm_instr_b_samepage__gt, arm_instr_b_samepage__le,
329            arm_instr_b_samepage, arm_instr_nop };
330    
331    
332  /*  /*
# Line 272  Y(b_samepage) Line 336  Y(b_samepage)
336   */   */
337  X(bx)  X(bx)
338  {  {
339          cpu->pc = cpu->cd.arm.r[ARM_PC] = reg(ic->arg[0]);          cpu->pc = reg(ic->arg[0]);
340          if (cpu->pc & 1) {          if (cpu->pc & 1) {
341                  fatal("thumb: TODO\n");                  fatal("thumb: TODO\n");
342                  exit(1);                  exit(1);
# Line 292  Y(bx) Line 356  Y(bx)
356   */   */
357  X(bx_trace)  X(bx_trace)
358  {  {
359          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
360          if (cpu->pc & 1) {          if (cpu->pc & 1) {
361                  fatal("thumb: TODO\n");                  fatal("thumb: TODO\n");
362                  exit(1);                  exit(1);
# Line 314  Y(bx_trace) Line 378  Y(bx_trace)
378   */   */
379  X(bl)  X(bl)
380  {  {
381          uint32_t lr, low_pc;          uint32_t pc = ((uint32_t)cpu->pc & 0xfffff000) + (int32_t)ic->arg[1];
382            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;  
383    
384          /*  Calculate new PC from this instruction + arg[0]  */          /*  Calculate new PC from this instruction + arg[0]  */
385          cpu->pc = cpu->cd.arm.r[ARM_PC] = lr - 4 + (int32_t)ic->arg[0];          cpu->pc = pc + (int32_t)ic->arg[0];
386    
387          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
388          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
# Line 342  Y(bl) Line 397  Y(bl)
397   */   */
398  X(blx)  X(blx)
399  {  {
400          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:  */  
401          cpu->cd.arm.r[ARM_LR] = lr;          cpu->cd.arm.r[ARM_LR] = lr;
402            cpu->pc = reg(ic->arg[0]);
         cpu->pc = cpu->cd.arm.r[ARM_PC] = reg(ic->arg[0]);  
403          if (cpu->pc & 1) {          if (cpu->pc & 1) {
404                  fatal("thumb: TODO\n");                  fatal("thumb: TODO\n");
405                  exit(1);                  exit(1);
# Line 374  Y(blx) Line 419  Y(blx)
419   */   */
420  X(bl_trace)  X(bl_trace)
421  {  {
422          uint32_t lr, low_pc;          uint32_t pc = ((uint32_t)cpu->pc & 0xfffff000) + (int32_t)ic->arg[1];
423            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;  
424    
425          /*  Calculate new PC from this instruction + arg[0]  */          /*  Calculate new PC from this instruction + arg[0]  */
426          cpu->pc = cpu->cd.arm.r[ARM_PC] = lr - 4 + (int32_t)ic->arg[0];          cpu->pc = pc + (int32_t)ic->arg[0];
427    
428          cpu_functioncall_trace(cpu, cpu->pc);          cpu_functioncall_trace(cpu, cpu->pc);
429    
# Line 404  Y(bl_trace) Line 440  Y(bl_trace)
440   */   */
441  X(bl_samepage)  X(bl_samepage)
442  {  {
443          uint32_t lr, low_pc;          cpu->cd.arm.r[ARM_LR] =
444                ((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:  */  
445          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
446  }  }
447  Y(bl_samepage)  Y(bl_samepage)
# Line 429  Y(bl_samepage) Line 454  Y(bl_samepage)
454   */   */
455  X(bl_samepage_trace)  X(bl_samepage_trace)
456  {  {
457          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);  
458    
459          /*  Link:  */          /*  Link and branch:  */
460          cpu->cd.arm.r[ARM_LR] = lr;          cpu->cd.arm.r[ARM_LR] = lr;
   
         /*  Branch:  */  
461          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];          cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
462    
463            /*  Synchronize the program counter:  */
464          low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)          low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)
465              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
466          tmp_pc = cpu->cd.arm.r[ARM_PC];          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
         tmp_pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)  
467              << ARM_INSTR_ALIGNMENT_SHIFT);              << ARM_INSTR_ALIGNMENT_SHIFT);
468          tmp_pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
469          cpu_functioncall_trace(cpu, tmp_pc);  
470            /*  ... and show trace:  */
471            cpu_functioncall_trace(cpu, cpu->pc);
472  }  }
473  Y(bl_samepage_trace)  Y(bl_samepage_trace)
474    
475    
476  #include "cpu_arm_instr_misc.c"  /*
477     *  clz: Count leading zeroes.
478     *
479     *  arg[0] = ptr to rm
480     *  arg[1] = ptr to rd
481     */
482    X(clz)
483    {
484            uint32_t rm = reg(ic->arg[0]);
485            int i = 32, n = 0, j;
486            while (i>0) {
487                    if (rm & 0xff000000) {
488                            for (j=0; j<8; j++) {
489                                    if (rm & 0x80000000)
490                                            break;
491                                    n ++;
492                                    rm <<= 1;
493                            }
494                            break;
495                    } else {
496                            rm <<= 8;
497                            i -= 8;
498                            n += 8;
499                    }
500            }
501            reg(ic->arg[1]) = n;
502    }
503    Y(clz)
504    
505    
506  /*  /*
# Line 474  X(muls) Line 519  X(muls)
519  {  {
520          uint32_t result;          uint32_t result;
521          result = reg(ic->arg[1]) * reg(ic->arg[2]);          result = reg(ic->arg[1]) * reg(ic->arg[2]);
522          cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N);          cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
523          if (result == 0)          if (result == 0)
524                  cpu->cd.arm.cpsr |= ARM_FLAG_Z;                  cpu->cd.arm.flags |= ARM_F_Z;
525          if (result & 0x80000000)          if (result & 0x80000000)
526                  cpu->cd.arm.cpsr |= ARM_FLAG_N;                  cpu->cd.arm.flags |= ARM_F_N;
527          reg(ic->arg[0]) = result;          reg(ic->arg[0]) = result;
528  }  }
529  Y(muls)  Y(muls)
# Line 509  X(mlas) Line 554  X(mlas)
554          rs = (iw >> 8) & 15;  rm = iw & 15;          rs = (iw >> 8) & 15;  rm = iw & 15;
555          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]
556              + cpu->cd.arm.r[rn];              + cpu->cd.arm.r[rn];
557          cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N);          cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
558          if (cpu->cd.arm.r[rd] == 0)          if (cpu->cd.arm.r[rd] == 0)
559                  cpu->cd.arm.cpsr |= ARM_FLAG_Z;                  cpu->cd.arm.flags |= ARM_F_Z;
560          if (cpu->cd.arm.r[rd] & 0x80000000)          if (cpu->cd.arm.r[rd] & 0x80000000)
561                  cpu->cd.arm.cpsr |= ARM_FLAG_N;                  cpu->cd.arm.flags |= ARM_F_N;
562  }  }
563  Y(mlas)  Y(mlas)
564    
# Line 528  X(mull) Line 573  X(mull)
573          /*  xxxx0000 1UAShhhh llllssss 1001mmmm  */          /*  xxxx0000 1UAShhhh llllssss 1001mmmm  */
574          uint32_t iw; uint64_t tmp; int u_bit, a_bit;          uint32_t iw; uint64_t tmp; int u_bit, a_bit;
575          iw = ic->arg[0];          iw = ic->arg[0];
576          u_bit = (iw >> 22) & 1; a_bit = (iw >> 21) & 1;          u_bit = iw & 0x00400000; a_bit = iw & 0x00200000;
577          tmp = cpu->cd.arm.r[iw & 15];          tmp = cpu->cd.arm.r[iw & 15];
578          if (u_bit)          if (u_bit)
579                  tmp = (int64_t)(int32_t)tmp                  tmp = (int64_t)(int32_t)tmp
# Line 550  Y(mull) Line 595  Y(mull)
595    
596    
597  /*  /*
598     *  smulXY:  16-bit * 16-bit multiplication (32-bit result)
599     *
600     *  arg[0] = ptr to rm
601     *  arg[1] = ptr to rs
602     *  arg[2] = ptr to rd
603     */
604    X(smulbb)
605    {
606            reg(ic->arg[2]) = (int32_t)(int16_t)reg(ic->arg[0]) *
607                (int32_t)(int16_t)reg(ic->arg[1]);
608    }
609    Y(smulbb)
610    X(smultb)
611    {
612            reg(ic->arg[2]) = (int32_t)(int16_t)(reg(ic->arg[0]) >> 16) *
613                (int32_t)(int16_t)reg(ic->arg[1]);
614    }
615    Y(smultb)
616    X(smulbt)
617    {
618            reg(ic->arg[2]) = (int32_t)(int16_t)reg(ic->arg[0]) *
619                (int32_t)(int16_t)(reg(ic->arg[1]) >> 16);
620    }
621    Y(smulbt)
622    X(smultt)
623    {
624            reg(ic->arg[2]) = (int32_t)(int16_t)(reg(ic->arg[0]) >> 16) *
625                (int32_t)(int16_t)(reg(ic->arg[1]) >> 16);
626    }
627    Y(smultt)
628    
629    
630    /*
631   *  mov_reg_reg:  Move a register to another.   *  mov_reg_reg:  Move a register to another.
632   *   *
633   *  arg[0] = ptr to source register   *  arg[0] = ptr to source register
# Line 563  Y(mov_reg_reg) Line 641  Y(mov_reg_reg)
641    
642    
643  /*  /*
644     *  mov_reg_pc:  Move the PC register to a normal register.
645     *
646     *  arg[0] = offset compared to start of current page + 8
647     *  arg[1] = ptr to destination register
648     */
649    X(mov_reg_pc)
650    {
651            reg(ic->arg[1]) = ((uint32_t)cpu->pc&0xfffff000) + (int32_t)ic->arg[0];
652    }
653    Y(mov_reg_pc)
654    
655    
656    /*
657   *  ret_trace:  "mov pc,lr" with trace enabled   *  ret_trace:  "mov pc,lr" with trace enabled
658   *  ret:  "mov pc,lr" without trace enabled   *  ret:  "mov pc,lr" without trace enabled
659   *   *
# Line 571  Y(mov_reg_reg) Line 662  Y(mov_reg_reg)
662  X(ret_trace)  X(ret_trace)
663  {  {
664          uint32_t old_pc, mask_within_page;          uint32_t old_pc, mask_within_page;
665          old_pc = cpu->cd.arm.r[ARM_PC];          old_pc = cpu->pc;
666          mask_within_page = ((ARM_IC_ENTRIES_PER_PAGE-1)          mask_within_page = ((ARM_IC_ENTRIES_PER_PAGE-1)
667              << ARM_INSTR_ALIGNMENT_SHIFT) |              << ARM_INSTR_ALIGNMENT_SHIFT) |
668              ((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);              ((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);
669    
670          /*  Update the PC register:  */          /*  Update the PC register:  */
671          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
672    
673          cpu_functioncall_trace_return(cpu);          cpu_functioncall_trace_return(cpu);
674    
# Line 596  X(ret_trace) Line 687  X(ret_trace)
687  Y(ret_trace)  Y(ret_trace)
688  X(ret)  X(ret)
689  {  {
690          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
691          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
692  }  }
693  Y(ret)  Y(ret)
# Line 620  X(msr_imm) Line 711  X(msr_imm)
711              (ic->arg[0] & ARM_FLAG_MODE));              (ic->arg[0] & ARM_FLAG_MODE));
712          uint32_t new_value = ic->arg[0];          uint32_t new_value = ic->arg[0];
713    
714            cpu->cd.arm.cpsr &= 0x0fffffff;
715            cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
716    
717          if (switch_register_banks)          if (switch_register_banks)
718                  arm_save_register_bank(cpu);                  arm_save_register_bank(cpu);
719    
720          cpu->cd.arm.cpsr &= ~mask;          cpu->cd.arm.cpsr &= ~mask;
721          cpu->cd.arm.cpsr |= (new_value & mask);          cpu->cd.arm.cpsr |= (new_value & mask);
722    
723            cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
724    
725          if (switch_register_banks)          if (switch_register_banks)
726                  arm_load_register_bank(cpu);                  arm_load_register_bank(cpu);
727  }  }
# Line 667  X(msr_imm_spsr) Line 763  X(msr_imm_spsr)
763          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
764          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)
765              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
766          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
767              << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
768          cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          old_pc = cpu->pc;
769          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);  
770  }  }
771                  exit(1);                  exit(1);
772          }          }
# Line 692  Y(msr_spsr) Line 787  Y(msr_spsr)
787   */   */
788  X(mrs)  X(mrs)
789  {  {
790            cpu->cd.arm.cpsr &= 0x0fffffff;
791            cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
792          reg(ic->arg[0]) = cpu->cd.arm.cpsr;          reg(ic->arg[0]) = cpu->cd.arm.cpsr;
793  }  }
794  Y(mrs)  Y(mrs)
795    
796    
797  /*  /*
798   *  mrs: Move from status/flag register to a normal register.   *  mrs: Move from saved status/flag register to a normal register.
799   *   *
800   *  arg[0] = pointer to rd   *  arg[0] = pointer to rd
801   */   */
# Line 727  Y(mrs_spsr) Line 824  Y(mrs_spsr)
824   *  arg[0] = copy of the instruction word   *  arg[0] = copy of the instruction word
825   */   */
826  X(mcr_mrc) {  X(mcr_mrc) {
827          uint32_t low_pc;          uint32_t low_pc = ((size_t)ic - (size_t)
         low_pc = ((size_t)ic - (size_t)  
828              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
829          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
830              << 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];  
831          arm_mcr_mrc(cpu, ic->arg[0]);          arm_mcr_mrc(cpu, ic->arg[0]);
832  }  }
833  Y(mcr_mrc)  Y(mcr_mrc)
834  X(cdp) {  X(cdp) {
835          uint32_t low_pc;          uint32_t low_pc = ((size_t)ic - (size_t)
         low_pc = ((size_t)ic - (size_t)  
836              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
837          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
838              << 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];  
839          arm_cdp(cpu, ic->arg[0]);          arm_cdp(cpu, ic->arg[0]);
840  }  }
841  Y(cdp)  Y(cdp)
# Line 755  Y(cdp) Line 846  Y(cdp)
846   */   */
847  X(openfirmware)  X(openfirmware)
848  {  {
849            /*  TODO: sync pc?  */
850          of_emul(cpu);          of_emul(cpu);
851          cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];          cpu->pc = cpu->cd.arm.r[ARM_LR];
852          if (cpu->machine->show_trace_tree)          if (cpu->machine->show_trace_tree)
853                  cpu_functioncall_trace_return(cpu);                  cpu_functioncall_trace_return(cpu);
854          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
# Line 764  X(openfirmware) Line 856  X(openfirmware)
856    
857    
858  /*  /*
859     *  reboot:
860     */
861    X(reboot)
862    {
863            cpu->running = 0;
864            cpu->n_translated_instrs --;
865            cpu->cd.arm.next_ic = &nothing_call;
866    }
867    
868    
869    /*
870   *  swi_useremul: Syscall.   *  swi_useremul: Syscall.
871   *   *
872   *  arg[0] = swi number   *  arg[0] = swi number
# Line 773  X(swi_useremul) Line 876  X(swi_useremul)
876          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
877          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)          uint32_t old_pc, low_pc = ((size_t)ic - (size_t)
878              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
879          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1)
880              << ARM_INSTR_ALIGNMENT_SHIFT);              << ARM_INSTR_ALIGNMENT_SHIFT);
881          cpu->cd.arm.r[ARM_PC] += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
882          old_pc = cpu->pc = cpu->cd.arm.r[ARM_PC];          old_pc = cpu->pc;
883    
884          useremul_syscall(cpu, ic->arg[0]);          useremul_syscall(cpu, ic->arg[0]);
885    
886          if (!cpu->running) {          if (!cpu->running) {
                 cpu->running_translated = 0;  
887                  cpu->n_translated_instrs --;                  cpu->n_translated_instrs --;
888                  cpu->cd.arm.next_ic = &nothing_call;                  cpu->cd.arm.next_ic = &nothing_call;
889          } else if (cpu->pc != old_pc) {          } else if (cpu->pc != old_pc) {
# Line 798  Y(swi_useremul) Line 900  Y(swi_useremul)
900   */   */
901  X(swi)  X(swi)
902  {  {
903          /*  Synchronize the program counter:  */          /*  Synchronize the program counter first:  */
904          uint32_t low_pc = ((size_t)ic - (size_t)          cpu->pc &= 0xfffff000;
905              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];  
   
906          arm_exception(cpu, ARM_EXCEPTION_SWI);          arm_exception(cpu, ARM_EXCEPTION_SWI);
907  }  }
908  Y(swi)  Y(swi)
909    
910    
911  /*  /*
912     *  und:  Undefined instruction.
913     */
914    X(und)
915    {
916            /*  Synchronize the program counter first:  */
917            cpu->pc &= 0xfffff000;
918            cpu->pc += ic->arg[0];
919            arm_exception(cpu, ARM_EXCEPTION_UND);
920    }
921    Y(und)
922    
923    
924    /*
925   *  swp, swpb:  Swap (word or byte).   *  swp, swpb:  Swap (word or byte).
926   *   *
927   *  arg[0] = ptr to rd   *  arg[0] = ptr to rd
# Line 822  X(swp) Line 932  X(swp)
932  {  {
933          uint32_t addr = reg(ic->arg[2]), data, data2;          uint32_t addr = reg(ic->arg[2]), data, data2;
934          unsigned char d[4];          unsigned char d[4];
935    
936          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
937          uint32_t low_pc = ((size_t)ic - (size_t)          uint32_t low_pc = ((size_t)ic - (size_t)
938              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
939          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
940              << 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];  
941    
942          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,
943              CACHE_DATA)) {              CACHE_DATA)) {
# Line 850  X(swpb) Line 959  X(swpb)
959  {  {
960          uint32_t addr = reg(ic->arg[2]), data;          uint32_t addr = reg(ic->arg[2]), data;
961          unsigned char d[1];          unsigned char d[1];
962    
963          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
964          uint32_t low_pc = ((size_t)ic - (size_t)          uint32_t low_pc = ((size_t)ic - (size_t)
965              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
966          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
967              << 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];  
968    
969          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,
970              CACHE_DATA)) {              CACHE_DATA)) {
# Line 877  Y(swpb) Line 985  Y(swpb)
985    
986  extern void (*arm_load_store_instr[1024])(struct cpu *,  extern void (*arm_load_store_instr[1024])(struct cpu *,
987          struct arm_instr_call *);          struct arm_instr_call *);
988    X(store_w1_word_u1_p0_imm);
989  X(store_w0_byte_u1_p0_imm);  X(store_w0_byte_u1_p0_imm);
990  X(store_w0_word_u1_p0_imm);  X(store_w0_word_u1_p0_imm);
991    X(store_w0_word_u1_p1_imm);
992    X(load_w1_word_u1_p0_imm);
993  X(load_w0_word_u1_p0_imm);  X(load_w0_word_u1_p0_imm);
994  X(load_w0_byte_u1_p1_imm);  X(load_w0_byte_u1_p1_imm);
995  X(load_w0_byte_u1_p1_reg);  X(load_w0_byte_u1_p1_reg);
996    X(load_w1_byte_u1_p1_imm);
997    
998  extern void (*arm_load_store_instr_pc[1024])(struct cpu *,  extern void (*arm_load_store_instr_pc[1024])(struct cpu *,
999          struct arm_instr_call *);          struct arm_instr_call *);
# Line 893  extern void (*arm_load_store_instr_3_pc[ Line 1005  extern void (*arm_load_store_instr_3_pc[
1005          struct arm_instr_call *);          struct arm_instr_call *);
1006    
1007  extern uint32_t (*arm_r[8192])(struct cpu *, struct arm_instr_call *);  extern uint32_t (*arm_r[8192])(struct cpu *, struct arm_instr_call *);
1008    extern void arm_r_r3_t0_c0(void);
1009    
1010  extern void (*arm_dpi_instr[2 * 2 * 2 * 16 * 16])(struct cpu *,  extern void (*arm_dpi_instr[2 * 2 * 2 * 16 * 16])(struct cpu *,
1011          struct arm_instr_call *);          struct arm_instr_call *);
1012    extern void (*arm_dpi_instr_regshort[2 * 16 * 16])(struct cpu *,
1013            struct arm_instr_call *);
1014  X(cmps);  X(cmps);
1015    X(teqs);
1016    X(tsts);
1017  X(sub);  X(sub);
1018  X(add);  X(add);
1019  X(subs);  X(subs);
1020    X(eor_regshort);
1021    X(cmps_regshort);
1022    
1023    
1024    #include "cpu_arm_instr_misc.c"
1025    
1026    
1027  /*  /*
1028   *  bdt_load:  Block Data Transfer, Load   *  bdt_load:  Block Data Transfer, Load
# Line 931  X(bdt_load) Line 1052  X(bdt_load)
1052          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
1053          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
1054              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
1055          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) <<          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
1056              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];  
1057    
1058          if (s_bit) {          if (s_bit) {
1059                  /*  Load to USR registers:  */                  /*  Load to USR registers:  */
# Line 1070  X(bdt_load) Line 1189  X(bdt_load)
1189                          arm_save_register_bank(cpu);                          arm_save_register_bank(cpu);
1190    
1191                  cpu->cd.arm.cpsr = new_cpsr;                  cpu->cd.arm.cpsr = new_cpsr;
1192                    cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
1193    
1194                  if (switch_register_banks)                  if (switch_register_banks)
1195                          arm_load_register_bank(cpu);                          arm_load_register_bank(cpu);
# Line 1077  X(bdt_load) Line 1197  X(bdt_load)
1197    
1198          /*  NOTE: Special case: Loading the PC  */          /*  NOTE: Special case: Loading the PC  */
1199          if (iw & 0x8000) {          if (iw & 0x8000) {
1200                  cpu->cd.arm.r[ARM_PC] &= ~3;                  cpu->pc = cpu->cd.arm.r[ARM_PC] & 0xfffffffc;
                 cpu->pc = cpu->cd.arm.r[ARM_PC];  
1201                  if (cpu->machine->show_trace_tree)                  if (cpu->machine->show_trace_tree)
1202                          cpu_functioncall_trace_return(cpu);                          cpu_functioncall_trace_return(cpu);
1203                  /*  TODO: There is no need to update the                  /*  TODO: There is no need to update the
# Line 1119  X(bdt_store) Line 1238  X(bdt_store)
1238          /*  Synchronize the program counter:  */          /*  Synchronize the program counter:  */
1239          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
1240              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
1241          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) <<          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
1242              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];  
1243    
1244          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)) {
1245                  if (!((iw >> i) & 1)) {                  if (!((iw >> i) & 1)) {
# Line 1151  X(bdt_store) Line 1268  X(bdt_store)
1268                          }                          }
1269                  }                  }
1270    
1271                    /*  NOTE/TODO: 8 vs 12 on some ARMs  */
1272                  if (i == ARM_PC)                  if (i == ARM_PC)
1273                          value += 12;    /*  NOTE/TODO: 8 on some ARMs  */                          value = cpu->pc + 12;
1274    
1275                  if (p_bit) {                  if (p_bit) {
1276                          if (u_bit)                          if (u_bit)
# Line 1210  Y(bdt_store) Line 1328  Y(bdt_store)
1328    
1329    
1330  /*  Various load/store multiple instructions:  */  /*  Various load/store multiple instructions:  */
1331  #include "tmp_arm_multi.c"  extern uint32_t *multi_opcode[256];
1332    extern void (**multi_opcode_f[256])(struct cpu *, struct arm_instr_call *);
1333    X(multi_0x08b15018);
1334    X(multi_0x08ac000c__ge);
1335    X(multi_0x08a05018);
1336    
1337    
1338  /*****************************************************************************/  /*****************************************************************************/
1339    
1340    
1341  /*  /*
  *  fill_loop_test:  
  *  
  *  A byte-fill loop. Fills at most one page at a time. If the page was not  
  *  in the host_store table, then the original sequence (beginning with  
  *  cmps rZ,#0) is executed instead.  
  *  
  *  L: cmps rZ,#0               ic[0]  
  *     strb rX,[rY],#1          ic[1]  
  *     sub  rZ,rZ,#1            ic[2]  
  *     bgt  L                   ic[3]  
  *  
  *  A maximum of 4 pages are filled before returning.  
  */  
 X(fill_loop_test)  
 {  
         int max_pages_left = 4;  
         uint32_t addr, a, n, ofs, maxlen;  
         uint32_t *rzp = (uint32_t *)(size_t)ic[0].arg[0];  
         unsigned char *page;  
   
 restart_loop:  
         addr = reg(ic[1].arg[0]);  
         page = cpu->cd.arm.host_store[addr >> 12];  
         if (page == NULL) {  
                 instr(cmps)(cpu, ic);  
                 return;  
         }  
   
         n = reg(rzp) + 1;  
         ofs = addr & 0xfff;  
         maxlen = 4096 - ofs;  
         if (n > maxlen)  
                 n = maxlen;  
   
         /*  printf("x = %x, n = %i\n", reg(ic[1].arg[2]), n);  */  
         memset(page + ofs, reg(ic[1].arg[2]), n);  
   
         reg(ic[1].arg[0]) = addr + n;  
   
         reg(rzp) -= n;  
         cpu->n_translated_instrs += (4 * n);  
   
         a = reg(rzp);  
   
         cpu->cd.arm.cpsr &=  
             ~(ARM_FLAG_Z | ARM_FLAG_N | ARM_FLAG_V | ARM_FLAG_C);  
         if (a != 0)  
                 cpu->cd.arm.cpsr |= ARM_FLAG_C;  
         else  
                 cpu->cd.arm.cpsr |= ARM_FLAG_Z;  
         if ((int32_t)a < 0)  
                 cpu->cd.arm.cpsr |= ARM_FLAG_N;  
   
         if (max_pages_left-- > 0 && (int32_t)a > 0)  
                 goto restart_loop;  
   
         cpu->n_translated_instrs --;  
   
         if ((int32_t)a > 0)  
                 cpu->cd.arm.next_ic = ic;  
         else  
                 cpu->cd.arm.next_ic = &ic[4];  
 }  
   
   
 /*  
  *  fill_loop_test2:  
  *  
  *  A word-fill loop. Fills at most one page at a time. If the page was not  
  *  in the host_store table, then the original sequence (beginning with  
  *  cmps rZ,#0) is executed instead.  
  *  
  *      L: str     rX,[rY],#4           ic[0]  
  *         subs    rZ,rZ,#4             ic[1]  
  *         bgt     L                    ic[2]  
  *  
  *  A maximum of 5 pages are filled before returning.  
  */  
 X(fill_loop_test2)  
 {  
         int max_pages_left = 5;  
         unsigned char x1,x2,x3,x4;  
         uint32_t addr, a, n, x, ofs, maxlen;  
         uint32_t *rzp = (uint32_t *)(size_t)ic[1].arg[0];  
         unsigned char *page;  
   
         x = reg(ic[0].arg[2]);  
         x1 = x; x2 = x >> 8; x3 = x >> 16; x4 = x >> 24;  
         if (x1 != x2 || x1 != x3 || x1 != x4) {  
                 instr(store_w0_word_u1_p0_imm)(cpu, ic);  
                 return;  
         }  
   
 restart_loop:  
         addr = reg(ic[0].arg[0]);  
         page = cpu->cd.arm.host_store[addr >> 12];  
         if (page == NULL || (addr & 3) != 0) {  
                 instr(store_w0_word_u1_p0_imm)(cpu, ic);  
                 return;  
         }  
   
         /*  printf("addr = 0x%08x, page = %p\n", addr, page);  
             printf("*rzp = 0x%08x\n", reg(rzp));  */  
   
         n = reg(rzp) / 4;  
         if (n == 0)  
                 n++;  
         /*  n = nr of _words_  */  
         ofs = addr & 0xfff;  
         maxlen = 4096 - ofs;  
         if (n*4 > maxlen)  
                 n = maxlen / 4;  
   
         /*  printf("x = %x, n = %i\n", x1, n);  */  
         memset(page + ofs, x1, n * 4);  
   
         reg(ic[0].arg[0]) = addr + n * 4;  
   
         reg(rzp) -= (n * 4);  
         cpu->n_translated_instrs += (3 * n);  
   
         a = reg(rzp);  
   
         cpu->cd.arm.cpsr &=  
             ~(ARM_FLAG_Z | ARM_FLAG_N | ARM_FLAG_V | ARM_FLAG_C);  
         if (a != 0)  
                 cpu->cd.arm.cpsr |= ARM_FLAG_C;  
         else  
                 cpu->cd.arm.cpsr |= ARM_FLAG_Z;  
         if ((int32_t)a < 0)  
                 cpu->cd.arm.cpsr |= ARM_FLAG_N;  
   
         if (max_pages_left-- > 0 && (int32_t)a > 0)  
                 goto restart_loop;  
   
         cpu->n_translated_instrs --;  
   
         if ((int32_t)a > 0)  
                 cpu->cd.arm.next_ic = ic;  
         else  
                 cpu->cd.arm.next_ic = &ic[3];  
 }  
   
   
 /*  
1342   *  netbsd_memset:   *  netbsd_memset:
1343   *   *
1344   *  The core of a NetBSD/arm memset.   *  The core of a NetBSD/arm memset.
# Line 1381  X(netbsd_memset) Line 1358  X(netbsd_memset)
1358    
1359                  instr(subs)(cpu, ic);                  instr(subs)(cpu, ic);
1360    
1361                  if (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) !=                  if (((cpu->cd.arm.flags & ARM_F_N)?1:0) !=
1362                      ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0)) {                      ((cpu->cd.arm.flags & ARM_F_V)?1:0)) {
1363                          cpu->n_translated_instrs += 16;                          cpu->n_translated_instrs += 16;
1364                          /*  Skip the store multiples:  */                          /*  Skip the store multiples:  */
1365                          cpu->cd.arm.next_ic = &ic[17];                          cpu->cd.arm.next_ic = &ic[17];
# Line 1411  X(netbsd_memset) Line 1388  X(netbsd_memset)
1388    
1389                  /*  Branch back if greater:  */                  /*  Branch back if greater:  */
1390                  cpu->n_translated_instrs += 1;                  cpu->n_translated_instrs += 1;
1391          } while (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) ==          } while (((cpu->cd.arm.flags & ARM_F_N)?1:0) ==
1392              ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0) &&              ((cpu->cd.arm.flags & ARM_F_V)?1:0) &&
1393              !(cpu->cd.arm.cpsr & ARM_FLAG_Z));              !(cpu->cd.arm.flags & ARM_F_Z));
1394    
1395          /*  Continue at the instruction after the bgt:  */          /*  Continue at the instruction after the bgt:  */
1396          cpu->cd.arm.next_ic = &ic[18];          cpu->cd.arm.next_ic = &ic[18];
# Line 1471  X(netbsd_memcpy) Line 1448  X(netbsd_memcpy)
1448    
1449                  /*  Loop while greater or equal:  */                  /*  Loop while greater or equal:  */
1450                  cpu->n_translated_instrs ++;                  cpu->n_translated_instrs ++;
1451          } while (((cpu->cd.arm.cpsr & ARM_FLAG_N)?1:0) ==          } while (((cpu->cd.arm.flags & ARM_F_N)?1:0) ==
1452              ((cpu->cd.arm.cpsr & ARM_FLAG_V)?1:0));              ((cpu->cd.arm.flags & ARM_F_V)?1:0));
1453    
1454          /*  Continue at the instruction after the bge:  */          /*  Continue at the instruction after the bge:  */
1455          cpu->cd.arm.next_ic = &ic[6];          cpu->cd.arm.next_ic = &ic[6];
# Line 1494  X(netbsd_cacheclean) Line 1471  X(netbsd_cacheclean)
1471  {  {
1472          uint32_t r1 = cpu->cd.arm.r[1];          uint32_t r1 = cpu->cd.arm.r[1];
1473          cpu->n_translated_instrs += ((r1 >> 5) * 3);          cpu->n_translated_instrs += ((r1 >> 5) * 3);
1474            cpu->cd.arm.r[0] += r1;
1475            cpu->cd.arm.r[1] = 0;
1476          cpu->cd.arm.next_ic = &ic[4];          cpu->cd.arm.next_ic = &ic[4];
1477  }  }
1478    
# Line 1545  X(netbsd_scanc) Line 1524  X(netbsd_scanc)
1524          cpu->cd.arm.r[3] = page[t & 0xfff];          cpu->cd.arm.r[3] = page[t & 0xfff];
1525    
1526          t = cpu->cd.arm.r[3] & cpu->cd.arm.r[ARM_IP];          t = cpu->cd.arm.r[3] & cpu->cd.arm.r[ARM_IP];
1527          cpu->cd.arm.cpsr &= ~(ARM_FLAG_Z | ARM_FLAG_N);          cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1528          if (t == 0)          if (t == 0)
1529                  cpu->cd.arm.cpsr |= ARM_FLAG_Z;                  cpu->cd.arm.flags |= ARM_F_Z;
1530    
1531          cpu->n_translated_instrs += 2;          cpu->n_translated_instrs += 2;
1532          cpu->cd.arm.next_ic = &ic[3];          cpu->cd.arm.next_ic = &ic[3];
1533  }  }
1534    
1535    
1536    /*
1537     *  strlen:
1538     *
1539     *  S: e5f03001   ldrb  rY,[rX,#1]!
1540     *     e3530000   cmps  rY,#0
1541     *     1afffffc   bne   S
1542     */
1543    X(strlen)
1544    {
1545            unsigned int n_loops = 0;
1546            uint32_t rY, rX = reg(ic[0].arg[0]);
1547            unsigned char *p;
1548    
1549            do {
1550                    rX ++;
1551                    p = cpu->cd.arm.host_load[rX >> 12];
1552                    if (p == NULL) {
1553                            cpu->n_translated_instrs += (n_loops * 3);
1554                            instr(load_w1_byte_u1_p1_imm)(cpu, ic);
1555                            return;
1556                    }
1557    
1558                    rY = reg(ic[0].arg[2]) = p[rX & 0xfff]; /*  load  */
1559                    reg(ic[0].arg[0]) = rX;                 /*  writeback  */
1560                    n_loops ++;
1561    
1562                    /*  Compare rY to zero:  */
1563                    cpu->cd.arm.flags = ARM_F_C;
1564                    if (rY == 0)
1565                            cpu->cd.arm.flags |= ARM_F_Z;
1566            } while (rY != 0);
1567    
1568            cpu->n_translated_instrs += (n_loops * 3) - 1;
1569            cpu->cd.arm.next_ic = &ic[3];
1570    }
1571    
1572    
1573    /*
1574     *  xchg:
1575     *
1576     *  e02YX00X     eor     rX,rY,rX
1577     *  e02XY00Y     eor     rY,rX,rY
1578     *  e02YX00X     eor     rX,rY,rX
1579     */
1580    X(xchg)
1581    {
1582            uint32_t tmp = reg(ic[0].arg[0]);
1583            cpu->n_translated_instrs += 2;
1584            cpu->cd.arm.next_ic = &ic[3];
1585            reg(ic[0].arg[0]) = reg(ic[1].arg[0]);
1586            reg(ic[1].arg[0]) = tmp;
1587    }
1588    
1589    
1590    /*
1591     *  netbsd_copyin:
1592     *
1593     *  e4b0a004     ldrt    sl,[r0],#4
1594     *  e4b0b004     ldrt    fp,[r0],#4
1595     *  e4b06004     ldrt    r6,[r0],#4
1596     *  e4b07004     ldrt    r7,[r0],#4
1597     *  e4b08004     ldrt    r8,[r0],#4
1598     *  e4b09004     ldrt    r9,[r0],#4
1599     */
1600    X(netbsd_copyin)
1601    {
1602            uint32_t r0 = cpu->cd.arm.r[0], ofs = (r0 & 0xffc), index = r0 >> 12;
1603            unsigned char *p = cpu->cd.arm.host_load[index];
1604            uint32_t *p32 = (uint32_t *) p, *q32;
1605            int ok = cpu->cd.arm.is_userpage[index >> 5] & (1 << (index & 31));
1606    
1607            if (ofs > 0x1000 - 6*4 || !ok || p == NULL) {
1608                    instr(load_w1_word_u1_p0_imm)(cpu, ic);
1609                    return;
1610            }
1611            q32 = &cpu->cd.arm.r[6];
1612            ofs >>= 2;
1613            q32[0] = p32[ofs+2];
1614            q32[1] = p32[ofs+3];
1615            q32[2] = p32[ofs+4];
1616            q32[3] = p32[ofs+5];
1617            q32[4] = p32[ofs+0];
1618            q32[5] = p32[ofs+1];
1619            cpu->cd.arm.r[0] = r0 + 24;
1620            cpu->n_translated_instrs += 5;
1621            cpu->cd.arm.next_ic = &ic[6];
1622    }
1623    
1624    
1625    /*
1626     *  netbsd_copyout:
1627     *
1628     *  e4a18004     strt    r8,[r1],#4
1629     *  e4a19004     strt    r9,[r1],#4
1630     *  e4a1a004     strt    sl,[r1],#4
1631     *  e4a1b004     strt    fp,[r1],#4
1632     *  e4a16004     strt    r6,[r1],#4
1633     *  e4a17004     strt    r7,[r1],#4
1634     */
1635    X(netbsd_copyout)
1636    {
1637            uint32_t r1 = cpu->cd.arm.r[1], ofs = (r1 & 0xffc), index = r1 >> 12;
1638            unsigned char *p = cpu->cd.arm.host_store[index];
1639            uint32_t *p32 = (uint32_t *) p, *q32;
1640            int ok = cpu->cd.arm.is_userpage[index >> 5] & (1 << (index & 31));
1641    
1642            if (ofs > 0x1000 - 6*4 || !ok || p == NULL) {
1643                    instr(store_w1_word_u1_p0_imm)(cpu, ic);
1644                    return;
1645            }
1646            q32 = &cpu->cd.arm.r[6];
1647            ofs >>= 2;
1648            p32[ofs  ] = q32[2];
1649            p32[ofs+1] = q32[3];
1650            p32[ofs+2] = q32[4];
1651            p32[ofs+3] = q32[5];
1652            p32[ofs+4] = q32[0];
1653            p32[ofs+5] = q32[1];
1654            cpu->cd.arm.r[1] = r1 + 24;
1655            cpu->n_translated_instrs += 5;
1656            cpu->cd.arm.next_ic = &ic[6];
1657    }
1658    
1659    
1660    /*
1661     *  cmps by 0, followed by beq (inside the same page):
1662     */
1663    X(cmps0_beq_samepage)
1664    {
1665            uint32_t a = reg(ic->arg[0]);
1666            cpu->n_translated_instrs ++;
1667            if (a == 0) {
1668                    cpu->cd.arm.flags = ARM_F_Z | ARM_F_C;
1669            } else {
1670                    /*  Semi-ugly hack which sets the negative-bit if a < 0:  */
1671                    cpu->cd.arm.flags = ARM_F_C | ((a >> 28) & 8);
1672            }
1673            if (a == 0)
1674                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1675            else
1676                    cpu->cd.arm.next_ic = &ic[2];
1677    }
1678    
1679    
1680    /*
1681     *  cmps followed by beq (inside the same page):
1682     */
1683    X(cmps_beq_samepage)
1684    {
1685            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1686            cpu->n_translated_instrs ++;
1687            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1688            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1689                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1690                    cpu->cd.arm.flags |= ARM_F_V;
1691            if (c == 0) {
1692                    cpu->cd.arm.flags |= ARM_F_Z;
1693                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1694            } else {
1695                    cpu->cd.arm.next_ic = &ic[2];
1696                    if (c & 0x80000000)
1697                            cpu->cd.arm.flags |= ARM_F_N;
1698            }
1699    }
1700    
1701    
1702    /*
1703     *  cmps followed by beq (not the same page):
1704     */
1705    X(cmps_0_beq)
1706    {
1707            uint32_t a = reg(ic->arg[0]);
1708            cpu->n_translated_instrs ++;
1709            if (a == 0) {
1710                    cpu->cd.arm.flags = ARM_F_Z | ARM_F_C;
1711                    cpu->pc = (uint32_t)(((uint32_t)cpu->pc & 0xfffff000)
1712                        + (int32_t)ic[1].arg[0]);
1713                    quick_pc_to_pointers(cpu);
1714            } else {
1715                    /*  Semi-ugly hack which sets the negative-bit if a < 0:  */
1716                    cpu->cd.arm.flags = ARM_F_C | ((a >> 28) & 8);
1717                    cpu->cd.arm.next_ic = &ic[2];
1718            }
1719    }
1720    X(cmps_pos_beq)
1721    {
1722            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1723            cpu->n_translated_instrs ++;
1724            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1725            if ((int32_t)a < 0 && (int32_t)c >= 0)
1726                    cpu->cd.arm.flags |= ARM_F_V;
1727            if (c == 0) {
1728                    cpu->cd.arm.flags |= ARM_F_Z;
1729                    cpu->pc = (uint32_t)(((uint32_t)cpu->pc & 0xfffff000)
1730                        + (int32_t)ic[1].arg[0]);
1731                    quick_pc_to_pointers(cpu);
1732            } else {
1733                    cpu->cd.arm.next_ic = &ic[2];
1734                    if (c & 0x80000000)
1735                            cpu->cd.arm.flags |= ARM_F_N;
1736            }
1737    }
1738    X(cmps_neg_beq)
1739    {
1740            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1741            cpu->n_translated_instrs ++;
1742            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1743            if ((int32_t)a >= 0 && (int32_t)c < 0)
1744                    cpu->cd.arm.flags |= ARM_F_V;
1745            if (c == 0) {
1746                    cpu->cd.arm.flags |= ARM_F_Z;
1747                    cpu->pc = (uint32_t)(((uint32_t)cpu->pc & 0xfffff000)
1748                        + (int32_t)ic[1].arg[0]);
1749                    quick_pc_to_pointers(cpu);
1750            } else {
1751                    cpu->cd.arm.next_ic = &ic[2];
1752                    if (c & 0x80000000)
1753                            cpu->cd.arm.flags |= ARM_F_N;
1754            }
1755    }
1756    
1757    
1758    /*
1759     *  cmps by 0, followed by bne (inside the same page):
1760     */
1761    X(cmps0_bne_samepage)
1762    {
1763            uint32_t a = reg(ic->arg[0]);
1764            cpu->n_translated_instrs ++;
1765            if (a == 0) {
1766                    cpu->cd.arm.flags = ARM_F_Z | ARM_F_C;
1767            } else {
1768                    /*  Semi-ugly hack which sets the negative-bit if a < 0:  */
1769                    cpu->cd.arm.flags = ARM_F_C | ((a >> 28) & 8);
1770            }
1771            if (a == 0)
1772                    cpu->cd.arm.next_ic = &ic[2];
1773            else
1774                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1775    }
1776    
1777    
1778    /*
1779     *  cmps followed by bne (inside the same page):
1780     */
1781    X(cmps_bne_samepage)
1782    {
1783            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1784            cpu->n_translated_instrs ++;
1785            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1786            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1787                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1788                    cpu->cd.arm.flags |= ARM_F_V;
1789            if (c == 0) {
1790                    cpu->cd.arm.flags |= ARM_F_Z;
1791                    cpu->cd.arm.next_ic = &ic[2];
1792            } else {
1793                    if (c & 0x80000000)
1794                            cpu->cd.arm.flags |= ARM_F_N;
1795                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1796            }
1797    }
1798    
1799    
1800    /*
1801     *  cmps followed by bcc (inside the same page):
1802     */
1803    X(cmps_bcc_samepage)
1804    {
1805            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1806            cpu->n_translated_instrs ++;
1807            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1808            if (c & 0x80000000)
1809                    cpu->cd.arm.flags |= ARM_F_N;
1810            else if (c == 0)
1811                    cpu->cd.arm.flags |= ARM_F_Z;
1812            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1813                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1814                    cpu->cd.arm.flags |= ARM_F_V;
1815            if (a >= b)
1816                    cpu->cd.arm.next_ic = &ic[2];
1817            else
1818                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1819    }
1820    
1821    
1822    /*
1823     *  cmps (reg) followed by bcc (inside the same page):
1824     */
1825    X(cmps_reg_bcc_samepage)
1826    {
1827            uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = a - b;
1828            cpu->n_translated_instrs ++;
1829            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1830            if (c & 0x80000000)
1831                    cpu->cd.arm.flags |= ARM_F_N;
1832            else if (c == 0)
1833                    cpu->cd.arm.flags |= ARM_F_Z;
1834            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1835                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1836                    cpu->cd.arm.flags |= ARM_F_V;
1837            if (a >= b)
1838                    cpu->cd.arm.next_ic = &ic[2];
1839            else
1840                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1841    }
1842    
1843    
1844    /*
1845     *  cmps followed by bhi (inside the same page):
1846     */
1847    X(cmps_bhi_samepage)
1848    {
1849            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1850            cpu->n_translated_instrs ++;
1851            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1852            if (c & 0x80000000)
1853                    cpu->cd.arm.flags |= ARM_F_N;
1854            else if (c == 0)
1855                    cpu->cd.arm.flags |= ARM_F_Z;
1856            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1857                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1858                    cpu->cd.arm.flags |= ARM_F_V;
1859            if (a > b)
1860                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1861            else
1862                    cpu->cd.arm.next_ic = &ic[2];
1863    }
1864    
1865    
1866    /*
1867     *  cmps (reg) followed by bhi (inside the same page):
1868     */
1869    X(cmps_reg_bhi_samepage)
1870    {
1871            uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = a - b;
1872            cpu->n_translated_instrs ++;
1873            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1874            if (c & 0x80000000)
1875                    cpu->cd.arm.flags |= ARM_F_N;
1876            else if (c == 0)
1877                    cpu->cd.arm.flags |= ARM_F_Z;
1878            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1879                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1880                    cpu->cd.arm.flags |= ARM_F_V;
1881            if (a > b)
1882                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1883            else
1884                    cpu->cd.arm.next_ic = &ic[2];
1885    }
1886    
1887    
1888    /*
1889     *  cmps followed by bgt (inside the same page):
1890     */
1891    X(cmps_bgt_samepage)
1892    {
1893            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1894            cpu->n_translated_instrs ++;
1895            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1896            if (c & 0x80000000)
1897                    cpu->cd.arm.flags |= ARM_F_N;
1898            else if (c == 0)
1899                    cpu->cd.arm.flags |= ARM_F_Z;
1900            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1901                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1902                    cpu->cd.arm.flags |= ARM_F_V;
1903            if ((int32_t)a > (int32_t)b)
1904                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1905            else
1906                    cpu->cd.arm.next_ic = &ic[2];
1907    }
1908    
1909    
1910    /*
1911     *  cmps followed by ble (inside the same page):
1912     */
1913    X(cmps_ble_samepage)
1914    {
1915            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a - b;
1916            cpu->n_translated_instrs ++;
1917            cpu->cd.arm.flags = ((uint32_t)a >= (uint32_t)b)? ARM_F_C : 0;
1918            if (c & 0x80000000)
1919                    cpu->cd.arm.flags |= ARM_F_N;
1920            else if (c == 0)
1921                    cpu->cd.arm.flags |= ARM_F_Z;
1922            if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1923                ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1924                    cpu->cd.arm.flags |= ARM_F_V;
1925            if ((int32_t)a <= (int32_t)b)
1926                    cpu->cd.arm.next_ic = (struct arm_instr_call *) ic[1].arg[0];
1927            else
1928                    cpu->cd.arm.next_ic = &ic[2];
1929    }
1930    
1931    
1932    /*
1933     *  teqs followed by beq (inside the same page):
1934     */
1935    X(teqs_beq_samepage)
1936    {
1937            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a ^ b;
1938            cpu->n_translated_instrs ++;
1939            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1940            if (c == 0) {
1941                    cpu->cd.arm.flags |= ARM_F_Z;
1942                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
1943                        ic[1].arg[0];
1944            } else {
1945                    if (c & 0x80000000)
1946                            cpu->cd.arm.flags |= ARM_F_N;
1947                    cpu->cd.arm.next_ic = &ic[2];
1948            }
1949    }
1950    
1951    
1952    /*
1953     *  tsts followed by beq (inside the same page):
1954     *  (arg[1] must not have its highest bit set))
1955     */
1956    X(tsts_lo_beq_samepage)
1957    {
1958            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a & b;
1959            cpu->n_translated_instrs ++;
1960            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1961            if (c == 0)
1962                    cpu->cd.arm.flags |= ARM_F_Z;
1963            if (c == 0)
1964                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
1965                        ic[1].arg[0];
1966            else
1967                    cpu->cd.arm.next_ic = &ic[2];
1968    }
1969    
1970    
1971    /*
1972     *  teqs followed by bne (inside the same page):
1973     */
1974    X(teqs_bne_samepage)
1975    {
1976            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a ^ b;
1977            cpu->n_translated_instrs ++;
1978            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1979            if (c == 0) {
1980                    cpu->cd.arm.flags |= ARM_F_Z;
1981            } else {
1982                    if (c & 0x80000000)
1983                            cpu->cd.arm.flags |= ARM_F_N;
1984            }
1985            if (c == 0)
1986                    cpu->cd.arm.next_ic = &ic[2];
1987            else
1988                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
1989                        ic[1].arg[0];
1990    }
1991    
1992    
1993    /*
1994     *  tsts followed by bne (inside the same page):
1995     *  (arg[1] must not have its highest bit set))
1996     */
1997    X(tsts_lo_bne_samepage)
1998    {
1999            uint32_t a = reg(ic->arg[0]), b = ic->arg[1], c = a & b;
2000            cpu->n_translated_instrs ++;
2001            cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
2002            if (c == 0)
2003                    cpu->cd.arm.flags |= ARM_F_Z;
2004            if (c == 0)
2005                    cpu->cd.arm.next_ic = &ic[2];
2006            else
2007                    cpu->cd.arm.next_ic = (struct arm_instr_call *)
2008                        ic[1].arg[0];
2009    }
2010    
2011    
2012  /*****************************************************************************/  /*****************************************************************************/
2013    
2014    
2015  X(end_of_page)  X(end_of_page)
2016  {  {
2017          /*  Update the PC:  (offset 0, but on the next page)  */          /*  Update the PC:  (offset 0, but on the next page)  */
2018          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
2019              << 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];  
2020    
2021          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
2022          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
# Line 1578  X(end_of_page) Line 2030  X(end_of_page)
2030    
2031    
2032  /*  /*
2033   *  arm_combine_netbsd_memset():   *  Combine: netbsd_memset():
2034   *   *
2035   *  Check for the core of a NetBSD/arm memset; large memsets use a sequence   *  Check for the core of a NetBSD/arm memset; large memsets use a sequence
2036   *  of 16 store-multiple instructions, each storing 2 registers at a time.   *  of 16 store-multiple instructions, each storing 2 registers at a time.
2037   */   */
2038  void arm_combine_netbsd_memset(struct cpu *cpu, struct arm_instr_call *ic,  void COMBINE(netbsd_memset)(struct cpu *cpu,
2039          int low_addr)          struct arm_instr_call *ic, int low_addr)
2040  {  {
2041    #ifdef HOST_LITTLE_ENDIAN
2042          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2043              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
2044    
# Line 1599  void arm_combine_netbsd_memset(struct cp Line 2052  void arm_combine_netbsd_memset(struct cp
2052                      ic[ 0].f == instr(b_samepage__gt) &&                      ic[ 0].f == instr(b_samepage__gt) &&
2053                      ic[ 0].arg[0] == (size_t)&ic[-17]) {                      ic[ 0].arg[0] == (size_t)&ic[-17]) {
2054                          ic[-17].f = instr(netbsd_memset);                          ic[-17].f = instr(netbsd_memset);
                         combined;  
2055                  }                  }
2056          }          }
2057    #endif
2058  }  }
2059    
2060    
2061  /*  /*
2062   *  arm_combine_netbsd_memcpy():   *  Combine: netbsd_memcpy():
2063   *   *
2064   *  Check for the core of a NetBSD/arm memcpy; large memcpys use a   *  Check for the core of a NetBSD/arm memcpy; large memcpys use a
2065   *  sequence of ldmia instructions.   *  sequence of ldmia instructions.
2066   */   */
2067  void arm_combine_netbsd_memcpy(struct cpu *cpu, struct arm_instr_call *ic,  void COMBINE(netbsd_memcpy)(struct cpu *cpu, struct arm_instr_call *ic,
2068          int low_addr)          int low_addr)
2069  {  {
2070    #ifdef HOST_LITTLE_ENDIAN
2071          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2072              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
2073    
# Line 1627  void arm_combine_netbsd_memcpy(struct cp Line 2081  void arm_combine_netbsd_memcpy(struct cp
2081                      ic[ 0].f == instr(b_samepage__ge) &&                      ic[ 0].f == instr(b_samepage__ge) &&
2082                      ic[ 0].arg[0] == (size_t)&ic[-5]) {                      ic[ 0].arg[0] == (size_t)&ic[-5]) {
2083                          ic[-5].f = instr(netbsd_memcpy);                          ic[-5].f = instr(netbsd_memcpy);
                         combined;  
2084                  }                  }
2085          }          }
2086    #endif
2087  }  }
2088    
2089    
2090  /*  /*
2091   *  arm_combine_netbsd_cacheclean():   *  Combine: netbsd_cacheclean():
2092   *   *
2093   *  Check for the core of a NetBSD/arm cache clean. (There are two variants.)   *  Check for the core of a NetBSD/arm cache clean. (There are two variants.)
2094   */   */
2095  void arm_combine_netbsd_cacheclean(struct cpu *cpu, struct arm_instr_call *ic,  void COMBINE(netbsd_cacheclean)(struct cpu *cpu,
2096          int low_addr)          struct arm_instr_call *ic, int low_addr)
2097  {  {
2098          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2099              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
# Line 1651  void arm_combine_netbsd_cacheclean(struc Line 2105  void arm_combine_netbsd_cacheclean(struc
2105                      ic[-1].f == instr(b_samepage__ne) &&                      ic[-1].f == instr(b_samepage__ne) &&
2106                      ic[-1].arg[0] == (size_t)&ic[-3]) {                      ic[-1].arg[0] == (size_t)&ic[-3]) {
2107                          ic[-3].f = instr(netbsd_cacheclean);                          ic[-3].f = instr(netbsd_cacheclean);
                         combined;  
2108                  }                  }
2109          }          }
2110  }  }
2111    
2112    
2113  /*  /*
2114   *  arm_combine_netbsd_cacheclean2():   *  Combine: netbsd_cacheclean2():
2115   *   *
2116   *  Check for the core of a NetBSD/arm cache clean. (Second variant.)   *  Check for the core of a NetBSD/arm cache clean. (Second variant.)
2117   */   */
2118  void arm_combine_netbsd_cacheclean2(struct cpu *cpu, struct arm_instr_call *ic,  void COMBINE(netbsd_cacheclean2)(struct cpu *cpu,
2119          int low_addr)          struct arm_instr_call *ic, int low_addr)
2120  {  {
2121          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2122              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
# Line 1676  void arm_combine_netbsd_cacheclean2(stru Line 2129  void arm_combine_netbsd_cacheclean2(stru
2129                      ic[-1].f == instr(subs) &&                      ic[-1].f == instr(subs) &&
2130                      ic[-1].arg[0]==ic[-1].arg[2] && ic[-1].arg[1] == 0x20) {                      ic[-1].arg[0]==ic[-1].arg[2] && ic[-1].arg[1] == 0x20) {
2131                          ic[-4].f = instr(netbsd_cacheclean2);                          ic[-4].f = instr(netbsd_cacheclean2);
                         combined;  
2132                  }                  }
2133          }          }
2134  }  }
2135    
2136    
2137  /*  /*
2138   *  arm_combine_netbsd_scanc():   *  Combine: netbsd_scanc():
2139   */   */
2140  void arm_combine_netbsd_scanc(struct cpu *cpu, struct arm_instr_call *ic,  void COMBINE(netbsd_scanc)(struct cpu *cpu,
2141          int low_addr)          struct arm_instr_call *ic, int low_addr)
2142  {  {
2143          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2144              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
2145    
2146          if (n_back >= 2) {          if (n_back < 2)
2147                  if (ic[-2].f == instr(load_w0_byte_u1_p1_imm) &&                  return;
2148                      ic[-1].f == instr(load_w0_byte_u1_p1_reg)) {  
2149                          ic[-2].f = instr(netbsd_scanc);          if (ic[-2].f == instr(load_w0_byte_u1_p1_imm) &&
2150                          combined;              ic[-2].arg[0] == (size_t)(&cpu->cd.arm.r[1]) &&
2151                  }              ic[-2].arg[1] == 0 &&
2152                ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[3]) &&
2153                ic[-1].f == instr(load_w0_byte_u1_p1_reg) &&
2154                ic[-1].arg[0] == (size_t)(&cpu->cd.arm.r[2]) &&
2155                ic[-1].arg[1] == (size_t)arm_r_r3_t0_c0 &&
2156                ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[3])) {
2157                    ic[-2].f = instr(netbsd_scanc);
2158          }          }
2159  }  }
2160    
2161    
2162  /*  /*
2163   *  arm_combine_test2():   *  Combine: strlen():
2164   */   */
2165  void arm_combine_test2(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)  void COMBINE(strlen)(struct cpu *cpu,
2166            struct arm_instr_call *ic, int low_addr)
2167  {  {
2168          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2169              & (ARM_IC_ENTRIES_PER_PAGE-1);              & (ARM_IC_ENTRIES_PER_PAGE-1);
2170    
2171          if (n_back >= 2) {          if (n_back < 2)
2172                  if (ic[-2].f == instr(store_w0_word_u1_p0_imm) &&                  return;
2173                      ic[-2].arg[1] == 4 &&  
2174                      ic[-1].f == instr(subs) &&          if (ic[-2].f == instr(load_w1_byte_u1_p1_imm) &&
2175                      ic[-1].arg[0] == ic[-1].arg[2] && ic[-1].arg[1] == 4 &&              ic[-2].arg[1] == 1 &&
2176                      ic[ 0].f == instr(b_samepage__gt) &&              ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[3]) &&
2177                      ic[ 0].arg[0] == (size_t)&ic[-2]) {              ic[-1].f == instr(cmps) &&
2178                          ic[-2].f = instr(fill_loop_test2);              ic[-1].arg[0] == (size_t)(&cpu->cd.arm.r[3]) &&
2179  printf("YO test2\n");              ic[-1].arg[1] == 0) {
2180                          combined;                  ic[-2].f = instr(strlen);
                 }  
2181          }          }
2182  }  }
2183    
2184    
2185  #if 0  /*
2186          /*  TODO: This is another test hack.  */   *  Combine: xchg():
2187     */
2188    void COMBINE(xchg)(struct cpu *cpu,
2189            struct arm_instr_call *ic, int low_addr)
2190    {
2191            int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2192                & (ARM_IC_ENTRIES_PER_PAGE-1);
2193            size_t a, b;
2194    
2195          if (n_back >= 3) {          if (n_back < 2)
2196                  if (ic[-3].f == instr(cmps) &&                  return;
2197                      ic[-3].arg[0] == ic[-1].arg[0] &&  
2198                      ic[-3].arg[1] == 0 &&          a = ic[-2].arg[0]; b = ic[-1].arg[0];
2199                      ic[-2].f == instr(store_w0_byte_u1_p0_imm) &&  
2200                      ic[-2].arg[1] == 1 &&          if (ic[-2].f == instr(eor_regshort) &&
2201                      ic[-1].f == instr(sub) &&              ic[-1].f == instr(eor_regshort) &&
2202                      ic[-1].arg[0] == ic[-1].arg[2] && ic[-1].arg[1] == 1 &&              ic[-2].arg[0] == a && ic[-2].arg[1] == b && ic[-2].arg[2] == b &&
2203                      ic[ 0].f == instr(b_samepage__gt) &&              ic[-1].arg[0] == b && ic[-1].arg[1] == a && ic[-1].arg[2] == a &&
2204                      ic[ 0].arg[0] == (size_t)&ic[-3]) {              ic[ 0].arg[0] == a && ic[ 0].arg[1] == b && ic[ 0].arg[2] == b) {
2205                          ic[-3].f = instr(fill_loop_test);                  ic[-2].f = instr(xchg);
2206                          combined;          }
2207                  }  }
2208    
2209    
2210    /*
2211     *  Combine: netbsd_copyin():
2212     */
2213    void COMBINE(netbsd_copyin)(struct cpu *cpu,
2214            struct arm_instr_call *ic, int low_addr)
2215    {
2216    #ifdef HOST_LITTLE_ENDIAN
2217            int i, n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2218                & (ARM_IC_ENTRIES_PER_PAGE-1);
2219    
2220            if (n_back < 5)
2221                    return;
2222    
2223            for (i=-5; i<0; i++) {
2224                    if (ic[i].f != instr(load_w1_word_u1_p0_imm) ||
2225                        ic[i].arg[0] != (size_t)(&cpu->cd.arm.r[0]) ||
2226                        ic[i].arg[1] != 4)
2227                            return;
2228            }
2229    
2230            if (ic[-5].arg[2] == (size_t)(&cpu->cd.arm.r[10]) &&
2231                ic[-4].arg[2] == (size_t)(&cpu->cd.arm.r[11]) &&
2232                ic[-3].arg[2] == (size_t)(&cpu->cd.arm.r[6]) &&
2233                ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[7]) &&
2234                ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[8])) {
2235                    ic[-5].f = instr(netbsd_copyin);
2236            }
2237    #endif
2238    }
2239    
2240    
2241    /*
2242     *  Combine: netbsd_copyout():
2243     */
2244    void COMBINE(netbsd_copyout)(struct cpu *cpu,
2245            struct arm_instr_call *ic, int low_addr)
2246    {
2247    #ifdef HOST_LITTLE_ENDIAN
2248            int i, n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2249                & (ARM_IC_ENTRIES_PER_PAGE-1);
2250    
2251            if (n_back < 5)
2252                    return;
2253    
2254            for (i=-5; i<0; i++) {
2255                    if (ic[i].f != instr(store_w1_word_u1_p0_imm) ||
2256                        ic[i].arg[0] != (size_t)(&cpu->cd.arm.r[1]) ||
2257                        ic[i].arg[1] != 4)
2258                            return;
2259            }
2260    
2261            if (ic[-5].arg[2] == (size_t)(&cpu->cd.arm.r[8]) &&
2262                ic[-4].arg[2] == (size_t)(&cpu->cd.arm.r[9]) &&
2263                ic[-3].arg[2] == (size_t)(&cpu->cd.arm.r[10]) &&
2264                ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[11]) &&
2265                ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[6])) {
2266                    ic[-5].f = instr(netbsd_copyout);
2267          }          }
         /*  TODO: Combine forward as well  */  
2268  #endif  #endif
2269    }
2270    
2271    
2272    /*
2273     *  Combine: cmps_b():
2274     */
2275    void COMBINE(cmps_b)(struct cpu *cpu,
2276            struct arm_instr_call *ic, int low_addr)
2277    {
2278            int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
2279                & (ARM_IC_ENTRIES_PER_PAGE-1);
2280            if (n_back < 1)
2281                    return;
2282            if (ic[0].f == instr(b__eq)) {
2283                    if (ic[-1].f == instr(cmps)) {
2284                            if (ic[-1].arg[1] == 0)
2285                                    ic[-1].f = instr(cmps_0_beq);
2286                            else if (ic[-1].arg[1] & 0x80000000)
2287                                    ic[-1].f = instr(cmps_neg_beq);
2288                            else
2289                                    ic[-1].f = instr(cmps_pos_beq);
2290                    }
2291                    return;
2292            }
2293            if (ic[0].f == instr(b_samepage__eq)) {
2294                    if (ic[-1].f == instr(cmps)) {
2295                            if (ic[-1].arg[1] == 0)
2296                                    ic[-1].f = instr(cmps0_beq_samepage);
2297                            else
2298                                    ic[-1].f = instr(cmps_beq_samepage);
2299                    }
2300                    if (ic[-1].f == instr(tsts) &&
2301                        !(ic[-1].arg[1] & 0x80000000)) {
2302                            ic[-1].f = instr(tsts_lo_beq_samepage);
2303                    }
2304                    if (ic[-1].f == instr(teqs)) {
2305                            ic[-1].f = instr(teqs_beq_samepage);
2306                    }
2307                    return;
2308            }
2309            if (ic[0].f == instr(b_samepage__ne)) {
2310                    if (ic[-1].f == instr(cmps)) {
2311                            if (ic[-1].arg[1] == 0)
2312                                    ic[-1].f = instr(cmps0_bne_samepage);
2313                            else
2314                                    ic[-1].f = instr(cmps_bne_samepage);
2315                    }
2316                    if (ic[-1].f == instr(tsts) &&
2317                        !(ic[-1].arg[1] & 0x80000000)) {
2318                            ic[-1].f = instr(tsts_lo_bne_samepage);
2319                    }
2320                    if (ic[-1].f == instr(teqs)) {
2321                            ic[-1].f = instr(teqs_bne_samepage);
2322                    }
2323                    return;
2324            }
2325            if (ic[0].f == instr(b_samepage__cc)) {
2326                    if (ic[-1].f == instr(cmps)) {
2327                            ic[-1].f = instr(cmps_bcc_samepage);
2328                    }
2329                    if (ic[-1].f == instr(cmps_regshort)) {
2330                            ic[-1].f = instr(cmps_reg_bcc_samepage);
2331                    }
2332                    return;
2333            }
2334            if (ic[0].f == instr(b_samepage__hi)) {
2335                    if (ic[-1].f == instr(cmps)) {
2336                            ic[-1].f = instr(cmps_bhi_samepage);
2337                    }
2338                    if (ic[-1].f == instr(cmps_regshort)) {
2339                            ic[-1].f = instr(cmps_reg_bhi_samepage);
2340                    }
2341                    return;
2342            }
2343            if (ic[0].f == instr(b_samepage__gt)) {
2344                    if (ic[-1].f == instr(cmps)) {
2345                            ic[-1].f = instr(cmps_bgt_samepage);
2346                    }
2347                    return;
2348            }
2349            if (ic[0].f == instr(b_samepage__le)) {
2350                    if (ic[-1].f == instr(cmps)) {
2351                            ic[-1].f = instr(cmps_ble_samepage);
2352                    }
2353                    return;
2354            }
2355    }
2356    
2357    
2358    /*****************************************************************************/
2359    
2360    
2361    static void arm_switch_clear(struct arm_instr_call *ic, int rd,
2362            int condition_code)
2363    {
2364            switch (rd) {
2365            case  0: ic->f = cond_instr(clear_r0); break;
2366            case  1: ic->f = cond_instr(clear_r1); break;
2367            case  2: ic->f = cond_instr(clear_r2); break;
2368            case  3: ic->f = cond_instr(clear_r3); break;
2369            case  4: ic->f = cond_instr(clear_r4); break;
2370            case  5: ic->f = cond_instr(clear_r5); break;
2371            case  6: ic->f = cond_instr(clear_r6); break;
2372            case  7: ic->f = cond_instr(clear_r7); break;
2373            case  8: ic->f = cond_instr(clear_r8); break;
2374            case  9: ic->f = cond_instr(clear_r9); break;
2375            case 10: ic->f = cond_instr(clear_r10); break;
2376            case 11: ic->f = cond_instr(clear_r11); break;
2377            case 12: ic->f = cond_instr(clear_r12); break;
2378            case 13: ic->f = cond_instr(clear_r13); break;
2379            case 14: ic->f = cond_instr(clear_r14); break;
2380            }
2381    }
2382    
2383    
2384    static void arm_switch_mov1(struct arm_instr_call *ic, int rd,
2385            int condition_code)
2386    {
2387            switch (rd) {
2388            case  0: ic->f = cond_instr(mov1_r0); break;
2389            case  1: ic->f = cond_instr(mov1_r1); break;
2390            case  2: ic->f = cond_instr(mov1_r2); break;
2391            case  3: ic->f = cond_instr(mov1_r3); break;
2392            case  4: ic->f = cond_instr(mov1_r4); break;
2393            case  5: ic->f = cond_instr(mov1_r5); break;
2394            case  6: ic->f = cond_instr(mov1_r6); break;
2395            case  7: ic->f = cond_instr(mov1_r7); break;
2396            case  8: ic->f = cond_instr(mov1_r8); break;
2397            case  9: ic->f = cond_instr(mov1_r9); break;
2398            case 10: ic->f = cond_instr(mov1_r10); break;
2399            case 11: ic->f = cond_instr(mov1_r11); break;
2400            case 12: ic->f = cond_instr(mov1_r12); break;
2401            case 13: ic->f = cond_instr(mov1_r13); break;
2402            case 14: ic->f = cond_instr(mov1_r14); break;
2403            }
2404    }
2405    
2406    
2407    static void arm_switch_add1(struct arm_instr_call *ic, int rd,
2408            int condition_code)
2409    {
2410            switch (rd) {
2411            case  0: ic->f = cond_instr(add1_r0); break;
2412            case  1: ic->f = cond_instr(add1_r1); break;
2413            case  2: ic->f = cond_instr(add1_r2); break;
2414            case  3: ic->f = cond_instr(add1_r3); break;
2415            case  4: ic->f = cond_instr(add1_r4); break;
2416            case  5: ic->f = cond_instr(add1_r5); break;
2417            case  6: ic->f = cond_instr(add1_r6); break;
2418            case  7: ic->f = cond_instr(add1_r7); break;
2419            case  8: ic->f = cond_instr(add1_r8); break;
2420            case  9: ic->f = cond_instr(add1_r9); break;
2421            case 10: ic->f = cond_instr(add1_r10); break;
2422            case 11: ic->f = cond_instr(add1_r11); break;
2423            case 12: ic->f = cond_instr(add1_r12); break;
2424            case 13: ic->f = cond_instr(add1_r13); break;
2425            case 14: ic->f = cond_instr(add1_r14); break;
2426            }
2427    }
2428    
2429    
2430  /*****************************************************************************/  /*****************************************************************************/
# Line 1762  X(to_be_translated) Line 2444  X(to_be_translated)
2444          unsigned char *page;          unsigned char *page;
2445          unsigned char ib[4];          unsigned char ib[4];
2446          int condition_code, main_opcode, secondary_opcode, s_bit, rn, rd, r8;          int condition_code, main_opcode, secondary_opcode, s_bit, rn, rd, r8;
2447          int p_bit, u_bit, b_bit, w_bit, l_bit, regform, rm, c, t, any_pc_reg;          int p_bit, u_bit, w_bit, l_bit, regform, rm, c, t, any_pc_reg;
2448          void (*samepage_function)(struct cpu *, struct arm_instr_call *);          void (*samepage_function)(struct cpu *, struct arm_instr_call *);
2449    
2450          /*  Figure out the address of the instruction:  */          /*  Figure out the address of the instruction:  */
2451          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)
2452              / sizeof(struct arm_instr_call);              / sizeof(struct arm_instr_call);
2453          addr = cpu->cd.arm.r[ARM_PC] & ~((ARM_IC_ENTRIES_PER_PAGE-1) <<          addr = cpu->pc & ~((ARM_IC_ENTRIES_PER_PAGE-1) <<
2454              ARM_INSTR_ALIGNMENT_SHIFT);              ARM_INSTR_ALIGNMENT_SHIFT);
2455          addr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          addr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
2456          cpu->pc = cpu->cd.arm.r[ARM_PC] = addr;          cpu->pc = addr;
2457          addr &= ~((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);          addr &= ~((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);
2458    
2459          /*  Read the instruction word from memory:  */          /*  Read the instruction word from memory:  */
2460          page = cpu->cd.arm.host_load[addr >> 12];          page = cpu->cd.arm.host_load[addr >> 12];
2461          if (page != NULL) {          if (page != NULL) {
2462                  /*  fatal("TRANSLATION HIT!\n");  */                  /*  fatal("TRANSLATION HIT! 0x%08x\n", addr);  */
2463                  memcpy(ib, page + (addr & 0xfff), sizeof(ib));                  memcpy(ib, page + (addr & 0xfff), sizeof(ib));
2464          } else {          } else {
2465                  /*  fatal("TRANSLATION MISS!\n");  */                  /*  fatal("TRANSLATION MISS! 0x%08x\n", addr);  */
2466                  if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],                  if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],
2467                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {                      sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
2468                          fatal("to_be_translated(): "                          fatal("to_be_translated(): "
# Line 1805  X(to_be_translated) Line 2487  X(to_be_translated)
2487          condition_code = iword >> 28;          condition_code = iword >> 28;
2488          main_opcode = (iword >> 24) & 15;          main_opcode = (iword >> 24) & 15;
2489          secondary_opcode = (iword >> 21) & 15;          secondary_opcode = (iword >> 21) & 15;
2490          u_bit = (iword >> 23) & 1;          u_bit = iword & 0x00800000;
2491          b_bit = (iword >> 22) & 1;          w_bit = iword & 0x00200000;
2492          w_bit = (iword >> 21) & 1;          s_bit = l_bit = iword & 0x00100000;
         s_bit = l_bit = (iword >> 20) & 1;  
2493          rn    = (iword >> 16) & 15;          rn    = (iword >> 16) & 15;
2494          rd    = (iword >> 12) & 15;          rd    = (iword >> 12) & 15;
2495          r8    = (iword >> 8) & 15;          r8    = (iword >> 8) & 15;
# Line 1873  X(to_be_translated) Line 2554  X(to_be_translated)
2554                          ic->arg[0] = iword;                          ic->arg[0] = iword;
2555                          break;                          break;
2556                  }                  }
2557                    if ((iword & 0x0f900ff0) == 0x01000050) {
2558                            fatal("TODO: q{,d}{add,sub}\n");
2559                            goto bad;
2560                    }
2561                  if ((iword & 0x0ff000d0) == 0x01200010) {                  if ((iword & 0x0ff000d0) == 0x01200010) {
2562                          /*  bx or blx  */                          /*  bx or blx  */
2563                          if (iword & 0x20)                          if (iword & 0x20)
# Line 1897  X(to_be_translated) Line 2582  X(to_be_translated)
2582                          ic->arg[2] = (size_t)(&cpu->cd.arm.r[rn]);                          ic->arg[2] = (size_t)(&cpu->cd.arm.r[rn]);
2583                          break;                          break;
2584                  }                  }
2585                    if ((iword & 0x0fff0ff0) == 0x016f0f10) {
2586                            ic->f = cond_instr(clz);
2587                            ic->arg[0] = (size_t)(&cpu->cd.arm.r[rm]);
2588                            ic->arg[1] = (size_t)(&cpu->cd.arm.r[rd]);
2589                            break;
2590                    }
2591                    if ((iword & 0x0ff00090) == 0x01000080) {
2592                            /*  TODO: smlaXX  */
2593                            goto bad;
2594                    }
2595                    if ((iword & 0x0ff00090) == 0x01400080) {
2596                            /*  TODO: smlalY  */
2597                            goto bad;
2598                    }
2599                    if ((iword & 0x0ff000b0) == 0x01200080) {
2600                            /*  TODO: smlawY  */
2601                            goto bad;
2602                    }
2603                    if ((iword & 0x0ff0f090) == 0x01600080) {
2604                            /*  smulXY (16-bit * 16-bit => 32-bit)  */
2605                            switch (iword & 0x60) {
2606                            case 0x00: ic->f = cond_instr(smulbb); break;
2607                            case 0x20: ic->f = cond_instr(smultb); break;
2608                            case 0x40: ic->f = cond_instr(smulbt); break;
2609                            default:   ic->f = cond_instr(smultt); break;
2610                            }
2611                            ic->arg[0] = (size_t)(&cpu->cd.arm.r[rm]);
2612                            ic->arg[1] = (size_t)(&cpu->cd.arm.r[r8]);
2613                            ic->arg[2] = (size_t)(&cpu->cd.arm.r[rn]); /*  Rd  */
2614                            break;
2615                    }
2616                    if ((iword & 0x0ff0f0b0) == 0x012000a0) {
2617                            /*  TODO: smulwY  */
2618                            goto bad;
2619                    }
2620                  if ((iword & 0x0fb0fff0) == 0x0120f000 ||                  if ((iword & 0x0fb0fff0) == 0x0120f000 ||
2621                      (iword & 0x0fb0f000) == 0x0320f000) {                      (iword & 0x0fb0f000) == 0x0320f000) {
2622                          /*  msr: move to [S|C]PSR from a register or                          /*  msr: move to [S|C]PSR from a register or
2623                              immediate value  */                              immediate value  */
                         if (rm == ARM_PC) {  
                                 fatal("msr PC?\n");  
                                 goto bad;  
                         }  
2624                          if (iword & 0x02000000) {                          if (iword & 0x02000000) {
2625                                  if (iword & 0x00400000)                                  if (iword & 0x00400000)
2626                                          ic->f = cond_instr(msr_imm_spsr);                                          ic->f = cond_instr(msr_imm_spsr);
2627                                  else                                  else
2628                                          ic->f = cond_instr(msr_imm);                                          ic->f = cond_instr(msr_imm);
2629                          } else {                          } else {
2630                                    if (rm == ARM_PC) {
2631                                            fatal("msr PC?\n");
2632                                            goto bad;
2633                                    }
2634                                  if (iword & 0x00400000)                                  if (iword & 0x00400000)
2635                                          ic->f = cond_instr(msr_spsr);                                          ic->f = cond_instr(msr_spsr);
2636                                  else                                  else
# Line 1992  X(to_be_translated) Line 2712  X(to_be_translated)
2712                          break;                          break;
2713                  }                  }
2714    
2715                  /*  "mov reg,reg":  */                  /*  "mov reg,reg" or "mov reg,pc":  */
2716                  if ((iword & 0x0fff0ff0) == 0x01a00000 &&                  if ((iword & 0x0fff0ff0) == 0x01a00000 && rd != ARM_PC) {
2717                      (iword&15) != ARM_PC && rd != ARM_PC) {                          if (rm != ARM_PC) {
2718                          ic->f = cond_instr(mov_reg_reg);                                  ic->f = cond_instr(mov_reg_reg);
2719                          ic->arg[0] = (size_t)(&cpu->cd.arm.r[iword & 15]);                                  ic->arg[0] = (size_t)(&cpu->cd.arm.r[rm]);
2720                            } else {
2721                                    ic->f = cond_instr(mov_reg_pc);
2722                                    ic->arg[0] = (addr & 0xfff) + 8;
2723                            }
2724                          ic->arg[1] = (size_t)(&cpu->cd.arm.r[rd]);                          ic->arg[1] = (size_t)(&cpu->cd.arm.r[rd]);
2725                          break;                          break;
2726                  }                  }
2727    
2728                  /*  "mov reg,#0":  */                  /*  "mov reg,#0":  */
2729                  if ((iword & 0x0fff0fff) == 0x03a03000 && rd != ARM_PC) {                  if ((iword & 0x0fff0fff) == 0x03a00000 && rd != ARM_PC) {
2730                          switch (rd) {                          arm_switch_clear(ic, rd, condition_code);
                         case  0: ic->f = cond_instr(clear_r0); break;  
                         case  1: ic->f = cond_instr(clear_r1); break;  
                         case  2: ic->f = cond_instr(clear_r2); break;  
                         case  3: ic->f = cond_instr(clear_r3); break;  
                         case  4: ic->f = cond_instr(clear_r4); break;  
                         case  5: ic->f = cond_instr(clear_r5); break;  
                         case  6: ic->f = cond_instr(clear_r6); break;  
                         case  7: ic->f = cond_instr(clear_r7); break;  
                         case  8: ic->f = cond_instr(clear_r8); break;  
                         case  9: ic->f = cond_instr(clear_r9); break;  
                         case 10: ic->f = cond_instr(clear_r10); break;  
                         case 11: ic->f = cond_instr(clear_r11); break;  
                         case 12: ic->f = cond_instr(clear_r12); break;  
                         case 13: ic->f = cond_instr(clear_r13); break;  
                         case 14: ic->f = cond_instr(clear_r14); break;  
                         }  
2731                          break;                          break;
2732                  }                  }
2733    
2734                  /*  "mov reg,#1":  */                  /*  "mov reg,#1":  */
2735                  if ((iword & 0x0fff0fff) == 0x03a03001 && rd != ARM_PC) {                  if ((iword & 0x0fff0fff) == 0x03a00001 && rd != ARM_PC) {
2736                          switch (rd) {                          arm_switch_mov1(ic, rd, condition_code);
2737                          case  0: ic->f = cond_instr(mov1_r0); break;                          break;
2738                          case  1: ic->f = cond_instr(mov1_r1); break;                  }
2739                          case  2: ic->f = cond_instr(mov1_r2); break;  
2740                          case  3: ic->f = cond_instr(mov1_r3); break;                  /*  "add reg,reg,#1":  */
2741                          case  4: ic->f = cond_instr(mov1_r4); break;                  if ((iword & 0x0ff00fff) == 0x02800001 && rd != ARM_PC
2742                          case  5: ic->f = cond_instr(mov1_r5); break;                      && rn == rd) {
2743                          case  6: ic->f = cond_instr(mov1_r6); break;                          arm_switch_add1(ic, rd, condition_code);
                         case  7: ic->f = cond_instr(mov1_r7); break;  
                         case  8: ic->f = cond_instr(mov1_r8); break;  
                         case  9: ic->f = cond_instr(mov1_r9); break;  
                         case 10: ic->f = cond_instr(mov1_r10); break;  
                         case 11: ic->f = cond_instr(mov1_r11); break;  
                         case 12: ic->f = cond_instr(mov1_r12); break;  
                         case 13: ic->f = cond_instr(mov1_r13); break;  
                         case 14: ic->f = cond_instr(mov1_r14); break;  
                         }  
2744                          break;                          break;
2745                  }                  }
2746    
# Line 2072  X(to_be_translated) Line 2771  X(to_be_translated)
2771                          ic->arg[1] = imm;                          ic->arg[1] = imm;
2772                  }                  }
2773    
2774                    /*  mvn #imm ==> mov #~imm  */
2775                    if (secondary_opcode == 0xf && !regform) {
2776                            secondary_opcode = 0xd;
2777                            ic->arg[1] = ~ic->arg[1];
2778                    }
2779    
2780                  ic->arg[0] = (size_t)(&cpu->cd.arm.r[rn]);                  ic->arg[0] = (size_t)(&cpu->cd.arm.r[rn]);
2781                  ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);                  ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);
2782                  any_pc_reg = 0;                  any_pc_reg = 0;
2783                  if (rn == ARM_PC || rd == ARM_PC)                  if (rn == ARM_PC || rd == ARM_PC)
2784                          any_pc_reg = 1;                          any_pc_reg = 1;
2785    
2786                  ic->f = arm_dpi_instr[condition_code +                  if (!any_pc_reg && regform && (iword & 0xfff) < ARM_PC) {
2787                      16 * secondary_opcode + (s_bit? 256 : 0) +                          ic->arg[1] = (size_t)(&cpu->cd.arm.r[rm]);
2788                      (any_pc_reg? 512 : 0) + (regform? 1024 : 0)];                          ic->f = arm_dpi_instr_regshort[condition_code +
2789                                16 * secondary_opcode + (s_bit? 256 : 0)];
2790                    } else
2791                            ic->f = arm_dpi_instr[condition_code +
2792                                16 * secondary_opcode + (s_bit? 256 : 0) +
2793                                (any_pc_reg? 512 : 0) + (regform? 1024 : 0)];
2794    
2795                    if (ic->f == instr(eor_regshort))
2796                            cpu->cd.arm.combination_check = COMBINE(xchg);
2797                  if (iword == 0xe113000c)                  if (iword == 0xe113000c)
2798                          cpu->combination_check = arm_combine_netbsd_scanc;                          cpu->cd.arm.combination_check = COMBINE(netbsd_scanc);
2799                  break;                  break;
2800    
2801          case 0x4:       /*  Load and store...  */          case 0x4:       /*  Load and store...  */
# Line 2112  X(to_be_translated) Line 2824  X(to_be_translated)
2824                          fatal("Not a Load/store TODO\n");                          fatal("Not a Load/store TODO\n");
2825                          goto bad;                          goto bad;
2826                  }                  }
2827                    /*  Special case: pc-relative load within the same page:  */
2828                    if (rn == ARM_PC && rd != ARM_PC && main_opcode < 6) {
2829                            int ofs = (addr & 0xfff) + 8, max = 0xffc;
2830                            int b_bit = iword & 0x00400000;
2831                            if (b_bit)
2832                                    max = 0xfff;
2833                            if (u_bit)
2834                                    ofs += (iword & 0xfff);
2835                            else
2836                                    ofs -= (iword & 0xfff);
2837                            /*  NOTE/TODO: This assumes 4KB pages,
2838                                it will not work with 1KB pages.  */
2839                            if (ofs >= 0 && ofs <= max) {
2840                                    unsigned char *p;
2841                                    unsigned char c[4];
2842                                    int len = b_bit? 1 : 4;
2843                                    uint32_t x, a = (addr & 0xfffff000) | ofs;
2844                                    /*  ic->f = cond_instr(mov);  */
2845                                    ic->f = arm_dpi_instr[condition_code + 16*0xd];
2846                                    ic->arg[2] = (size_t)(&cpu->cd.arm.r[rd]);
2847                                    p = cpu->cd.arm.host_load[a >> 12];
2848                                    if (p != NULL) {
2849                                            memcpy(c, p + (a & 0xfff), len);
2850                                    } else {
2851                                            if (!cpu->memory_rw(cpu, cpu->mem, a,
2852                                                c, len, MEM_READ, CACHE_DATA)) {
2853                                                    fatal("to_be_translated(): "
2854                                                        "read failed X: TODO\n");
2855                                                    goto bad;
2856                                            }
2857                                    }
2858                                    if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2859                                            x = c[0] + (c[1]<<8) +
2860                                                (c[2]<<16) + (c[3]<<24);
2861                                    else
2862                                            x = c[3] + (c[2]<<8) +
2863                                                (c[1]<<16) + (c[0]<<24);
2864                                    if (b_bit)
2865                                            x = c[0];
2866                                    ic->arg[1] = x;
2867                            }
2868                    }
2869                    if (iword == 0xe4b09004)
2870                            cpu->cd.arm.combination_check = COMBINE(netbsd_copyin);
2871                    if (iword == 0xe4a17004)
2872                            cpu->cd.arm.combination_check = COMBINE(netbsd_copyout);
2873                  break;                  break;
2874    
2875          case 0x8:       /*  Multiple load/store...  (Block data transfer)  */          case 0x8:       /*  Multiple load/store...  (Block data transfer)  */
# Line 2162  X(to_be_translated) Line 2920  X(to_be_translated)
2920                  if (main_opcode == 0x0a) {                  if (main_opcode == 0x0a) {
2921                          ic->f = cond_instr(b);                          ic->f = cond_instr(b);
2922                          samepage_function = cond_instr(b_samepage);                          samepage_function = cond_instr(b_samepage);
                         /*  if (iword == 0xcafffffc)  
                                 cpu->combination_check = arm_combine_test2;  */  
2923                          if (iword == 0xcaffffed)                          if (iword == 0xcaffffed)
2924                                  cpu->combination_check =                                  cpu->cd.arm.combination_check =
2925                                      arm_combine_netbsd_memset;                                      COMBINE(netbsd_memset);
2926                          if (iword == 0xaafffff9)                          if (iword == 0xaafffff9)
2927                                  cpu->combination_check =                                  cpu->cd.arm.combination_check =
2928                                      arm_combine_netbsd_memcpy;                                      COMBINE(netbsd_memcpy);
2929                  } else {                  } else {
2930                          if (cpu->machine->show_trace_tree) {                          if (cpu->machine->show_trace_tree) {
2931                                  ic->f = cond_instr(bl_trace);                                  ic->f = cond_instr(bl_trace);
# Line 2181  X(to_be_translated) Line 2937  X(to_be_translated)
2937                          }                          }
2938                  }                  }
2939    
2940                    /*  arg 1 = offset of current instruction  */
2941                    /*  arg 2 = offset of the following instruction  */
2942                    ic->arg[1] = addr & 0xffc;
2943                    ic->arg[2] = (addr & 0xffc) + 4;
2944    
2945                  ic->arg[0] = (iword & 0x00ffffff) << 2;                  ic->arg[0] = (iword & 0x00ffffff) << 2;
2946                  /*  Sign-extend:  */                  /*  Sign-extend:  */
2947                  if (ic->arg[0] & 0x02000000)                  if (ic->arg[0] & 0x02000000)
# Line 2190  X(to_be_translated) Line 2951  X(to_be_translated)
2951                   */                   */
2952                  ic->arg[0] = (int32_t)(ic->arg[0] + 8);                  ic->arg[0] = (int32_t)(ic->arg[0] + 8);
2953    
2954                  /*  Special case: branch within the same page:  */                  /*
2955                     *  Special case: branch within the same page:
2956                     *
2957                     *  arg[0] = addr of the arm_instr_call of the target
2958                     *  arg[1] = addr of the next arm_instr_call.
2959                     */
2960                  {                  {
2961                          uint32_t mask_within_page =                          uint32_t mask_within_page =
2962                              ((ARM_IC_ENTRIES_PER_PAGE-1) <<                              ((ARM_IC_ENTRIES_PER_PAGE-1) <<
# Line 2205  X(to_be_translated) Line 2971  X(to_be_translated)
2971                                      cpu->cd.arm.cur_ic_page +                                      cpu->cd.arm.cur_ic_page +
2972                                      ((new_pc & mask_within_page) >>                                      ((new_pc & mask_within_page) >>
2973                                      ARM_INSTR_ALIGNMENT_SHIFT));                                      ARM_INSTR_ALIGNMENT_SHIFT));
2974                                    ic->arg[1] = (size_t) (
2975                                        cpu->cd.arm.cur_ic_page +
2976                                        (((addr & mask_within_page) + 4) >>
2977                                        ARM_INSTR_ALIGNMENT_SHIFT));
2978                            } else if (main_opcode == 0x0a) {
2979                                    /*  Special hack for a plain "b":  */
2980                                    ic->arg[0] += ic->arg[1];
2981                          }                          }
2982                  }                  }
2983    
2984  #if 0                  if (main_opcode == 0xa && (condition_code <= 1
2985                  /*  Hm. This doesn't really increase performance.  */                      || condition_code == 3 || condition_code == 8
2986                        || condition_code == 12 || condition_code == 13))
2987                            cpu->cd.arm.combination_check = COMBINE(cmps_b);
2988    
2989                    if (iword == 0x1afffffc)
2990                            cpu->cd.arm.combination_check = COMBINE(strlen);
2991    
2992                    /*  Hm. Does this really increase performance?  */
2993                  if (iword == 0x8afffffa)                  if (iword == 0x8afffffa)
2994                          cpu->combination_check = arm_combine_netbsd_cacheclean2;                          cpu->cd.arm.combination_check =
2995                                COMBINE(netbsd_cacheclean2);
2996                    break;
2997    
2998            case 0xc:
2999            case 0xd:
3000                    /*
3001                     *  xxxx1100 0100nnnn ddddcccc oooommmm    MCRR c,op,Rd,Rn,CRm
3002                     *  xxxx1100 0101nnnn ddddcccc oooommmm    MRRC c,op,Rd,Rn,CRm
3003                     */
3004                    if ((iword & 0x0fe00fff) == 0x0c400000) {
3005                            /*  Special case: mar/mra DSP instructions  */
3006                            fatal("TODO: mar/mra DSP instructions!\n");
3007                            /*  Perhaps these are actually identical to MCRR/MRRC */
3008                            goto bad;
3009                    }
3010    
3011                    if ((iword & 0x0fe00000) == 0x0c400000) {
3012                            fatal("MCRR/MRRC: TODO\n");
3013                            goto bad;
3014                    }
3015    
3016                    /*
3017                     *  TODO: LDC/STC
3018                     *
3019                     *  For now, treat as Undefined instructions. This causes e.g.
3020                     *  Linux/ARM to emulate these instructions (floating point).
3021                     */
3022    #if 0
3023                    ic->f = cond_instr(und);
3024                    ic->arg[0] = addr & 0xfff;
3025    #else
3026                    fatal("LDC/STC: TODO\n");
3027                    goto bad;
3028  #endif  #endif
3029                  break;                  break;
3030    
3031          case 0xe:          case 0xe:
3032                    if ((iword & 0x0ff00ff0) == 0x0e200010) {
3033                            /*  Special case: mia* DSP instructions  */
3034                            /*  See Intel's 27343601.pdf, page 16-20  */
3035                            fatal("TODO: mia* DSP instructions!\n");
3036                            goto bad;
3037                    }
3038                  if (iword & 0x10) {                  if (iword & 0x10) {
3039                          /*  xxxx1110 oooLNNNN ddddpppp qqq1MMMM  MCR/MRC  */                          /*  xxxx1110 oooLNNNN ddddpppp qqq1MMMM  MCR/MRC  */
3040                          ic->arg[0] = iword;                          ic->arg[0] = iword;
# Line 2226  X(to_be_translated) Line 3045  X(to_be_translated)
3045                          ic->f = cond_instr(cdp);                          ic->f = cond_instr(cdp);
3046                  }                  }
3047                  if (iword == 0xee070f9a)                  if (iword == 0xee070f9a)
3048                          cpu->combination_check = arm_combine_netbsd_cacheclean;                          cpu->cd.arm.combination_check =
3049                                COMBINE(netbsd_cacheclean);
3050                  break;                  break;
3051    
3052          case 0xf:          case 0xf:
3053                  /*  SWI:  */                  /*  SWI:  */
3054                  /*  Default handler:  */                  /*  Default handler:  */
3055                  ic->f = cond_instr(swi);                  ic->f = cond_instr(swi);
3056                  if (iword == 0xef8c64be) {                  ic->arg[0] = addr & 0xfff;
3057                    if (iword == 0xef8c64eb) {
3058                            /*  Hack for rebooting a machine:  */
3059                            ic->f = instr(reboot);
3060                    } else if (iword == 0xef8c64be) {
3061                          /*  Hack for openfirmware prom emulation:  */                          /*  Hack for openfirmware prom emulation:  */
3062                          ic->f = instr(openfirmware);                          ic->f = instr(openfirmware);
3063                  } else if (cpu->machine->userland_emul != NULL) {                  } else if (cpu->machine->userland_emul != NULL) {

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

  ViewVC Help
Powered by ViewVC 1.1.26