/[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 20 by dpavlin, Mon Oct 8 16:19:23 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.54 2005/11/19 18:53:07 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 203  uint8_t condition_gt[16] = { 1,0,1,0, 0, Line 205  uint8_t condition_gt[16] = { 1,0,1,0, 0,
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)
# Line 215  X(invalid) { Line 215  X(invalid) {
215              << ARM_INSTR_ALIGNMENT_SHIFT);              << ARM_INSTR_ALIGNMENT_SHIFT);
216          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
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
# Line 587  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 725  X(msr_imm_spsr) Line 766  X(msr_imm_spsr)
766          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << ARM_INSTR_ALIGNMENT_SHIFT);
767          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
768          old_pc = cpu->pc;          old_pc = cpu->pc;
769          printf("msr_spsr: old pc = 0x%08x\n", old_pc);          printf("msr_spsr: old pc = 0x%08"PRIx32"\n", old_pc);
770  }  }
771                  exit(1);                  exit(1);
772          }          }
# Line 820  X(openfirmware) Line 861  X(openfirmware)
861  X(reboot)  X(reboot)
862  {  {
863          cpu->running = 0;          cpu->running = 0;
         cpu->running_translated = 0;  
864          cpu->n_translated_instrs --;          cpu->n_translated_instrs --;
865          cpu->cd.arm.next_ic = &nothing_call;          cpu->cd.arm.next_ic = &nothing_call;
866  }  }
# Line 844  X(swi_useremul) Line 884  X(swi_useremul)
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 1289  Y(bdt_store) Line 1328  Y(bdt_store)
1328    
1329    
1330  /*  Various load/store multiple instructions:  */  /*  Various load/store multiple instructions:  */
1331  uint32_t *multi_opcode[256];  extern uint32_t *multi_opcode[256];
1332  void (**multi_opcode_f[256])(struct cpu *, struct arm_instr_call *);  extern void (**multi_opcode_f[256])(struct cpu *, struct arm_instr_call *);
1333  X(multi_0x08b15018);  X(multi_0x08b15018);
1334  X(multi_0x08ac000c__ge);  X(multi_0x08ac000c__ge);
1335  X(multi_0x08a05018);  X(multi_0x08a05018);
# Line 1991  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,  void COMBINE(netbsd_memset)(struct cpu *cpu,
2039          struct arm_instr_call *ic, int low_addr)          struct arm_instr_call *ic, int low_addr)
2040  {  {
2041  #ifdef HOST_LITTLE_ENDIAN  #ifdef HOST_LITTLE_ENDIAN
# Line 2013  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  #endif
# Line 2021  void arm_combine_netbsd_memset(struct cp Line 2059  void arm_combine_netbsd_memset(struct cp
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,  void COMBINE(netbsd_memcpy)(struct cpu *cpu, struct arm_instr_call *ic,
2068          struct arm_instr_call *ic, int low_addr)          int low_addr)
2069  {  {
2070  #ifdef HOST_LITTLE_ENDIAN  #ifdef HOST_LITTLE_ENDIAN
2071          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
# Line 2043  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  #endif
# Line 2051  void arm_combine_netbsd_memcpy(struct cp Line 2088  void arm_combine_netbsd_memcpy(struct cp
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,  void COMBINE(netbsd_cacheclean)(struct cpu *cpu,
2096          struct arm_instr_call *ic, 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)
# Line 2068  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,  void COMBINE(netbsd_cacheclean2)(struct cpu *cpu,
2119          struct arm_instr_call *ic, 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)
# Line 2093  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,  void COMBINE(netbsd_scanc)(struct cpu *cpu,
2141          struct arm_instr_call *ic, 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)
# Line 2120  void arm_combine_netbsd_scanc(struct cpu Line 2155  void arm_combine_netbsd_scanc(struct cpu
2155              ic[-1].arg[1] == (size_t)arm_r_r3_t0_c0 &&              ic[-1].arg[1] == (size_t)arm_r_r3_t0_c0 &&
2156              ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[3])) {              ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[3])) {
2157                  ic[-2].f = instr(netbsd_scanc);                  ic[-2].f = instr(netbsd_scanc);
                 combined;  
2158          }          }
2159  }  }
2160    
2161    
2162  /*  /*
2163   *  arm_combine_strlen():   *  Combine: strlen():
2164   */   */
2165  void arm_combine_strlen(struct cpu *cpu,  void COMBINE(strlen)(struct cpu *cpu,
2166          struct arm_instr_call *ic, int low_addr)          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)
# Line 2144  void arm_combine_strlen(struct cpu *cpu, Line 2178  void arm_combine_strlen(struct cpu *cpu,
2178              ic[-1].arg[0] == (size_t)(&cpu->cd.arm.r[3]) &&              ic[-1].arg[0] == (size_t)(&cpu->cd.arm.r[3]) &&
2179              ic[-1].arg[1] == 0) {              ic[-1].arg[1] == 0) {
2180                  ic[-2].f = instr(strlen);                  ic[-2].f = instr(strlen);
                 combined;  
2181          }          }
2182  }  }
2183    
2184    
2185  /*  /*
2186   *  arm_combine_xchg():   *  Combine: xchg():
2187   */   */
2188  void arm_combine_xchg(struct cpu *cpu,  void COMBINE(xchg)(struct cpu *cpu,
2189          struct arm_instr_call *ic, int low_addr)          struct arm_instr_call *ic, int low_addr)
2190  {  {
2191          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
# Line 2170  void arm_combine_xchg(struct cpu *cpu, Line 2203  void arm_combine_xchg(struct cpu *cpu,
2203              ic[-1].arg[0] == b && ic[-1].arg[1] == a && ic[-1].arg[2] == a &&              ic[-1].arg[0] == b && ic[-1].arg[1] == a && ic[-1].arg[2] == a &&
2204              ic[ 0].arg[0] == a && ic[ 0].arg[1] == b && ic[ 0].arg[2] == b) {              ic[ 0].arg[0] == a && ic[ 0].arg[1] == b && ic[ 0].arg[2] == b) {
2205                  ic[-2].f = instr(xchg);                  ic[-2].f = instr(xchg);
                 combined;  
2206          }          }
2207  }  }
2208    
2209    
2210  /*  /*
2211   *  arm_combine_netbsd_copyin():   *  Combine: netbsd_copyin():
2212   */   */
2213  void arm_combine_netbsd_copyin(struct cpu *cpu,  void COMBINE(netbsd_copyin)(struct cpu *cpu,
2214          struct arm_instr_call *ic, int low_addr)          struct arm_instr_call *ic, int low_addr)
2215  {  {
2216  #ifdef HOST_LITTLE_ENDIAN  #ifdef HOST_LITTLE_ENDIAN
# Line 2201  void arm_combine_netbsd_copyin(struct cp Line 2233  void arm_combine_netbsd_copyin(struct cp
2233              ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[7]) &&              ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[7]) &&
2234              ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[8])) {              ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[8])) {
2235                  ic[-5].f = instr(netbsd_copyin);                  ic[-5].f = instr(netbsd_copyin);
                 combined;  
2236          }          }
2237  #endif  #endif
2238  }  }
2239    
2240    
2241  /*  /*
2242   *  arm_combine_netbsd_copyout():   *  Combine: netbsd_copyout():
2243   */   */
2244  void arm_combine_netbsd_copyout(struct cpu *cpu,  void COMBINE(netbsd_copyout)(struct cpu *cpu,
2245          struct arm_instr_call *ic, int low_addr)          struct arm_instr_call *ic, int low_addr)
2246  {  {
2247  #ifdef HOST_LITTLE_ENDIAN  #ifdef HOST_LITTLE_ENDIAN
# Line 2233  void arm_combine_netbsd_copyout(struct c Line 2264  void arm_combine_netbsd_copyout(struct c
2264              ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[11]) &&              ic[-2].arg[2] == (size_t)(&cpu->cd.arm.r[11]) &&
2265              ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[6])) {              ic[-1].arg[2] == (size_t)(&cpu->cd.arm.r[6])) {
2266                  ic[-5].f = instr(netbsd_copyout);                  ic[-5].f = instr(netbsd_copyout);
                 combined;  
2267          }          }
2268  #endif  #endif
2269  }  }
2270    
2271    
2272  /*  /*
2273   *  arm_combine_cmps_b():   *  Combine: cmps_b():
2274   */   */
2275  void arm_combine_cmps_b(struct cpu *cpu,  void COMBINE(cmps_b)(struct cpu *cpu,
2276          struct arm_instr_call *ic, int low_addr)          struct arm_instr_call *ic, int low_addr)
2277  {  {
2278          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
# Line 2257  void arm_combine_cmps_b(struct cpu *cpu, Line 2287  void arm_combine_cmps_b(struct cpu *cpu,
2287                                  ic[-1].f = instr(cmps_neg_beq);                                  ic[-1].f = instr(cmps_neg_beq);
2288                          else                          else
2289                                  ic[-1].f = instr(cmps_pos_beq);                                  ic[-1].f = instr(cmps_pos_beq);
                         combined;  
2290                  }                  }
2291                  return;                  return;
2292          }          }
# Line 2267  void arm_combine_cmps_b(struct cpu *cpu, Line 2296  void arm_combine_cmps_b(struct cpu *cpu,
2296                                  ic[-1].f = instr(cmps0_beq_samepage);                                  ic[-1].f = instr(cmps0_beq_samepage);
2297                          else                          else
2298                                  ic[-1].f = instr(cmps_beq_samepage);                                  ic[-1].f = instr(cmps_beq_samepage);
                         combined;  
