Revision 6f27aba6
b/target-sparc/cpu.h | ||
---|---|---|
98 | 98 |
#define PS_AG (1<<0) |
99 | 99 |
|
100 | 100 |
#define FPRS_FEF (1<<2) |
101 |
|
|
102 |
#define HS_PRIV (1<<2) |
|
101 | 103 |
#endif |
102 | 104 |
|
103 | 105 |
/* Fcc */ |
... | ... | |
166 | 168 |
|
167 | 169 |
typedef struct sparc_def_t sparc_def_t; |
168 | 170 |
|
171 |
#if !defined(TARGET_SPARC64) |
|
169 | 172 |
#define NB_MMU_MODES 2 |
173 |
#else |
|
174 |
#define NB_MMU_MODES 3 |
|
175 |
#endif |
|
170 | 176 |
|
171 | 177 |
typedef struct CPUSPARCState { |
172 | 178 |
target_ulong gregs[8]; /* general registers */ |
... | ... | |
323 | 329 |
#define cpu_list sparc_cpu_list |
324 | 330 |
|
325 | 331 |
/* MMU modes definitions */ |
326 |
#define MMU_MODE0_SUFFIX _kernel |
|
327 |
#define MMU_MODE1_SUFFIX _user |
|
328 |
#define MMU_USER_IDX 1 |
|
332 |
#define MMU_MODE0_SUFFIX _user |
|
333 |
#define MMU_MODE1_SUFFIX _kernel |
|
334 |
#ifdef TARGET_SPARC64 |
|
335 |
#define MMU_MODE2_SUFFIX _hypv |
|
336 |
#endif |
|
337 |
#define MMU_USER_IDX 0 |
|
329 | 338 |
static inline int cpu_mmu_index (CPUState *env) |
330 | 339 |
{ |
331 |
return env->psrs == 0 ? 1 : 0; |
|
340 |
#if defined(CONFIG_USER_ONLY) |
|
341 |
return 0; |
|
342 |
#elif !defined(TARGET_SPARC64) |
|
343 |
return env->psrs; |
|
344 |
#else |
|
345 |
if (!env->psrs) |
|
346 |
return 0; |
|
347 |
else if ((env->hpstate & HS_PRIV) == 0) |
|
348 |
return 1; |
|
349 |
else |
|
350 |
return 2; |
|
351 |
#endif |
|
352 |
} |
|
353 |
|
|
354 |
static inline int cpu_fpu_enabled(CPUState *env) |
|
355 |
{ |
|
356 |
#if defined(CONFIG_USER_ONLY) |
|
357 |
return 1; |
|
358 |
#elif !defined(TARGET_SPARC64) |
|
359 |
return env->psref; |
|
360 |
#else |
|
361 |
return ((env->pstate & PS_PEF) != 0) && ((env->fprs & FPRS_FEF) != 0); |
|
362 |
#endif |
|
332 | 363 |
} |
333 | 364 |
|
334 | 365 |
#include "cpu-all.h" |
b/target-sparc/op.c | ||
---|---|---|
1023 | 1023 |
|
1024 | 1024 |
#define MEMSUFFIX _kernel |
1025 | 1025 |
#include "op_mem.h" |
1026 |
|
|
1027 |
#ifdef TARGET_SPARC64 |
|
1028 |
#define MEMSUFFIX _hypv |
|
1029 |
#include "op_mem.h" |
|
1030 |
#endif |
|
1026 | 1031 |
#endif |
1027 | 1032 |
|
1028 | 1033 |
void OPPROTO op_ldfsr(void) |
b/target-sparc/op_helper.c | ||
---|---|---|
789 | 789 |
{ |
790 | 790 |
uint64_t ret = 0; |
791 | 791 |
|
792 |
if (asi < 0x80 && (env->pstate & PS_PRIV) == 0) |
|
792 |
if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) |
|
793 |
|| (asi >= 0x30 && asi < 0x80) && !(env->hpstate & HS_PRIV)) |
|
793 | 794 |
raise_exception(TT_PRIV_ACT); |
794 | 795 |
|
795 | 796 |
switch (asi) { |
... | ... | |
800 | 801 |
case 0x88: // Primary LE |
801 | 802 |
case 0x8a: // Primary no-fault LE |
802 | 803 |
if ((asi & 0x80) && (env->pstate & PS_PRIV)) { |
803 |
switch(size) { |
|
804 |
case 1: |
|
805 |
ret = ldub_kernel(T0); |
|
806 |
break; |
|
807 |
case 2: |
|
808 |
ret = lduw_kernel(T0 & ~1); |
|
809 |
break; |
|
810 |
case 4: |
|
811 |
ret = ldl_kernel(T0 & ~3); |
|
812 |
break; |
|
813 |
default: |
|
814 |
case 8: |
|
815 |
ret = ldq_kernel(T0 & ~7); |
|
816 |
break; |
|
804 |
if (env->hpstate & HS_PRIV) { |
|
805 |
switch(size) { |
|
806 |
case 1: |
|
807 |
ret = ldub_hypv(T0); |
|
808 |
break; |
|
809 |
case 2: |
|
810 |
ret = lduw_hypv(T0 & ~1); |
|
811 |
break; |
|
812 |
case 4: |
|
813 |
ret = ldl_hypv(T0 & ~3); |
|
814 |
break; |
|
815 |
default: |
|
816 |
case 8: |
|
817 |
ret = ldq_hypv(T0 & ~7); |
|
818 |
break; |
|
819 |
} |
|
820 |
} else { |
|
821 |
switch(size) { |
|
822 |
case 1: |
|
823 |
ret = ldub_kernel(T0); |
|
824 |
break; |
|
825 |
case 2: |
|
826 |
ret = lduw_kernel(T0 & ~1); |
|
827 |
break; |
|
828 |
case 4: |
|
829 |
ret = ldl_kernel(T0 & ~3); |
|
830 |
break; |
|
831 |
default: |
|
832 |
case 8: |
|
833 |
ret = ldq_kernel(T0 & ~7); |
|
834 |
break; |
|
835 |
} |
|
817 | 836 |
} |
818 | 837 |
} else { |
819 | 838 |
switch(size) { |
... | ... | |
987 | 1006 |
|
988 | 1007 |
void helper_st_asi(int asi, int size) |
989 | 1008 |
{ |
990 |
if (asi < 0x80 && (env->pstate & PS_PRIV) == 0) |
|
1009 |
if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) |
|
1010 |
|| (asi >= 0x30 && asi < 0x80) && !(env->hpstate & HS_PRIV)) |
|
991 | 1011 |
raise_exception(TT_PRIV_ACT); |
992 | 1012 |
|
993 | 1013 |
/* Convert to little endian */ |
... | ... | |
1022 | 1042 |
case 0x80: // Primary |
1023 | 1043 |
case 0x88: // Primary LE |
1024 | 1044 |
if ((asi & 0x80) && (env->pstate & PS_PRIV)) { |
1025 |
switch(size) { |
|
1026 |
case 1: |
|
1027 |
stb_kernel(T0, T1); |
|
1028 |
break; |
|
1029 |
case 2: |
|
1030 |
stw_kernel(T0 & ~1, T1); |
|
1031 |
break; |
|
1032 |
case 4: |
|
1033 |
stl_kernel(T0 & ~3, T1); |
|
1034 |
break; |
|
1035 |
case 8: |
|
1036 |
default: |
|
1037 |
stq_kernel(T0 & ~7, T1); |
|
1038 |
break; |
|
1045 |
if (env->hpstate & HS_PRIV) { |
|
1046 |
switch(size) { |
|
1047 |
case 1: |
|
1048 |
stb_hypv(T0, T1); |
|
1049 |
break; |
|
1050 |
case 2: |
|
1051 |
stw_hypv(T0 & ~1, T1); |
|
1052 |
break; |
|
1053 |
case 4: |
|
1054 |
stl_hypv(T0 & ~3, T1); |
|
1055 |
break; |
|
1056 |
case 8: |
|
1057 |
default: |
|
1058 |
stq_hypv(T0 & ~7, T1); |
|
1059 |
break; |
|
1060 |
} |
|
1061 |
} else { |
|
1062 |
switch(size) { |
|
1063 |
case 1: |
|
1064 |
stb_kernel(T0, T1); |
|
1065 |
break; |
|
1066 |
case 2: |
|
1067 |
stw_kernel(T0 & ~1, T1); |
|
1068 |
break; |
|
1069 |
case 4: |
|
1070 |
stl_kernel(T0 & ~3, T1); |
|
1071 |
break; |
|
1072 |
case 8: |
|
1073 |
default: |
|
1074 |
stq_kernel(T0 & ~7, T1); |
|
1075 |
break; |
|
1076 |
} |
|
1039 | 1077 |
} |
1040 | 1078 |
} else { |
1041 | 1079 |
switch(size) { |
b/target-sparc/translate.c | ||
---|---|---|
361 | 361 |
#endif |
362 | 362 |
#define gen_op_ldst(name) gen_op_##name##_raw() |
363 | 363 |
#else |
364 |
#define supervisor(dc) (dc->mem_idx == 1)
|
|
364 |
#define supervisor(dc) (dc->mem_idx >= 1)
|
|
365 | 365 |
#ifdef TARGET_SPARC64 |
366 | 366 |
#define hypervisor(dc) (dc->mem_idx == 2) |
367 |
#endif |
|
368 |
#define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])() |
|
367 |
#define OP_LD_TABLE(width) \ |
|
368 |
static GenOpFunc * const gen_op_##width[] = { \ |
|
369 |
&gen_op_##width##_user, \ |
|
370 |
&gen_op_##width##_kernel, \ |
|
371 |
&gen_op_##width##_hypv, \ |
|
372 |
}; |
|
373 |
#else |
|
369 | 374 |
#define OP_LD_TABLE(width) \ |
370 | 375 |
static GenOpFunc * const gen_op_##width[] = { \ |
371 | 376 |
&gen_op_##width##_user, \ |
372 | 377 |
&gen_op_##width##_kernel, \ |
373 | 378 |
}; |
374 | 379 |
#endif |
380 |
#define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])() |
|
381 |
#endif |
|
375 | 382 |
|
376 | 383 |
#ifndef CONFIG_USER_ONLY |
377 | 384 |
OP_LD_TABLE(ld); |
... | ... | |
3378 | 3385 |
dc->pc = pc_start; |
3379 | 3386 |
last_pc = dc->pc; |
3380 | 3387 |
dc->npc = (target_ulong) tb->cs_base; |
3381 |
#if defined(CONFIG_USER_ONLY) |
|
3382 |
dc->mem_idx = 0; |
|
3383 |
dc->fpu_enabled = 1; |
|
3384 |
#else |
|
3385 |
dc->mem_idx = ((env->psrs) != 0); |
|
3386 |
#ifdef TARGET_SPARC64 |
|
3387 |
dc->fpu_enabled = (((env->pstate & PS_PEF) != 0) && ((env->fprs & FPRS_FEF) != 0)); |
|
3388 |
#else |
|
3389 |
dc->fpu_enabled = ((env->psref) != 0); |
|
3390 |
#endif |
|
3391 |
#endif |
|
3388 |
dc->mem_idx = cpu_mmu_index(env); |
|
3389 |
dc->fpu_enabled = cpu_fpu_enabled(env); |
|
3392 | 3390 |
gen_opc_ptr = gen_opc_buf; |
3393 | 3391 |
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
3394 | 3392 |
gen_opparam_ptr = gen_opparam_buf; |
... | ... | |
3522 | 3520 |
env->psrps = 1; |
3523 | 3521 |
#ifdef TARGET_SPARC64 |
3524 | 3522 |
env->pstate = PS_PRIV; |
3523 |
env->hpstate = HS_PRIV; |
|
3525 | 3524 |
env->pc = 0x1fff0000000ULL; |
3526 | 3525 |
#else |
3527 | 3526 |
env->pc = 0; |
Also available in: Unified diff