From: Thorsten Zitterell <the.real.hik@gmx.net>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] ARM XScale extension
Date: Wed, 04 Oct 2006 23:49:23 +0200 [thread overview]
Message-ID: <45242C63.7000306@gmx.net> (raw)
[-- Attachment #1: Type: text/plain, Size: 371 bytes --]
Hi,
the attached file includes preliminary support for the Intel XScale CPU.
I have also written code which emulates a Gumstix [1] system in QEMU -
based on this processor - and got a Linux kernel up and running.
Could you please apply this patch to CVS?
Comments?
I will send further patches if this is all right so far...
--
Thorsten
[1] http://www.gumstix.org
[-- Attachment #2: xscale.patch --]
[-- Type: text/x-patch, Size: 9358 bytes --]
diff -u -r qemu.orig/target-arm/cpu.h qemu.new/target-arm/cpu.h
--- qemu.orig/target-arm/cpu.h 2006-02-20 01:33:36.000000000 +0100
+++ qemu.new/target-arm/cpu.h 2006-10-04 22:11:15.532962000 +0200
@@ -47,6 +47,8 @@
typedef struct CPUARMState {
/* Regs for current mode. */
uint32_t regs[16];
+ /* Accumulator for XScale, by now only ACC0 supported */
+ uint64_t acc[8];
/* Frequently accessed CPSR bits are stored separately for efficiently.
This contains all the other bits. Use cpsr_{read,write} to accless
the whole CPSR. */
@@ -69,6 +71,14 @@
uint32_t QF; /* 0 or 1 */
int thumb; /* 0 = arm mode, 1 = thumb mode */
+
+ /* System control coprocessor (cp14) */
+ struct {
+ uint32_t pmnc; /* Performance Monitor Control Register */
+ uint32_t ccnt; /* Clock Counter Register */
+ uint32_t pmn0; /* Performance Count Register 0 */
+ uint32_t pmn1; /* Performance Count Register 1 */
+ } cp14;
/* System control coprocessor (cp15) */
struct {
@@ -200,7 +210,8 @@
enum arm_features {
ARM_FEATURE_VFP,
- ARM_FEATURE_AUXCR /* ARM1026 Auxiliary control register. */
+ ARM_FEATURE_AUXCR, /* ARM1026 Auxiliary control register. */
+ ARM_FEATURE_XSCALE /* Intel XScale extensions */
};
static inline int arm_feature(CPUARMState *env, int feature)
@@ -212,6 +223,7 @@
#define ARM_CPUID_ARM1026 0x4106a262
#define ARM_CPUID_ARM926 0x41069265
+#define ARM_CPUID_PXA255 0x69052d00
#if defined(CONFIG_USER_ONLY)
#define TARGET_PAGE_BITS 12
diff -u -r qemu.orig/target-arm/exec.h qemu.new/target-arm/exec.h
--- qemu.orig/target-arm/exec.h 2005-11-26 11:38:39.000000000 +0100
+++ qemu.new/target-arm/exec.h 2006-07-05 16:00:25.000000000 +0200
@@ -53,6 +53,8 @@
void cpu_lock(void);
void cpu_unlock(void);
+void helper_set_cp14(CPUState *, uint32_t, uint32_t);
+uint32_t helper_get_cp14(CPUState *, uint32_t);
void helper_set_cp15(CPUState *, uint32_t, uint32_t);
uint32_t helper_get_cp15(CPUState *, uint32_t);
diff -u -r qemu.orig/target-arm/helper.c qemu.new/target-arm/helper.c
--- qemu.orig/target-arm/helper.c 2006-09-09 16:36:26.000000000 +0200
+++ qemu.new/target-arm/helper.c 2006-10-04 22:12:11.995788000 +0200
@@ -40,6 +40,9 @@
{
env->cp15.c0_cpuid = id;
switch (id) {
+ case ARM_CPUID_PXA255:
+ set_feature(env, ARM_FEATURE_XSCALE);
+ break;
case ARM_CPUID_ARM926:
set_feature(env, ARM_FEATURE_VFP);
env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
@@ -322,13 +325,17 @@
phys_addr = (desc & 0xfffff000) | (address & 0xfff);
ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
break;
- case 3: /* 1k page. */
- if (type == 1) {
- /* Page translation fault. */
- code = 7;
- goto do_fault;
+ case 3: /* 1k page. */
+ if (arm_feature(env, ARM_FEATURE_XSCALE)) {
+ phys_addr = (desc & 0xfffff000) | (address & 0xfff);
+ } else {
+ if (type == 1) {
+ /* Page translation fault. */
+ code = 7;
+ goto do_fault;
+ }
+ phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
}
- phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
ap = (desc >> 4) & 3;
break;
default:
@@ -391,6 +398,62 @@
return phys_addr;
}
+void helper_set_cp14(CPUState *env, uint32_t insn, uint32_t val)
+{
+ uint32_t op2;
+
+ op2 = (insn >> 5) & 7;
+ switch ((insn >> 16) & 0xf) {
+ case 0: /* Performance Monitor Control Register */
+ env->cp14.pmnc = val;
+ printf("Performance registers unsupported!\n");
+ break;
+ case 1: /* Performance Monitor Control Register */
+ env->cp14.ccnt = val;
+ printf("Performance registers unsupported!\n");
+ break;
+ case 2: /* Performance Monitor Control Register 0 */
+ env->cp14.pmn0 = val;
+ printf("Performance registers unsupported!\n");
+ break;
+ case 3: /* Performance Monitor Control Register 1 */
+ env->cp14.pmn1 = val;
+ printf("Performance registers unsupported!\n");
+ break;
+ }
+ return;
+bad_reg:
+ /* ??? For debugging only. Should raise illegal instruction exception. */
+ cpu_abort(env, "Unimplemented cp14 register read\n");
+ return;
+}
+
+uint32_t helper_get_cp14(CPUState *env, uint32_t insn)
+{
+ uint32_t op2;
+
+ op2 = (insn >> 5) & 7;
+ switch ((insn >> 16) & 0xf) {
+ case 0: /* Performance Monitor Control Register */
+ printf("Performance registers unsupported!\n");
+ return env->cp14.pmnc;
+ case 1: /* Performance Monitor Control Register */
+ printf("Performance registers unsupported!\n");
+ return env->cp14.ccnt;
+ case 2: /* Performance Monitor Control Register 0 */
+ printf("Performance registers unsupported!\n");
+ return env->cp14.pmn0;
+ case 3: /* Performance Monitor Control Register 1 */
+ printf("Performance registers unsupported!\n");
+ return env->cp14.pmn1;
+ }
+ return 0;
+bad_reg:
+ /* ??? For debugging only. Should raise illegal instruction exception. */
+ cpu_abort(env, "Unimplemented cp14 register read\n");
+ return 0;
+}
+
void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
{
uint32_t op2;
diff -u -r qemu.orig/target-arm/op.c qemu.new/target-arm/op.c
--- qemu.orig/target-arm/op.c 2006-06-26 21:55:19.000000000 +0200
+++ qemu.new/target-arm/op.c 2006-10-04 23:29:19.499215000 +0200
@@ -85,6 +85,21 @@
#define SET_REG(x) REG = x & ~(uint32_t)1
#include "op_template.h"
+void OPPROTO op_acc0_T0_T1(void)
+{
+ uint64_t res;
+ res = ((uint64_t)T0 << 32) | T1;
+ env->acc[0] = res;
+}
+
+void OPPROTO op_T0_T1_acc0(void)
+{
+ uint64_t res;
+ res = env->acc[0];
+ T0 = res >> 32;
+ T1 = res & 0xffffffff;
+}
+
void OPPROTO op_bx_T0(void)
{
env->regs[15] = T0 & ~(uint32_t)1;
@@ -1148,6 +1163,19 @@
T1 = (int32_t)T0 >> 31;
}
+void OPPROTO op_movl_cp14_T0(void)
+{
+ helper_set_cp14(env, PARAM1, T0);
+ FORCE_RET();
+}
+
+void OPPROTO op_movl_T0_cp14(void)
+{
+ T0 = helper_get_cp14(env, PARAM1);
+ FORCE_RET();
+}
+
+
void OPPROTO op_movl_cp15_T0(void)
{
helper_set_cp15(env, PARAM1, T0);
diff -u -r qemu.orig/target-arm/translate.c qemu.new/target-arm/translate.c
--- qemu.orig/target-arm/translate.c 2006-06-14 16:36:07.000000000 +0200
+++ qemu.new/target-arm/translate.c 2006-10-04 22:59:51.695175000 +0200
@@ -490,6 +490,63 @@
gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
}
+/* Disassemble system coprocessor (cp0) instruction. Return nonzero if
+ instruction is not defined. */
+static int disas_cp0_insn(DisasContext *s, uint32_t insn)
+{
+ uint32_t rdhi, rdlo;
+ if ((insn & 0x0fe00f10) == 0x0e200010) {
+ printf ("cp0 multiply\n");
+ return 1;
+ } else if ((insn & 0x0fe00ff8) == 0x0c400000) {
+ rdhi = (insn >> 16) & 0xf;
+ rdlo = (insn >> 12) & 0xf;
+ if (insn & (1 << 20)) {
+ /* write ACC */
+ gen_op_T0_T1_acc0;
+ gen_op_movl_TN_reg[0][rdhi]();
+ gen_op_movl_TN_reg[1][rdlo]();
+ } else {
+ /* read ACC */
+ gen_op_movl_reg_TN[0][rdhi]();
+ gen_op_movl_reg_TN[1][rdlo]();
+ gen_op_acc0_T0_T1;
+ }
+ return 0;
+ } else printf("Unknown cp0 instruction\n");
+ return 1;
+}
+
+/* Disassemble system coprocessor (cp14) instruction. Return nonzero if
+ instruction is not defined. */
+static int disas_cp14_insn(DisasContext *s, uint32_t insn)
+{
+ uint32_t rd;
+ /*
+ xxxx1110 oooLNNNN ddddpppp qqq1MMMM MRC/MCR
+ MCR/MCR p,o,Rd,CRN,CRM,q
+ */
+
+ if (IS_USER(s)) {
+ return 1;
+ }
+ if ((insn & 0x0f000f00) == 0x0e000e00) { /* fixme */
+ rd = (insn >> 12) & 0xf;
+ if (insn & (1 << 20)) { /* 0/1 Store/Load */
+ gen_op_movl_T0_cp14(insn);
+ gen_movl_reg_T0(s, rd);
+ } else {
+ gen_movl_T0_reg(s, rd);
+ gen_op_movl_cp14_T0(insn);
+ }
+ return 0;
+ } else printf("Unknown cp14 instruction\n");
+ return 1;
+
+ printf("cp14 instruction %x\n",insn);
+ return 0;
+}
+
/* Disassemble system coprocessor (cp15) instruction. Return nonzero if
instruction is not defined. */
static int disas_cp15_insn(DisasContext *s, uint32_t insn)
@@ -1795,11 +1852,19 @@
/* Coprocessor. */
op1 = (insn >> 8) & 0xf;
switch (op1) {
+ case 0:
+ if (disas_cp0_insn (s, insn))
+ goto illegal_op;
+ break;
case 10:
case 11:
if (disas_vfp_insn (env, s, insn))
goto illegal_op;
break;
+ case 14:
+ if (disas_cp14_insn (s, insn))
+ goto illegal_op;
+ break;
case 15:
if (disas_cp15_insn (s, insn))
goto illegal_op;
next reply other threads:[~2006-10-04 21:49 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-10-04 21:49 Thorsten Zitterell [this message]
2006-10-04 21:58 ` [Qemu-devel] ARM XScale extension Lennert Buytenhek
2006-10-04 22:46 ` Thorsten Zitterell
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=45242C63.7000306@gmx.net \
--to=the.real.hik@gmx.net \
--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.