Revision be147d08 target-ppc/translate.c
b/target-ppc/translate.c | ||
---|---|---|
480 | 480 |
PPC_FLOAT_EXT = 0x0000080000000000ULL, |
481 | 481 |
/* New wait instruction (PowerPC 2.0x) */ |
482 | 482 |
PPC_WAIT = 0x0000100000000000ULL, |
483 |
/* New 64 bits extensions (PowerPC 2.0x) */ |
|
484 |
PPC_64BX = 0x0000200000000000ULL, |
|
483 | 485 |
}; |
484 | 486 |
|
485 | 487 |
/*****************************************************************************/ |
... | ... | |
1141 | 1143 |
/* Set process priority to normal */ |
1142 | 1144 |
gen_op_store_pri(4); |
1143 | 1145 |
break; |
1146 |
#if !defined(CONFIG_USER_ONLY) |
|
1147 |
case 31: |
|
1148 |
if (ctx->supervisor > 0) { |
|
1149 |
/* Set process priority to very low */ |
|
1150 |
gen_op_store_pri(1); |
|
1151 |
} |
|
1152 |
break; |
|
1153 |
case 5: |
|
1154 |
if (ctx->supervisor > 0) { |
|
1155 |
/* Set process priority to medium-hight */ |
|
1156 |
gen_op_store_pri(5); |
|
1157 |
} |
|
1158 |
break; |
|
1159 |
case 3: |
|
1160 |
if (ctx->supervisor > 0) { |
|
1161 |
/* Set process priority to high */ |
|
1162 |
gen_op_store_pri(6); |
|
1163 |
} |
|
1164 |
break; |
|
1165 |
#if defined(TARGET_PPC64H) |
|
1166 |
case 7: |
|
1167 |
if (ctx->supervisor > 1) { |
|
1168 |
/* Set process priority to very high */ |
|
1169 |
gen_op_store_pri(7); |
|
1170 |
} |
|
1171 |
break; |
|
1172 |
#endif |
|
1173 |
#endif |
|
1144 | 1174 |
default: |
1145 | 1175 |
/* nop */ |
1146 | 1176 |
break; |
... | ... | |
1902 | 1932 |
|
1903 | 1933 |
/*** Addressing modes ***/ |
1904 | 1934 |
/* Register indirect with immediate index : EA = (rA|0) + SIMM */ |
1905 |
static inline void gen_addr_imm_index (DisasContext *ctx, int maskl)
|
|
1935 |
static inline void gen_addr_imm_index (DisasContext *ctx, target_long maskl)
|
|
1906 | 1936 |
{ |
1907 | 1937 |
target_long simm = SIMM(ctx->opcode); |
1908 | 1938 |
|
1909 |
if (maskl) |
|
1910 |
simm &= ~0x03; |
|
1939 |
simm &= ~maskl; |
|
1911 | 1940 |
if (rA(ctx->opcode) == 0) { |
1912 | 1941 |
gen_set_T0(simm); |
1913 | 1942 |
} else { |
... | ... | |
2051 | 2080 |
return; \ |
2052 | 2081 |
} \ |
2053 | 2082 |
if (type == PPC_64B) \ |
2054 |
gen_addr_imm_index(ctx, 1); \
|
|
2083 |
gen_addr_imm_index(ctx, 0x03); \
|
|
2055 | 2084 |
else \ |
2056 | 2085 |
gen_addr_imm_index(ctx, 0); \ |
2057 | 2086 |
op_ldst(l##width); \ |
... | ... | |
2116 | 2145 |
return; |
2117 | 2146 |
} |
2118 | 2147 |
} |
2119 |
gen_addr_imm_index(ctx, 1);
|
|
2148 |
gen_addr_imm_index(ctx, 0x03);
|
|
2120 | 2149 |
if (ctx->opcode & 0x02) { |
2121 | 2150 |
/* lwa (lwau is undefined) */ |
2122 | 2151 |
op_ldst(lwa); |
... | ... | |
2128 | 2157 |
if (Rc(ctx->opcode)) |
2129 | 2158 |
gen_op_store_T0_gpr(rA(ctx->opcode)); |
2130 | 2159 |
} |
2160 |
/* lq */ |
|
2161 |
GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX) |
|
2162 |
{ |
|
2163 |
#if defined(CONFIG_USER_ONLY) |
|
2164 |
GEN_EXCP_PRIVOPC(ctx); |
|
2165 |
#else |
|
2166 |
int ra, rd; |
|
2167 |
|
|
2168 |
/* Restore CPU state */ |
|
2169 |
if (unlikely(ctx->supervisor == 0)) { |
|
2170 |
GEN_EXCP_PRIVOPC(ctx); |
|
2171 |
return; |
|
2172 |
} |
|
2173 |
ra = rA(ctx->opcode); |
|
2174 |
rd = rD(ctx->opcode); |
|
2175 |
if (unlikely((rd & 1) || rd == ra)) { |
|
2176 |
GEN_EXCP_INVAL(ctx); |
|
2177 |
return; |
|
2178 |
} |
|
2179 |
if (unlikely(ctx->mem_idx & 1)) { |
|
2180 |
/* Little-endian mode is not handled */ |
|
2181 |
GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE); |
|
2182 |
return; |
|
2183 |
} |
|
2184 |
gen_addr_imm_index(ctx, 0x0F); |
|
2185 |
op_ldst(ld); |
|
2186 |
gen_op_store_T1_gpr(rd); |
|
2187 |
gen_op_addi(8); |
|
2188 |
op_ldst(ld); |
|
2189 |
gen_op_store_T1_gpr(rd + 1); |
|
2190 |
#endif |
|
2191 |
} |
|
2131 | 2192 |
#endif |
2132 | 2193 |
|
2133 | 2194 |
/*** Integer store ***/ |
... | ... | |
2147 | 2208 |
return; \ |
2148 | 2209 |
} \ |
2149 | 2210 |
if (type == PPC_64B) \ |
2150 |
gen_addr_imm_index(ctx, 1); \
|
|
2211 |
gen_addr_imm_index(ctx, 0x03); \
|
|
2151 | 2212 |
else \ |
2152 | 2213 |
gen_addr_imm_index(ctx, 0); \ |
2153 | 2214 |
gen_op_load_gpr_T1(rS(ctx->opcode)); \ |
... | ... | |
2193 | 2254 |
OP_ST_TABLE(d); |
2194 | 2255 |
GEN_STUX(d, 0x15, 0x05, PPC_64B); |
2195 | 2256 |
GEN_STX(d, 0x15, 0x04, PPC_64B); |
2196 |
GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000002, PPC_64B)
|
|
2257 |
GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B)
|
|
2197 | 2258 |
{ |
2198 |
if (Rc(ctx->opcode)) { |
|
2199 |
if (unlikely(rA(ctx->opcode) == 0)) { |
|
2259 |
int rs; |
|
2260 |
|
|
2261 |
rs = rS(ctx->opcode); |
|
2262 |
if ((ctx->opcode & 0x3) == 0x2) { |
|
2263 |
#if defined(CONFIG_USER_ONLY) |
|
2264 |
GEN_EXCP_PRIVOPC(ctx); |
|
2265 |
#else |
|
2266 |
/* stq */ |
|
2267 |
if (unlikely(ctx->supervisor == 0)) { |
|
2268 |
GEN_EXCP_PRIVOPC(ctx); |
|
2269 |
return; |
|
2270 |
} |
|
2271 |
if (unlikely(rs & 1)) { |
|
2200 | 2272 |
GEN_EXCP_INVAL(ctx); |
2201 | 2273 |
return; |
2202 | 2274 |
} |
2275 |
if (unlikely(ctx->mem_idx & 1)) { |
|
2276 |
/* Little-endian mode is not handled */ |
|
2277 |
GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE); |
|
2278 |
return; |
|
2279 |
} |
|
2280 |
gen_addr_imm_index(ctx, 0x03); |
|
2281 |
gen_op_load_gpr_T1(rs); |
|
2282 |
op_ldst(std); |
|
2283 |
gen_op_addi(8); |
|
2284 |
gen_op_load_gpr_T1(rs + 1); |
|
2285 |
op_ldst(std); |
|
2286 |
#endif |
|
2287 |
} else { |
|
2288 |
/* std / stdu */ |
|
2289 |
if (Rc(ctx->opcode)) { |
|
2290 |
if (unlikely(rA(ctx->opcode) == 0)) { |
|
2291 |
GEN_EXCP_INVAL(ctx); |
|
2292 |
return; |
|
2293 |
} |
|
2294 |
} |
|
2295 |
gen_addr_imm_index(ctx, 0x03); |
|
2296 |
gen_op_load_gpr_T1(rs); |
|
2297 |
op_ldst(std); |
|
2298 |
if (Rc(ctx->opcode)) |
|
2299 |
gen_op_store_T0_gpr(rA(ctx->opcode)); |
|
2203 | 2300 |
} |
2204 |
gen_addr_imm_index(ctx, 1); |
|
2205 |
gen_op_load_gpr_T1(rS(ctx->opcode)); |
|
2206 |
op_ldst(std); |
|
2207 |
if (Rc(ctx->opcode)) |
|
2208 |
gen_op_store_T0_gpr(rA(ctx->opcode)); |
|
2209 | 2301 |
} |
2210 | 2302 |
#endif |
2211 | 2303 |
/*** Integer load and store with byte reverse ***/ |
... | ... | |
2620 | 2712 |
GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT) |
2621 | 2713 |
{ |
2622 | 2714 |
/* Stop translation, as the CPU is supposed to sleep from now */ |
2623 |
/* XXX: TODO: handle this idle CPU case */
|
|
2624 |
GEN_STOP(ctx);
|
|
2715 |
gen_op_wait();
|
|
2716 |
GEN_EXCP(ctx, EXCP_HLT, 1);
|
|
2625 | 2717 |
} |
2626 | 2718 |
|
2627 | 2719 |
/*** Floating-point load ***/ |
... | ... | |
3077 | 3169 |
} |
3078 | 3170 |
#endif |
3079 | 3171 |
|
3172 |
#if defined(TARGET_PPC64H) |
|
3173 |
GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64B) |
|
3174 |
{ |
|
3175 |
#if defined(CONFIG_USER_ONLY) |
|
3176 |
GEN_EXCP_PRIVOPC(ctx); |
|
3177 |
#else |
|
3178 |
/* Restore CPU state */ |
|
3179 |
if (unlikely(ctx->supervisor <= 1)) { |
|
3180 |
GEN_EXCP_PRIVOPC(ctx); |
|
3181 |
return; |
|
3182 |
} |
|
3183 |
gen_op_hrfid(); |
|
3184 |
GEN_SYNC(ctx); |
|
3185 |
#endif |
|
3186 |
} |
|
3187 |
#endif |
|
3188 |
|
|
3080 | 3189 |
/* sc */ |
3081 | 3190 |
GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW) |
3082 | 3191 |
{ |
... | ... | |
3193 | 3302 |
uint32_t sprn = SPR(ctx->opcode); |
3194 | 3303 |
|
3195 | 3304 |
#if !defined(CONFIG_USER_ONLY) |
3305 |
#if defined(TARGET_PPC64H) |
|
3306 |
if (ctx->supervisor == 2) |
|
3307 |
read_cb = ctx->spr_cb[sprn].hea_read; |
|
3308 |
else |
|
3309 |
#endif |
|
3196 | 3310 |
if (ctx->supervisor) |
3197 | 3311 |
read_cb = ctx->spr_cb[sprn].oea_read; |
3198 | 3312 |
else |
... | ... | |
3253 | 3367 |
|
3254 | 3368 |
/* mtmsr */ |
3255 | 3369 |
#if defined(TARGET_PPC64) |
3256 |
GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001FF801, PPC_64B)
|
|
3370 |
GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
|
|
3257 | 3371 |
{ |
3258 | 3372 |
#if defined(CONFIG_USER_ONLY) |
3259 | 3373 |
GEN_EXCP_PRIVREG(ctx); |
... | ... | |
3262 | 3376 |
GEN_EXCP_PRIVREG(ctx); |
3263 | 3377 |
return; |
3264 | 3378 |
} |
3265 |
gen_update_nip(ctx, ctx->nip); |
|
3266 | 3379 |
gen_op_load_gpr_T0(rS(ctx->opcode)); |
3267 |
gen_op_store_msr(); |
|
3268 |
/* Must stop the translation as machine state (may have) changed */ |
|
3269 |
/* Note that mtmsr is not always defined as context-synchronizing */ |
|
3270 |
GEN_STOP(ctx); |
|
3380 |
if (ctx->opcode & 0x00010000) { |
|
3381 |
/* Special form that does not need any synchronisation */ |
|
3382 |
gen_op_update_riee(); |
|
3383 |
} else { |
|
3384 |
gen_update_nip(ctx, ctx->nip); |
|
3385 |
gen_op_store_msr(); |
|
3386 |
/* Must stop the translation as machine state (may have) changed */ |
|
3387 |
/* Note that mtmsr is not always defined as context-synchronizing */ |
|
3388 |
GEN_STOP(ctx); |
|
3389 |
} |
|
3271 | 3390 |
#endif |
3272 | 3391 |
} |
3273 | 3392 |
#endif |
... | ... | |
3281 | 3400 |
GEN_EXCP_PRIVREG(ctx); |
3282 | 3401 |
return; |
3283 | 3402 |
} |
3284 |
gen_update_nip(ctx, ctx->nip); |
|
3285 | 3403 |
gen_op_load_gpr_T0(rS(ctx->opcode)); |
3404 |
if (ctx->opcode & 0x00010000) { |
|
3405 |
/* Special form that does not need any synchronisation */ |
|
3406 |
gen_op_update_riee(); |
|
3407 |
} else { |
|
3408 |
gen_update_nip(ctx, ctx->nip); |
|
3286 | 3409 |
#if defined(TARGET_PPC64) |
3287 |
if (!ctx->sf_mode) |
|
3288 |
gen_op_store_msr_32(); |
|
3289 |
else |
|
3410 |
if (!ctx->sf_mode)
|
|
3411 |
gen_op_store_msr_32();
|
|
3412 |
else
|
|
3290 | 3413 |
#endif |
3291 |
gen_op_store_msr(); |
|
3292 |
/* Must stop the translation as machine state (may have) changed */ |
|
3293 |
/* Note that mtmsrd is not always defined as context-synchronizing */ |
|
3294 |
GEN_STOP(ctx); |
|
3414 |
gen_op_store_msr(); |
|
3415 |
/* Must stop the translation as machine state (may have) changed */ |
|
3416 |
/* Note that mtmsrd is not always defined as context-synchronizing */ |
|
3417 |
GEN_STOP(ctx); |
|
3418 |
} |
|
3295 | 3419 |
#endif |
3296 | 3420 |
} |
3297 | 3421 |
|
... | ... | |
3302 | 3426 |
uint32_t sprn = SPR(ctx->opcode); |
3303 | 3427 |
|
3304 | 3428 |
#if !defined(CONFIG_USER_ONLY) |
3429 |
#if defined(TARGET_PPC64H) |
|
3430 |
if (ctx->supervisor == 2) |
|
3431 |
write_cb = ctx->spr_cb[sprn].hea_write; |
|
3432 |
else |
|
3433 |
#endif |
|
3305 | 3434 |
if (ctx->supervisor) |
3306 | 3435 |
write_cb = ctx->spr_cb[sprn].oea_write; |
3307 | 3436 |
else |
... | ... | |
6011 | 6140 |
ctx.mem_idx |= msr_sf << 1; |
6012 | 6141 |
#endif |
6013 | 6142 |
#else |
6014 |
ctx.supervisor = 1 - msr_pr; |
|
6143 |
#if defined(TARGET_PPC64H) |
|
6144 |
if (msr_pr == 0 && msr_hv == 1) |
|
6145 |
ctx.supervisor = 2; |
|
6146 |
else |
|
6147 |
#endif |
|
6148 |
ctx.supervisor = 1 - msr_pr; |
|
6015 | 6149 |
ctx.mem_idx = ((1 - msr_pr) << 1) | msr_le; |
6016 | 6150 |
#if defined(TARGET_PPC64) |
6017 | 6151 |
ctx.mem_idx |= msr_sf << 2; |
Also available in: Unified diff