target/mips: Add a placeholder for R5900 SQ, handle user mode RDHWR
Add placeholder for SQ instruction, handle RDHWR. Reviewed-by: Aleksandar Markovic <amarkovic@wavecomp.com> Signed-off-by: Fredrik Noring <noring@nocrew.org> Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
This commit is contained in:
parent
dd581bf97d
commit
bb41e74b66
@ -24420,6 +24420,53 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gen_tx79_sq(DisasContext *ctx, int base, int rt, int offset)
|
||||||
|
{
|
||||||
|
generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_SQ */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The TX79-specific instruction Store Quadword
|
||||||
|
*
|
||||||
|
* +--------+-------+-------+------------------------+
|
||||||
|
* | 011111 | base | rt | offset | SQ
|
||||||
|
* +--------+-------+-------+------------------------+
|
||||||
|
* 6 5 5 16
|
||||||
|
*
|
||||||
|
* has the same opcode as the Read Hardware Register instruction
|
||||||
|
*
|
||||||
|
* +--------+-------+-------+-------+-------+--------+
|
||||||
|
* | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
|
||||||
|
* +--------+-------+-------+-------+-------+--------+
|
||||||
|
* 6 5 5 5 5 6
|
||||||
|
*
|
||||||
|
* that is required, trapped and emulated by the Linux kernel. However, all
|
||||||
|
* RDHWR encodings yield address error exceptions on the TX79 since the SQ
|
||||||
|
* offset is odd. Therefore all valid SQ instructions can execute normally.
|
||||||
|
* In user mode, QEMU must verify the upper and lower 11 bits to distinguish
|
||||||
|
* between SQ and RDHWR, as the Linux kernel does.
|
||||||
|
*/
|
||||||
|
static void decode_tx79_sq(CPUMIPSState *env, DisasContext *ctx)
|
||||||
|
{
|
||||||
|
int base = extract32(ctx->opcode, 21, 5);
|
||||||
|
int rt = extract32(ctx->opcode, 16, 5);
|
||||||
|
int offset = extract32(ctx->opcode, 0, 16);
|
||||||
|
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
|
||||||
|
uint32_t op2 = extract32(ctx->opcode, 6, 5);
|
||||||
|
|
||||||
|
if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
|
||||||
|
int rd = extract32(ctx->opcode, 11, 5);
|
||||||
|
|
||||||
|
gen_rdhwr(ctx, rt, rd, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gen_tx79_sq(ctx, base, rt, offset);
|
||||||
|
}
|
||||||
|
|
||||||
static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
|
static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
|
||||||
{
|
{
|
||||||
int rs, rt, rd, sa;
|
int rs, rt, rd, sa;
|
||||||
@ -25720,7 +25767,11 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
|
|||||||
decode_opc_special2_legacy(env, ctx);
|
decode_opc_special2_legacy(env, ctx);
|
||||||
break;
|
break;
|
||||||
case OPC_SPECIAL3:
|
case OPC_SPECIAL3:
|
||||||
decode_opc_special3(env, ctx);
|
if (ctx->insn_flags & INSN_R5900) {
|
||||||
|
decode_tx79_sq(env, ctx); /* TX79_SQ */
|
||||||
|
} else {
|
||||||
|
decode_opc_special3(env, ctx);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case OPC_REGIMM:
|
case OPC_REGIMM:
|
||||||
op1 = MASK_REGIMM(ctx->opcode);
|
op1 = MASK_REGIMM(ctx->opcode);
|
||||||
|
Loading…
Reference in New Issue
Block a user