/[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 21 by dpavlin, Mon Oct 8 16:19:23 2007 UTC revision 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2006  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_arm_instr.c,v 1.54 2005/11/19 18:53:07 debug Exp $   *  $Id: cpu_arm_instr.c,v 1.60 2006/02/09 22:40:27 debug Exp $
29   *   *
30   *  ARM instructions.   *  ARM instructions.
31   *   *
# Line 36  Line 36 
36   */   */
37    
38    
 #include "arm_quick_pc_to_pointers.h"  
   
39  /*  #define GATHER_BDT_STATISTICS  */  /*  #define GATHER_BDT_STATISTICS  */
40    
41    
# Line 587  Y(mull) Line 585  Y(mull)
585    
586    
587  /*  /*
588     *  smulXY:  16-bit * 16-bit multiplication (32-bit result)
589     *
590     *  arg[0] = ptr to rm
591     *  arg[1] = ptr to rs
592     *  arg[2] = ptr to rd
593     */
594    X(smulbb)
595    {
596            reg(ic->arg[2]) = (int32_t)(int16_t)reg(ic->arg[0]) *
597                (int32_t)(int16_t)reg(ic->arg[1]);
598    }
599    Y(smulbb)
600    X(smultb)
601    {
602            reg(ic->arg[2]) = (int32_t)(int16_t)(reg(ic->arg[0]) >> 16) *
603                (int32_t)(int16_t)reg(ic->arg[1]);
604    }
605    Y(smultb)
606    X(smulbt)
607    {
608            reg(ic->arg[2]) = (int32_t)(int16_t)reg(ic->arg[0]) *
609                (int32_t)(int16_t)(reg(ic->arg[1]) >> 16);
610    }
611    Y(smulbt)
612    X(smultt)
613    {
614            reg(ic->arg[2]) = (int32_t)(int16_t)(reg(ic->arg[0]) >> 16) *
615                (int32_t)(int16_t)(reg(ic->arg[1]) >> 16);
616    }
617    Y(smultt)
618    
619    
620    /*
621   *  mov_reg_reg:  Move a register to another.   *  mov_reg_reg:  Move a register to another.
622   *   *
623   *  arg[0] = ptr to source register   *  arg[0] = ptr to source register
# Line 1991  X(end_of_page) Line 2022  X(end_of_page)
2022    
2023    
2024  /*  /*
2025   *  arm_combine_netbsd_memset():   *  Combine: netbsd_memset():
2026   *   *
2027   *  Check for the core of a NetBSD/arm memset; large memsets use a sequence   *  Check for the core of a NetBSD/arm memset; large memsets use a sequence
2028   *  of 16 store-multiple instructions, each storing 2 registers at a time.   *  of 16 store-multiple instructions, each storing 2 registers at a time.
2029   */   */
2030  void arm_combine_netbsd_memset(struct cpu *cpu,  void COMBINE(netbsd_memset)(struct cpu *cpu,
2031          struct arm_instr_call *ic, int low_addr)          struct arm_instr_call *ic, int low_addr)
2032  {  {
2033  #ifdef HOST_LITTLE_ENDIAN  #ifdef HOST_LITTLE_ENDIAN
# Line 2021  void arm_combine_netbsd_memset(struct cp Line 2052  void arm_combine_netbsd_memset(struct cp
2052    
2053    
2054  /*  /*
2055   *  arm_combine_netbsd_memcpy():   *  Combine: netbsd_memcpy():
2056   *   *
2057   *  Check for the core of a NetBSD/arm memcpy; large memcpys use a   *  Check for the core of a NetBSD/arm memcpy; large memcpys use a
2058   *  sequence of ldmia instructions.   *  sequence of ldmia instructions.
2059   */   */
2060  void arm_combine_netbsd_memcpy(struct cpu *cpu,  void COMBINE(netbsd_memcpy)(struct cpu *cpu, struct arm_instr_call *ic,
2061          struct arm_instr_call *ic, int low_addr)          int low_addr)
2062  {  {
2063  #ifdef HOST_LITTLE_ENDIAN  #ifdef HOST_LITTLE_ENDIAN
2064          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
# Line 2051  void arm_combine_netbsd_memcpy(struct cp Line 2082  void arm_combine_netbsd_memcpy(struct cp
2082    
2083    
2084  /*  /*
2085   *  arm_combine_netbsd_cacheclean():   *  Combine: netbsd_cacheclean():
2086   *   *
2087   *  Check for the core of a NetBSD/arm cache clean. (There are two variants.)   *  Check for the core of a NetBSD/arm cache clean. (There are two variants.)
2088   */   */
2089  void arm_combine_netbsd_cacheclean(struct cpu *cpu,  void COMBINE(netbsd_cacheclean)(struct cpu *cpu,
2090          struct arm_instr_call *ic, int low_addr)          struct arm_instr_call *ic, int low_addr)
2091  {  {
2092          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
# Line 2075  void arm_combine_netbsd_cacheclean(struc Line 2106  void arm_combine_netbsd_cacheclean(struc
2106    
2107    
2108  /*  /*
2109   *  arm_combine_netbsd_cacheclean2():   *  Combine: netbsd_cacheclean2():
2110   *   *
2111   *  Check for the core of a NetBSD/arm cache clean. (Second variant.)   *  Check for the core of a NetBSD/arm cache clean. (Second variant.)
2112   */   */
2113  void arm_combine_netbsd_cacheclean2(struct cpu *cpu,  void COMBINE(netbsd_cacheclean2)(struct cpu *cpu,
2114          struct arm_instr_call *ic, int low_addr)          struct arm_instr_call *ic, int low_addr)
2115  {  {
2116          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
# Line 2100  void arm_combine_netbsd_cacheclean2(stru Line 2131  void arm_combine_netbsd_cacheclean2(stru
2131    
2132    
2133  /*  /*
2134   *  arm_combine_netbsd_scanc():   *  Combine: netbsd_scanc():
2135   */   */
2136  void arm_combine_netbsd_scanc(struct cpu *cpu,  void COMBINE(netbsd_scanc)(struct cpu *cpu,
2137          struct arm_instr_call *ic, int low_addr)          struct arm_instr_call *ic, int low_addr)
2138  {  {
2139          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
# Line 2126  void arm_combine_netbsd_scanc(struct cpu Line 2157  void arm_combine_netbsd_scanc(struct cpu
2157    
2158    
2159  /*  /*
2160   *  arm_combine_strlen():   *  Combine: strlen():
2161   */   */
2162  void arm_combine_strlen(struct cpu *cpu,  void COMBINE(strlen)(struct cpu *cpu,
2163          struct arm_instr_call *ic, int low_addr)          struct arm_instr_call *ic, int low_addr)
2164  {  {
2165          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
# Line 2150  void arm_combine_strlen(struct cpu *cpu, Line 2181  void arm_combine_strlen(struct cpu *cpu,
2181    
2182    
2183  /*  /*
2184   *  arm_combine_xchg():   *  Combine: xchg():
2185   */   */
2186  void arm_combine_xchg(struct cpu *cpu,  void COMBINE(xchg)(struct cpu *cpu,
2187          struct arm_instr_call *ic, int low_addr)          struct arm_instr_call *ic, int low_addr)
2188  {  {
2189          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
# Line 2176  void arm_combine_xchg(struct cpu *cpu, Line 2207  void arm_combine_xchg(struct cpu *cpu,
2207    
2208    
2209  /*  /*
2210   *  arm_combine_netbsd_copyin():   *  Combine: netbsd_copyin():
2211   */   */
2212  void arm_combine_netbsd_copyin(struct cpu *cpu,  void COMBINE(netbsd_copyin)(struct cpu *cpu,
2213          struct arm_instr_call *ic, int low_addr)          struct arm_instr_call *ic, int low_addr)
2214  {  {
2215  #ifdef HOST_LITTLE_ENDIAN  #ifdef HOST_LITTLE_ENDIAN
# Line 2208  void arm_combine_netbsd_copyin(struct cp Line 2239  void arm_combine_netbsd_copyin(struct cp
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 2240  void arm_combine_netbsd_copyout(struct c Line 2271  void arm_combine_netbsd_copyout(struct c
2271    
2272    
2273  /*  /*
2274   *  arm_combine_cmps_b():   *  Combine: cmps_b():
2275   */   */
2276  void arm_combine_cmps_b(struct cpu *cpu,  void COMBINE(cmps_b)(struct cpu *cpu,
2277          struct arm_instr_call *ic, int low_addr)          struct arm_instr_call *ic, int low_addr)
2278  {  {
2279          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)          int n_back = (low_addr >> ARM_INSTR_ALIGNMENT_SHIFT)
# Line 2424  static void arm_switch_add1(struct arm_i Line 2455  static void arm_switch_add1(struct arm_i
2455  X(to_be_translated)  X(to_be_translated)
2456  {  {
2457          uint32_t addr, low_pc, iword, imm = 0;          uint32_t addr, low_pc, iword, imm = 0;
2458    #ifdef DYNTRANS_BACKEND
2459            int simple = 0;
2460    #endif
2461          unsigned char *page;          unsigned char *page;
2462          unsigned char ib[4];          unsigned char ib[4];
2463          int condition_code, main_opcode, secondary_opcode, s_bit, rn, rd, r8;          int condition_code, main_opcode, secondary_opcode, s_bit, rn, rd, r8;
# Line 2584  X(to_be_translated) Line 2618  X(to_be_translated)
2618                          goto bad;                          goto bad;
2619                  }                  }
2620                  if ((iword & 0x0ff0f090) == 0x01600080) {                  if ((iword & 0x0ff0f090) == 0x01600080) {
2621                          /*  TODO: smulXY  */                          /*  smulXY (16-bit * 16-bit => 32-bit)  */
2622                          goto bad;                          switch (iword & 0x60) {
2623                            case 0x00: ic->f = cond_instr(smulbb); break;
2624                            case 0x20: ic->f = cond_instr(smultb); break;
2625                            case 0x40: ic->f = cond_instr(smulbt); break;
2626                            default:   ic->f = cond_instr(smultt); break;
2627                            }
2628                            ic->arg[0] = (size_t)(&cpu->cd.arm.r[rm]);
2629                            ic->arg[1] = (size_t)(&cpu->cd.arm.r[r8]);
2630                            ic->arg[2] = (size_t)(&cpu->cd.arm.r[rn]); /*  Rd  */
2631                            break;
2632                  }                  }
2633                  if ((iword & 0x0ff0f0b0) == 0x012000a0) {                  if ((iword & 0x0ff0f0b0) == 0x012000a0) {
2634                          /*  TODO: smulwY  */                          /*  TODO: smulwY  */
# Line 2702  X(to_be_translated) Line 2745  X(to_be_translated)
2745                  /*  "mov reg,#0":  */                  /*  "mov reg,#0":  */
2746                  if ((iword & 0x0fff0fff) == 0x03a00000 && rd != ARM_PC) {                  if ((iword & 0x0fff0fff) == 0x03a00000 && rd != ARM_PC) {
2747                          arm_switch_clear(ic, rd, condition_code);                          arm_switch_clear(ic, rd, condition_code);
2748    #ifdef DYNTRANS_BACKEND
2749    simple = 1;
2750    #endif
2751                          break;                          break;
2752                  }                  }
2753    
2754                  /*  "mov reg,#1":  */                  /*  "mov reg,#1":  */
2755                  if ((iword & 0x0fff0fff) == 0x03a00001 && rd != ARM_PC) {                  if ((iword & 0x0fff0fff) == 0x03a00001 && rd != ARM_PC) {
2756                          arm_switch_mov1(ic, rd, condition_code);                          arm_switch_mov1(ic, rd, condition_code);
2757    #ifdef DYNTRANS_BACKEND
2758    simple = 1;
2759    #endif
2760                          break;                          break;
2761                  }                  }
2762    
# Line 2715  X(to_be_translated) Line 2764  X(to_be_translated)
2764                  if ((iword & 0x0ff00fff) == 0x02800001 && rd != ARM_PC                  if ((iword & 0x0ff00fff) == 0x02800001 && rd != ARM_PC
2765                      && rn == rd) {                      && rn == rd) {
2766                          arm_switch_add1(ic, rd, condition_code);                          arm_switch_add1(ic, rd, condition_code);
2767    #ifdef DYNTRANS_BACKEND
2768    simple = 1;
2769    #endif
2770                          break;                          break;
2771                  }                  }
2772    
# Line 2767  X(to_be_translated) Line 2819  X(to_be_translated)
2819                              (any_pc_reg? 512 : 0) + (regform? 1024 : 0)];                              (any_pc_reg? 512 : 0) + (regform? 1024 : 0)];
2820    
2821                  if (ic->f == instr(eor_regshort))                  if (ic->f == instr(eor_regshort))
2822                          cpu->cd.arm.combination_check = arm_combine_xchg;                          cpu->cd.arm.combination_check = COMBINE(xchg);
2823                  if (iword == 0xe113000c)                  if (iword == 0xe113000c)
2824                          cpu->cd.arm.combination_check =                          cpu->cd.arm.combination_check = COMBINE(netbsd_scanc);
                             arm_combine_netbsd_scanc;  
2825                  break;                  break;
2826    
2827          case 0x4:       /*  Load and store...  */          case 0x4:       /*  Load and store...  */
# Line 2842  X(to_be_translated) Line 2893  X(to_be_translated)
2893                          }                          }
2894                  }                  }
2895                  if (iword == 0xe4b09004)                  if (iword == 0xe4b09004)
2896                          cpu->cd.arm.combination_check =                          cpu->cd.arm.combination_check = COMBINE(netbsd_copyin);
                             arm_combine_netbsd_copyin;  
2897                  if (iword == 0xe4a17004)                  if (iword == 0xe4a17004)
2898                          cpu->cd.arm.combination_check =                          cpu->cd.arm.combination_check = COMBINE(netbsd_copyout);
                             arm_combine_netbsd_copyout;  
2899                  break;                  break;
2900    
2901          case 0x8:       /*  Multiple load/store...  (Block data transfer)  */          case 0x8:       /*  Multiple load/store...  (Block data transfer)  */
# Line 2899  X(to_be_translated) Line 2948  X(to_be_translated)
2948                          samepage_function = cond_instr(b_samepage);                          samepage_function = cond_instr(b_samepage);
2949                          if (iword == 0xcaffffed)                          if (iword == 0xcaffffed)
2950                                  cpu->cd.arm.combination_check =                                  cpu->cd.arm.combination_check =
2951                                      arm_combine_netbsd_memset;                                      COMBINE(netbsd_memset);
2952                          if (iword == 0xaafffff9)                          if (iword == 0xaafffff9)
2953                                  cpu->cd.arm.combination_check =                                  cpu->cd.arm.combination_check =
2954                                      arm_combine_netbsd_memcpy;                                      COMBINE(netbsd_memcpy);
2955                  } else {                  } else {
2956                          if (cpu->machine->show_trace_tree) {                          if (cpu->machine->show_trace_tree) {
2957                                  ic->f = cond_instr(bl_trace);                                  ic->f = cond_instr(bl_trace);
# Line 2961  X(to_be_translated) Line 3010  X(to_be_translated)
3010                  if (main_opcode == 0xa && (condition_code <= 1                  if (main_opcode == 0xa && (condition_code <= 1
3011                      || condition_code == 3 || condition_code == 8                      || condition_code == 3 || condition_code == 8
3012                      || condition_code == 12 || condition_code == 13))                      || condition_code == 12 || condition_code == 13))
3013                          cpu->cd.arm.combination_check = arm_combine_cmps_b;                          cpu->cd.arm.combination_check = COMBINE(cmps_b);
3014    
3015                  if (iword == 0x1afffffc)                  if (iword == 0x1afffffc)
3016                          cpu->cd.arm.combination_check = arm_combine_strlen;                          cpu->cd.arm.combination_check = COMBINE(strlen);
3017    
3018                  /*  Hm. Does this really increase performance?  */                  /*  Hm. Does this really increase performance?  */
3019                  if (iword == 0x8afffffa)                  if (iword == 0x8afffffa)
3020                          cpu->cd.arm.combination_check =                          cpu->cd.arm.combination_check =
3021                              arm_combine_netbsd_cacheclean2;                              COMBINE(netbsd_cacheclean2);
3022                  break;                  break;
3023    
3024          case 0xc:          case 0xc:
# Line 2978  X(to_be_translated) Line 3027  X(to_be_translated)
3027                   *  xxxx1100 0100nnnn ddddcccc oooommmm    MCRR c,op,Rd,Rn,CRm                   *  xxxx1100 0100nnnn ddddcccc oooommmm    MCRR c,op,Rd,Rn,CRm
3028                   *  xxxx1100 0101nnnn ddddcccc oooommmm    MRRC c,op,Rd,Rn,CRm                   *  xxxx1100 0101nnnn ddddcccc oooommmm    MRRC c,op,Rd,Rn,CRm
3029                   */                   */
3030                    if ((iword & 0x0fe00fff) == 0x0c400000) {
3031                            /*  Special case: mar/mra DSP instructions  */
3032                            fatal("TODO: mar/mra DSP instructions!\n");
3033                            /*  Perhaps these are actually identical to MCRR/MRRC */
3034                            goto bad;
3035                    }
3036    
3037                  if ((iword & 0x0fe00000) == 0x0c400000) {                  if ((iword & 0x0fe00000) == 0x0c400000) {
3038                          fatal("MCRR/MRRC: TODO\n");                          fatal("MCRR/MRRC: TODO\n");
3039                          goto bad;                          goto bad;
# Line 2989  X(to_be_translated) Line 3045  X(to_be_translated)
3045                   *  For now, treat as Undefined instructions. This causes e.g.                   *  For now, treat as Undefined instructions. This causes e.g.
3046                   *  Linux/ARM to emulate these instructions (floating point).                   *  Linux/ARM to emulate these instructions (floating point).
3047                   */                   */
3048    #if 0
3049                  ic->f = cond_instr(und);                  ic->f = cond_instr(und);
3050                  ic->arg[0] = addr & 0xfff;                  ic->arg[0] = addr & 0xfff;
3051    #else
3052                    fatal("LDC/STC: TODO\n");
3053                    goto bad;
3054    #endif
3055                  break;                  break;
3056    
3057          case 0xe:          case 0xe:
3058                    if ((iword & 0x0ff00ff0) == 0x0e200010) {
3059                            /*  Special case: mia* DSP instructions  */
3060                            /*  See Intel's 27343601.pdf, page 16-20  */
3061                            fatal("TODO: mia* DSP instructions!\n");
3062                            goto bad;
3063                    }
3064                  if (iword & 0x10) {                  if (iword & 0x10) {
3065                          /*  xxxx1110 oooLNNNN ddddpppp qqq1MMMM  MCR/MRC  */                          /*  xxxx1110 oooLNNNN ddddpppp qqq1MMMM  MCR/MRC  */
3066                          ic->arg[0] = iword;                          ic->arg[0] = iword;
# Line 3005  X(to_be_translated) Line 3072  X(to_be_translated)
3072                  }                  }
3073                  if (iword == 0xee070f9a)                  if (iword == 0xee070f9a)
3074                          cpu->cd.arm.combination_check =                          cpu->cd.arm.combination_check =
3075                              arm_combine_netbsd_cacheclean;                              COMBINE(netbsd_cacheclean);
3076                  break;                  break;
3077    
3078          case 0xf:          case 0xf:

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

  ViewVC Help
Powered by ViewVC 1.1.26