From: Paul Brook <paul@codesourcery.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [patch] Thumb bugfixes
Date: Wed, 27 Apr 2005 00:20:02 +0100 [thread overview]
Message-ID: <200504270020.02222.paul@codesourcery.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 72 bytes --]
The attached patch fixes several bugs in the arm thumb emulation.
Paul
[-- Attachment #2: patch.qemu_thumb_bugs --]
[-- Type: text/x-diff, Size: 8946 bytes --]
Index: target-arm/op.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-arm/op.c,v
retrieving revision 1.12
diff -u -p -r1.12 op.c
--- target-arm/op.c 26 Apr 2005 20:36:11 -0000 1.12
+++ target-arm/op.c 26 Apr 2005 23:18:40 -0000
@@ -824,12 +824,13 @@ void OPPROTO op_shrl_T0_im_thumb(void)
shift = PARAM1;
if (shift == 0) {
- env->CF = 0;
+ env->CF = ((uint32_t)shift) >> 31;
T0 = 0;
} else {
env->CF = (T0 >> (shift - 1)) & 1;
T0 = T0 >> shift;
}
+ env->NZF = T0;
FORCE_RET();
}
Index: target-arm/translate.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-arm/translate.c,v
retrieving revision 1.23
diff -u -p -r1.23 translate.c
--- target-arm/translate.c 26 Apr 2005 20:36:11 -0000 1.23
+++ target-arm/translate.c 26 Apr 2005 23:18:40 -0000
@@ -38,6 +38,7 @@ typedef struct DisasContext {
int condlabel;
struct TranslationBlock *tb;
int singlestep_enabled;
+ int thumb;
} DisasContext;
#define DISAS_JUMP_NEXT 4
@@ -268,8 +269,11 @@ static inline void gen_movl_TN_reg(Disas
int val;
if (reg == 15) {
- /* normaly, since we updated PC, we need only to add 4 */
- val = (long)s->pc + 4;
+ /* normaly, since we updated PC, we need only to add one insn */
+ if (s->thumb)
+ val = (long)s->pc + 2;
+ else
+ val = (long)s->pc + 4;
gen_op_movl_TN_im[t](val);
} else {
gen_op_movl_TN_reg[t][reg]();
@@ -897,6 +901,8 @@ static inline void gen_jmp (DisasContext
{
if (__builtin_expect(s->singlestep_enabled, 0)) {
/* An indirect jump so that we still trigger the debug exception. */
+ if (s->thumb)
+ dest |= 1;
gen_op_movl_T0_im(dest);
gen_bx(s);
} else {
@@ -1552,7 +1558,7 @@ static void disas_thumb_insn(DisasContex
gen_movl_T1_reg(s, rm);
}
if (insn & (1 << 9))
- gen_op_addl_T0_T1_cc();
+ gen_op_subl_T0_T1_cc();
else
gen_op_addl_T0_T1_cc();
gen_movl_reg_T0(s, rd);
@@ -1595,11 +1601,10 @@ static void disas_thumb_insn(DisasContex
case 4:
if (insn & (1 << 11)) {
rd = (insn >> 8) & 7;
- /* load pc-relative */
- val = (insn & 0xff) * 4;
+ /* load pc-relative. Bit 1 of PC is ignored. */
+ val = s->pc + 2 + ((insn & 0xff) * 4);
+ val &= ~(uint32_t)2;
gen_op_movl_T1_im(val);
- gen_movl_T2_reg(s, 15);
- gen_op_addl_T1_T2();
gen_op_ldl_T0_T1();
gen_movl_reg_T0(s, rd);
break;
@@ -1658,7 +1663,7 @@ static void disas_thumb_insn(DisasContex
gen_movl_T0_reg(s, rd);
gen_movl_T1_reg(s, rm);
- switch (insn >> 6) {
+ switch (op) {
case 0x0: /* and */
gen_op_andl_T0_T1();
gen_op_logic_T0_cc();
@@ -1689,8 +1694,9 @@ static void disas_thumb_insn(DisasContex
gen_op_andl_T0_T1();
gen_op_logic_T0_cc();
rd = 16;
+ break;
case 0x9: /* neg */
- gen_op_rsbl_T0_T1_cc();
+ gen_op_subl_T0_T1_cc();
break;
case 0xa: /* cmp */
gen_op_subl_T0_T1_cc();
@@ -1716,11 +1722,12 @@ static void disas_thumb_insn(DisasContex
gen_op_notl_T1();
gen_op_logic_T1_cc();
val = 1;
+ rm = rd;
break;
}
if (rd != 16) {
if (val)
- gen_movl_reg_T1(s, rd);
+ gen_movl_reg_T1(s, rm);
else
gen_movl_reg_T0(s, rd);
}
@@ -1756,7 +1763,7 @@ static void disas_thumb_insn(DisasContex
gen_op_ldl_T0_T1();
break;
case 5: /* ldrh */
- gen_op_ldsw_T0_T1();
+ gen_op_lduw_T0_T1();
break;
case 6: /* ldrb */
gen_op_ldub_T0_T1();
@@ -1851,11 +1858,13 @@ static void disas_thumb_insn(DisasContex
case 10:
/* add to high reg */
rd = (insn >> 8) & 7;
- if (insn & (1 << 11))
- rm = 13; /* sp */
- else
- rm = 15; /* pc */
- gen_movl_T0_reg(s, rm);
+ if (insn & (1 << 11)) {
+ /* SP */
+ gen_movl_T0_reg(s, 13);
+ } else {
+ /* PC. bit 1 is ignored. */
+ gen_op_movl_T0_im((s->pc + 2) & ~(uint32_t)2);
+ }
val = (insn & 0xff) * 4;
gen_op_movl_T1_im(val);
gen_op_addl_T0_T1();
@@ -1880,11 +1889,19 @@ static void disas_thumb_insn(DisasContex
case 4: case 5: case 0xc: case 0xd:
/* push/pop */
gen_movl_T1_reg(s, 13);
- if (insn & (1 << 11))
- val = 4;
+ if (insn & (1 << 8))
+ offset = 4;
else
- val = -4;
- gen_op_movl_T2_im(val);
+ offset = 0;
+ for (i = 0; i < 8; i++) {
+ if (insn & (1 << i))
+ offset += 4;
+ }
+ if ((insn & (1 << 11)) == 0) {
+ gen_op_movl_T2_im(-offset);
+ gen_op_addl_T1_T2();
+ }
+ gen_op_movl_T2_im(4);
for (i = 0; i < 8; i++) {
if (insn & (1 << i)) {
if (insn & (1 << 11)) {
@@ -1896,7 +1913,7 @@ static void disas_thumb_insn(DisasContex
gen_movl_T0_reg(s, i);
gen_op_stl_T0_T1();
}
- /* move to the next address */
+ /* advance to the next address. */
gen_op_addl_T1_T2();
}
}
@@ -1913,7 +1930,10 @@ static void disas_thumb_insn(DisasContex
}
gen_op_addl_T1_T2();
}
-
+ if ((insn & (1 << 11)) == 0) {
+ gen_op_movl_T2_im(-offset);
+ gen_op_addl_T1_T2();
+ }
/* write back the new stack pointer */
gen_movl_reg_T1(s, 13);
/* set the new PC value */
@@ -1931,14 +1951,8 @@ static void disas_thumb_insn(DisasContex
rn = (insn >> 8) & 0x7;
gen_movl_T1_reg(s, rn);
gen_op_movl_T2_im(4);
- val = 0;
for (i = 0; i < 8; i++) {
if (insn & (1 << i)) {
- /* advance to the next address */
- if (val)
- gen_op_addl_T1_T2();
- else
- val = 1;
if (insn & (1 << 11)) {
/* load */
gen_op_ldl_T0_T1();
@@ -1948,8 +1962,12 @@ static void disas_thumb_insn(DisasContex
gen_movl_T0_reg(s, i);
gen_op_stl_T0_T1();
}
+ /* advance to the next address */
+ gen_op_addl_T1_T2();
}
}
+ /* Base register writeback. */
+ gen_movl_reg_T1(s, rn);
break;
case 13:
@@ -1976,9 +1994,9 @@ static void disas_thumb_insn(DisasContex
gen_movl_T1_reg(s, 15);
/* jump to the offset */
- val = (uint32_t)s->pc;
+ val = (uint32_t)s->pc + 2;
offset = ((int32_t)insn << 24) >> 24;
- val += (offset << 1) + 2;
+ val += offset << 1;
gen_jmp(s, val);
break;
@@ -2002,19 +2020,20 @@ static void disas_thumb_insn(DisasContex
gen_op_movl_T1_im(val | 1);
gen_movl_reg_T1(s, 14);
- val += offset;
+ val += offset << 1;
if (insn & (1 << 11)) {
/* bl */
gen_jmp(s, val);
} else {
/* blx */
+ val &= ~(uint32_t)2;
gen_op_movl_T0_im(val);
gen_bx(s);
}
}
return;
undef:
- gen_op_movl_T0_im((long)s->pc - 4);
+ gen_op_movl_T0_im((long)s->pc - 2);
gen_op_movl_reg_TN[0][15]();
gen_op_undef_insn();
s->is_jmp = DISAS_JUMP;
@@ -2045,6 +2064,7 @@ static inline int gen_intermediate_code_
dc->pc = pc_start;
dc->singlestep_enabled = env->singlestep_enabled;
dc->condjmp = 0;
+ dc->thumb = env->thumb;
nb_gen_labels = 0;
lj = -1;
do {
@@ -2128,7 +2148,7 @@ static inline int gen_intermediate_code_
if (loglevel & CPU_LOG_TB_IN_ASM) {
fprintf(logfile, "----------------\n");
fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
- target_disas(logfile, pc_start, dc->pc - pc_start, 0);
+ target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);
fprintf(logfile, "\n");
if (loglevel & (CPU_LOG_TB_OP)) {
fprintf(logfile, "OP:\n");
reply other threads:[~2005-04-26 23:23 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=200504270020.02222.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.