From: Paul Brook <paul@codesourcery.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [patch] Arm conditional execution
Date: Sun, 24 Apr 2005 01:18:10 +0100 [thread overview]
Message-ID: <200504240118.11417.paul@codesourcery.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 249 bytes --]
The attached patch changes arm conditional execution so a conditional
non-branch instruction no longer terminates the translation block. The patch
has no measurable effect on performance. However it does make single-stepping
work properly.
Paul
[-- Attachment #2: patch.qemu_condexec --]
[-- Type: text/x-diff, Size: 7638 bytes --]
? target-arm/p
Index: target-arm/op.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-arm/op.c,v
retrieving revision 1.11
diff -u -p -r1.11 op.c
--- target-arm/op.c 17 Apr 2005 19:16:13 -0000 1.11
+++ target-arm/op.c 24 Apr 2005 00:08:53 -0000
@@ -251,104 +251,109 @@ void OPPROTO op_logic_T1_cc(void)
void OPPROTO op_test_eq(void)
{
if (env->NZF == 0)
- JUMP_TB(op_test_eq, PARAM1, 0, PARAM2);
+ GOTO_LABEL_PARAM(1);;
FORCE_RET();
}
void OPPROTO op_test_ne(void)
{
if (env->NZF != 0)
- JUMP_TB(op_test_ne, PARAM1, 0, PARAM2);
+ GOTO_LABEL_PARAM(1);;
FORCE_RET();
}
void OPPROTO op_test_cs(void)
{
if (env->CF != 0)
- JUMP_TB(op_test_cs, PARAM1, 0, PARAM2);
+ GOTO_LABEL_PARAM(1);
FORCE_RET();
}
void OPPROTO op_test_cc(void)
{
if (env->CF == 0)
- JUMP_TB(op_test_cc, PARAM1, 0, PARAM2);
+ GOTO_LABEL_PARAM(1);
FORCE_RET();
}
void OPPROTO op_test_mi(void)
{
if ((env->NZF & 0x80000000) != 0)
- JUMP_TB(op_test_mi, PARAM1, 0, PARAM2);
+ GOTO_LABEL_PARAM(1);
FORCE_RET();
}
void OPPROTO op_test_pl(void)
{
if ((env->NZF & 0x80000000) == 0)
- JUMP_TB(op_test_pl, PARAM1, 0, PARAM2);
+ GOTO_LABEL_PARAM(1);
FORCE_RET();
}
void OPPROTO op_test_vs(void)
{
if ((env->VF & 0x80000000) != 0)
- JUMP_TB(op_test_vs, PARAM1, 0, PARAM2);
+ GOTO_LABEL_PARAM(1);
FORCE_RET();
}
void OPPROTO op_test_vc(void)
{
if ((env->VF & 0x80000000) == 0)
- JUMP_TB(op_test_vc, PARAM1, 0, PARAM2);
+ GOTO_LABEL_PARAM(1);
FORCE_RET();
}
void OPPROTO op_test_hi(void)
{
if (env->CF != 0 && env->NZF != 0)
- JUMP_TB(op_test_hi, PARAM1, 0, PARAM2);
+ GOTO_LABEL_PARAM(1);
FORCE_RET();
}
void OPPROTO op_test_ls(void)
{
if (env->CF == 0 || env->NZF == 0)
- JUMP_TB(op_test_ls, PARAM1, 0, PARAM2);
+ GOTO_LABEL_PARAM(1);
FORCE_RET();
}
void OPPROTO op_test_ge(void)
{
if (((env->VF ^ env->NZF) & 0x80000000) == 0)
- JUMP_TB(op_test_ge, PARAM1, 0, PARAM2);
+ GOTO_LABEL_PARAM(1);
FORCE_RET();
}
void OPPROTO op_test_lt(void)
{
if (((env->VF ^ env->NZF) & 0x80000000) != 0)
- JUMP_TB(op_test_lt, PARAM1, 0, PARAM2);
+ GOTO_LABEL_PARAM(1);
FORCE_RET();
}
void OPPROTO op_test_gt(void)
{
if (env->NZF != 0 && ((env->VF ^ env->NZF) & 0x80000000) == 0)
- JUMP_TB(op_test_gt, PARAM1, 0, PARAM2);
+ GOTO_LABEL_PARAM(1);
FORCE_RET();
}
void OPPROTO op_test_le(void)
{
if (env->NZF == 0 || ((env->VF ^ env->NZF) & 0x80000000) != 0)
- JUMP_TB(op_test_le, PARAM1, 0, PARAM2);
+ GOTO_LABEL_PARAM(1);
FORCE_RET();
}
-void OPPROTO op_jmp(void)
+void OPPROTO op_jmp0(void)
{
- JUMP_TB(op_jmp, PARAM1, 1, PARAM2);
+ JUMP_TB(op_jmp0, PARAM1, 0, PARAM2);
+}
+
+void OPPROTO op_jmp1(void)
+{
+ JUMP_TB(op_jmp1, PARAM1, 1, PARAM2);
}
void OPPROTO op_exit_tb(void)
Index: target-arm/translate.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-arm/translate.c,v
retrieving revision 1.22
diff -u -p -r1.22 translate.c
--- target-arm/translate.c 23 Apr 2005 18:46:03 -0000 1.22
+++ target-arm/translate.c 24 Apr 2005 00:08:53 -0000
@@ -32,6 +32,10 @@
typedef struct DisasContext {
target_ulong pc;
int is_jmp;
+ /* Nonzero if this instruction has been conditionally skipped. */
+ int condjmp;
+ /* The label that will be jumped to when the instruction is skipped. */
+ int condlabel;
struct TranslationBlock *tb;
int singlestep_enabled;
} DisasContext;
@@ -53,7 +57,7 @@ enum {
#include "gen-op.h"
-static GenOpFunc2 *gen_test_cc[14] = {
+static GenOpFunc1 *gen_test_cc[14] = {
gen_op_test_eq,
gen_op_test_ne,
gen_op_test_cs,
@@ -896,7 +900,7 @@ static inline void gen_jmp (DisasContext
gen_op_movl_T0_im(dest);
gen_bx(s);
} else {
- gen_op_jmp((long)s->tb, dest);
+ gen_op_jmp0((long)s->tb, dest);
s->is_jmp = DISAS_TB_JUMP;
}
}
@@ -939,8 +943,11 @@ static void disas_arm_insn(CPUState * en
if (cond != 0xe) {
/* if not always execute, we generate a conditional jump to
next instruction */
- gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
- s->is_jmp = DISAS_JUMP_NEXT;
+ s->condlabel = gen_new_label();
+ gen_test_cc[cond ^ 1](s->condlabel);
+ s->condjmp = 1;
+ //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
+ //s->is_jmp = DISAS_JUMP_NEXT;
}
if ((insn & 0x0f900000) == 0x03000000) {
if ((insn & 0x0ff0f000) != 0x0360f000)
@@ -1961,8 +1968,11 @@ static void disas_thumb_insn(DisasContex
break;
}
/* generate a conditional jump to next instruction */
- gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
- s->is_jmp = DISAS_JUMP_NEXT;
+ s->condlabel = gen_new_label();
+ gen_test_cc[cond ^ 1](s->condlabel);
+ s->condjmp = 1;
+ //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
+ //s->is_jmp = DISAS_JUMP_NEXT;
gen_movl_T1_reg(s, 15);
/* jump to the offset */
@@ -2034,6 +2044,8 @@ static inline int gen_intermediate_code_
dc->is_jmp = DISAS_NEXT;
dc->pc = pc_start;
dc->singlestep_enabled = env->singlestep_enabled;
+ dc->condjmp = 0;
+ nb_gen_labels = 0;
lj = -1;
do {
if (env->nb_breakpoints > 0) {
@@ -2057,25 +2069,41 @@ static inline int gen_intermediate_code_
gen_opc_pc[lj] = dc->pc;
gen_opc_instr_start[lj] = 1;
}
+
if (env->thumb)
disas_thumb_insn(dc);
else
disas_arm_insn(env, dc);
+
+ if (dc->condjmp && !dc->is_jmp) {
+ gen_set_label(dc->condlabel);
+ dc->condjmp = 0;
+ }
+ /* Translation stops when a conditional branch is enoutered.
+ * Otherwise the subsequent code could get translated several times.
+ */
} while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
!env->singlestep_enabled &&
(dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
+ /* It this stage dc->condjmp will only be set when the skipped
+ * instruction was a conditional branch, and teh PC has already been
+ * written. */
if (__builtin_expect(env->singlestep_enabled, 0)) {
/* Make sure the pc is updated, and raise a debug exception. */
- if (dc->is_jmp == DISAS_NEXT || dc->is_jmp == DISAS_JUMP_NEXT) {
+ if (dc->condjmp) {
+ gen_op_debug();
+ gen_set_label(dc->condlabel);
+ }
+ if (dc->condjmp || !dc->is_jmp) {
gen_op_movl_T0_im((long)dc->pc);
gen_op_movl_reg_TN[0][15]();
+ dc->condjmp = 0;
}
gen_op_debug();
} else {
switch(dc->is_jmp) {
- case DISAS_JUMP_NEXT:
case DISAS_NEXT:
- gen_op_jmp((long)dc->tb, (long)dc->pc);
+ gen_op_jmp1((long)dc->tb, (long)dc->pc);
break;
default:
case DISAS_JUMP:
@@ -2088,6 +2116,11 @@ static inline int gen_intermediate_code_
/* nothing more to generate */
break;
}
+ if (dc->condjmp) {
+ gen_set_label(dc->condlabel);
+ gen_op_jmp1((long)dc->tb, (long)dc->pc);
+ dc->condjmp = 0;
+ }
}
*gen_opc_ptr = INDEX_op_end;
reply other threads:[~2005-04-24 0:28 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200504240118.11417.paul@codesourcery.com \
--to=paul@codesourcery.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.