Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
qemu
提交
b9c6cbff
Q
qemu
项目概览
openeuler
/
qemu
通知
10
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Q
qemu
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
b9c6cbff
编写于
8月 09, 2011
作者:
E
Edgar E. Iglesias
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'pm-arm/for-upstream' into pm
上级
1da005b3
a492892c
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
121 addition
and
42 deletion
+121
-42
target-arm/cpu.h
target-arm/cpu.h
+2
-0
target-arm/helper.c
target-arm/helper.c
+44
-3
target-arm/translate.c
target-arm/translate.c
+75
-39
未找到文件。
target-arm/cpu.h
浏览文件 @
b9c6cbff
...
...
@@ -374,6 +374,7 @@ enum arm_features {
ARM_FEATURE_V4T
,
ARM_FEATURE_V5
,
ARM_FEATURE_STRONGARM
,
ARM_FEATURE_VAPA
,
/* cp15 VA to PA lookups */
};
static
inline
int
arm_feature
(
CPUARMState
*
env
,
int
feature
)
...
...
@@ -420,6 +421,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
#define ARM_CPUID_PXA270_C5 0x69054117
#define ARM_CPUID_ARM1136 0x4117b363
#define ARM_CPUID_ARM1136_R2 0x4107b362
#define ARM_CPUID_ARM1176 0x410fb767
#define ARM_CPUID_ARM11MPCORE 0x410fb022
#define ARM_CPUID_CORTEXA8 0x410fc080
#define ARM_CPUID_CORTEXA9 0x410fc090
...
...
target-arm/helper.c
浏览文件 @
b9c6cbff
...
...
@@ -35,6 +35,12 @@ static uint32_t arm1136_cp15_c0_c1[8] =
static
uint32_t
arm1136_cp15_c0_c2
[
8
]
=
{
0x00140011
,
0x12002111
,
0x11231111
,
0x01102131
,
0x141
,
0
,
0
,
0
};
static
uint32_t
arm1176_cp15_c0_c1
[
8
]
=
{
0x111
,
0x11
,
0x33
,
0
,
0x01130003
,
0x10030302
,
0x01222100
,
0
};
static
uint32_t
arm1176_cp15_c0_c2
[
8
]
=
{
0x0140011
,
0x12002111
,
0x11231121
,
0x01102131
,
0x01141
,
0
,
0
,
0
};
static
uint32_t
cpu_arm_find_by_name
(
const
char
*
name
);
static
inline
void
set_feature
(
CPUARMState
*
env
,
int
feature
)
...
...
@@ -70,13 +76,24 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
env
->
cp15
.
c0_cachetype
=
0x1dd20d2
;
env
->
cp15
.
c1_sys
=
0x00090078
;
break
;
case
ARM_CPUID_ARM1136_R2
:
case
ARM_CPUID_ARM1136
:
/* This is the 1136 r1, which is a v6K core */
set_feature
(
env
,
ARM_FEATURE_V6K
);
/* Fall through */
case
ARM_CPUID_ARM1136_R2
:
/* What qemu calls "arm1136_r2" is actually the 1136 r0p2, ie an
* older core than plain "arm1136". In particular this does not
* have the v6K features.
*/
set_feature
(
env
,
ARM_FEATURE_V4T
);
set_feature
(
env
,
ARM_FEATURE_V5
);
set_feature
(
env
,
ARM_FEATURE_V6
);
set_feature
(
env
,
ARM_FEATURE_VFP
);
set_feature
(
env
,
ARM_FEATURE_AUXCR
);
/* These ID register values are correct for 1136 but may be wrong
* for 1136_r2 (in particular r0p2 does not actually implement most
* of the ID registers).
*/
env
->
vfp
.
xregs
[
ARM_VFP_FPSID
]
=
0x410120b4
;
env
->
vfp
.
xregs
[
ARM_VFP_MVFR0
]
=
0x11111111
;
env
->
vfp
.
xregs
[
ARM_VFP_MVFR1
]
=
0x00000000
;
...
...
@@ -85,6 +102,22 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
env
->
cp15
.
c0_cachetype
=
0x1dd20d2
;
env
->
cp15
.
c1_sys
=
0x00050078
;
break
;
case
ARM_CPUID_ARM1176
:
set_feature
(
env
,
ARM_FEATURE_V4T
);
set_feature
(
env
,
ARM_FEATURE_V5
);
set_feature
(
env
,
ARM_FEATURE_V6
);
set_feature
(
env
,
ARM_FEATURE_V6K
);
set_feature
(
env
,
ARM_FEATURE_VFP
);
set_feature
(
env
,
ARM_FEATURE_AUXCR
);
set_feature
(
env
,
ARM_FEATURE_VAPA
);
env
->
vfp
.
xregs
[
ARM_VFP_FPSID
]
=
0x410120b5
;
env
->
vfp
.
xregs
[
ARM_VFP_MVFR0
]
=
0x11111111
;
env
->
vfp
.
xregs
[
ARM_VFP_MVFR1
]
=
0x00000000
;
memcpy
(
env
->
cp15
.
c0_c1
,
arm1176_cp15_c0_c1
,
8
*
sizeof
(
uint32_t
));
memcpy
(
env
->
cp15
.
c0_c2
,
arm1176_cp15_c0_c2
,
8
*
sizeof
(
uint32_t
));
env
->
cp15
.
c0_cachetype
=
0x1dd20d2
;
env
->
cp15
.
c1_sys
=
0x00050078
;
break
;
case
ARM_CPUID_ARM11MPCORE
:
set_feature
(
env
,
ARM_FEATURE_V4T
);
set_feature
(
env
,
ARM_FEATURE_V5
);
...
...
@@ -92,6 +125,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
set_feature
(
env
,
ARM_FEATURE_V6K
);
set_feature
(
env
,
ARM_FEATURE_VFP
);
set_feature
(
env
,
ARM_FEATURE_AUXCR
);
set_feature
(
env
,
ARM_FEATURE_VAPA
);
env
->
vfp
.
xregs
[
ARM_VFP_FPSID
]
=
0x410120b4
;
env
->
vfp
.
xregs
[
ARM_VFP_MVFR0
]
=
0x11111111
;
env
->
vfp
.
xregs
[
ARM_VFP_MVFR1
]
=
0x00000000
;
...
...
@@ -222,6 +256,11 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
cpu_abort
(
env
,
"Bad CPU ID: %x
\n
"
,
id
);
break
;
}
/* Some features automatically imply others: */
if
(
arm_feature
(
env
,
ARM_FEATURE_V7
))
{
set_feature
(
env
,
ARM_FEATURE_VAPA
);
}
}
void
cpu_reset
(
CPUARMState
*
env
)
...
...
@@ -380,6 +419,7 @@ static const struct arm_cpu_t arm_cpu_names[] = {
{
ARM_CPUID_ARM1026
,
"arm1026"
},
{
ARM_CPUID_ARM1136
,
"arm1136"
},
{
ARM_CPUID_ARM1136_R2
,
"arm1136-r2"
},
{
ARM_CPUID_ARM1176
,
"arm1176"
},
{
ARM_CPUID_ARM11MPCORE
,
"arm11mpcore"
},
{
ARM_CPUID_CORTEXM3
,
"cortex-m3"
},
{
ARM_CPUID_CORTEXA8
,
"cortex-a8"
},
...
...
@@ -948,7 +988,7 @@ static inline int check_ap(CPUState *env, int ap, int domain, int access_type,
case
6
:
return
prot_ro
;
case
7
:
if
(
!
arm_feature
(
env
,
ARM_FEATURE_V
7
))
if
(
!
arm_feature
(
env
,
ARM_FEATURE_V
6K
))
return
0
;
return
prot_ro
;
default:
...
...
@@ -1502,7 +1542,7 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
goto
bad_reg
;
}
/* No cache, so nothing to do except VA->PA translations. */
if
(
arm_feature
(
env
,
ARM_FEATURE_V
6K
))
{
if
(
arm_feature
(
env
,
ARM_FEATURE_V
APA
))
{
switch
(
crm
)
{
case
4
:
if
(
arm_feature
(
env
,
ARM_FEATURE_V7
))
{
...
...
@@ -1848,6 +1888,7 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
return
1
;
case
ARM_CPUID_ARM1136
:
case
ARM_CPUID_ARM1136_R2
:
case
ARM_CPUID_ARM1176
:
return
7
;
case
ARM_CPUID_ARM11MPCORE
:
return
1
;
...
...
target-arm/translate.c
浏览文件 @
b9c6cbff
...
...
@@ -2498,12 +2498,6 @@ static int cp15_user_ok(CPUState *env, uint32_t insn)
if
(
op
==
2
||
(
op
==
3
&&
(
insn
&
ARM_CP_RW_BIT
)))
return
1
;
}
if
(
cpn
==
7
)
{
/* ISB, DSB, DMB. */
if
((
cpm
==
5
&&
op
==
4
)
||
(
cpm
==
10
&&
(
op
==
4
||
op
==
5
)))
return
1
;
}
return
0
;
}
...
...
@@ -2579,39 +2573,60 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
/* cdp */
return
1
;
}
if
(
IS_USER
(
s
)
&&
!
cp15_user_ok
(
env
,
insn
))
{
return
1
;
}
/* Pre-v7 versions of the architecture implemented WFI via coprocessor
* instructions rather than a separate instruction.
/* We special case a number of cp15 instructions which were used
* for things which are real instructions in ARMv7. This allows
* them to work in linux-user mode which doesn't provide functional
* get_cp15/set_cp15 helpers, and is more efficient anyway.
*/
if
((
insn
&
0x0fff0fff
)
==
0x0e070f90
)
{
switch
((
insn
&
0x0fff0fff
))
{
case
0x0e070f90
:
/* 0,c7,c0,4: Standard v6 WFI (also used in some pre-v6 cores).
* In v7, this must NOP.
*/
if
(
IS_USER
(
s
))
{
return
1
;
}
if
(
!
arm_feature
(
env
,
ARM_FEATURE_V7
))
{
/* Wait for interrupt. */
gen_set_pc_im
(
s
->
pc
);
s
->
is_jmp
=
DISAS_WFI
;
}
return
0
;
}
if
((
insn
&
0x0fff0fff
)
==
0x0e070f58
)
{
case
0x0e070f58
:
/* 0,c7,c8,2: Not all pre-v6 cores implemented this WFI,
* so this is slightly over-broad.
*/
if
(
!
arm_feature
(
env
,
ARM_FEATURE_V6
))
{
if
(
!
IS_USER
(
s
)
&&
!
arm_feature
(
env
,
ARM_FEATURE_V6
))
{
/* Wait for interrupt. */
gen_set_pc_im
(
s
->
pc
);
s
->
is_jmp
=
DISAS_WFI
;
return
0
;
}
/* Otherwise
fall through
to handle via helper function.
/* Otherwise
continue
to handle via helper function.
* In particular, on v7 and some v6 cores this is one of
* the VA-PA registers.
*/
break
;
case
0x0e070f3d
:
/* 0,c7,c13,1: prefetch-by-MVA in v6, NOP in v7 */
if
(
arm_feature
(
env
,
ARM_FEATURE_V6
))
{
return
IS_USER
(
s
)
?
1
:
0
;
}
break
;
case
0x0e070f95
:
/* 0,c7,c5,4 : ISB */
case
0x0e070f9a
:
/* 0,c7,c10,4: DSB */
case
0x0e070fba
:
/* 0,c7,c10,5: DMB */
/* Barriers in both v6 and v7 */
if
(
arm_feature
(
env
,
ARM_FEATURE_V6
))
{
return
0
;
}
break
;
default:
break
;
}
if
(
IS_USER
(
s
)
&&
!
cp15_user_ok
(
env
,
insn
))
{
return
1
;
}
rd
=
(
insn
>>
12
)
&
0xf
;
...
...
@@ -3056,6 +3071,17 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
/* Source and destination the same. */
gen_mov_F0_vreg
(
dp
,
rd
);
break
;
case
4
:
case
5
:
case
6
:
case
7
:
/* VCVTB, VCVTT: only present with the halfprec extension,
* UNPREDICTABLE if bit 8 is set (we choose to UNDEF)
*/
if
(
dp
||
!
arm_feature
(
env
,
ARM_FEATURE_VFP_FP16
))
{
return
1
;
}
/* Otherwise fall through */
default:
/* One source operand. */
gen_mov_F0_vreg
(
dp
,
rm
);
...
...
@@ -3152,24 +3178,18 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
gen_vfp_sqrt
(
dp
);
break
;
case
4
:
/* vcvtb.f32.f16 */
if
(
!
arm_feature
(
env
,
ARM_FEATURE_VFP_FP16
))
return
1
;
tmp
=
gen_vfp_mrs
();
tcg_gen_ext16u_i32
(
tmp
,
tmp
);
gen_helper_vfp_fcvt_f16_to_f32
(
cpu_F0s
,
tmp
,
cpu_env
);
tcg_temp_free_i32
(
tmp
);
break
;
case
5
:
/* vcvtt.f32.f16 */
if
(
!
arm_feature
(
env
,
ARM_FEATURE_VFP_FP16
))
return
1
;
tmp
=
gen_vfp_mrs
();
tcg_gen_shri_i32
(
tmp
,
tmp
,
16
);
gen_helper_vfp_fcvt_f16_to_f32
(
cpu_F0s
,
tmp
,
cpu_env
);
tcg_temp_free_i32
(
tmp
);
break
;
case
6
:
/* vcvtb.f16.f32 */
if
(
!
arm_feature
(
env
,
ARM_FEATURE_VFP_FP16
))
return
1
;
tmp
=
tcg_temp_new_i32
();
gen_helper_vfp_fcvt_f32_to_f16
(
tmp
,
cpu_F0s
,
cpu_env
);
gen_mov_F0_vreg
(
0
,
rd
);
...
...
@@ -3180,8 +3200,6 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
gen_vfp_msr
(
tmp
);
break
;
case
7
:
/* vcvtt.f16.f32 */
if
(
!
arm_feature
(
env
,
ARM_FEATURE_VFP_FP16
))
return
1
;
tmp
=
tcg_temp_new_i32
();
gen_helper_vfp_fcvt_f32_to_f16
(
tmp
,
cpu_F0s
,
cpu_env
);
tcg_gen_shli_i32
(
tmp
,
tmp
,
16
);
...
...
@@ -3270,12 +3288,10 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
gen_vfp_toul
(
dp
,
32
-
rm
,
0
);
break
;
default:
/* undefined */
printf
(
"rn:%d
\n
"
,
rn
);
return
1
;
}
break
;
default:
/* undefined */
printf
(
"op:%d
\n
"
,
op
);
return
1
;
}
...
...
@@ -3382,17 +3398,18 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
VFP_DREG_D
(
rd
,
insn
);
else
rd
=
VFP_SREG_D
(
insn
);
if
(
s
->
thumb
&&
rn
==
15
)
{
addr
=
tcg_temp_new_i32
();
tcg_gen_movi_i32
(
addr
,
s
->
pc
&
~
2
);
}
else
{
addr
=
load_reg
(
s
,
rn
);
}
if
((
insn
&
0x01200000
)
==
0x01000000
)
{
/* Single load/store */
offset
=
(
insn
&
0xff
)
<<
2
;
if
((
insn
&
(
1
<<
23
))
==
0
)
offset
=
-
offset
;
if
(
s
->
thumb
&&
rn
==
15
)
{
/* This is actually UNPREDICTABLE */
addr
=
tcg_temp_new_i32
();
tcg_gen_movi_i32
(
addr
,
s
->
pc
&
~
2
);
}
else
{
addr
=
load_reg
(
s
,
rn
);
}
tcg_gen_addi_i32
(
addr
,
addr
,
offset
);
if
(
insn
&
(
1
<<
20
))
{
gen_vfp_ld
(
s
,
dp
,
addr
);
...
...
@@ -3404,11 +3421,34 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
tcg_temp_free_i32
(
addr
);
}
else
{
/* load/store multiple */
int
w
=
insn
&
(
1
<<
21
);
if
(
dp
)
n
=
(
insn
>>
1
)
&
0x7f
;
else
n
=
insn
&
0xff
;
if
(
w
&&
!
(((
insn
>>
23
)
^
(
insn
>>
24
))
&
1
))
{
/* P == U , W == 1 => UNDEF */
return
1
;
}
if
(
n
==
0
||
(
rd
+
n
)
>
32
||
(
dp
&&
n
>
16
))
{
/* UNPREDICTABLE cases for bad immediates: we choose to
* UNDEF to avoid generating huge numbers of TCG ops
*/
return
1
;
}
if
(
rn
==
15
&&
w
)
{
/* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
return
1
;
}
if
(
s
->
thumb
&&
rn
==
15
)
{
/* This is actually UNPREDICTABLE */
addr
=
tcg_temp_new_i32
();
tcg_gen_movi_i32
(
addr
,
s
->
pc
&
~
2
);
}
else
{
addr
=
load_reg
(
s
,
rn
);
}
if
(
insn
&
(
1
<<
24
))
/* pre-decrement */
tcg_gen_addi_i32
(
addr
,
addr
,
-
((
insn
&
0xff
)
<<
2
));
...
...
@@ -3428,7 +3468,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
}
tcg_gen_addi_i32
(
addr
,
addr
,
offset
);
}
if
(
insn
&
(
1
<<
21
)
)
{
if
(
w
)
{
/* writeback */
if
(
insn
&
(
1
<<
24
))
offset
=
-
offset
*
n
;
...
...
@@ -6330,8 +6370,6 @@ static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
return
0
;
}
}
fprintf
(
stderr
,
"Unknown cp14 read op1:%d crn:%d crm:%d op2:%d
\n
"
,
op1
,
crn
,
crm
,
op2
);
return
1
;
}
...
...
@@ -6363,8 +6401,6 @@ static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
return
0
;
}
}
fprintf
(
stderr
,
"Unknown cp14 write op1:%d crn:%d crm:%d op2:%d
\n
"
,
op1
,
crn
,
crm
,
op2
);
return
1
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录