aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFredrik Noring <noring@nocrew.org>2018-10-21 17:35:41 +0200
committerAleksandar Markovic <amarkovic@wavecomp.com>2018-10-24 15:20:30 +0200
commitbb41e74b66a8879ba5c23db145039faa27df5766 (patch)
treef1ee60ee7f26ad69c609dc11974a89dd62705d35
parentdd581bf97d58d999fc58634c12251c1ea632a75d (diff)
downloadqemu-bb41e74b66a8879ba5c23db145039faa27df5766.zip
qemu-bb41e74b66a8879ba5c23db145039faa27df5766.tar.gz
qemu-bb41e74b66a8879ba5c23db145039faa27df5766.tar.bz2
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>
-rw-r--r--target/mips/translate.c53
1 files changed, 52 insertions, 1 deletions
diff --git a/target/mips/translate.c b/target/mips/translate.c
index 3c6a2c9..19a8aba 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -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)
{
int rs, rt, rd, sa;
@@ -25720,7 +25767,11 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
decode_opc_special2_legacy(env, ctx);
break;
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;
case OPC_REGIMM:
op1 = MASK_REGIMM(ctx->opcode);