/[qemu]/qemu/target-arm/translate.c
ViewVC logotype

Diff of /qemu/target-arm/translate.c

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

revision 1.31 by bellard, Mon Nov 21 23:30:54 2005 UTC revision 1.32 by bellard, Sat Nov 26 10:38:39 2005 UTC
# Line 28  Line 28 
28  #include "exec-all.h"  #include "exec-all.h"
29  #include "disas.h"  #include "disas.h"
30    
31    #define ENABLE_ARCH_5J  0
32    #define ENABLE_ARCH_6   1
33    #define ENABLE_ARCH_6T2 1
34    
35    #define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op;
36    
37  /* internal defines */  /* internal defines */
38  typedef struct DisasContext {  typedef struct DisasContext {
39      target_ulong pc;      target_ulong pc;
# Line 39  typedef struct DisasContext { Line 45  typedef struct DisasContext {
45      struct TranslationBlock *tb;      struct TranslationBlock *tb;
46      int singlestep_enabled;      int singlestep_enabled;
47      int thumb;      int thumb;
48    #if !defined(CONFIG_USER_ONLY)
49        int user;
50    #endif
51  } DisasContext;  } DisasContext;
52    
53    #if defined(CONFIG_USER_ONLY)
54    #define IS_USER(s) 1
55    #else
56    #define IS_USER(s) (s->user)
57    #endif
58    
59  #define DISAS_JUMP_NEXT 4  #define DISAS_JUMP_NEXT 4
60    
61  #ifdef USE_DIRECT_JUMP  #ifdef USE_DIRECT_JUMP
# Line 270  static inline void gen_bx(DisasContext * Line 285  static inline void gen_bx(DisasContext *
285    gen_op_bx_T0();    gen_op_bx_T0();
286  }  }
287    
288    
289    #if defined(CONFIG_USER_ONLY)
290    #define gen_ldst(name, s) gen_op_##name##_raw()
291    #else
292    #define gen_ldst(name, s) do { \
293        if (IS_USER(s)) \
294            gen_op_##name##_user(); \
295        else \
296            gen_op_##name##_kernel(); \
297        } while (0)
298    #endif
299    
300  static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)  static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
301  {  {
302      int val;      int val;
# Line 319  static inline void gen_movl_reg_T1(Disas Line 346  static inline void gen_movl_reg_T1(Disas
346      gen_movl_reg_TN(s, reg, 1);      gen_movl_reg_TN(s, reg, 1);
347  }  }
348    
349    /* Force a TB lookup after an instruction that changes the CPU state.  */
350    static inline void gen_lookup_tb(DisasContext *s)
351    {
352        gen_op_movl_T0_im(s->pc);
353        gen_movl_reg_T0(s, 15);
354        s->is_jmp = DISAS_UPDATE;
355    }
356    
357  static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)  static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
358  {  {
359      int val, rm, shift, shiftop;      int val, rm, shift, shiftop;
# Line 395  VFP_OP(toui) Line 430  VFP_OP(toui)
430  VFP_OP(touiz)  VFP_OP(touiz)
431  VFP_OP(tosi)  VFP_OP(tosi)
432  VFP_OP(tosiz)  VFP_OP(tosiz)
 VFP_OP(ld)  
 VFP_OP(st)  
433    
434  #undef VFP_OP  #undef VFP_OP
435    
436    static inline void gen_vfp_ld(DisasContext *s, int dp)
437    {
438        if (dp)
439            gen_ldst(vfp_ldd, s);
440        else
441            gen_ldst(vfp_lds, s);
442    }
443    
444    static inline void gen_vfp_st(DisasContext *s, int dp)
445    {
446        if (dp)
447            gen_ldst(vfp_std, s);
448        else
449            gen_ldst(vfp_sts, s);
450    }
451    
452  static inline long  static inline long
453  vfp_reg_offset (int dp, int reg)  vfp_reg_offset (int dp, int reg)
454  {  {
# Line 437  static inline void gen_mov_vreg_F0(int d Line 486  static inline void gen_mov_vreg_F0(int d
486          gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));          gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
487  }  }
488    
489    /* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
490       instruction is not defined.  */
491    static int disas_cp15_insn(DisasContext *s, uint32_t insn)
492    {
493        uint32_t rd;
494    
495        /* ??? Some cp15 registers are accessible from userspace.  */
496        if (IS_USER(s)) {
497            return 1;
498        }
499        rd = (insn >> 12) & 0xf;
500        if (insn & (1 << 20)) {
501            gen_op_movl_T0_cp15(insn);
502            /* If the destination register is r15 then sets condition codes.  */
503            if (rd != 15)
504                gen_movl_reg_T0(s, rd);
505        } else {
506            gen_movl_T0_reg(s, rd);
507            gen_op_movl_cp15_T0(insn);
508        }
509        gen_lookup_tb(s);
510        return 0;
511    }
512    
513  /* Disassemble a VFP instruction.  Returns nonzero if an error occured  /* Disassemble a VFP instruction.  Returns nonzero if an error occured
514     (ie. an undefined instruction).  */     (ie. an undefined instruction).  */
515  static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)  static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
# Line 499  static int disas_vfp_insn(CPUState * env Line 572  static int disas_vfp_insn(CPUState * env
572                          gen_op_vfp_mrs();                          gen_op_vfp_mrs();
573                      }                      }
574                      if (rd == 15) {                      if (rd == 15) {
575                          /* This will only set the 4 flag bits */                          /* Set the 4 flag bits in the CPSR.  */
576                          gen_op_movl_psr_T0();                          gen_op_movl_cpsr_T0(0xf0000000);
577                      } else                      } else
578                          gen_movl_reg_T0(s, rd);                          gen_movl_reg_T0(s, rd);
579                  } else {                  } else {
# Line 516  static int disas_vfp_insn(CPUState * env Line 589  static int disas_vfp_insn(CPUState * env
589                              gen_op_vfp_movl_fpscr_T0();                              gen_op_vfp_movl_fpscr_T0();
590                              /* This could change vector settings, so jump to                              /* This could change vector settings, so jump to
591                                 the next instuction.  */                                 the next instuction.  */
592                              gen_op_movl_T0_im(s->pc);                              gen_lookup_tb(s);
                             gen_movl_reg_T0(s, 15);  
                             s->is_jmp = DISAS_UPDATE;  
593                              break;                              break;
594                          default:                          default:
595                              return 1;                              return 1;
# Line 848  static int disas_vfp_insn(CPUState * env Line 919  static int disas_vfp_insn(CPUState * env
919                      offset = -offset;                      offset = -offset;
920                  gen_op_addl_T1_im(offset);                  gen_op_addl_T1_im(offset);
921                  if (insn & (1 << 20)) {                  if (insn & (1 << 20)) {
922                      gen_vfp_ld(dp);                      gen_vfp_ld(s, dp);
923                      gen_mov_vreg_F0(dp, rd);                      gen_mov_vreg_F0(dp, rd);
924                  } else {                  } else {
925                      gen_mov_F0_vreg(dp, rd);                      gen_mov_F0_vreg(dp, rd);
926                      gen_vfp_st(dp);                      gen_vfp_st(s, dp);
927                  }                  }
928              } else {              } else {
929                  /* load/store multiple */                  /* load/store multiple */
# Line 871  static int disas_vfp_insn(CPUState * env Line 942  static int disas_vfp_insn(CPUState * env
942                  for (i = 0; i < n; i++) {                  for (i = 0; i < n; i++) {
943                      if (insn & (1 << 20)) {                      if (insn & (1 << 20)) {
944                          /* load */                          /* load */
945                          gen_vfp_ld(dp);                          gen_vfp_ld(s, dp);
946                          gen_mov_vreg_F0(dp, rd + i);                          gen_mov_vreg_F0(dp, rd + i);
947                      } else {                      } else {
948                          /* store */                          /* store */
949                          gen_mov_F0_vreg(dp, rd + i);                          gen_mov_F0_vreg(dp, rd + i);
950                          gen_vfp_st(dp);                          gen_vfp_st(s, dp);
951                      }                      }
952                      gen_op_addl_T1_im(offset);                      gen_op_addl_T1_im(offset);
953                  }                  }
# Line 939  static inline void gen_jmp (DisasContext Line 1010  static inline void gen_jmp (DisasContext
1010      }      }
1011  }  }
1012    
1013    static inline void gen_mulxy(int x, int y)
1014    {
1015        if (x & 2)
1016            gen_op_sarl_T0_im(16);
1017        else
1018            gen_op_sxth_T0();
1019        if (y & 1)
1020            gen_op_sarl_T1_im(16);
1021        else
1022            gen_op_sxth_T1();
1023        gen_op_mul_T0_T1();
1024    }
1025    
1026    /* Return the mask of PSR bits set by a MSR instruction.  */
1027    static uint32_t msr_mask(DisasContext *s, int flags) {
1028        uint32_t mask;
1029    
1030        mask = 0;
1031        if (flags & (1 << 0))
1032            mask |= 0xff;
1033        if (flags & (1 << 1))
1034            mask |= 0xff00;
1035        if (flags & (1 << 2))
1036            mask |= 0xff0000;
1037        if (flags & (1 << 3))
1038            mask |= 0xff000000;
1039        /* Mask out undefined bits and state bits.  */
1040        mask &= 0xf89f03df;
1041        /* Mask out privileged bits.  */
1042        if (IS_USER(s))
1043            mask &= 0xf80f0200;
1044        return mask;
1045    }
1046    
1047    /* Returns nonzero if access to the PSR is not permitted.  */
1048    static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
1049    {
1050        if (spsr) {
1051            /* ??? This is also undefined in system mode.  */
1052            if (IS_USER(s))
1053                return 1;
1054            gen_op_movl_spsr_T0(mask);
1055        } else {
1056            gen_op_movl_cpsr_T0(mask);
1057        }
1058        gen_lookup_tb(s);
1059        return 0;
1060    }
1061    
1062    static void gen_exception_return(DisasContext *s)
1063    {
1064        gen_op_movl_reg_TN[0][15]();
1065        gen_op_movl_T0_spsr();
1066        gen_op_movl_cpsr_T0(0xffffffff);
1067        s->is_jmp = DISAS_UPDATE;
1068    }
1069    
1070  static void disas_arm_insn(CPUState * env, DisasContext *s)  static void disas_arm_insn(CPUState * env, DisasContext *s)
1071  {  {
1072      unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;      unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
1073            
1074      insn = ldl(s->pc);      insn = ldl_code(s->pc);
1075      s->pc += 4;      s->pc += 4;
1076            
1077      cond = insn >> 28;      cond = insn >> 28;
# Line 971  static void disas_arm_insn(CPUState * en Line 1099  static void disas_arm_insn(CPUState * en
1099              /* Coprocessor double register transfer.  */              /* Coprocessor double register transfer.  */
1100          } else if ((insn & 0x0f000010) == 0x0e000010) {          } else if ((insn & 0x0f000010) == 0x0e000010) {
1101              /* Additional coprocessor register transfer.  */              /* Additional coprocessor register transfer.  */
1102            } else if ((insn & 0x0ff10010) == 0x01000000) {
1103                /* cps (privileged) */
1104            } else if ((insn & 0x0ffffdff) == 0x01010000) {
1105                /* setend */
1106                if (insn & (1 << 9)) {
1107                    /* BE8 mode not implemented.  */
1108                    goto illegal_op;
1109                }
1110                return;
1111          }          }
1112          goto illegal_op;          goto illegal_op;
1113      }      }
# Line 984  static void disas_arm_insn(CPUState * en Line 1121  static void disas_arm_insn(CPUState * en
1121          //s->is_jmp = DISAS_JUMP_NEXT;          //s->is_jmp = DISAS_JUMP_NEXT;
1122      }      }
1123      if ((insn & 0x0f900000) == 0x03000000) {      if ((insn & 0x0f900000) == 0x03000000) {
1124          if ((insn & 0x0ff0f000) != 0x0360f000)          if ((insn & 0x0fb0f000) != 0x0320f000)
1125              goto illegal_op;              goto illegal_op;
1126          /* CPSR = immediate */          /* CPSR = immediate */
1127          val = insn & 0xff;          val = insn & 0xff;
# Line 992  static void disas_arm_insn(CPUState * en Line 1129  static void disas_arm_insn(CPUState * en
1129          if (shift)          if (shift)
1130              val = (val >> shift) | (val << (32 - shift));              val = (val >> shift) | (val << (32 - shift));
1131          gen_op_movl_T0_im(val);          gen_op_movl_T0_im(val);
1132          if (insn & (1 << 19))          if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf),
1133              gen_op_movl_psr_T0();                             (insn & (1 << 22)) != 0))
1134                goto illegal_op;
1135      } else if ((insn & 0x0f900000) == 0x01000000      } else if ((insn & 0x0f900000) == 0x01000000
1136                 && (insn & 0x00000090) != 0x00000090) {                 && (insn & 0x00000090) != 0x00000090) {
1137          /* miscellaneous instructions */          /* miscellaneous instructions */
# Line 1002  static void disas_arm_insn(CPUState * en Line 1140  static void disas_arm_insn(CPUState * en
1140          rm = insn & 0xf;          rm = insn & 0xf;
1141          switch (sh) {          switch (sh) {
1142          case 0x0: /* move program status register */          case 0x0: /* move program status register */
             if (op1 & 2) {  
                 /* SPSR not accessible in user mode */  
                 goto illegal_op;  
             }  
1143              if (op1 & 1) {              if (op1 & 1) {
1144                  /* CPSR = reg */                  /* PSR = reg */
1145                  gen_movl_T0_reg(s, rm);                  gen_movl_T0_reg(s, rm);
1146                  if (insn & (1 << 19))                  if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf),
1147                      gen_op_movl_psr_T0();                                     (op1 & 2) != 0))
1148                        goto illegal_op;
1149              } else {              } else {
1150                  /* reg = CPSR */                  /* reg = CPSR */
1151                  rd = (insn >> 12) & 0xf;                  rd = (insn >> 12) & 0xf;
1152                  gen_op_movl_T0_psr();                  if (op1 & 2) {
1153                        if (IS_USER(s))
1154                            goto illegal_op;
1155                        gen_op_movl_T0_spsr();
1156                    } else {
1157                        gen_op_movl_T0_cpsr();
1158                    }
1159                  gen_movl_reg_T0(s, rd);                  gen_movl_reg_T0(s, rd);
1160              }              }
1161              break;              break;
# Line 1033  static void disas_arm_insn(CPUState * en Line 1174  static void disas_arm_insn(CPUState * en
1174                  goto illegal_op;                  goto illegal_op;
1175              }              }
1176              break;              break;
1177            case 0x2:
1178                if (op1 == 1) {
1179                    ARCH(5J); /* bxj */
1180                    /* Trivial implementation equivalent to bx.  */
1181                    gen_movl_T0_reg(s, rm);
1182                    gen_bx(s);
1183                } else {
1184                    goto illegal_op;
1185                }
1186                break;
1187          case 0x3:          case 0x3:
1188              if (op1 != 1)              if (op1 != 1)
1189                goto illegal_op;                goto illegal_op;
# Line 1071  static void disas_arm_insn(CPUState * en Line 1222  static void disas_arm_insn(CPUState * en
1222                  if (sh & 4)                  if (sh & 4)
1223                      gen_op_sarl_T1_im(16);                      gen_op_sarl_T1_im(16);
1224                  else                  else
1225                      gen_op_sxl_T1();                      gen_op_sxth_T1();
1226                  gen_op_imulw_T0_T1();                  gen_op_imulw_T0_T1();
1227                  if ((sh & 2) == 0) {                  if ((sh & 2) == 0) {
1228                      gen_movl_T1_reg(s, rn);                      gen_movl_T1_reg(s, rn);
# Line 1081  static void disas_arm_insn(CPUState * en Line 1232  static void disas_arm_insn(CPUState * en
1232              } else {              } else {
1233                  /* 16 * 16 */                  /* 16 * 16 */
1234                  gen_movl_T0_reg(s, rm);                  gen_movl_T0_reg(s, rm);
                 if (sh & 2)  
                     gen_op_sarl_T0_im(16);  
                 else  
                     gen_op_sxl_T0();  
1235                  gen_movl_T1_reg(s, rs);                  gen_movl_T1_reg(s, rs);
1236                  if (sh & 4)                  gen_mulxy(sh & 2, sh & 4);
                     gen_op_sarl_T1_im(16);  
                 else  
                     gen_op_sxl_T1();  
1237                  if (op1 == 2) {                  if (op1 == 2) {
1238                      gen_op_imull_T0_T1();                      gen_op_signbit_T1_T0();
1239                      gen_op_addq_T0_T1(rn, rd);                      gen_op_addq_T0_T1(rn, rd);
1240                      gen_movl_reg_T0(s, rn);                      gen_movl_reg_T0(s, rn);
1241                      gen_movl_reg_T1(s, rd);                      gen_movl_reg_T1(s, rd);
1242                  } else {                  } else {
                     gen_op_mul_T0_T1();  
1243                      if (op1 == 0) {                      if (op1 == 0) {
1244                          gen_movl_T1_reg(s, rn);                          gen_movl_T1_reg(s, rn);
1245                          gen_op_addl_T0_T1_setq();                          gen_op_addl_T0_T1_setq();
# Line 1176  static void disas_arm_insn(CPUState * en Line 1319  static void disas_arm_insn(CPUState * en
1319                  gen_op_logic_T0_cc();                  gen_op_logic_T0_cc();
1320              break;              break;
1321          case 0x02:          case 0x02:
1322              if (set_cc)              if (set_cc && rd == 15) {
1323                    /* SUBS r15, ... is used for exception return.  */
1324                    if (IS_USER(s))
1325                        goto illegal_op;
1326                  gen_op_subl_T0_T1_cc();                  gen_op_subl_T0_T1_cc();
1327              else                  gen_exception_return(s);
1328                  gen_op_subl_T0_T1();              } else {
1329              gen_movl_reg_T0(s, rd);                  if (set_cc)
1330                        gen_op_subl_T0_T1_cc();
1331                    else
1332                        gen_op_subl_T0_T1();
1333                    gen_movl_reg_T0(s, rd);
1334                }
1335              break;              break;
1336          case 0x03:          case 0x03:
1337              if (set_cc)              if (set_cc)
# Line 1246  static void disas_arm_insn(CPUState * en Line 1397  static void disas_arm_insn(CPUState * en
1397                  gen_op_logic_T0_cc();                  gen_op_logic_T0_cc();
1398              break;              break;
1399          case 0x0d:          case 0x0d:
1400              gen_movl_reg_T1(s, rd);              if (logic_cc && rd == 15) {
1401              if (logic_cc)                  /* MOVS r15, ... is used for exception return.  */
1402                  gen_op_logic_T1_cc();                  if (IS_USER(s))
1403                        goto illegal_op;
1404                    gen_op_movl_T0_T1();
1405                    gen_exception_return(s);
1406                } else {
1407                    gen_movl_reg_T1(s, rd);
1408                    if (logic_cc)
1409                        gen_op_logic_T1_cc();
1410                }
1411              break;              break;
1412          case 0x0e:          case 0x0e:
1413              gen_op_bicl_T0_T1();              gen_op_bicl_T0_T1();
# Line 1301  static void disas_arm_insn(CPUState * en Line 1460  static void disas_arm_insn(CPUState * en
1460                          if (insn & (1 << 21)) /* mult accumulate */                          if (insn & (1 << 21)) /* mult accumulate */
1461                              gen_op_addq_T0_T1(rn, rd);                              gen_op_addq_T0_T1(rn, rd);
1462                          if (!(insn & (1 << 23))) { /* double accumulate */                          if (!(insn & (1 << 23))) { /* double accumulate */
1463                                ARCH(6);
1464                              gen_op_addq_lo_T0_T1(rn);                              gen_op_addq_lo_T0_T1(rn);
1465                              gen_op_addq_lo_T0_T1(rd);                              gen_op_addq_lo_T0_T1(rd);
1466                          }                          }
# Line 1322  static void disas_arm_insn(CPUState * en Line 1482  static void disas_arm_insn(CPUState * en
1482                          gen_movl_T0_reg(s, rm);                          gen_movl_T0_reg(s, rm);
1483                          gen_movl_T1_reg(s, rn);                          gen_movl_T1_reg(s, rn);
1484                          if (insn & (1 << 22)) {                          if (insn & (1 << 22)) {
1485                              gen_op_swpb_T0_T1();                              gen_ldst(swpb, s);
1486                          } else {                          } else {
1487                              gen_op_swpl_T0_T1();                              gen_ldst(swpl, s);
1488                          }                          }
1489                          gen_movl_reg_T0(s, rd);                          gen_movl_reg_T0(s, rd);
1490                      }                      }
# Line 1340  static void disas_arm_insn(CPUState * en Line 1500  static void disas_arm_insn(CPUState * en
1500                      /* load */                      /* load */
1501                      switch(sh) {                      switch(sh) {
1502                      case 1:                      case 1:
1503                          gen_op_lduw_T0_T1();                          gen_ldst(lduw, s);
1504                          break;                          break;
1505                      case 2:                      case 2:
1506                          gen_op_ldsb_T0_T1();                          gen_ldst(ldsb, s);
1507                          break;                          break;
1508                      default:                      default:
1509                      case 3:                      case 3:
1510                          gen_op_ldsw_T0_T1();                          gen_ldst(ldsw, s);
1511                          break;                          break;
1512                      }                      }
1513                      gen_movl_reg_T0(s, rd);                      gen_movl_reg_T0(s, rd);
# Line 1356  static void disas_arm_insn(CPUState * en Line 1516  static void disas_arm_insn(CPUState * en
1516                      if (sh & 1) {                      if (sh & 1) {
1517                          /* store */                          /* store */
1518                          gen_movl_T0_reg(s, rd);                          gen_movl_T0_reg(s, rd);
1519                          gen_op_stl_T0_T1();                          gen_ldst(stl, s);
1520                          gen_op_addl_T1_im(4);                          gen_op_addl_T1_im(4);
1521                          gen_movl_T0_reg(s, rd + 1);                          gen_movl_T0_reg(s, rd + 1);
1522                          gen_op_stl_T0_T1();                          gen_ldst(stl, s);
1523                          if ((insn & (1 << 24)) || (insn & (1 << 20)))                          if ((insn & (1 << 24)) || (insn & (1 << 20)))
1524                              gen_op_addl_T1_im(-4);                              gen_op_addl_T1_im(-4);
1525                      } else {                      } else {
1526                          /* load */                          /* load */
1527                          gen_op_ldl_T0_T1();                          gen_ldst(ldl, s);
1528                          gen_movl_reg_T0(s, rd);                          gen_movl_reg_T0(s, rd);
1529                          gen_op_addl_T1_im(4);                          gen_op_addl_T1_im(4);
1530                          gen_op_ldl_T0_T1();                          gen_ldst(ldl, s);
1531                          gen_movl_reg_T0(s, rd + 1);                          gen_movl_reg_T0(s, rd + 1);
1532                          if ((insn & (1 << 24)) || (insn & (1 << 20)))                          if ((insn & (1 << 24)) || (insn & (1 << 20)))
1533                              gen_op_addl_T1_im(-4);                              gen_op_addl_T1_im(-4);
# Line 1375  static void disas_arm_insn(CPUState * en Line 1535  static void disas_arm_insn(CPUState * en
1535                  } else {                  } else {
1536                      /* store */                      /* store */
1537                      gen_movl_T0_reg(s, rd);                      gen_movl_T0_reg(s, rd);
1538                      gen_op_stw_T0_T1();                      gen_ldst(stw, s);
1539                  }                  }
1540                  if (!(insn & (1 << 24))) {                  if (!(insn & (1 << 24))) {
1541                      gen_add_datah_offset(s, insn);                      gen_add_datah_offset(s, insn);
# Line 1393  static void disas_arm_insn(CPUState * en Line 1553  static void disas_arm_insn(CPUState * en
1553              rn = (insn >> 16) & 0xf;              rn = (insn >> 16) & 0xf;
1554              rd = (insn >> 12) & 0xf;              rd = (insn >> 12) & 0xf;
1555              gen_movl_T1_reg(s, rn);              gen_movl_T1_reg(s, rn);
1556                i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
1557              if (insn & (1 << 24))              if (insn & (1 << 24))
1558                  gen_add_data_offset(s, insn);                  gen_add_data_offset(s, insn);
1559              if (insn & (1 << 20)) {              if (insn & (1 << 20)) {
1560                  /* load */                  /* load */
1561    #if defined(CONFIG_USER_ONLY)
1562                  if (insn & (1 << 22))                  if (insn & (1 << 22))
1563                      gen_op_ldub_T0_T1();                      gen_op_ldub_raw();
1564                  else                  else
1565                      gen_op_ldl_T0_T1();                      gen_op_ldl_raw();
1566    #else
1567                    if (insn & (1 << 22)) {
1568                        if (i)
1569                            gen_op_ldub_user();
1570                        else
1571                            gen_op_ldub_kernel();
1572                    } else {
1573                        if (i)
1574                            gen_op_ldl_user();
1575                        else
1576                            gen_op_ldl_kernel();
1577                    }
1578    #endif
1579                  if (rd == 15)                  if (rd == 15)
1580                      gen_bx(s);                      gen_bx(s);
1581                  else                  else
# Line 1408  static void disas_arm_insn(CPUState * en Line 1583  static void disas_arm_insn(CPUState * en
1583              } else {              } else {
1584                  /* store */                  /* store */
1585                  gen_movl_T0_reg(s, rd);                  gen_movl_T0_reg(s, rd);
1586    #if defined(CONFIG_USER_ONLY)
1587                  if (insn & (1 << 22))                  if (insn & (1 << 22))
1588                      gen_op_stb_T0_T1();                      gen_op_stb_raw();
1589                  else                  else
1590                      gen_op_stl_T0_T1();                      gen_op_stl_raw();
1591    #else
1592                    if (insn & (1 << 22)) {
1593                        if (i)
1594                            gen_op_stb_user();
1595                        else
1596                            gen_op_stb_kernel();
1597                    } else {
1598                        if (i)
1599                            gen_op_stl_user();
1600                        else
1601                            gen_op_stl_kernel();
1602                    }
1603    #endif
1604              }              }
1605              if (!(insn & (1 << 24))) {              if (!(insn & (1 << 24))) {
1606                  gen_add_data_offset(s, insn);                  gen_add_data_offset(s, insn);
# Line 1423  static void disas_arm_insn(CPUState * en Line 1612  static void disas_arm_insn(CPUState * en
1612          case 0x08:          case 0x08:
1613          case 0x09:          case 0x09:
1614              {              {
1615                  int j, n;                  int j, n, user;
1616                  /* load/store multiple words */                  /* load/store multiple words */
1617                  /* XXX: store correct base if write back */                  /* XXX: store correct base if write back */
1618                  if (insn & (1 << 22))                  user = 0;
1619                      goto illegal_op; /* only usable in supervisor mode */                  if (insn & (1 << 22)) {
1620                        if (IS_USER(s))
1621                            goto illegal_op; /* only usable in supervisor mode */
1622    
1623                        if ((insn & (1 << 15)) == 0)
1624                            user = 1;
1625                    }
1626                  rn = (insn >> 16) & 0xf;                  rn = (insn >> 16) & 0xf;
1627                  gen_movl_T1_reg(s, rn);                  gen_movl_T1_reg(s, rn);
1628                                    
# Line 1460  static void disas_arm_insn(CPUState * en Line 1655  static void disas_arm_insn(CPUState * en
1655                      if (insn & (1 << i)) {                      if (insn & (1 << i)) {
1656                          if (insn & (1 << 20)) {                          if (insn & (1 << 20)) {
1657                              /* load */                              /* load */
1658                              gen_op_ldl_T0_T1();                              gen_ldst(ldl, s);
1659                              if (i == 15)                              if (i == 15) {
1660                                  gen_bx(s);                                  gen_bx(s);
1661                              else                              } else if (user) {
1662                                    gen_op_movl_user_T0(i);
1663                                } else {
1664                                  gen_movl_reg_T0(s, i);                                  gen_movl_reg_T0(s, i);
1665                                }
1666                          } else {                          } else {
1667                              /* store */                              /* store */
1668                              if (i == 15) {                              if (i == 15) {
1669                                  /* special case: r15 = PC + 12 */                                  /* special case: r15 = PC + 12 */
1670                                  val = (long)s->pc + 8;                                  val = (long)s->pc + 8;
1671                                  gen_op_movl_TN_im[0](val);                                  gen_op_movl_TN_im[0](val);
1672                                } else if (user) {
1673                                    gen_op_movl_T0_user(i);
1674                              } else {                              } else {
1675                                  gen_movl_T0_reg(s, i);                                  gen_movl_T0_reg(s, i);
1676                              }                              }
1677                              gen_op_stl_T0_T1();                              gen_ldst(stl, s);
1678                          }                          }
1679                          j++;                          j++;
1680                          /* no need to add after the last transfer */                          /* no need to add after the last transfer */
# Line 1503  static void disas_arm_insn(CPUState * en Line 1703  static void disas_arm_insn(CPUState * en
1703                      }                      }
1704                      gen_movl_reg_T1(s, rn);                      gen_movl_reg_T1(s, rn);
1705                  }                  }
1706                    if ((insn & (1 << 22)) && !user) {
1707                        /* Restore CPSR from SPSR.  */
1708                        gen_op_movl_T0_spsr();
1709                        gen_op_movl_cpsr_T0(0xffffffff);
1710                        s->is_jmp = DISAS_UPDATE;
1711                    }
1712              }              }
1713              break;              break;
1714          case 0xa:          case 0xa:
# Line 1532  static void disas_arm_insn(CPUState * en Line 1738  static void disas_arm_insn(CPUState * en
1738                  if (disas_vfp_insn (env, s, insn))                  if (disas_vfp_insn (env, s, insn))
1739                      goto illegal_op;                      goto illegal_op;
1740                  break;                  break;
1741                case 15:
1742                    if (disas_cp15_insn (s, insn))
1743                        goto illegal_op;
1744                    break;
1745              default:              default:
1746                  /* unknown coprocessor.  */                  /* unknown coprocessor.  */
1747                  goto illegal_op;                  goto illegal_op;
# Line 1561  static void disas_thumb_insn(DisasContex Line 1771  static void disas_thumb_insn(DisasContex
1771      int32_t offset;      int32_t offset;
1772      int i;      int i;
1773    
1774      insn = lduw(s->pc);      insn = lduw_code(s->pc);
1775      s->pc += 2;      s->pc += 2;
1776        
1777      switch (insn >> 12) {      switch (insn >> 12) {
1778      case 0: case 1:      case 0: case 1:
1779          rd = insn & 7;          rd = insn & 7;
# Line 1628  static void disas_thumb_insn(DisasContex Line 1838  static void disas_thumb_insn(DisasContex
1838              val = s->pc + 2 + ((insn & 0xff) * 4);              val = s->pc + 2 + ((insn & 0xff) * 4);
1839              val &= ~(uint32_t)2;              val &= ~(uint32_t)2;
1840              gen_op_movl_T1_im(val);              gen_op_movl_T1_im(val);
1841              gen_op_ldl_T0_T1();              gen_ldst(ldl, s);
1842              gen_movl_reg_T0(s, rd);              gen_movl_reg_T0(s, rd);
1843              break;              break;
1844          }          }
# Line 1771  static void disas_thumb_insn(DisasContex Line 1981  static void disas_thumb_insn(DisasContex
1981    
1982          switch (op) {          switch (op) {
1983          case 0: /* str */          case 0: /* str */
1984              gen_op_stl_T0_T1();              gen_ldst(stl, s);
1985              break;              break;
1986          case 1: /* strh */          case 1: /* strh */
1987              gen_op_stw_T0_T1();              gen_ldst(stw, s);
1988              break;              break;
1989          case 2: /* strb */          case 2: /* strb */
1990              gen_op_stb_T0_T1();              gen_ldst(stb, s);
1991              break;              break;
1992          case 3: /* ldrsb */          case 3: /* ldrsb */
1993              gen_op_ldsb_T0_T1();              gen_ldst(ldsb, s);
1994              break;              break;
1995          case 4: /* ldr */          case 4: /* ldr */
1996              gen_op_ldl_T0_T1();              gen_ldst(ldl, s);
1997              break;              break;
1998          case 5: /* ldrh */          case 5: /* ldrh */
1999              gen_op_lduw_T0_T1();              gen_ldst(lduw, s);
2000              break;              break;
2001          case 6: /* ldrb */          case 6: /* ldrb */
2002              gen_op_ldub_T0_T1();              gen_ldst(ldub, s);
2003              break;              break;
2004          case 7: /* ldrsh */          case 7: /* ldrsh */
2005              gen_op_ldsw_T0_T1();              gen_ldst(ldsw, s);
2006              break;              break;
2007          }          }
2008          if (op >= 3) /* load */          if (op >= 3) /* load */
# Line 1810  static void disas_thumb_insn(DisasContex Line 2020  static void disas_thumb_insn(DisasContex
2020    
2021          if (insn & (1 << 11)) {          if (insn & (1 << 11)) {
2022              /* load */              /* load */
2023              gen_op_ldl_T0_T1();              gen_ldst(ldl, s);
2024              gen_movl_reg_T0(s, rd);              gen_movl_reg_T0(s, rd);
2025          } else {          } else {
2026              /* store */              /* store */
2027              gen_movl_T0_reg(s, rd);              gen_movl_T0_reg(s, rd);
2028              gen_op_stl_T0_T1();              gen_ldst(stl, s);
2029          }          }
2030          break;          break;
2031    
# Line 1830  static void disas_thumb_insn(DisasContex Line 2040  static void disas_thumb_insn(DisasContex
2040    
2041          if (insn & (1 << 11)) {          if (insn & (1 << 11)) {
2042              /* load */              /* load */
2043              gen_op_ldub_T0_T1();              gen_ldst(ldub, s);
2044              gen_movl_reg_T0(s, rd);              gen_movl_reg_T0(s, rd);
2045          } else {          } else {
2046              /* store */              /* store */
2047              gen_movl_T0_reg(s, rd);              gen_movl_T0_reg(s, rd);
2048              gen_op_stb_T0_T1();              gen_ldst(stb, s);
2049          }          }
2050          break;          break;
2051    
# Line 1850  static void disas_thumb_insn(DisasContex Line 2060  static void disas_thumb_insn(DisasContex
2060    
2061          if (insn & (1 << 11)) {          if (insn & (1 << 11)) {
2062              /* load */              /* load */
2063              gen_op_lduw_T0_T1();              gen_ldst(lduw, s);
2064              gen_movl_reg_T0(s, rd);              gen_movl_reg_T0(s, rd);
2065          } else {          } else {
2066              /* store */              /* store */
2067              gen_movl_T0_reg(s, rd);              gen_movl_T0_reg(s, rd);
2068              gen_op_stw_T0_T1();              gen_ldst(stw, s);
2069          }          }
2070          break;          break;
2071    
# Line 1869  static void disas_thumb_insn(DisasContex Line 2079  static void disas_thumb_insn(DisasContex
2079    
2080          if (insn & (1 << 11)) {          if (insn & (1 << 11)) {
2081              /* load */              /* load */
2082              gen_op_ldl_T0_T1();              gen_ldst(ldl, s);
2083              gen_movl_reg_T0(s, rd);              gen_movl_reg_T0(s, rd);
2084          } else {          } else {
2085              /* store */              /* store */
2086              gen_movl_T0_reg(s, rd);              gen_movl_T0_reg(s, rd);
2087              gen_op_stl_T0_T1();              gen_ldst(stl, s);
2088          }          }
2089          break;          break;
2090    
# Line 1929  static void disas_thumb_insn(DisasContex Line 2139  static void disas_thumb_insn(DisasContex
2139                  if (insn & (1 << i)) {                  if (insn & (1 << i)) {
2140                      if (insn & (1 << 11)) {                      if (insn & (1 << 11)) {
2141                          /* pop */                          /* pop */
2142                          gen_op_ldl_T0_T1();                          gen_ldst(ldl, s);
2143                          gen_movl_reg_T0(s, i);                          gen_movl_reg_T0(s, i);
2144                      } else {                      } else {
2145                          /* push */                          /* push */
2146                          gen_movl_T0_reg(s, i);                          gen_movl_T0_reg(s, i);
2147                          gen_op_stl_T0_T1();                          gen_ldst(stl, s);
2148                      }                      }
2149                      /* advance to the next address.  */                      /* advance to the next address.  */
2150                      gen_op_addl_T1_T2();                      gen_op_addl_T1_T2();
# Line 1943  static void disas_thumb_insn(DisasContex Line 2153  static void disas_thumb_insn(DisasContex
2153              if (insn & (1 << 8)) {              if (insn & (1 << 8)) {
2154                  if (insn & (1 << 11)) {                  if (insn & (1 << 11)) {
2155                      /* pop pc */                      /* pop pc */
2156                      gen_op_ldl_T0_T1();                      gen_ldst(ldl, s);
2157                      /* don't set the pc until the rest of the instruction                      /* don't set the pc until the rest of the instruction
2158                         has completed */                         has completed */
2159                  } else {                  } else {
2160                      /* push lr */                      /* push lr */
2161                      gen_movl_T0_reg(s, 14);                      gen_movl_T0_reg(s, 14);
2162                      gen_op_stl_T0_T1();                      gen_ldst(stl, s);
2163                  }                  }
2164                  gen_op_addl_T1_T2();                  gen_op_addl_T1_T2();
2165              }              }
# Line 1978  static void disas_thumb_insn(DisasContex Line 2188  static void disas_thumb_insn(DisasContex
2188              if (insn & (1 << i)) {              if (insn & (1 << i)) {
2189                  if (insn & (1 << 11)) {                  if (insn & (1 << 11)) {
2190                      /* load */                      /* load */
2191                      gen_op_ldl_T0_T1();                      gen_ldst(ldl, s);
2192                      gen_movl_reg_T0(s, i);                      gen_movl_reg_T0(s, i);
2193                  } else {                  } else {
2194                      /* store */                      /* store */
2195                      gen_movl_T0_reg(s, i);                      gen_movl_T0_reg(s, i);
2196                      gen_op_stl_T0_T1();                      gen_ldst(stl, s);
2197                  }                  }
2198                  /* advance to the next address */                  /* advance to the next address */
2199                  gen_op_addl_T1_T2();                  gen_op_addl_T1_T2();
2200              }              }
2201          }          }
2202          /* Base register writeback.  */          /* Base register writeback.  */
2203          gen_movl_reg_T1(s, rn);          if ((insn & (1 << rn)) == 0)
2204                gen_movl_reg_T1(s, rn);
2205          break;          break;
2206    
2207      case 13:      case 13:
# Line 2036  static void disas_thumb_insn(DisasContex Line 2247  static void disas_thumb_insn(DisasContex
2247      case 15:      case 15:
2248          /* branch and link [and switch to arm] */          /* branch and link [and switch to arm] */
2249          offset = ((int32_t)insn << 21) >> 10;          offset = ((int32_t)insn << 21) >> 10;
2250          insn = lduw(s->pc);          insn = lduw_code(s->pc);
2251          offset |= insn & 0x7ff;          offset |= insn & 0x7ff;
2252    
2253          val = (uint32_t)s->pc + 2;          val = (uint32_t)s->pc + 2;
# Line 2073  static inline int gen_intermediate_code_ Line 2284  static inline int gen_intermediate_code_
2284      uint16_t *gen_opc_end;      uint16_t *gen_opc_end;
2285      int j, lj;      int j, lj;
2286      target_ulong pc_start;      target_ulong pc_start;
2287        uint32_t next_page_start;
2288            
2289      /* generate intermediate code */      /* generate intermediate code */
2290      pc_start = tb->pc;      pc_start = tb->pc;
# Line 2088  static inline int gen_intermediate_code_ Line 2300  static inline int gen_intermediate_code_
2300      dc->singlestep_enabled = env->singlestep_enabled;      dc->singlestep_enabled = env->singlestep_enabled;
2301      dc->condjmp = 0;      dc->condjmp = 0;
2302      dc->thumb = env->thumb;      dc->thumb = env->thumb;
2303    #if !defined(CONFIG_USER_ONLY)
2304        dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
2305    #endif
2306        next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
2307      nb_gen_labels = 0;      nb_gen_labels = 0;
2308      lj = -1;      lj = -1;
2309      do {      do {
# Line 2124  static inline int gen_intermediate_code_ Line 2340  static inline int gen_intermediate_code_
2340          }          }
2341          /* Translation stops when a conditional branch is enoutered.          /* Translation stops when a conditional branch is enoutered.
2342           * Otherwise the subsequent code could get translated several times.           * Otherwise the subsequent code could get translated several times.
2343           */           * Also stop translation when a page boundary is reached.  This
2344             * ensures prefech aborts occur at the right place.  */
2345      } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&      } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
2346               !env->singlestep_enabled &&               !env->singlestep_enabled &&
2347               (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));               dc->pc < next_page_start);
2348      /* It this stage dc->condjmp will only be set when the skipped      /* At this stage dc->condjmp will only be set when the skipped
2349       * instruction was a conditional branch, and teh PC has already been       * instruction was a conditional branch, and the PC has already been
2350       * written.  */       * written.  */
2351      if (__builtin_expect(env->singlestep_enabled, 0)) {      if (__builtin_expect(env->singlestep_enabled, 0)) {
2352          /* Make sure the pc is updated, and raise a debug exception.  */          /* Make sure the pc is updated, and raise a debug exception.  */
# Line 2180  static inline int gen_intermediate_code_ Line 2397  static inline int gen_intermediate_code_
2397          }          }
2398      }      }
2399  #endif  #endif
2400      if (!search_pc)      if (search_pc) {
2401            j = gen_opc_ptr - gen_opc_buf;
2402            lj++;
2403            while (lj <= j)
2404                gen_opc_instr_start[lj++] = 0;
2405            tb->size = 0;
2406        } else {
2407          tb->size = dc->pc - pc_start;          tb->size = dc->pc - pc_start;
2408        }
2409      return 0;      return 0;
2410  }  }
2411    
# Line 2195  int gen_intermediate_code_pc(CPUState *e Line 2419  int gen_intermediate_code_pc(CPUState *e
2419      return gen_intermediate_code_internal(env, tb, 1);      return gen_intermediate_code_internal(env, tb, 1);
2420  }  }
2421    
2422    void cpu_reset(CPUARMState *env)
2423    {
2424    #if defined (CONFIG_USER_ONLY)
2425        /* SVC mode with interrupts disabled.  */
2426        env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
2427    #else
2428        env->uncached_cpsr = ARM_CPU_MODE_USR;
2429    #endif
2430        env->regs[15] = 0;
2431    }
2432    
2433  CPUARMState *cpu_arm_init(void)  CPUARMState *cpu_arm_init(void)
2434  {  {
2435      CPUARMState *env;      CPUARMState *env;
# Line 2203  CPUARMState *cpu_arm_init(void) Line 2438  CPUARMState *cpu_arm_init(void)
2438      if (!env)      if (!env)
2439          return NULL;          return NULL;
2440      cpu_exec_init(env);      cpu_exec_init(env);
2441        cpu_reset(env);
2442        tlb_flush(env, 1);
2443      return env;      return env;
2444  }  }
2445    
# Line 2211  void cpu_arm_close(CPUARMState *env) Line 2448  void cpu_arm_close(CPUARMState *env)
2448      free(env);      free(env);
2449  }  }
2450    
2451    static const char *cpu_mode_names[16] = {
2452      "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
2453      "???", "???", "???", "und", "???", "???", "???", "sys"
2454    };
2455  void cpu_dump_state(CPUState *env, FILE *f,  void cpu_dump_state(CPUState *env, FILE *f,
2456                      int (*cpu_fprintf)(FILE *f, const char *fmt, ...),                      int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2457                      int flags)                      int flags)
# Line 2221  void cpu_dump_state(CPUState *env, FILE Line 2462  void cpu_dump_state(CPUState *env, FILE
2462          float s;          float s;
2463      } s0, s1;      } s0, s1;
2464      CPU_DoubleU d;      CPU_DoubleU d;
2465        uint32_t psr;
2466    
2467      for(i=0;i<16;i++) {      for(i=0;i<16;i++) {
2468          cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);          cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
# Line 2229  void cpu_dump_state(CPUState *env, FILE Line 2471  void cpu_dump_state(CPUState *env, FILE
2471          else          else
2472              cpu_fprintf(f, " ");              cpu_fprintf(f, " ");
2473      }      }
2474      cpu_fprintf(f, "PSR=%08x %c%c%c%c %c\n",      psr = cpsr_read(env);
2475               env->cpsr,      cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d %x\n",
2476              env->cpsr & (1 << 31) ? 'N' : '-',                  psr,
2477              env->cpsr & (1 << 30) ? 'Z' : '-',                  psr & (1 << 31) ? 'N' : '-',
2478              env->cpsr & (1 << 29) ? 'C' : '-',                  psr & (1 << 30) ? 'Z' : '-',
2479              env->cpsr & (1 << 28) ? 'V' : '-',                  psr & (1 << 29) ? 'C' : '-',
2480              env->thumb ? 'T' : 'A');                  psr & (1 << 28) ? 'V' : '-',
2481                    psr & CPSR_T ? 'T' : 'A',
2482                    cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
2483    
2484      for (i = 0; i < 16; i++) {      for (i = 0; i < 16; i++) {
2485          d.d = env->vfp.regs[i];          d.d = env->vfp.regs[i];
# Line 2250  void cpu_dump_state(CPUState *env, FILE Line 2494  void cpu_dump_state(CPUState *env, FILE
2494      cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.fpscr);      cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.fpscr);
2495  }  }
2496    
 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)  
 {  
     return addr;  
 }  
   
 #if defined(CONFIG_USER_ONLY)  
   
 int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,  
                               int is_user, int is_softmmu)  
 {  
     env->cp15_6 = address;  
     if (rw == 2) {  
         env->exception_index = EXCP_PREFETCH_ABORT;  
     } else {  
         env->exception_index = EXCP_DATA_ABORT;  
     }  
     return 1;  
 }  
   
 #else  
   
 #error not implemented  
   
 #endif  

Legend:
Removed from v.1.31  
changed lines
  Added in v.1.32

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26