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;
|