2299                  }                  }
2300                  if (ic[-1].f == instr(tsts) &&                  if (ic[-1].f == instr(tsts) &&
2301                      !(ic[-1].arg[1] & 0x80000000)) {                      !(ic[-1].arg[1] & 0x80000000)) {
2302                          ic[-1].f = instr(tsts_lo_beq_samepage);                          ic[-1].f = instr(tsts_lo_beq_samepage);
                         combined;  
2303                  }                  }
2304                  if (ic[-1].f == instr(teqs)) {                  if (ic[-1].f == instr(teqs)) {
2305                          ic[-1].f = instr(teqs_beq_samepage);                          ic[-1].f = instr(teqs_beq_samepage);
                         combined;  
2306                  }                  }
2307                  return;                  return;
2308          }          }
# Line 2286  void arm_combine_cmps_b(struct cpu *cpu, Line 2312  void arm_combine_cmps_b(struct cpu *cpu,
2312                                  ic[-1].f = instr(cmps0_bne_samepage);                                  ic[-1].f = instr(cmps0_bne_samepage);
2313                          else                          else
2314                                  ic[-1].f = instr(cmps_bne_samepage);                                  ic[-1].f = instr(cmps_bne_samepage);
                         combined;  
2315                  }                  }
2316                  if (ic[-1].f == instr(tsts) &&                  if (ic[-1].f == instr(tsts) &&
2317                      !(ic[-1].arg[1] & 0x80000000)) {                      !(ic[-1].arg[1] & 0x80000000)) {
2318                          ic[-1].f = instr(tsts_lo_bne_samepage);                          ic[-1].f = instr(tsts_lo_bne_samepage);
                         combined;  
2319                  }                  }
2320                  if (ic[-1].f == instr(teqs)) {                  if (ic[-1].f == instr(teqs)) {
2321                          ic[-1].f = instr(teqs_bne_samepage);                          ic[-1].f = instr(teqs_bne_samepage);
                         combined;  
2322                  }                  }
2323                  return;                  return;
2324          }          }
2325          if (ic[0].f == instr(b_samepage__cc)) {          if (ic[0].f == instr(b_samepage__cc)) {
2326                  if (ic[-1].f == instr(cmps)) {                  if (ic[-1].f == instr(cmps)) {
2327                          ic[-1].f = instr(cmps_bcc_samepage);                          ic[-1].f = instr(cmps_bcc_samepage);
                         combined;  
2328                  }                  }
2329                  if (ic[-1].f == instr(cmps_regshort)) {                  if (ic[-1].f == instr(cmps_regshort)) {
2330                          ic[-1].f = instr(cmps_reg_bcc_samepage);                          ic[-1].f = instr(cmps_reg_bcc_samepage);
                         combined;  
2331                  }                  }
2332                  return;                  return;
2333          }          }
2334          if (ic[0].f == instr(b_samepage__hi)) {          if (ic[0].f == instr(b_samepage__hi)) {
2335                  if (ic[-1].f == instr(cmps)) {                  if (ic[-1].f == instr(cmps)) {
2336                          ic[-1].f = instr(cmps_bhi_samepage);                          ic[-1].f = instr(cmps_bhi_samepage);
                         combined;  
2337                  }                  }
2338                  if (ic[-1].f == instr(cmps_regshort)) {                  if (ic[-1].f == instr(cmps_regshort)) {
2339                          ic[-1].f = instr(cmps_reg_bhi_samepage);                          ic[-1].f = instr(cmps_reg_bhi_samepage);
                         combined;  
2340                  }                  }
2341                  return;                  return;
2342          }          }
2343          if (ic[0].f == instr(b_samepage__gt)) {          if (ic[0].f == instr(b_samepage__gt)) {
2344                  if (ic[-1].f == instr(cmps)) {                  if (ic[-1].f == instr(cmps)) {
2345                          ic[-1].f = instr(cmps_bgt_samepage);                          ic[-1].f = instr(cmps_bgt_samepage);
                         combined;  
2346                  }                  }
2347                  return;                  return;
2348          }          }
2349          if (ic[0].f == instr(b_samepage__le)) {          if (ic[0].f == instr(b_samepage__le)) {
2350                  if (ic[-1].f == instr(cmps)) {                  if (ic[-1].f == instr(cmps)) {
2351                          ic[-1].f = instr(cmps_ble_samepage);                          ic[-1].f = instr(cmps_ble_samepage);
                         combined;  
2352                  }                  }
2353                  return;                  return;
2354          }          }
# Line 2584  X(to_be_translated) Line 2601  X(to_be_translated)
2601                          goto bad;                          goto bad;
2602                  }                  }
2603                  if ((iword & 0x0ff0f090) == 0x01600080) {                  if ((iword & 0x0ff0f090) == 0x01600080) {
2604                          /*  TODO: smulXY  */                          /*  smulXY (16-bit * 16-bit => 32-bit)  */
2605                          goto bad;                          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) {                  if ((iword & 0x0ff0f0b0) == 0x012000a0) {
2617                          /*  TODO: smulwY  */                          /*  TODO: smulwY  */
# Line 2595  X(to_be_translated) Line 2621  X(to_be_translated)
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 2767  X(to_be_translated) Line 2793  X(to_be_translated)
2793                              (any_pc_reg? 512 : 0) + (regform? 1024 : 0)];                              (any_pc_reg? 512 : 0) + (regform? 1024 : 0)];
2794    
2795                  if (ic->f == instr(eor_regshort))                  if (ic->f == instr(eor_regshort))
2796                          cpu->cd.arm.combination_check = arm_combine_xchg;                          cpu->cd.arm.combination_check = COMBINE(xchg);
2797                  if (iword == 0xe113000c)                  if (iword == 0xe113000c)
2798                          cpu->cd.arm.combination_check =                          cpu->cd.arm.combination_check = COMBINE(netbsd_scanc);
                             arm_combine_netbsd_scanc;  
2799                  break;                  break;
2800    
2801          case 0x4:       /*  Load and store...  */          case 0x4:       /*  Load and store...  */
# Line 2842  X(to_be_translated) Line 2867  X(to_be_translated)
2867                          }                          }
2868                  }                  }
2869                  if (iword == 0xe4b09004)                  if (iword == 0xe4b09004)
2870                          cpu->cd.arm.combination_check =                          cpu->cd.arm.combination_check = COMBINE(netbsd_copyin);
                             arm_combine_netbsd_copyin;  
2871                  if (iword == 0xe4a17004)                  if (iword == 0xe4a17004)
2872                          cpu->cd.arm.combination_check =                          cpu->cd.arm.combination_check = COMBINE(netbsd_copyout);
                             arm_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 2899  X(to_be_translated) Line 2922  X(to_be_translated)
2922                          samepage_function = cond_instr(b_samepage);                          samepage_function = cond_instr(b_samepage);
2923                          if (iword == 0xcaffffed)                          if (iword == 0xcaffffed)
2924                                  cpu->cd.arm.combination_check =                                  cpu->cd.arm.combination_check =
2925                                      arm_combine_netbsd_memset;                                      COMBINE(netbsd_memset);
2926                          if (iword == 0xaafffff9)                          if (iword == 0xaafffff9)
2927                                  cpu->cd.arm.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 2961  X(to_be_translated) Line 2984  X(to_be_translated)
2984                  if (main_opcode == 0xa && (condition_code <= 1                  if (main_opcode == 0xa && (condition_code <= 1
2985                      || condition_code == 3 || condition_code == 8                      || condition_code == 3 || condition_code == 8
2986                      || condition_code == 12 || condition_code == 13))                      || condition_code == 12 || condition_code == 13))
2987                          cpu->cd.arm.combination_check = arm_combine_cmps_b;                          cpu->cd.arm.combination_check = COMBINE(cmps_b);
2988    
2989                  if (iword == 0x1afffffc)                  if (iword == 0x1afffffc)
2990                          cpu->cd.arm.combination_check = arm_combine_strlen;                          cpu->cd.arm.combination_check = COMBINE(strlen);
2991    
2992                  /*  Hm. Does this really increase performance?  */                  /*  Hm. Does this really increase performance?  */
2993                  if (iword == 0x8afffffa)                  if (iword == 0x8afffffa)
2994                          cpu->cd.arm.combination_check =                          cpu->cd.arm.combination_check =
2995                              arm_combine_netbsd_cacheclean2;                              COMBINE(netbsd_cacheclean2);
2996                  break;                  break;
2997    
2998          case 0xc:          case 0xc:
# Line 2978  X(to_be_translated) Line 3001  X(to_be_translated)
3001                   *  xxxx1100 0100nnnn ddddcccc oooommmm    MCRR c,op,Rd,Rn,CRm                   *  xxxx1100 0100nnnn ddddcccc oooommmm    MCRR c,op,Rd,Rn,CRm
3002                   *  xxxx1100 0101nnnn ddddcccc oooommmm    MRRC c,op,Rd,Rn,CRm                   *  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) {                  if ((iword & 0x0fe00000) == 0x0c400000) {
3012                          fatal("MCRR/MRRC: TODO\n");                          fatal("MCRR/MRRC: TODO\n");
3013                          goto bad;                          goto bad;
# Line 2989  X(to_be_translated) Line 3019  X(to_be_translated)
3019                   *  For now, treat as Undefined instructions. This causes e.g.                   *  For now, treat as Undefined instructions. This causes e.g.
3020                   *  Linux/ARM to emulate these instructions (floating point).                   *  Linux/ARM to emulate these instructions (floating point).
3021                   */                   */
3022    #if 0
3023                  ic->f = cond_instr(und);                  ic->f = cond_instr(und);
3024                  ic->arg[0] = addr & 0xfff;                  ic->arg[0] = addr & 0xfff;
3025    #else
3026                    fatal("LDC/STC: TODO\n");
3027                    goto bad;
3028    #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 3005  X(to_be_translated) Line 3046  X(to_be_translated)
3046                  }                  }
3047                  if (iword == 0xee070f9a)                  if (iword == 0xee070f9a)
3048                          cpu->cd.arm.combination_check =                          cpu->cd.arm.combination_check =
3049                              arm_combine_netbsd_cacheclean;                              COMBINE(netbsd_cacheclean);
3050                  break;                  break;
3051    
3052          case 0xf:          case 0xf:

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

  ViewVC Help
Powered by ViewVC 1.1.26