summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcelo Tosatti <mtosatti@redhat.com>2011-05-03 17:16:57 -0300
committerMarcelo Tosatti <mtosatti@redhat.com>2011-05-03 17:16:57 -0300
commit4183a43d1405fbb9da3ccb3dcff223266a36df9f (patch)
treef09ab17c574665ba73ebce9932f16afc76037fff
parenta670ad63cf5ce7aa71cfae8057d9d1dc72f36f10 (diff)
parenta1d8db07fb46e1da410ca7b4ce24a997707d4a53 (diff)
Merge commit 'a1d8db07fb46e1da410ca7b4ce24a997707d4a53' into upstream-merge
* commit 'a1d8db07fb46e1da410ca7b4ce24a997707d4a53': (72 commits) target-i386: fix constants wrt softfloat target-i386: fix helper_fprem() and helper_fprem1() wrt softfloat target-i386: fix logarithmic and trigonometric helpers wrt softfloat target-i386: add CPU86_LDouble <-> double conversion functions target-i386: replace approx_rsqrt and approx_rcp by softfloat ops target-i386: fix helper_fsqrt() wrt softfloat target-i386: fix helper_fdiv() wrt softfloat target-i386: fix helper_fxtract() wrt softfloat target-i386: fix helper_fbld_ST0() wrt softfloat target-i386: fix helper_fscale() wrt softfloat softfloat-native: add float*_is_any_nan() functions softfloat-native: fix float*_scalbn() functions softfloat: fix float*_scalnb() corner cases softfloat: add floatx80_compare*() functions softfloat-native: add a few constant values softfloat: add pi constants softfloat: add floatx80 constants softfloat: fix floatx80_is_infinity() softfloat: fix floatx80 handling of NaN vmstate: port mac_dbdma ... Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r--Makefile.target2
-rw-r--r--cpu-exec.c2
-rw-r--r--exec-all.h7
-rw-r--r--exec.c9
-rw-r--r--fpu/softfloat-native.c26
-rw-r--r--fpu/softfloat-native.h36
-rw-r--r--fpu/softfloat-specialize.h23
-rw-r--r--fpu/softfloat.c93
-rw-r--r--fpu/softfloat.h14
-rw-r--r--hw/adb.c83
-rw-r--r--hw/ads7846.c41
-rw-r--r--hw/arm_boot.c2
-rw-r--r--hw/arm_timer.c66
-rw-r--r--hw/armv7m_nvic.c39
-rw-r--r--hw/collie.c69
-rw-r--r--hw/cuda.c116
-rw-r--r--hw/flash.h4
-rw-r--r--hw/heathrow_pic.c62
-rw-r--r--hw/hw.h17
-rw-r--r--hw/m48t59.c36
-rw-r--r--hw/mac_dbdma.c83
-rw-r--r--hw/mac_nvram.c32
-rw-r--r--hw/max111x.c51
-rw-r--r--hw/mipsnet.c53
-rw-r--r--hw/nand.c79
-rw-r--r--hw/piix4.c44
-rw-r--r--hw/pl011.c76
-rw-r--r--hw/pl022.c84
-rw-r--r--hw/ppc4xx_pci.c80
-rw-r--r--hw/ppce500_pci.c87
-rw-r--r--hw/ptimer.c59
-rw-r--r--hw/pxa2xx.c158
-rw-r--r--hw/pxa2xx_keypad.c53
-rw-r--r--hw/pxa2xx_lcd.c138
-rw-r--r--hw/s390-virtio-bus.c10
-rw-r--r--hw/s390-virtio.c21
-rw-r--r--hw/stellaris.c323
-rw-r--r--hw/stellaris_input.c50
-rw-r--r--hw/strongarm.c1598
-rw-r--r--hw/strongarm.h64
-rw-r--r--hw/syborg_keyboard.c57
-rw-r--r--hw/syborg_pointer.c73
-rw-r--r--hw/syborg_rtc.c34
-rw-r--r--hw/syborg_serial.c60
-rw-r--r--hw/syborg_timer.c46
-rw-r--r--qemu-timer.h2
-rw-r--r--target-alpha/op_helper.c2
-rw-r--r--target-alpha/translate.c3
-rw-r--r--target-arm/cpu.h3
-rw-r--r--target-arm/helper.c18
-rw-r--r--target-arm/op_helper.c2
-rw-r--r--target-arm/translate.c7
-rw-r--r--target-cris/op_helper.c2
-rw-r--r--target-cris/translate.c3
-rw-r--r--target-i386/exec.h20
-rw-r--r--target-i386/op_helper.c207
-rw-r--r--target-i386/ops_sse.h36
-rw-r--r--target-i386/translate.c7
-rw-r--r--target-lm32/op_helper.c2
-rw-r--r--target-lm32/translate.c3
-rw-r--r--target-m68k/op_helper.c2
-rw-r--r--target-m68k/translate.c3
-rw-r--r--target-microblaze/op_helper.c2
-rw-r--r--target-microblaze/translate.c3
-rw-r--r--target-mips/op_helper.c4
-rw-r--r--target-mips/translate.c3
-rw-r--r--target-ppc/op_helper.c2
-rw-r--r--target-ppc/translate.c3
-rw-r--r--target-s390x/op_helper.c2
-rw-r--r--target-s390x/translate.c3
-rw-r--r--target-sh4/op_helper.c2
-rw-r--r--target-sh4/translate.c3
-rw-r--r--target-sparc/op_helper.c2
-rw-r--r--target-sparc/translate.c3
-rw-r--r--target-unicore32/translate.c3
-rw-r--r--translate-all.c5
76 files changed, 3010 insertions, 1512 deletions
diff --git a/Makefile.target b/Makefile.target
index 3a3720541..8ba95676c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -379,6 +379,8 @@ obj-arm-y += syborg.o syborg_fb.o syborg_interrupt.o syborg_keyboard.o
obj-arm-y += syborg_serial.o syborg_timer.o syborg_pointer.o syborg_rtc.o
obj-arm-y += syborg_virtio.o
obj-arm-y += vexpress.o
+obj-arm-y += strongarm.o
+obj-arm-y += collie.o
obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
obj-sh4-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
diff --git a/cpu-exec.c b/cpu-exec.c
index 584da7d31..b9b04aec7 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -816,7 +816,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, puc);
+ cpu_restore_state(tb, env, pc);
}
/* we restore the process signal mask as the sigreturn should
diff --git a/exec-all.h b/exec-all.h
index 496c001c0..7c2d29ff9 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -77,15 +77,14 @@ extern uint16_t gen_opc_icount[OPC_BUF_SIZE];
void gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
void gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
-void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc);
+void restore_state_to_opc(CPUState *env, struct TranslationBlock *tb,
+ int pc_pos);
void cpu_gen_init(void);
int cpu_gen_code(CPUState *env, struct TranslationBlock *tb,
int *gen_code_size_ptr);
int cpu_restore_state(struct TranslationBlock *tb,
- CPUState *env, unsigned long searched_pc,
- void *puc);
+ CPUState *env, unsigned long searched_pc);
void cpu_resume_from_signal(CPUState *env1, void *puc);
void cpu_io_recompile(CPUState *env, void *retaddr);
TranslationBlock *tb_gen_code(CPUState *env,
diff --git a/exec.c b/exec.c
index 594dfcbbd..2f4058993 100644
--- a/exec.c
+++ b/exec.c
@@ -1079,8 +1079,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
restore the CPU state */
current_tb_modified = 1;
- cpu_restore_state(current_tb, env,
- env->mem_io_pc, NULL);
+ cpu_restore_state(current_tb, env, env->mem_io_pc);
cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
&current_flags);
}
@@ -1188,7 +1187,7 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr,
restore the CPU state */
current_tb_modified = 1;
- cpu_restore_state(current_tb, env, pc, puc);
+ cpu_restore_state(current_tb, env, pc);
cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
&current_flags);
}
@@ -3290,7 +3289,7 @@ static void check_watchpoint(int offset, int len_mask, int flags)
cpu_abort(env, "check_watchpoint: could not find TB for "
"pc=%p", (void *)env->mem_io_pc);
}
- cpu_restore_state(tb, env, env->mem_io_pc, NULL);
+ cpu_restore_state(tb, env, env->mem_io_pc);
tb_phys_invalidate(tb, -1);
if (wp->flags & BP_STOP_BEFORE_ACCESS) {
env->exception_index = EXCP_DEBUG;
@@ -4334,7 +4333,7 @@ void cpu_io_recompile(CPUState *env, void *retaddr)
retaddr);
}
n = env->icount_decr.u16.low + tb->icount;
- cpu_restore_state(tb, env, (unsigned long)retaddr, NULL);
+ cpu_restore_state(tb, env, (unsigned long)retaddr);
/* Calculate how many instructions had been executed before the fault
occurred. */
n = n - env->icount_decr.u16.low;
diff --git a/fpu/softfloat-native.c b/fpu/softfloat-native.c
index a47b0d48e..3bb38860a 100644
--- a/fpu/softfloat-native.c
+++ b/fpu/softfloat-native.c
@@ -264,6 +264,15 @@ int float32_is_quiet_nan( float32 a1 )
return ( 0xFF800000 < ( a<<1 ) );
}
+int float32_is_any_nan( float32 a1 )
+{
+ float32u u;
+ uint32_t a;
+ u.f = a1;
+ a = u.i;
+ return (a & ~(1 << 31)) > 0x7f800000U;
+}
+
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision conversion routines.
*----------------------------------------------------------------------------*/
@@ -423,6 +432,16 @@ int float64_is_quiet_nan( float64 a1 )
}
+int float64_is_any_nan( float64 a1 )
+{
+ float64u u;
+ uint64_t a;
+ u.f = a1;
+ a = u.i;
+
+ return (a & ~(1ULL << 63)) > LIT64 (0x7FF0000000000000 );
+}
+
#ifdef FLOATX80
/*----------------------------------------------------------------------------
@@ -512,4 +531,11 @@ int floatx80_is_quiet_nan( floatx80 a1 )
return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (uint64_t) ( u.i.low<<1 );
}
+int floatx80_is_any_nan( floatx80 a1 )
+{
+ floatx80u u;
+ u.f = a1;
+ return ((u.i.high & 0x7FFF) == 0x7FFF) && ( u.i.low<<1 );
+}
+
#endif
diff --git a/fpu/softfloat-native.h b/fpu/softfloat-native.h
index ea7a15e1c..6afb74a15 100644
--- a/fpu/softfloat-native.h
+++ b/fpu/softfloat-native.h
@@ -172,6 +172,15 @@ float128 int64_to_float128( int64_t STATUS_PARAM);
#endif
/*----------------------------------------------------------------------------
+| Software IEC/IEEE single-precision conversion constants.
+*----------------------------------------------------------------------------*/
+#define float32_zero (0.0)
+#define float32_one (1.0)
+#define float32_ln2 (0.6931471)
+#define float32_pi (3.1415926)
+#define float32_half (0.5)
+
+/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision conversion routines.
*----------------------------------------------------------------------------*/
int float32_to_int32( float32 STATUS_PARAM);
@@ -246,6 +255,7 @@ int float32_compare( float32, float32 STATUS_PARAM );
int float32_compare_quiet( float32, float32 STATUS_PARAM );
int float32_is_signaling_nan( float32 );
int float32_is_quiet_nan( float32 );
+int float32_is_any_nan( float32 );
INLINE float32 float32_abs(float32 a)
{
@@ -274,12 +284,21 @@ INLINE float32 float32_is_zero(float32 a)
return fpclassify(a) == FP_ZERO;
}
-INLINE float32 float32_scalbn(float32 a, int n)
+INLINE float32 float32_scalbn(float32 a, int n STATUS_PARAM)
{
return scalbnf(a, n);
}
/*----------------------------------------------------------------------------
+| Software IEC/IEEE double-precision conversion constants.
+*----------------------------------------------------------------------------*/
+#define float64_zero (0.0)
+#define float64_one (1.0)
+#define float64_ln2 (0.693147180559945)
+#define float64_pi (3.141592653589793)
+#define float64_half (0.5)
+
+/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision conversion routines.
*----------------------------------------------------------------------------*/
int float64_to_int32( float64 STATUS_PARAM );
@@ -357,6 +376,7 @@ INLINE int float64_unordered_quiet( float64 a, float64 b STATUS_PARAM)
int float64_compare( float64, float64 STATUS_PARAM );
int float64_compare_quiet( float64, float64 STATUS_PARAM );
int float64_is_signaling_nan( float64 );
+int float64_is_any_nan( float64 );
int float64_is_quiet_nan( float64 );
INLINE float64 float64_abs(float64 a)
@@ -386,7 +406,7 @@ INLINE float64 float64_is_zero(float64 a)
return fpclassify(a) == FP_ZERO;
}
-INLINE float64 float64_scalbn(float64 a, int n)
+INLINE float64 float64_scalbn(float64 a, int n STATUS_PARAM)
{
return scalbn(a, n);
}
@@ -394,6 +414,15 @@ INLINE float64 float64_scalbn(float64 a, int n)
#ifdef FLOATX80
/*----------------------------------------------------------------------------
+| Software IEC/IEEE extended double-precision conversion constants.
+*----------------------------------------------------------------------------*/
+#define floatx80_zero (0.0L)
+#define floatx80_one (1.0L)
+#define floatx80_ln2 (0.69314718055994530943L)
+#define floatx80_pi (3.14159265358979323851L)
+#define floatx80_half (0.5L)
+
+/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision conversion routines.
*----------------------------------------------------------------------------*/
int floatx80_to_int32( floatx80 STATUS_PARAM );
@@ -465,6 +494,7 @@ int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_is_signaling_nan( floatx80 );
int floatx80_is_quiet_nan( floatx80 );
+int floatx80_is_any_nan( floatx80 );
INLINE floatx80 floatx80_abs(floatx80 a)
{
@@ -493,7 +523,7 @@ INLINE floatx80 floatx80_is_zero(floatx80 a)
return fpclassify(a) == FP_ZERO;
}
-INLINE floatx80 floatx80_scalbn(floatx80 a, int n)
+INLINE floatx80 floatx80_scalbn(floatx80 a, int n STATUS_PARAM)
{
return scalbnl(a, n);
}
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index b1101872a..9d68aae9d 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -603,9 +603,15 @@ static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
commonNaNT z;
if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
- z.sign = a.high>>15;
- z.low = 0;
- z.high = a.low;
+ if ( a.low >> 63 ) {
+ z.sign = a.high >> 15;
+ z.low = 0;
+ z.high = a.low << 1;
+ } else {
+ z.sign = floatx80_default_nan_high >> 15;
+ z.low = 0;
+ z.high = floatx80_default_nan_low << 1;
+ }
return z;
}
@@ -624,11 +630,14 @@ static floatx80 commonNaNToFloatx80( commonNaNT a STATUS_PARAM)
return z;
}
- if (a.high)
- z.low = a.high;
- else
+ if (a.high >> 1) {
+ z.low = LIT64( 0x8000000000000000 ) | a.high >> 1;
+ z.high = ( ( (uint16_t) a.sign )<<15 ) | 0x7FFF;
+ } else {
z.low = floatx80_default_nan_low;
- z.high = ( ( (uint16_t) a.sign )<<15 ) | 0x7FFF;
+ z.high = floatx80_default_nan_high;
+ }
+
return z;
}
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 6ce0b61c1..baba1dc44 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6190,6 +6190,52 @@ int float ## s ## _compare_quiet( float ## s a, float ## s b STATUS_PARAM ) \
COMPARE(32, 0xff)
COMPARE(64, 0x7ff)
+INLINE int floatx80_compare_internal( floatx80 a, floatx80 b,
+ int is_quiet STATUS_PARAM )
+{
+ flag aSign, bSign;
+
+ if (( ( extractFloatx80Exp( a ) == 0x7fff ) &&
+ ( extractFloatx80Frac( a )<<1 ) ) ||
+ ( ( extractFloatx80Exp( b ) == 0x7fff ) &&
+ ( extractFloatx80Frac( b )<<1 ) )) {
+ if (!is_quiet ||
+ floatx80_is_signaling_nan( a ) ||
+ floatx80_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid STATUS_VAR);
+ }
+ return float_relation_unordered;
+ }
+ aSign = extractFloatx80Sign( a );
+ bSign = extractFloatx80Sign( b );
+ if ( aSign != bSign ) {
+
+ if ( ( ( (uint16_t) ( ( a.high | b.high ) << 1 ) ) == 0) &&
+ ( ( a.low | b.low ) == 0 ) ) {
+ /* zero case */
+ return float_relation_equal;
+ } else {
+ return 1 - (2 * aSign);
+ }
+ } else {
+ if (a.low == b.low && a.high == b.high) {
+ return float_relation_equal;
+ } else {
+ return 1 - 2 * (aSign ^ ( lt128( a.high, a.low, b.high, b.low ) ));
+ }
+ }
+}
+
+int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
+{
+ return floatx80_compare_internal(a, b, 0 STATUS_VAR);
+}
+
+int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
+{
+ return floatx80_compare_internal(a, b, 1 STATUS_VAR);
+}
+
INLINE int float128_compare_internal( float128 a, float128 b,
int is_quiet STATUS_PARAM )
{
@@ -6287,7 +6333,7 @@ MINMAX(64, 0x7ff)
float32 float32_scalbn( float32 a, int n STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int16_t aExp;
uint32_t aSig;
a = float32_squash_input_denormal(a STATUS_VAR);
@@ -6296,6 +6342,9 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM )
aSign = extractFloat32Sign( a );
if ( aExp == 0xFF ) {
+ if ( aSig ) {
+ return propagateFloat32NaN( a, a STATUS_VAR );
+ }
return a;
}
if ( aExp != 0 )
@@ -6303,6 +6352,12 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM )
else if ( aSig == 0 )
return a;
+ if (n > 0x200) {
+ n = 0x200;
+ } else if (n < -0x200) {
+ n = -0x200;
+ }
+
aExp += n - 1;
aSig <<= 7;
return normalizeRoundAndPackFloat32( aSign, aExp, aSig STATUS_VAR );
@@ -6311,7 +6366,7 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM )
float64 float64_scalbn( float64 a, int n STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int16_t aExp;
uint64_t aSig;
a = float64_squash_input_denormal(a STATUS_VAR);
@@ -6320,6 +6375,9 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
aSign = extractFloat64Sign( a );
if ( aExp == 0x7FF ) {
+ if ( aSig ) {
+ return propagateFloat64NaN( a, a STATUS_VAR );
+ }
return a;
}
if ( aExp != 0 )
@@ -6327,6 +6385,12 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
else if ( aSig == 0 )
return a;
+ if (n > 0x1000) {
+ n = 0x1000;
+ } else if (n < -0x1000) {
+ n = -0x1000;
+ }
+
aExp += n - 1;
aSig <<= 10;
return normalizeRoundAndPackFloat64( aSign, aExp, aSig STATUS_VAR );
@@ -6336,19 +6400,29 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int32_t aExp;
uint64_t aSig;
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
- if ( aExp == 0x7FF ) {
+ if ( aExp == 0x7FFF ) {
+ if ( aSig<<1 ) {
+ return propagateFloatx80NaN( a, a STATUS_VAR );
+ }
return a;
}
+
if (aExp == 0 && aSig == 0)
return a;
+ if (n > 0x10000) {
+ n = 0x10000;
+ } else if (n < -0x10000) {
+ n = -0x10000;
+ }
+
aExp += n;
return normalizeRoundAndPackFloatx80( STATUS(floatx80_rounding_precision),
aSign, aExp, aSig, 0 STATUS_VAR );
@@ -6359,7 +6433,7 @@ floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM )
float128 float128_scalbn( float128 a, int n STATUS_PARAM )
{
flag aSign;
- int32 aExp;
+ int32_t aExp;
uint64_t aSig0, aSig1;
aSig1 = extractFloat128Frac1( a );
@@ -6367,6 +6441,9 @@ float128 float128_scalbn( float128 a, int n STATUS_PARAM )
aExp = extractFloat128Exp( a );
aSign = extractFloat128Sign( a );
if ( aExp == 0x7FFF ) {
+ if ( aSig0 | aSig1 ) {
+ return propagateFloat128NaN( a, a STATUS_VAR );
+ }
return a;
}
if ( aExp != 0 )
@@ -6374,6 +6451,12 @@ float128 float128_scalbn( float128 a, int n STATUS_PARAM )
else if ( aSig0 == 0 && aSig1 == 0 )
return a;
+ if (n > 0x10000) {
+ n = 0x10000;
+ } else if (n < -0x10000) {
+ n = -0x10000;
+ }
+
aExp += n - 1;
return normalizeRoundAndPackFloat128( aSign, aExp, aSig0, aSig1
STATUS_VAR );
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 340f0a9f2..5eff0858f 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -154,6 +154,7 @@ typedef struct {
uint64_t low;
uint16_t high;
} floatx80;
+#define make_floatx80(exp, mant) ((floatx80) { mant, exp })
#endif
#ifdef FLOAT128
typedef struct {
@@ -386,6 +387,7 @@ INLINE float32 float32_set_sign(float32 a, int sign)
#define float32_zero make_float32(0)
#define float32_one make_float32(0x3f800000)
#define float32_ln2 make_float32(0x3f317218)
+#define float32_pi make_float32(0x40490fdb)
#define float32_half make_float32(0x3f000000)
#define float32_infinity make_float32(0x7f800000)
@@ -498,6 +500,7 @@ INLINE float64 float64_set_sign(float64 a, int sign)
#define float64_zero make_float64(0)
#define float64_one make_float64(0x3ff0000000000000LL)
#define float64_ln2 make_float64(0x3fe62e42fefa39efLL)
+#define float64_pi make_float64(0x400921fb54442d18LL)
#define float64_half make_float64(0x3fe0000000000000LL)
#define float64_infinity make_float64(0x7ff0000000000000LL)
@@ -547,6 +550,8 @@ int floatx80_eq_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_unordered_quiet( floatx80, floatx80 STATUS_PARAM );
+int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
+int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_is_quiet_nan( floatx80 );
int floatx80_is_signaling_nan( floatx80 );
floatx80 floatx80_maybe_silence_nan( floatx80 );
@@ -566,7 +571,7 @@ INLINE floatx80 floatx80_chs(floatx80 a)
INLINE int floatx80_is_infinity(floatx80 a)
{
- return (a.high & 0x7fff) == 0x7fff && a.low == 0;
+ return (a.high & 0x7fff) == 0x7fff && a.low == 0x8000000000000000LL;
}
INLINE int floatx80_is_neg(floatx80 a)
@@ -584,6 +589,13 @@ INLINE int floatx80_is_any_nan(floatx80 a)
return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1);
}
+#define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
+#define floatx80_one make_floatx80(0x3fff, 0x8000000000000000LL)
+#define floatx80_ln2 make_floatx80(0x3ffe, 0xb17217f7d1cf79acLL)
+#define floatx80_pi make_floatx80(0x4000, 0xc90fdaa22168c235LL)
+#define floatx80_half make_floatx80(0x3ffe, 0x8000000000000000LL)
+#define floatx80_infinity make_floatx80(0x7fff, 0x8000000000000000LL)
+
/*----------------------------------------------------------------------------
| The pattern for a default generated extended double-precision NaN. The
| `high' and `low' values hold the most- and least-significant bits,
diff --git a/hw/adb.c b/hw/adb.c
index 99b30f6bc..7499cdcef 100644
--- a/hw/adb.c
+++ b/hw/adb.c
@@ -261,30 +261,19 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
return olen;
}
-static void adb_kbd_save(QEMUFile *f, void *opaque)
-{
- KBDState *s = (KBDState *)opaque;
-
- qemu_put_buffer(f, s->data, sizeof(s->data));
- qemu_put_sbe32s(f, &s->rptr);
- qemu_put_sbe32s(f, &s->wptr);
- qemu_put_sbe32s(f, &s->count);
-}
-
-static int adb_kbd_load(QEMUFile *f, void *opaque, int version_id)
-{
- KBDState *s = (KBDState *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_buffer(f, s->data, sizeof(s->data));
- qemu_get_sbe32s(f, &s->rptr);
- qemu_get_sbe32s(f, &s->wptr);
- qemu_get_sbe32s(f, &s->count);
-
- return 0;
-}
+static const VMStateDescription vmstate_adb_kbd = {
+ .name = "adb_kbd",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_BUFFER(data, KBDState),
+ VMSTATE_INT32(rptr, KBDState),
+ VMSTATE_INT32(wptr, KBDState),
+ VMSTATE_INT32(count, KBDState),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int adb_kbd_reset(ADBDevice *d)
{
@@ -305,8 +294,7 @@ void adb_kbd_init(ADBBusState *bus)
d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
adb_kbd_reset, s);
qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
- register_savevm(NULL, "adb_kbd", -1, 1, adb_kbd_save,
- adb_kbd_load, s);
+ vmstate_register(NULL, -1, &vmstate_adb_kbd, s);
}
/***************************************************************/
@@ -439,32 +427,20 @@ static int adb_mouse_reset(ADBDevice *d)
return 0;
}
-static void adb_mouse_save(QEMUFile *f, void *opaque)
-{
- MouseState *s = (MouseState *)opaque;
-
- qemu_put_sbe32s(f, &s->buttons_state);
- qemu_put_sbe32s(f, &s->last_buttons_state);
- qemu_put_sbe32s(f, &s->dx);
- qemu_put_sbe32s(f, &s->dy);
- qemu_put_sbe32s(f, &s->dz);
-}
-
-static int adb_mouse_load(QEMUFile *f, void *opaque, int version_id)
-{
- MouseState *s = (MouseState *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_sbe32s(f, &s->buttons_state);
- qemu_get_sbe32s(f, &s->last_buttons_state);
- qemu_get_sbe32s(f, &s->dx);
- qemu_get_sbe32s(f, &s->dy);
- qemu_get_sbe32s(f, &s->dz);
-
- return 0;
-}
+static const VMStateDescription vmstate_adb_mouse = {
+ .name = "adb_mouse",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32(buttons_state, MouseState),
+ VMSTATE_INT32(last_buttons_state, MouseState),
+ VMSTATE_INT32(dx, MouseState),
+ VMSTATE_INT32(dy, MouseState),
+ VMSTATE_INT32(dz, MouseState),
+ VMSTATE_END_OF_LIST()
+ }
+};
void adb_mouse_init(ADBBusState *bus)
{
@@ -475,6 +451,5 @@ void adb_mouse_init(ADBBusState *bus)
d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
adb_mouse_reset, s);
qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
- register_savevm(NULL, "adb_mouse", -1, 1, adb_mouse_save,
- adb_mouse_load, s);
+ vmstate_register(NULL, -1, &vmstate_adb_mouse, s);
}
diff --git a/hw/ads7846.c b/hw/ads7846.c
index b3bbeaf68..9c58a5f59 100644
--- a/hw/ads7846.c
+++ b/hw/ads7846.c
@@ -105,35 +105,30 @@ static void ads7846_ts_event(void *opaque,
}
}
-static void ads7846_save(QEMUFile *f, void *opaque)
+static int ads7856_post_load(void *opaque, int version_id)
{
- ADS7846State *s = (ADS7846State *) opaque;
- int i;
-
- for (i = 0; i < 8; i ++)
- qemu_put_be32(f, s->input[i]);
- qemu_put_be32(f, s->noise);
- qemu_put_be32(f, s->cycle);
- qemu_put_be32(f, s->output);
-}
-
-static int ads7846_load(QEMUFile *f, void *opaque, int version_id)
-{
- ADS7846State *s = (ADS7846State *) opaque;
- int i;
-
- for (i = 0; i < 8; i ++)
- s->input[i] = qemu_get_be32(f);
- s->noise = qemu_get_be32(f);
- s->cycle = qemu_get_be32(f);
- s->output = qemu_get_be32(f);
+ ADS7846State *s = opaque;
s->pressure = 0;
ads7846_int_update(s);
-
return 0;
}
+static const VMStateDescription vmstate_ads7846 = {
+ .name = "ads7846",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .post_load = ads7856_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32_ARRAY(input, ADS7846State, 8),
+ VMSTATE_INT32(noise, ADS7846State),
+ VMSTATE_INT32(cycle, ADS7846State),
+ VMSTATE_INT32(output, ADS7846State),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static int ads7846_init(SSISlave *dev)
{
ADS7846State *s = FROM_SSI_SLAVE(ADS7846State, dev);
@@ -151,7 +146,7 @@ static int ads7846_init(SSISlave *dev)
ads7846_int_update(s);
- register_savevm(NULL, "ads7846", -1, 0, ads7846_save, ads7846_load, s);
+ vmstate_register(NULL, -1, &vmstate_ads7846, s);
return 0;
}
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index 41e99d133..bfac982e6 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -15,7 +15,7 @@
#define KERNEL_ARGS_ADDR 0x100
#define KERNEL_LOAD_ADDR 0x00010000
-#define INITRD_LOAD_ADDR 0x00800000
+#define INITRD_LOAD_ADDR 0x00d00000
/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */
static uint32_t bootloader[] = {
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 82f05dec8..dac9e7075 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -140,28 +140,19 @@ static void arm_timer_tick(void *opaque)
arm_timer_update(s);
}
-static void arm_timer_save(QEMUFile *f, void *opaque)
-{
- arm_timer_state *s = (arm_timer_state *)opaque;
- qemu_put_be32(f, s->control);
- qemu_put_be32(f, s->limit);
- qemu_put_be32(f, s->int_level);
- qemu_put_ptimer(f, s->timer);
-}
-
-static int arm_timer_load(QEMUFile *f, void *opaque, int version_id)
-{
- arm_timer_state *s = (arm_timer_state *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->control = qemu_get_be32(f);
- s->limit = qemu_get_be32(f);
- s->int_level = qemu_get_be32(f);
- qemu_get_ptimer(f, s->timer);
- return 0;
-}
+static const VMStateDescription vmstate_arm_timer = {
+ .name = "arm_timer",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(control, arm_timer_state),
+ VMSTATE_UINT32(limit, arm_timer_state),
+ VMSTATE_INT32(int_level, arm_timer_state),
+ VMSTATE_PTIMER(timer, arm_timer_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
static arm_timer_state *arm_timer_init(uint32_t freq)
{
@@ -174,7 +165,7 @@ static arm_timer_state *arm_timer_init(uint32_t freq)
bh = qemu_bh_new(arm_timer_tick, s);
s->timer = ptimer_init(bh);
- register_savevm(NULL, "arm_timer", -1, 1, arm_timer_save, arm_timer_load, s);
+ vmstate_register(NULL, -1, &vmstate_arm_timer, s);
return s;
}
@@ -235,24 +226,17 @@ static CPUWriteMemoryFunc * const sp804_writefn[] = {
sp804_write
};
-static void sp804_save(QEMUFile *f, void *opaque)
-{
- sp804_state *s = (sp804_state *)opaque;
- qemu_put_be32(f, s->level[0]);
- qemu_put_be32(f, s->level[1]);
-}
-
-static int sp804_load(QEMUFile *f, void *opaque, int version_id)
-{
- sp804_state *s = (sp804_state *)opaque;
- if (version_id != 1)
- return -EINVAL;
-
- s->level[0] = qemu_get_be32(f);
- s->level[1] = qemu_get_be32(f);
- return 0;
-}
+static const VMStateDescription vmstate_sp804 = {
+ .name = "sp804",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32_ARRAY(level, sp804_state, 2),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int sp804_init(SysBusDevice *dev)
{
@@ -271,7 +255,7 @@ static int sp804_init(SysBusDevice *dev)
iomemtype = cpu_register_io_memory(sp804_readfn,
sp804_writefn, s, DEVICE_NATIVE_ENDIAN);
sysbus_init_mmio(dev, 0x1000, iomemtype);
- register_savevm(&dev->qdev, "sp804", -1, 1, sp804_save, sp804_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_sp804, s);
return 0;
}
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index ffe16b8a6..d06eec9b3 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -365,30 +365,19 @@ static void nvic_writel(void *opaque, uint32_t offset, uint32_t value)
}
}
-static void nvic_save(QEMUFile *f, void *opaque)
-{
- nvic_state *s = (nvic_state *)opaque;
-
- qemu_put_be32(f, s->systick.control);
- qemu_put_be32(f, s->systick.reload);
- qemu_put_be64(f, s->systick.tick);
- qemu_put_timer(f, s->systick.timer);
-}
-
-static int nvic_load(QEMUFile *f, void *opaque, int version_id)
-{
- nvic_state *s = (nvic_state *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->systick.control = qemu_get_be32(f);
- s->systick.reload = qemu_get_be32(f);
- s->systick.tick = qemu_get_be64(f);
- qemu_get_timer(f, s->systick.timer);
-
- return 0;
-}
+static const VMStateDescription vmstate_nvic = {
+ .name = "armv7m_nvic",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(systick.control, nvic_state),
+ VMSTATE_UINT32(systick.reload, nvic_state),
+ VMSTATE_INT64(systick.tick, nvic_state),
+ VMSTATE_TIMER(systick.timer, nvic_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int armv7m_nvic_init(SysBusDevice *dev)
{
@@ -397,7 +386,7 @@ static int armv7m_nvic_init(SysBusDevice *dev)
gic_init(&s->gic);
cpu_register_physical_memory(0xe000e000, 0x1000, s->gic.iomemtype);
s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
- register_savevm(&dev->qdev, "armv7m_nvic", -1, 1, nvic_save, nvic_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);
return 0;
}
diff --git a/hw/collie.c b/hw/collie.c
new file mode 100644
index 000000000..156404d9f
--- /dev/null
+++ b/hw/collie.c
@@ -0,0 +1,69 @@
+/*
+ * SA-1110-based Sharp Zaurus SL-5500 platform.
+ *
+ * Copyright (C) 2011 Dmitry Eremin-Solenikov
+ *
+ * This code is licensed under GNU GPL v2.
+ */
+#include "hw.h"
+#include "sysbus.h"
+#include "boards.h"
+#include "devices.h"
+#include "strongarm.h"
+#include "arm-misc.h"
+#include "flash.h"
+#include "blockdev.h"
+
+static struct arm_boot_info collie_binfo = {
+ .loader_start = SA_SDCS0,
+ .ram_size = 0x20000000,
+};
+
+static void collie_init(ram_addr_t ram_size,
+ const char *boot_device,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename, const char *cpu_model)
+{
+ StrongARMState *s;
+ DriveInfo *dinfo;
+ ram_addr_t phys_flash;
+
+ if (!cpu_model) {
+ cpu_model = "sa1110";
+ }
+
+ s = sa1110_init(collie_binfo.ram_size, cpu_model);
+
+ phys_flash = qemu_ram_alloc(NULL, "collie.fl1", 0x02000000);
+ dinfo = drive_get(IF_PFLASH, 0, 0);
+ pflash_cfi01_register(SA_CS0, phys_flash,
+ dinfo ? dinfo->bdrv : NULL, (64 * 1024),
+ 512, 4, 0x00, 0x00, 0x00, 0x00, 0);
+
+ phys_flash = qemu_ram_alloc(NULL, "collie.fl2", 0x02000000);
+ dinfo = drive_get(IF_PFLASH, 0, 1);
+ pflash_cfi01_register(SA_CS1, phys_flash,
+ dinfo ? dinfo->bdrv : NULL, (64 * 1024),
+ 512, 4, 0x00, 0x00, 0x00, 0x00, 0);
+
+ sysbus_create_simple("scoop", 0x40800000, NULL);
+
+ collie_binfo.kernel_filename = kernel_filename;
+ collie_binfo.kernel_cmdline = kernel_cmdline;
+ collie_binfo.initrd_filename = initrd_filename;
+ collie_binfo.board_id = 0x208;
+ arm_load_kernel(s->env, &collie_binfo);
+}
+
+static QEMUMachine collie_machine = {
+ .name = "collie",
+ .desc = "Collie PDA (SA-1110)",
+ .init = collie_init,
+};
+
+static void collie_machine_init(void)
+{
+ qemu_register_machine(&collie_machine);
+}
+
+machine_init(collie_machine_init)
diff --git a/hw/cuda.c b/hw/cuda.c
index 37aa3f47f..065c362ae 100644
--- a/hw/cuda.c
+++ b/hw/cuda.c
@@ -644,80 +644,56 @@ static CPUReadMemoryFunc * const cuda_read[] = {
&cuda_readl,
};
-static void cuda_save_timer(QEMUFile *f, CUDATimer *s)
+static bool cuda_timer_exist(void *opaque, int version_id)
{
- qemu_put_be16s(f, &s->latch);
- qemu_put_be16s(f, &s->counter_value);
- qemu_put_sbe64s(f, &s->load_time);
- qemu_put_sbe64s(f, &s->next_irq_time);
- if (s->timer)
- qemu_put_timer(f, s->timer);
-}
-
-static void cuda_save(QEMUFile *f, void *opaque)
-{
- CUDAState *s = (CUDAState *)opaque;
-
- qemu_put_ubyte(f, s->b);
- qemu_put_ubyte(f, s->a);
- qemu_put_ubyte(f, s->dirb);
- qemu_put_ubyte(f, s->dira);
- qemu_put_ubyte(f, s->sr);
- qemu_put_ubyte(f, s->acr);
- qemu_put_ubyte(f, s->pcr);
- qemu_put_ubyte(f, s->ifr);
- qemu_put_ubyte(f, s->ier);
- qemu_put_ubyte(f, s->anh);
- qemu_put_sbe32s(f, &s->data_in_size);
- qemu_put_sbe32s(f, &s->data_in_index);
- qemu_put_sbe32s(f, &s->data_out_index);
- qemu_put_ubyte(f, s->autopoll);
- qemu_put_buffer(f, s->data_in, sizeof(s->data_in));
- qemu_put_buffer(f, s->data_out, sizeof(s->data_out));
- qemu_put_be32s(f, &s->tick_offset);
- cuda_save_timer(f, &s->timers[0]);
- cuda_save_timer(f, &s->timers[1]);
-}
+ CUDATimer *s = opaque;
-static void cuda_load_timer(QEMUFile *f, CUDATimer *s)
-{
- qemu_get_be16s(f, &s->latch);
- qemu_get_be16s(f, &s->counter_value);
- qemu_get_sbe64s(f, &s->load_time);
- qemu_get_sbe64s(f, &s->next_irq_time);
- if (s->timer)
- qemu_get_timer(f, s->timer);
+ return s->timer != NULL;
}
-static int cuda_load(QEMUFile *f, void *opaque, int version_id)
-{
- CUDAState *s = (CUDAState *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->b = qemu_get_ubyte(f);
- s->a = qemu_get_ubyte(f);
- s->dirb = qemu_get_ubyte(f);
- s->dira = qemu_get_ubyte(f);
- s->sr = qemu_get_ubyte(f);
- s->acr = qemu_get_ubyte(f);
- s->pcr = qemu_get_ubyte(f);
- s->ifr = qemu_get_ubyte(f);
- s->ier = qemu_get_ubyte(f);
- s->anh = qemu_get_ubyte(f);
- qemu_get_sbe32s(f, &s->data_in_size);
- qemu_get_sbe32s(f, &s->data_in_index);
- qemu_get_sbe32s(f, &s->data_out_index);
- s->autopoll = qemu_get_ubyte(f);
- qemu_get_buffer(f, s->data_in, sizeof(s->data_in));
- qemu_get_buffer(f, s->data_out, sizeof(s->data_out));
- qemu_get_be32s(f, &s->tick_offset);
- cuda_load_timer(f, &s->timers[0]);
- cuda_load_timer(f, &s->timers[1]);
+static const VMStateDescription vmstate_cuda_timer = {
+ .name = "cuda_timer",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT16(latch, CUDATimer),
+ VMSTATE_UINT16(counter_value, CUDATimer),
+ VMSTATE_INT64(load_time, CUDATimer),
+ VMSTATE_INT64(next_irq_time, CUDATimer),
+ VMSTATE_TIMER_TEST(timer, CUDATimer, cuda_timer_exist),
+ VMSTATE_END_OF_LIST()
+ }
+};
- return 0;
-}
+static const VMStateDescription vmstate_cuda = {
+ .name = "cuda",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(a, CUDAState),
+ VMSTATE_UINT8(b, CUDAState),
+ VMSTATE_UINT8(dira, CUDAState),
+ VMSTATE_UINT8(dirb, CUDAState),
+ VMSTATE_UINT8(sr, CUDAState),
+ VMSTATE_UINT8(acr, CUDAState),
+ VMSTATE_UINT8(pcr, CUDAState),
+ VMSTATE_UINT8(ifr, CUDAState),
+ VMSTATE_UINT8(ier, CUDAState),
+ VMSTATE_UINT8(anh, CUDAState),
+ VMSTATE_INT32(data_in_size, CUDAState),
+ VMSTATE_INT32(data_in_index, CUDAState),
+ VMSTATE_INT32(data_out_index, CUDAState),
+ VMSTATE_UINT8(autopoll, CUDAState),
+ VMSTATE_BUFFER(data_in, CUDAState),
+ VMSTATE_BUFFER(data_out, CUDAState),
+ VMSTATE_UINT32(tick_offset, CUDAState),
+ VMSTATE_STRUCT_ARRAY(timers, CUDAState, 2, 1,
+ vmstate_cuda_timer, CUDATimer),
+ VMSTATE_END_OF_LIST()
+ }
+};
static void cuda_reset(void *opaque)
{
@@ -764,6 +740,6 @@ void cuda_init (int *cuda_mem_index, qemu_irq irq)
s->adb_poll_timer = qemu_new_timer_ns(vm_clock, cuda_adb_poll, s);
*cuda_mem_index = cpu_register_io_memory(cuda_read, cuda_write, s,
DEVICE_NATIVE_ENDIAN);
- register_savevm(NULL, "cuda", -1, 1, cuda_save, cuda_load, s);
+ vmstate_register(NULL, -1, &vmstate_cuda, s);
qemu_register_reset(cuda_reset, s);
}
diff --git a/hw/flash.h b/hw/flash.h
index d7d103e66..c22e1a922 100644
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -21,8 +21,8 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
typedef struct NANDFlashState NANDFlashState;
NANDFlashState *nand_init(int manf_id, int chip_id);
void nand_done(NANDFlashState *s);
-void nand_setpins(NANDFlashState *s,
- int cle, int ale, int ce, int wp, int gnd);
+void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
+ uint8_t ce, uint8_t wp, uint8_t gnd);
void nand_getpins(NANDFlashState *s, int *rb);
void nand_setio(NANDFlashState *s, uint8_t value);
uint8_t nand_getio(NANDFlashState *s);
diff --git a/hw/heathrow_pic.c b/hw/heathrow_pic.c
index b19b754b3..5fd71a0f7 100644
--- a/hw/heathrow_pic.c
+++ b/hw/heathrow_pic.c
@@ -159,42 +159,31 @@ static void heathrow_pic_set_irq(void *opaque, int num, int level)
heathrow_pic_update(s);
}
-static void heathrow_pic_save_one(QEMUFile *f, HeathrowPIC *s)
-{
- qemu_put_be32s(f, &s->events);
- qemu_put_be32s(f, &s->mask);
- qemu_put_be32s(f, &s->levels);
- qemu_put_be32s(f, &s->level_triggered);
-}
-
-static void heathrow_pic_save(QEMUFile *f, void *opaque)
-{
- HeathrowPICS *s = (HeathrowPICS *)opaque;
-
- heathrow_pic_save_one(f, &s->pics[0]);
- heathrow_pic_save_one(f, &s->pics[1]);
-}
-
-static void heathrow_pic_load_one(QEMUFile *f, HeathrowPIC *s)
-{
- qemu_get_be32s(f, &s->events);
- qemu_get_be32s(f, &s->mask);
- qemu_get_be32s(f, &s->levels);
- qemu_get_be32s(f, &s->level_triggered);
-}
-
-static int heathrow_pic_load(QEMUFile *f, void *opaque, int version_id)
-{
- HeathrowPICS *s = (HeathrowPICS *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- heathrow_pic_load_one(f, &s->pics[0]);
- heathrow_pic_load_one(f, &s->pics[1]);
+static const VMStateDescription vmstate_heathrow_pic_one = {
+ .name = "heathrow_pic_one",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(events, HeathrowPIC),
+ VMSTATE_UINT32(mask, HeathrowPIC),
+ VMSTATE_UINT32(levels, HeathrowPIC),
+ VMSTATE_UINT32(level_triggered, HeathrowPIC),
+ VMSTATE_END_OF_LIST()
+ }
+};
- return 0;
-}
+static const VMStateDescription vmstate_heathrow_pic = {
+ .name = "heathrow_pic",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT_ARRAY(pics, HeathrowPICS, 2, 1,
+ vmstate_heathrow_pic_one, HeathrowPIC),
+ VMSTATE_END_OF_LIST()
+ }
+};
static void heathrow_pic_reset_one(HeathrowPIC *s)
{
@@ -223,8 +212,7 @@ qemu_irq *heathrow_pic_init(int *pmem_index,
*pmem_index = cpu_register_io_memory(pic_read, pic_write, s,
DEVICE_LITTLE_ENDIAN);
- register_savevm(NULL, "heathrow_pic", -1, 1, heathrow_pic_save,
- heathrow_pic_load, s);
+ vmstate_register(NULL, -1, &vmstate_heathrow_pic, s);
qemu_register_reset(heathrow_pic_reset, s);
return qemu_allocate_irqs(heathrow_pic_set_irq, s, 64);
}
diff --git a/hw/hw.h b/hw/hw.h
index 87b0328b9..2ca601d49 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -693,6 +693,17 @@ extern const VMStateDescription vmstate_usb_device;
.offset = vmstate_offset_macaddr(_state, _field), \
}
+extern const VMStateDescription vmstate_ptimer;
+
+#define VMSTATE_PTIMER(_field, _state) { \
+ .name = (stringify(_field)), \
+ .version_id = (1), \
+ .vmsd = &vmstate_ptimer, \
+ .size = sizeof(ptimer_state *), \
+ .flags = VMS_STRUCT|VMS_POINTER, \
+ .offset = vmstate_offset_pointer(_state, _field, ptimer_state), \
+}
+
/* _f : field name
_f_n : num of elements field_name
_n : num of elements
@@ -797,12 +808,6 @@ extern const VMStateDescription vmstate_usb_device;
#define VMSTATE_TIMER_ARRAY(_f, _s, _n) \
VMSTATE_ARRAY_OF_POINTER(_f, _s, _n, 0, vmstate_info_timer, QEMUTimer *)
-#define VMSTATE_PTIMER_V(_f, _s, _v) \
- VMSTATE_POINTER(_f, _s, _v, vmstate_info_ptimer, ptimer_state *)
-
-#define VMSTATE_PTIMER(_f, _s) \
- VMSTATE_PTIMER_V(_f, _s, 0)
-
#define VMSTATE_BOOL_ARRAY_V(_f, _s, _n, _v) \
VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_bool, bool)
diff --git a/hw/m48t59.c b/hw/m48t59.c
index 9f39d6bbf..537c0f7b1 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -585,28 +585,18 @@ static CPUReadMemoryFunc * const nvram_read[] = {
&nvram_readl,
};
-static void m48t59_save(QEMUFile *f, void *opaque)
-{
- M48t59State *s = opaque;
-
- qemu_put_8s(f, &s->lock);
- qemu_put_be16s(f, &s->addr);
- qemu_put_buffer(f, s->buffer, s->size);
-}
-
-static int m48t59_load(QEMUFile *f, void *opaque, int version_id)
-{
- M48t59State *s = opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_8s(f, &s->lock);
- qemu_get_be16s(f, &s->addr);
- qemu_get_buffer(f, s->buffer, s->size);
-
- return 0;
-}
+static const VMStateDescription vmstate_m48t59 = {
+ .name = "m48t59",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(lock, M48t59State),
+ VMSTATE_UINT16(addr, M48t59State),
+ VMSTATE_VBUFFER_UINT32(buffer, M48t59State, 0, NULL, 0, size),
+ VMSTATE_END_OF_LIST()
+ }
+};
static void m48t59_reset_common(M48t59State *NVRAM)
{
@@ -696,7 +686,7 @@ static void m48t59_init_common(M48t59State *s)
}
qemu_get_timedate(&s->alarm, 0);
- register_savevm(NULL, "m48t59", -1, 1, m48t59_save, m48t59_load, s);
+ vmstate_register(NULL, -1, &vmstate_m48t59, s);
}
static int m48t59_init_isa1(ISADevice *dev)
diff --git a/hw/mac_dbdma.c b/hw/mac_dbdma.c
index 5680fa9c1..ed4458e3b 100644
--- a/hw/mac_dbdma.c
+++ b/hw/mac_dbdma.c
@@ -165,6 +165,10 @@ typedef struct DBDMA_channel {
int processing;
} DBDMA_channel;
+typedef struct {
+ DBDMA_channel channels[DBDMA_CHANNELS];
+} DBDMAState;
+
#ifdef DEBUG_DBDMA
static void dump_dbdma_cmd(dbdma_cmd *cmd)
{
@@ -617,31 +621,34 @@ static void channel_run(DBDMA_channel *ch)
}
}
-static void DBDMA_run (DBDMA_channel *ch)
+static void DBDMA_run(DBDMAState *s)
{
int channel;
- for (channel = 0; channel < DBDMA_CHANNELS; channel++, ch++) {
- uint32_t status = ch->regs[DBDMA_STATUS];
- if (!ch->processing && (status & RUN) && (status & ACTIVE))
- channel_run(ch);
+ for (channel = 0; channel < DBDMA_CHANNELS; channel++) {
+ DBDMA_channel *ch = &s->channels[channel];
+ uint32_t status = ch->regs[DBDMA_STATUS];
+ if (!ch->processing && (status & RUN) && (status & ACTIVE)) {
+ channel_run(ch);
+ }
}
}
static void DBDMA_run_bh(void *opaque)
{
- DBDMA_channel *ch = opaque;
+ DBDMAState *s = opaque;
DBDMA_DPRINTF("DBDMA_run_bh\n");
- DBDMA_run(ch);
+ DBDMA_run(s);
}
void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
DBDMA_rw rw, DBDMA_flush flush,
void *opaque)
{
- DBDMA_channel *ch = ( DBDMA_channel *)dbdma + nchan;
+ DBDMAState *s = dbdma;
+ DBDMA_channel *ch = &s->channels[nchan];
DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan);
@@ -700,7 +707,8 @@ static void dbdma_writel (void *opaque,
target_phys_addr_t addr, uint32_t value)
{
int channel = addr >> DBDMA_CHANNEL_SHIFT;
- DBDMA_channel *ch = (DBDMA_channel *)opaque + channel;
+ DBDMAState *s = opaque;
+ DBDMA_channel *ch = &s->channels[channel];
int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08x\n", addr, value);
@@ -749,7 +757,8 @@ static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
{
uint32_t value;
int channel = addr >> DBDMA_CHANNEL_SHIFT;
- DBDMA_channel *ch = (DBDMA_channel *)opaque + channel;
+ DBDMAState *s = opaque;
+ DBDMA_channel *ch = &s->channels[channel];
int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
value = ch->regs[reg];
@@ -801,49 +810,47 @@ static CPUReadMemoryFunc * const dbdma_read[] = {
dbdma_readl,
};
-static void dbdma_save(QEMUFile *f, void *opaque)
-{
- DBDMA_channel *s = opaque;
- unsigned int i, j;
-
- for (i = 0; i < DBDMA_CHANNELS; i++)
- for (j = 0; j < DBDMA_REGS; j++)
- qemu_put_be32s(f, &s[i].regs[j]);
-}
-
-static int dbdma_load(QEMUFile *f, void *opaque, int version_id)
-{
- DBDMA_channel *s = opaque;
- unsigned int i, j;
-
- if (version_id != 2)
- return -EINVAL;
-
- for (i = 0; i < DBDMA_CHANNELS; i++)
- for (j = 0; j < DBDMA_REGS; j++)
- qemu_get_be32s(f, &s[i].regs[j]);
+static const VMStateDescription vmstate_dbdma_channel = {
+ .name = "dbdma_channel",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(regs, struct DBDMA_channel, DBDMA_REGS),
+ VMSTATE_END_OF_LIST()
+ }
+};
- return 0;
-}
+static const VMStateDescription vmstate_dbdma = {
+ .name = "dbdma",
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .minimum_version_id_old = 2,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT_ARRAY(channels, DBDMAState, DBDMA_CHANNELS, 1,
+ vmstate_dbdma_channel, DBDMA_channel),
+ VMSTATE_END_OF_LIST()
+ }
+};
static void dbdma_reset(void *opaque)
{
- DBDMA_channel *s = opaque;
+ DBDMAState *s = opaque;
int i;
for (i = 0; i < DBDMA_CHANNELS; i++)
- memset(s[i].regs, 0, DBDMA_SIZE);
+ memset(s->channels[i].regs, 0, DBDMA_SIZE);
}
void* DBDMA_init (int *dbdma_mem_index)
{
- DBDMA_channel *s;
+ DBDMAState *s;
- s = qemu_mallocz(sizeof(DBDMA_channel) * DBDMA_CHANNELS);
+ s = qemu_mallocz(sizeof(DBDMAState));
*dbdma_mem_index = cpu_register_io_memory(dbdma_read, dbdma_write, s,
DEVICE_LITTLE_ENDIAN);
- register_savevm(NULL, "dbdma", -1, 1, dbdma_save, dbdma_load, s);
+ vmstate_register(NULL, -1, &vmstate_dbdma, s);
qemu_register_reset(dbdma_reset, s);
dbdma_bh = qemu_bh_new(DBDMA_run_bh, s);
diff --git a/hw/mac_nvram.c b/hw/mac_nvram.c
index c2a2fc21e..61e53d28b 100644
--- a/hw/mac_nvram.c
+++ b/hw/mac_nvram.c
@@ -38,7 +38,7 @@
#endif
struct MacIONVRAMState {
- target_phys_addr_t size;
+ uint32_t size;
int mem_index;
unsigned int it_shift;
uint8_t *data;
@@ -105,24 +105,17 @@ static CPUReadMemoryFunc * const nvram_read[] = {
&macio_nvram_readb,
};
-static void macio_nvram_save(QEMUFile *f, void *opaque)
-{
- MacIONVRAMState *s = (MacIONVRAMState *)opaque;
-
- qemu_put_buffer(f, s->data, s->size);
-}
-
-static int macio_nvram_load(QEMUFile *f, void *opaque, int version_id)
-{
- MacIONVRAMState *s = (MacIONVRAMState *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- qemu_get_buffer(f, s->data, s->size);
+static const VMStateDescription vmstate_macio_nvram = {
+ .name = "macio_nvram",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_VBUFFER_UINT32(data, MacIONVRAMState, 0, NULL, 0, size),
+ VMSTATE_END_OF_LIST()
+ }
+};
- return 0;
-}
static void macio_nvram_reset(void *opaque)
{
@@ -141,8 +134,7 @@ MacIONVRAMState *macio_nvram_init (int *mem_index, target_phys_addr_t size,
s->mem_index = cpu_register_io_memory(nvram_read, nvram_write, s,
DEVICE_NATIVE_ENDIAN);
*mem_index = s->mem_index;
- register_savevm(NULL, "macio_nvram", -1, 1, macio_nvram_save,
- macio_nvram_load, s);
+ vmstate_register(NULL, -1, &vmstate_macio_nvram, s);
qemu_register_reset(macio_nvram_reset, s);
return s;
diff --git a/hw/max111x.c b/hw/max111x.c
index 2844665ba..70cd1af24 100644
--- a/hw/max111x.c
+++ b/hw/max111x.c
@@ -15,7 +15,7 @@ typedef struct {
uint8_t tb1, rb2, rb3;
int cycle;
- int input[8];
+ uint8_t input[8];
int inputs, com;
} MAX111xState;
@@ -94,36 +94,22 @@ static uint32_t max111x_transfer(SSISlave *dev, uint32_t value)
return max111x_read(s);
}
-static void max111x_save(QEMUFile *f, void *opaque)
-{
- MAX111xState *s = (MAX111xState *) opaque;
- int i;
-
- qemu_put_8s(f, &s->tb1);
- qemu_put_8s(f, &s->rb2);
- qemu_put_8s(f, &s->rb3);
- qemu_put_be32(f, s->inputs);
- qemu_put_be32(f, s->com);
- for (i = 0; i < s->inputs; i ++)
- qemu_put_byte(f, s->input[i]);
-}
-
-static int max111x_load(QEMUFile *f, void *opaque, int version_id)
-{
- MAX111xState *s = (MAX111xState *) opaque;
- int i;
-
- qemu_get_8s(f, &s->tb1);
- qemu_get_8s(f, &s->rb2);
- qemu_get_8s(f, &s->rb3);
- if (s->inputs != qemu_get_be32(f))
- return -EINVAL;
- s->com = qemu_get_be32(f);
- for (i = 0; i < s->inputs; i ++)
- s->input[i] = qemu_get_byte(f);
-
- return 0;
-}
+static const VMStateDescription vmstate_max111x = {
+ .name = "max111x",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(tb1, MAX111xState),
+ VMSTATE_UINT8(rb2, MAX111xState),
+ VMSTATE_UINT8(rb3, MAX111xState),
+ VMSTATE_INT32_EQUAL(inputs, MAX111xState),
+ VMSTATE_INT32(com, MAX111xState),
+ VMSTATE_ARRAY_INT32_UNSAFE(input, MAX111xState, inputs,
+ vmstate_info_uint8, uint8_t),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int max111x_init(SSISlave *dev, int inputs)
{
@@ -143,8 +129,7 @@ static int max111x_init(SSISlave *dev, int inputs)
s->input[7] = 0x80;
s->com = 0;
- register_savevm(&dev->qdev, "max111x", -1, 0,
- max111x_save, max111x_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_max111x, s);
return 0;
}
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index c5e54ffc3..26aad51ea 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -202,44 +202,29 @@ static void mipsnet_ioport_write(void *opaque, uint32_t addr, uint32_t val)
}
}
-static void mipsnet_save(QEMUFile *f, void *opaque)
-{
- MIPSnetState *s = opaque;
-
- qemu_put_be32s(f, &s->busy);
- qemu_put_be32s(f, &s->rx_count);
- qemu_put_be32s(f, &s->rx_read);
- qemu_put_be32s(f, &s->tx_count);
- qemu_put_be32s(f, &s->tx_written);
- qemu_put_be32s(f, &s->intctl);
- qemu_put_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE);
- qemu_put_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE);
-}
-
-static int mipsnet_load(QEMUFile *f, void *opaque, int version_id)
-{
- MIPSnetState *s = opaque;
-
- if (version_id > 0)
- return -EINVAL;
-
- qemu_get_be32s(f, &s->busy);
- qemu_get_be32s(f, &s->rx_count);
- qemu_get_be32s(f, &s->rx_read);
- qemu_get_be32s(f, &s->tx_count);
- qemu_get_be32s(f, &s->tx_written);
- qemu_get_be32s(f, &s->intctl);
- qemu_get_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE);
- qemu_get_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE);
-
- return 0;
-}
+static const VMStateDescription vmstate_mipsnet = {
+ .name = "mipsnet",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(busy, MIPSnetState),
+ VMSTATE_UINT32(rx_count, MIPSnetState),
+ VMSTATE_UINT32(rx_read, MIPSnetState),
+ VMSTATE_UINT32(tx_count, MIPSnetState),
+ VMSTATE_UINT32(tx_written, MIPSnetState),
+ VMSTATE_UINT32(intctl, MIPSnetState),
+ VMSTATE_BUFFER(rx_buffer, MIPSnetState),
+ VMSTATE_BUFFER(tx_buffer, MIPSnetState),
+ VMSTATE_END_OF_LIST()
+ }
+};
static void mipsnet_cleanup(VLANClientState *nc)
{
MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
- unregister_savevm(NULL, "mipsnet", s);
+ vmstate_unregister(NULL, &vmstate_mipsnet, s);
isa_unassign_ioport(s->io_base, 36);
@@ -284,5 +269,5 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
}
mipsnet_reset(s);
- register_savevm(NULL, "mipsnet", 0, 0, mipsnet_save, mipsnet_load, s);
+ vmstate_register(NULL, 0, &vmstate_mipsnet, s);
}
diff --git a/hw/nand.c b/hw/nand.c
index f414aa139..37e51d714 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -52,7 +52,7 @@ struct NANDFlashState {
BlockDriverState *bdrv;
int mem_oob;
- int cle, ale, ce, wp, gnd;
+ uint8_t cle, ale, ce, wp, gnd;
uint8_t io[MAX_PAGE + MAX_OOB + 0x400];
uint8_t *ioaddr;
@@ -66,6 +66,8 @@ struct NANDFlashState {
void (*blk_write)(NANDFlashState *s);
void (*blk_erase)(NANDFlashState *s);
void (*blk_load)(NANDFlashState *s, uint32_t addr, int offset);
+
+ uint32_t ioaddr_vmstate;
};
# define NAND_NO_AUTOINCR 0x00000001
@@ -281,56 +283,59 @@ static void nand_command(NANDFlashState *s)
}
}
-static void nand_save(QEMUFile *f, void *opaque)
+static void nand_pre_save(void *opaque)
{
- NANDFlashState *s = (NANDFlashState *) opaque;
- qemu_put_byte(f, s->cle);
- qemu_put_byte(f, s->ale);
- qemu_put_byte(f, s->ce);
- qemu_put_byte(f, s->wp);
- qemu_put_byte(f, s->gnd);
- qemu_put_buffer(f, s->io, sizeof(s->io));
- qemu_put_be32(f, s->ioaddr - s->io);
- qemu_put_be32(f, s->iolen);
-
- qemu_put_be32s(f, &s->cmd);
- qemu_put_be32s(f, &s->addr);
- qemu_put_be32(f, s->addrlen);
- qemu_put_be32(f, s->status);
- qemu_put_be32(f, s->offset);
- /* XXX: do we want to save s->storage too? */
+ NANDFlashState *s = opaque;
+
+ s->ioaddr_vmstate = s->ioaddr - s->io;
}
-static int nand_load(QEMUFile *f, void *opaque, int version_id)
+static int nand_post_load(void *opaque, int version_id)
{
- NANDFlashState *s = (NANDFlashState *) opaque;
- s->cle = qemu_get_byte(f);
- s->ale = qemu_get_byte(f);
- s->ce = qemu_get_byte(f);
- s->wp = qemu_get_byte(f);
- s->gnd = qemu_get_byte(f);
- qemu_get_buffer(f, s->io, sizeof(s->io));
- s->ioaddr = s->io + qemu_get_be32(f);
- s->iolen = qemu_get_be32(f);
- if (s->ioaddr >= s->io + sizeof(s->io) || s->ioaddr < s->io)
+ NANDFlashState *s = opaque;
+
+ if (s->ioaddr_vmstate > sizeof(s->io)) {
return -EINVAL;
+ }
+ s->ioaddr = s->io + s->ioaddr_vmstate;
- qemu_get_be32s(f, &s->cmd);
- qemu_get_be32s(f, &s->addr);
- s->addrlen = qemu_get_be32(f);
- s->status = qemu_get_be32(f);
- s->offset = qemu_get_be32(f);
return 0;
}
+static const VMStateDescription vmstate_nand = {
+ .name = "nand",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .pre_save = nand_pre_save,
+ .post_load = nand_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(cle, NANDFlashState),
+ VMSTATE_UINT8(ale, NANDFlashState),
+ VMSTATE_UINT8(ce, NANDFlashState),
+ VMSTATE_UINT8(wp, NANDFlashState),
+ VMSTATE_UINT8(gnd, NANDFlashState),
+ VMSTATE_BUFFER(io, NANDFlashState),
+ VMSTATE_UINT32(ioaddr_vmstate, NANDFlashState),
+ VMSTATE_INT32(iolen, NANDFlashState),
+ VMSTATE_UINT32(cmd, NANDFlashState),
+ VMSTATE_UINT32(addr, NANDFlashState),
+ VMSTATE_INT32(addrlen, NANDFlashState),
+ VMSTATE_INT32(status, NANDFlashState),
+ VMSTATE_INT32(offset, NANDFlashState),
+ /* XXX: do we want to save s->storage too? */
+ VMSTATE_END_OF_LIST()
+ }
+};
+
/*
* Chip inputs are CLE, ALE, CE, WP, GND and eight I/O pins. Chip
* outputs are R/B and eight I/O pins.
*
* CE, WP and R/B are active low.
*/
-void nand_setpins(NANDFlashState *s,
- int cle, int ale, int ce, int wp, int gnd)
+void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale,
+ uint8_t ce, uint8_t wp, uint8_t gnd)
{
s->cle = cle;
s->ale = ale;
@@ -502,7 +507,7 @@ NANDFlashState *nand_init(int manf_id, int chip_id)
is used. */
s->ioaddr = s->io;
- register_savevm(NULL, "nand", -1, 0, nand_save, nand_load, s);
+ vmstate_register(NULL, -1, &vmstate_nand, s);
return s;
}
diff --git a/hw/piix4.c b/hw/piix4.c
index 72073cd0a..71f1f84dc 100644
--- a/hw/piix4.c
+++ b/hw/piix4.c
@@ -30,10 +30,14 @@
PCIDevice *piix4_dev;
+typedef struct PIIX4State {
+ PCIDevice dev;
+} PIIX4State;
+
static void piix4_reset(void *opaque)
{
- PCIDevice *d = opaque;
- uint8_t *pci_conf = d->config;
+ PIIX4State *d = opaque;
+ uint8_t *pci_conf = d->dev.config;
pci_conf[0x04] = 0x07; // master, memory and I/O
pci_conf[0x05] = 0x00;
@@ -68,33 +72,30 @@ static void piix4_reset(void *opaque)
pci_conf[0xae] = 0x00;
}
-static void piix_save(QEMUFile* f, void *opaque)
-{
- PCIDevice *d = opaque;
- pci_device_save(d, f);
-}
-
-static int piix_load(QEMUFile* f, void *opaque, int version_id)
-{
- PCIDevice *d = opaque;
- if (version_id != 2)
- return -EINVAL;
- return pci_device_load(d, f);
-}
+static const VMStateDescription vmstate_piix4 = {
+ .name = "PIIX4",
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .minimum_version_id_old = 2,
+ .fields = (VMStateField[]) {
+ VMSTATE_PCI_DEVICE(dev, PIIX4State),
+ VMSTATE_END_OF_LIST()
+ }
+};
-static int piix4_initfn(PCIDevice *d)
+static int piix4_initfn(PCIDevice *dev)
{
+ PIIX4State *d = DO_UPCAST(PIIX4State, dev, dev);
uint8_t *pci_conf;
- isa_bus_new(&d->qdev);
- register_savevm(&d->qdev, "PIIX4", 0, 2, piix_save, piix_load, d);
+ isa_bus_new(&d->dev.qdev);
- pci_conf = d->config;
+ pci_conf = d->dev.config;
pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82371AB_0); // 82371AB/EB/MB PIIX4 PCI-to-ISA bridge
pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA);
- piix4_dev = d;
+ piix4_dev = &d->dev;
qemu_register_reset(piix4_reset, d);
return 0;
}
@@ -111,7 +112,8 @@ static PCIDeviceInfo piix4_info[] = {
{
.qdev.name = "PIIX4",
.qdev.desc = "ISA bridge",
- .qdev.size = sizeof(PCIDevice),
+ .qdev.size = sizeof(PIIX4State),
+ .qdev.vmsd = &vmstate_piix4,
.qdev.no_user = 1,
.no_hotplug = 1,
.init = piix4_initfn,
diff --git a/hw/pl011.c b/hw/pl011.c
index 77f0dbf13..3b94b14cb 100644
--- a/hw/pl011.c
+++ b/hw/pl011.c
@@ -235,56 +235,30 @@ static CPUWriteMemoryFunc * const pl011_writefn[] = {
pl011_write
};
-static void pl011_save(QEMUFile *f, void *opaque)
-{
- pl011_state *s = (pl011_state *)opaque;
- int i;
-
- qemu_put_be32(f, s->readbuff);
- qemu_put_be32(f, s->flags);
- qemu_put_be32(f, s->lcr);
- qemu_put_be32(f, s->cr);
- qemu_put_be32(f, s->dmacr);
- qemu_put_be32(f, s->int_enabled);
- qemu_put_be32(f, s->int_level);
- for (i = 0; i < 16; i++)
- qemu_put_be32(f, s->read_fifo[i]);
- qemu_put_be32(f, s->ilpr);
- qemu_put_be32(f, s->ibrd);
- qemu_put_be32(f, s->fbrd);
- qemu_put_be32(f, s->ifl);
- qemu_put_be32(f, s->read_pos);
- qemu_put_be32(f, s->read_count);
- qemu_put_be32(f, s->read_trigger);
-}
-
-static int pl011_load(QEMUFile *f, void *opaque, int version_id)
-{
- pl011_state *s = (pl011_state *)opaque;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->readbuff = qemu_get_be32(f);
- s->flags = qemu_get_be32(f);
- s->lcr = qemu_get_be32(f);
- s->cr = qemu_get_be32(f);
- s->dmacr = qemu_get_be32(f);
- s->int_enabled = qemu_get_be32(f);
- s->int_level = qemu_get_be32(f);
- for (i = 0; i < 16; i++)
- s->read_fifo[i] = qemu_get_be32(f);
- s->ilpr = qemu_get_be32(f);
- s->ibrd = qemu_get_be32(f);
- s->fbrd = qemu_get_be32(f);
- s->ifl = qemu_get_be32(f);
- s->read_pos = qemu_get_be32(f);
- s->read_count = qemu_get_be32(f);
- s->read_trigger = qemu_get_be32(f);
-
- return 0;
-}
+static const VMStateDescription vmstate_pl011 = {
+ .name = "pl011",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(readbuff, pl011_state),
+ VMSTATE_UINT32(flags, pl011_state),
+ VMSTATE_UINT32(lcr, pl011_state),
+ VMSTATE_UINT32(cr, pl011_state),
+ VMSTATE_UINT32(dmacr, pl011_state),
+ VMSTATE_UINT32(int_enabled, pl011_state),
+ VMSTATE_UINT32(int_level, pl011_state),
+ VMSTATE_UINT32_ARRAY(read_fifo, pl011_state, 16),
+ VMSTATE_UINT32(ilpr, pl011_state),
+ VMSTATE_UINT32(ibrd, pl011_state),
+ VMSTATE_UINT32(fbrd, pl011_state),
+ VMSTATE_UINT32(ifl, pl011_state),
+ VMSTATE_INT32(read_pos, pl011_state),
+ VMSTATE_INT32(read_count, pl011_state),
+ VMSTATE_INT32(read_trigger, pl011_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int pl011_init(SysBusDevice *dev, const unsigned char *id)
{
@@ -307,7 +281,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id)
qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
pl011_event, s);
}
- register_savevm(&dev->qdev, "pl011_uart", -1, 1, pl011_save, pl011_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_pl011, s);
return 0;
}
diff --git a/hw/pl022.c b/hw/pl022.c
index ffe05ab74..00e494a0d 100644
--- a/hw/pl022.c
+++ b/hw/pl022.c
@@ -239,54 +239,42 @@ static CPUWriteMemoryFunc * const pl022_writefn[] = {
pl022_write
};
-static void pl022_save(QEMUFile *f, void *opaque)
-{
- pl022_state *s = (pl022_state *)opaque;
- int i;
-
- qemu_put_be32(f, s->cr0);
- qemu_put_be32(f, s->cr1);
- qemu_put_be32(f, s->bitmask);
- qemu_put_be32(f, s->sr);
- qemu_put_be32(f, s->cpsr);
- qemu_put_be32(f, s->is);
- qemu_put_be32(f, s->im);
- qemu_put_be32(f, s->tx_fifo_head);
- qemu_put_be32(f, s->rx_fifo_head);
- qemu_put_be32(f, s->tx_fifo_len);
- qemu_put_be32(f, s->rx_fifo_len);
- for (i = 0; i < 8; i++) {
- qemu_put_be16(f, s->tx_fifo[i]);
- qemu_put_be16(f, s->rx_fifo[i]);
- }
-}
-
-static int pl022_load(QEMUFile *f, void *opaque, int version_id)
-{
- pl022_state *s = (pl022_state *)opaque;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->cr0 = qemu_get_be32(f);
- s->cr1 = qemu_get_be32(f);
- s->bitmask = qemu_get_be32(f);
- s->sr = qemu_get_be32(f);
- s->cpsr = qemu_get_be32(f);
- s->is = qemu_get_be32(f);
- s->im = qemu_get_be32(f);
- s->tx_fifo_head = qemu_get_be32(f);
- s->rx_fifo_head = qemu_get_be32(f);
- s->tx_fifo_len = qemu_get_be32(f);
- s->rx_fifo_len = qemu_get_be32(f);
- for (i = 0; i < 8; i++) {
- s->tx_fifo[i] = qemu_get_be16(f);
- s->rx_fifo[i] = qemu_get_be16(f);
+static const VMStateDescription vmstate_pl022 = {
+ .name = "pl022_ssp",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(cr0, pl022_state),
+ VMSTATE_UINT32(cr1, pl022_state),
+ VMSTATE_UINT32(bitmask, pl022_state),
+ VMSTATE_UINT32(sr, pl022_state),
+ VMSTATE_UINT32(cpsr, pl022_state),
+ VMSTATE_UINT32(is, pl022_state),
+ VMSTATE_UINT32(im, pl022_state),
+ VMSTATE_INT32(tx_fifo_head, pl022_state),
+ VMSTATE_INT32(rx_fifo_head, pl022_state),
+ VMSTATE_INT32(tx_fifo_len, pl022_state),
+ VMSTATE_INT32(rx_fifo_len, pl022_state),
+ VMSTATE_UINT16(tx_fifo[0], pl022_state),
+ VMSTATE_UINT16(rx_fifo[0], pl022_state),
+ VMSTATE_UINT16(tx_fifo[1], pl022_state),
+ VMSTATE_UINT16(rx_fifo[1], pl022_state),
+ VMSTATE_UINT16(tx_fifo[2], pl022_state),
+ VMSTATE_UINT16(rx_fifo[2], pl022_state),
+ VMSTATE_UINT16(tx_fifo[3], pl022_state),
+ VMSTATE_UINT16(rx_fifo[3], pl022_state),
+ VMSTATE_UINT16(tx_fifo[4], pl022_state),
+ VMSTATE_UINT16(rx_fifo[4], pl022_state),
+ VMSTATE_UINT16(tx_fifo[5], pl022_state),
+ VMSTATE_UINT16(rx_fifo[5], pl022_state),
+ VMSTATE_UINT16(tx_fifo[6], pl022_state),
+ VMSTATE_UINT16(rx_fifo[6], pl022_state),
+ VMSTATE_UINT16(tx_fifo[7], pl022_state),
+ VMSTATE_UINT16(rx_fifo[7], pl022_state),
+ VMSTATE_END_OF_LIST()
}
-
- return 0;
-}
+};
static int pl022_init(SysBusDevice *dev)
{
@@ -300,7 +288,7 @@ static int pl022_init(SysBusDevice *dev)
sysbus_init_irq(dev, &s->irq);
s->ssi = ssi_create_bus(&dev->qdev, "ssi");
pl022_reset(s);
- register_savevm(&dev->qdev, "pl022_ssp", -1, 1, pl022_save, pl022_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_pl022, s);
return 0;
}
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index f62f1f91d..299473c4b 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -285,50 +285,48 @@ static void ppc4xx_pci_set_irq(void *opaque, int irq_num, int level)
qemu_set_irq(pci_irqs[irq_num], level);
}
-static void ppc4xx_pci_save(QEMUFile *f, void *opaque)
-{
- PPC4xxPCIState *controller = opaque;
- int i;
-
- pci_device_save(controller->pci_dev, f);
-
- for (i = 0; i < PPC4xx_PCI_NR_PMMS; i++) {
- qemu_put_be32s(f, &controller->pmm[i].la);
- qemu_put_be32s(f, &controller->pmm[i].ma);
- qemu_put_be32s(f, &controller->pmm[i].pcila);
- qemu_put_be32s(f, &controller->pmm[i].pciha);
- }
-
- for (i = 0; i < PPC4xx_PCI_NR_PTMS; i++) {
- qemu_put_be32s(f, &controller->ptm[i].ms);
- qemu_put_be32s(f, &controller->ptm[i].la);
+static const VMStateDescription vmstate_pci_master_map = {
+ .name = "pci_master_map",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(la, struct PCIMasterMap),
+ VMSTATE_UINT32(ma, struct PCIMasterMap),
+ VMSTATE_UINT32(pcila, struct PCIMasterMap),
+ VMSTATE_UINT32(pciha, struct PCIMasterMap),
+ VMSTATE_END_OF_LIST()
}
-}
-
-static int ppc4xx_pci_load(QEMUFile *f, void *opaque, int version_id)
-{
- PPC4xxPCIState *controller = opaque;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- pci_device_load(controller->pci_dev, f);
+};
- for (i = 0; i < PPC4xx_PCI_NR_PMMS; i++) {
- qemu_get_be32s(f, &controller->pmm[i].la);
- qemu_get_be32s(f, &controller->pmm[i].ma);
- qemu_get_be32s(f, &controller->pmm[i].pcila);
- qemu_get_be32s(f, &controller->pmm[i].pciha);
+static const VMStateDescription vmstate_pci_target_map = {
+ .name = "pci_target_map",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(ms, struct PCITargetMap),
+ VMSTATE_UINT32(la, struct PCITargetMap),
+ VMSTATE_END_OF_LIST()
}
+};
- for (i = 0; i < PPC4xx_PCI_NR_PTMS; i++) {
- qemu_get_be32s(f, &controller->ptm[i].ms);
- qemu_get_be32s(f, &controller->ptm[i].la);
+static const VMStateDescription vmstate_ppc4xx_pci = {
+ .name = "ppc4xx_pci",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_PCI_DEVICE_POINTER(pci_dev, PPC4xxPCIState),
+ VMSTATE_STRUCT_ARRAY(pmm, PPC4xxPCIState, PPC4xx_PCI_NR_PMMS, 1,
+ vmstate_pci_master_map,
+ struct PCIMasterMap),
+ VMSTATE_STRUCT_ARRAY(ptm, PPC4xxPCIState, PPC4xx_PCI_NR_PTMS, 1,
+ vmstate_pci_target_map,
+ struct PCITargetMap),
+ VMSTATE_END_OF_LIST()
}
-
- return 0;
-}
+};
/* XXX Interrupt acknowledge cycles not supported. */
PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
@@ -381,8 +379,8 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
qemu_register_reset(ppc4xx_pci_reset, controller);
/* XXX load/save code not tested. */
- register_savevm(&controller->pci_dev->qdev, "ppc4xx_pci", ppc4xx_pci_id++,
- 1, ppc4xx_pci_save, ppc4xx_pci_load, controller);
+ vmstate_register(&controller->pci_dev->qdev, ppc4xx_pci_id++,
+ &vmstate_ppc4xx_pci, controller);
return controller->pci_state.bus;
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 2fc879236..83a20e462 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -216,56 +216,49 @@ static void mpc85xx_pci_set_irq(void *opaque, int irq_num, int level)
qemu_set_irq(pic[irq_num], level);
}
-static void ppce500_pci_save(QEMUFile *f, void *opaque)
-{
- PPCE500PCIState *controller = opaque;
- int i;
-
- pci_device_save(controller->pci_dev, f);
-
- for (i = 0; i < PPCE500_PCI_NR_POBS; i++) {
- qemu_put_be32s(f, &controller->pob[i].potar);
- qemu_put_be32s(f, &controller->pob[i].potear);
- qemu_put_be32s(f, &controller->pob[i].powbar);
- qemu_put_be32s(f, &controller->pob[i].powar);
- }
-
- for (i = 0; i < PPCE500_PCI_NR_PIBS; i++) {
- qemu_put_be32s(f, &controller->pib[i].pitar);
- qemu_put_be32s(f, &controller->pib[i].piwbar);
- qemu_put_be32s(f, &controller->pib[i].piwbear);
- qemu_put_be32s(f, &controller->pib[i].piwar);
+static const VMStateDescription vmstate_pci_outbound = {
+ .name = "pci_outbound",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(potar, struct pci_outbound),
+ VMSTATE_UINT32(potear, struct pci_outbound),
+ VMSTATE_UINT32(powbar, struct pci_outbound),
+ VMSTATE_UINT32(powar, struct pci_outbound),
+ VMSTATE_END_OF_LIST()
}
- qemu_put_be32s(f, &controller->gasket_time);
-}
-
-static int ppce500_pci_load(QEMUFile *f, void *opaque, int version_id)
-{
- PPCE500PCIState *controller = opaque;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- pci_device_load(controller->pci_dev, f);
+};
- for (i = 0; i < PPCE500_PCI_NR_POBS; i++) {
- qemu_get_be32s(f, &controller->pob[i].potar);
- qemu_get_be32s(f, &controller->pob[i].potear);
- qemu_get_be32s(f, &controller->pob[i].powbar);
- qemu_get_be32s(f, &controller->pob[i].powar);
+static const VMStateDescription vmstate_pci_inbound = {
+ .name = "pci_inbound",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(pitar, struct pci_inbound),
+ VMSTATE_UINT32(piwbar, struct pci_inbound),
+ VMSTATE_UINT32(piwbear, struct pci_inbound),
+ VMSTATE_UINT32(piwar, struct pci_inbound),
+ VMSTATE_END_OF_LIST()
}
+};
- for (i = 0; i < PPCE500_PCI_NR_PIBS; i++) {
- qemu_get_be32s(f, &controller->pib[i].pitar);
- qemu_get_be32s(f, &controller->pib[i].piwbar);
- qemu_get_be32s(f, &controller->pib[i].piwbear);
- qemu_get_be32s(f, &controller->pib[i].piwar);
+static const VMStateDescription vmstate_ppce500_pci = {
+ .name = "ppce500_pci",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_PCI_DEVICE_POINTER(pci_dev, PPCE500PCIState),
+ VMSTATE_STRUCT_ARRAY(pob, PPCE500PCIState, PPCE500_PCI_NR_POBS, 1,
+ vmstate_pci_outbound, struct pci_outbound),
+ VMSTATE_STRUCT_ARRAY(pib, PPCE500PCIState, PPCE500_PCI_NR_PIBS, 1,
+ vmstate_pci_outbound, struct pci_inbound),
+ VMSTATE_UINT32(gasket_time, PPCE500PCIState),
+ VMSTATE_END_OF_LIST()
}
- qemu_get_be32s(f, &controller->gasket_time);
-
- return 0;
-}
+};
PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
{
@@ -314,8 +307,8 @@ PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers)
PCIE500_REG_SIZE, index);
/* XXX load/save code not tested. */
- register_savevm(&d->qdev, "ppce500_pci", ppce500_pci_id++,
- 1, ppce500_pci_save, ppce500_pci_load, controller);
+ vmstate_register(&d->qdev, ppce500_pci_id++, &vmstate_ppce500_pci,
+ controller);
return controller->pci_state.bus;
diff --git a/hw/ptimer.c b/hw/ptimer.c
index e68c1d141..47964a67e 100644
--- a/hw/ptimer.c
+++ b/hw/ptimer.c
@@ -11,7 +11,7 @@
struct ptimer_state
{
- int enabled; /* 0 = disabled, 1 = periodic, 2 = oneshot. */
+ uint8_t enabled; /* 0 = disabled, 1 = periodic, 2 = oneshot. */
uint64_t limit;
uint64_t delta;
uint32_t period_frac;
@@ -188,49 +188,22 @@ void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
}
}
-void qemu_put_ptimer(QEMUFile *f, ptimer_state *s)
-{
- qemu_put_byte(f, s->enabled);
- qemu_put_be64s(f, &s->limit);
- qemu_put_be64s(f, &s->delta);
- qemu_put_be32s(f, &s->period_frac);
- qemu_put_sbe64s(f, &s->period);
- qemu_put_sbe64s(f, &s->last_event);
- qemu_put_sbe64s(f, &s->next_event);
- qemu_put_timer(f, s->timer);
-}
-
-void qemu_get_ptimer(QEMUFile *f, ptimer_state *s)
-{
- s->enabled = qemu_get_byte(f);
- qemu_get_be64s(f, &s->limit);
- qemu_get_be64s(f, &s->delta);
- qemu_get_be32s(f, &s->period_frac);
- qemu_get_sbe64s(f, &s->period);
- qemu_get_sbe64s(f, &s->last_event);
- qemu_get_sbe64s(f, &s->next_event);
- qemu_get_timer(f, s->timer);
-}
-
-static int get_ptimer(QEMUFile *f, void *pv, size_t size)
-{
- ptimer_state *v = pv;
-
- qemu_get_ptimer(f, v);
- return 0;
-}
-
-static void put_ptimer(QEMUFile *f, void *pv, size_t size)
-{
- ptimer_state *v = pv;
-
- qemu_put_ptimer(f, v);
-}
-
-const VMStateInfo vmstate_info_ptimer = {
+const VMStateDescription vmstate_ptimer = {
.name = "ptimer",
- .get = get_ptimer,
- .put = put_ptimer,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(enabled, ptimer_state),
+ VMSTATE_UINT64(limit, ptimer_state),
+ VMSTATE_UINT64(delta, ptimer_state),
+ VMSTATE_UINT32(period_frac, ptimer_state),
+ VMSTATE_INT64(period, ptimer_state),
+ VMSTATE_INT64(last_event, ptimer_state),
+ VMSTATE_INT64(next_event, ptimer_state),
+ VMSTATE_TIMER(timer, ptimer_state),
+ VMSTATE_END_OF_LIST()
+ }
};
ptimer_state *ptimer_init(QEMUBH *bh)
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 9b95e2c8e..ac5d95d71 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -146,25 +146,16 @@ static CPUWriteMemoryFunc * const pxa2xx_pm_writefn[] = {
pxa2xx_pm_write,
};
-static void pxa2xx_pm_save(QEMUFile *f, void *opaque)
-{
- PXA2xxState *s = (PXA2xxState *) opaque;
- int i;
-
- for (i = 0; i < 0x40; i ++)
- qemu_put_be32s(f, &s->pm_regs[i]);
-}
-
-static int pxa2xx_pm_load(QEMUFile *f, void *opaque, int version_id)
-{
- PXA2xxState *s = (PXA2xxState *) opaque;
- int i;
-
- for (i = 0; i < 0x40; i ++)
- qemu_get_be32s(f, &s->pm_regs[i]);
-
- return 0;
-}
+static const VMStateDescription vmstate_pxa2xx_pm = {
+ .name = "pxa2xx_pm",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(pm_regs, PXA2xxState, 0x40),
+ VMSTATE_END_OF_LIST()
+ }
+};
#define CCCR 0x00 /* Core Clock Configuration register */
#define CKEN 0x04 /* Clock Enable register */
@@ -227,29 +218,18 @@ static CPUWriteMemoryFunc * const pxa2xx_cm_writefn[] = {
pxa2xx_cm_write,
};
-static void pxa2xx_cm_save(QEMUFile *f, void *opaque)
-{
- PXA2xxState *s = (PXA2xxState *) opaque;
- int i;
-
- for (i = 0; i < 4; i ++)
- qemu_put_be32s(f, &s->cm_regs[i]);
- qemu_put_be32s(f, &s->clkcfg);
- qemu_put_be32s(f, &s->pmnc);
-}
-
-static int pxa2xx_cm_load(QEMUFile *f, void *opaque, int version_id)
-{
- PXA2xxState *s = (PXA2xxState *) opaque;
- int i;
-
- for (i = 0; i < 4; i ++)
- qemu_get_be32s(f, &s->cm_regs[i]);
- qemu_get_be32s(f, &s->clkcfg);
- qemu_get_be32s(f, &s->pmnc);
-
- return 0;
-}
+static const VMStateDescription vmstate_pxa2xx_cm = {
+ .name = "pxa2xx_cm",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(cm_regs, PXA2xxState, 4),
+ VMSTATE_UINT32(clkcfg, PXA2xxState),
+ VMSTATE_UINT32(pmnc, PXA2xxState),
+ VMSTATE_END_OF_LIST()
+ }
+};
static uint32_t pxa2xx_clkpwr_read(void *opaque, int op2, int reg, int crm)
{
@@ -527,25 +507,16 @@ static CPUWriteMemoryFunc * const pxa2xx_mm_writefn[] = {
pxa2xx_mm_write,
};
-static void pxa2xx_mm_save(QEMUFile *f, void *opaque)
-{
- PXA2xxState *s = (PXA2xxState *) opaque;
- int i;
-
- for (i = 0; i < 0x1a; i ++)
- qemu_put_be32s(f, &s->mm_regs[i]);
-}
-
-static int pxa2xx_mm_load(QEMUFile *f, void *opaque, int version_id)
-{
- PXA2xxState *s = (PXA2xxState *) opaque;
- int i;
-
- for (i = 0; i < 0x1a; i ++)
- qemu_get_be32s(f, &s->mm_regs[i]);
-
- return 0;
-}
+static const VMStateDescription vmstate_pxa2xx_mm = {
+ .name = "pxa2xx_mm",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(mm_regs, PXA2xxState, 0x1a),
+ VMSTATE_END_OF_LIST()
+ }
+};
/* Synchronous Serial Ports */
typedef struct {
@@ -1748,39 +1719,23 @@ static CPUWriteMemoryFunc * const pxa2xx_i2s_writefn[] = {
pxa2xx_i2s_write,
};
-static void pxa2xx_i2s_save(QEMUFile *f, void *opaque)
-{
- PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
-
- qemu_put_be32s(f, &s->control[0]);
- qemu_put_be32s(f, &s->control[1]);
- qemu_put_be32s(f, &s->status);
- qemu_put_be32s(f, &s->mask);
- qemu_put_be32s(f, &s->clk);
-
- qemu_put_be32(f, s->enable);
- qemu_put_be32(f, s->rx_len);
- qemu_put_be32(f, s->tx_len);
- qemu_put_be32(f, s->fifo_len);
-}
-
-static int pxa2xx_i2s_load(QEMUFile *f, void *opaque, int version_id)
-{
- PXA2xxI2SState *s = (PXA2xxI2SState *) opaque;
-
- qemu_get_be32s(f, &s->control[0]);
- qemu_get_be32s(f, &s->control[1]);
- qemu_get_be32s(f, &s->status);
- qemu_get_be32s(f, &s->mask);
- qemu_get_be32s(f, &s->clk);
-
- s->enable = qemu_get_be32(f);
- s->rx_len = qemu_get_be32(f);
- s->tx_len = qemu_get_be32(f);
- s->fifo_len = qemu_get_be32(f);
-
- return 0;
-}
+static const VMStateDescription vmstate_pxa2xx_i2s = {
+ .name = "pxa2xx_i2s",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(control, PXA2xxI2SState, 2),
+ VMSTATE_UINT32(status, PXA2xxI2SState),
+ VMSTATE_UINT32(mask, PXA2xxI2SState),
+ VMSTATE_UINT32(clk, PXA2xxI2SState),
+ VMSTATE_INT32(enable, PXA2xxI2SState),
+ VMSTATE_INT32(rx_len, PXA2xxI2SState),
+ VMSTATE_INT32(tx_len, PXA2xxI2SState),
+ VMSTATE_INT32(fifo_len, PXA2xxI2SState),
+ VMSTATE_END_OF_LIST()
+ }
+};
static void pxa2xx_i2s_data_req(void *opaque, int tx, int rx)
{
@@ -1822,8 +1777,7 @@ static PXA2xxI2SState *pxa2xx_i2s_init(target_phys_addr_t base,
pxa2xx_i2s_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(base, 0x100000, iomemtype);
- register_savevm(NULL, "pxa2xx_i2s", base, 0,
- pxa2xx_i2s_save, pxa2xx_i2s_load, s);
+ vmstate_register(NULL, base, &vmstate_pxa2xx_i2s, s);
return s;
}
@@ -2188,7 +2142,7 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn,
pxa2xx_cm_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype);
- register_savevm(NULL, "pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
+ vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
@@ -2199,13 +2153,13 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn,
pxa2xx_mm_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype);
- register_savevm(NULL, "pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
+ vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
s->pm_base = 0x40f00000;
iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
pxa2xx_pm_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(s->pm_base, 0x100, iomemtype);
- register_savevm(NULL, "pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
+ vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
for (i = 0; pxa27x_ssp[i].io_base; i ++);
s->ssp = (SSIBus **)qemu_mallocz(sizeof(SSIBus *) * i);
@@ -2324,7 +2278,7 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
iomemtype = cpu_register_io_memory(pxa2xx_cm_readfn,
pxa2xx_cm_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(s->cm_base, 0x1000, iomemtype);
- register_savevm(NULL, "pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
+ vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s);
cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
@@ -2335,13 +2289,13 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
iomemtype = cpu_register_io_memory(pxa2xx_mm_readfn,
pxa2xx_mm_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(s->mm_base, 0x1000, iomemtype);
- register_savevm(NULL, "pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
+ vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s);
s->pm_base = 0x40f00000;
iomemtype = cpu_register_io_memory(pxa2xx_pm_readfn,
pxa2xx_pm_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(s->pm_base, 0x100, iomemtype);
- register_savevm(NULL, "pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
+ vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s);
for (i = 0; pxa255_ssp[i].io_base; i ++);
s->ssp = (SSIBus **)qemu_mallocz(sizeof(SSIBus *) * i);
diff --git a/hw/pxa2xx_keypad.c b/hw/pxa2xx_keypad.c
index d77dbf179..10ef154aa 100644
--- a/hw/pxa2xx_keypad.c
+++ b/hw/pxa2xx_keypad.c
@@ -289,40 +289,22 @@ static CPUWriteMemoryFunc * const pxa2xx_keypad_writefn[] = {
pxa2xx_keypad_write
};
-static void pxa2xx_keypad_save(QEMUFile *f, void *opaque)
-{
- PXA2xxKeyPadState *s = (PXA2xxKeyPadState *) opaque;
-
- qemu_put_be32s(f, &s->kpc);
- qemu_put_be32s(f, &s->kpdk);
- qemu_put_be32s(f, &s->kprec);
- qemu_put_be32s(f, &s->kpmk);
- qemu_put_be32s(f, &s->kpas);
- qemu_put_be32s(f, &s->kpasmkp[0]);
- qemu_put_be32s(f, &s->kpasmkp[1]);
- qemu_put_be32s(f, &s->kpasmkp[2]);
- qemu_put_be32s(f, &s->kpasmkp[3]);
- qemu_put_be32s(f, &s->kpkdi);
-
-}
-
-static int pxa2xx_keypad_load(QEMUFile *f, void *opaque, int version_id)
-{
- PXA2xxKeyPadState *s = (PXA2xxKeyPadState *) opaque;
-
- qemu_get_be32s(f, &s->kpc);
- qemu_get_be32s(f, &s->kpdk);
- qemu_get_be32s(f, &s->kprec);
- qemu_get_be32s(f, &s->kpmk);
- qemu_get_be32s(f, &s->kpas);
- qemu_get_be32s(f, &s->kpasmkp[0]);
- qemu_get_be32s(f, &s->kpasmkp[1]);
- qemu_get_be32s(f, &s->kpasmkp[2]);
- qemu_get_be32s(f, &s->kpasmkp[3]);
- qemu_get_be32s(f, &s->kpkdi);
-
- return 0;
-}
+static const VMStateDescription vmstate_pxa2xx_keypad = {
+ .name = "pxa2xx_keypad",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(kpc, PXA2xxKeyPadState),
+ VMSTATE_UINT32(kpdk, PXA2xxKeyPadState),
+ VMSTATE_UINT32(kprec, PXA2xxKeyPadState),
+ VMSTATE_UINT32(kpmk, PXA2xxKeyPadState),
+ VMSTATE_UINT32(kpas, PXA2xxKeyPadState),
+ VMSTATE_UINT32_ARRAY(kpasmkp, PXA2xxKeyPadState, 4),
+ VMSTATE_UINT32(kpkdi, PXA2xxKeyPadState),
+ VMSTATE_END_OF_LIST()
+ }
+};
PXA2xxKeyPadState *pxa27x_keypad_init(target_phys_addr_t base,
qemu_irq irq)
@@ -337,8 +319,7 @@ PXA2xxKeyPadState *pxa27x_keypad_init(target_phys_addr_t base,
pxa2xx_keypad_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(base, 0x00100000, iomemtype);
- register_savevm(NULL, "pxa2xx_keypad", 0, 0,
- pxa2xx_keypad_save, pxa2xx_keypad_load, s);
+ vmstate_register(NULL, 0, &vmstate_pxa2xx_keypad, s);
return s;
}
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 5b2b07e02..e5248023f 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -15,6 +15,20 @@
#include "sysemu.h"
#include "framebuffer.h"
+struct DMAChannel {
+ target_phys_addr_t branch;
+ uint8_t up;
+ uint8_t palette[1024];
+ uint8_t pbuffer[1024];
+ void (*redraw)(PXA2xxLCDState *s, target_phys_addr_t addr,
+ int *miny, int *maxy);
+
+ target_phys_addr_t descriptor;
+ target_phys_addr_t source;
+ uint32_t id;
+ uint32_t command;
+};
+
struct PXA2xxLCDState {
qemu_irq irq;
int irqlevel;
@@ -50,19 +64,7 @@ struct PXA2xxLCDState {
uint32_t liidr;
uint8_t bscntr;
- struct {
- target_phys_addr_t branch;
- int up;
- uint8_t palette[1024];
- uint8_t pbuffer[1024];
- void (*redraw)(PXA2xxLCDState *s, target_phys_addr_t addr,
- int *miny, int *maxy);
-
- target_phys_addr_t descriptor;
- target_phys_addr_t source;
- uint32_t id;
- uint32_t command;
- } dma_ch[7];
+ struct DMAChannel dma_ch[7];
qemu_irq vsync_cb;
int orientation;
@@ -831,74 +833,26 @@ static void pxa2xx_lcdc_orientation(void *opaque, int angle)
pxa2xx_lcdc_resize(s);
}
-static void pxa2xx_lcdc_save(QEMUFile *f, void *opaque)
-{
- PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
- int i;
-
- qemu_put_be32(f, s->irqlevel);
- qemu_put_be32(f, s->transp);
-
- for (i = 0; i < 6; i ++)
- qemu_put_be32s(f, &s->control[i]);
- for (i = 0; i < 2; i ++)
- qemu_put_be32s(f, &s->status[i]);
- for (i = 0; i < 2; i ++)
- qemu_put_be32s(f, &s->ovl1c[i]);
- for (i = 0; i < 2; i ++)
- qemu_put_be32s(f, &s->ovl2c[i]);
- qemu_put_be32s(f, &s->ccr);
- qemu_put_be32s(f, &s->cmdcr);
- qemu_put_be32s(f, &s->trgbr);
- qemu_put_be32s(f, &s->tcr);
- qemu_put_be32s(f, &s->liidr);
- qemu_put_8s(f, &s->bscntr);
-
- for (i = 0; i < 7; i ++) {
- qemu_put_betl(f, s->dma_ch[i].branch);
- qemu_put_byte(f, s->dma_ch[i].up);
- qemu_put_buffer(f, s->dma_ch[i].pbuffer, sizeof(s->dma_ch[i].pbuffer));
-
- qemu_put_betl(f, s->dma_ch[i].descriptor);
- qemu_put_betl(f, s->dma_ch[i].source);
- qemu_put_be32s(f, &s->dma_ch[i].id);
- qemu_put_be32s(f, &s->dma_ch[i].command);
+static const VMStateDescription vmstate_dma_channel = {
+ .name = "dma_channel",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINTTL(branch, struct DMAChannel),
+ VMSTATE_UINT8(up, struct DMAChannel),
+ VMSTATE_BUFFER(pbuffer, struct DMAChannel),
+ VMSTATE_UINTTL(descriptor, struct DMAChannel),
+ VMSTATE_UINTTL(source, struct DMAChannel),
+ VMSTATE_UINT32(id, struct DMAChannel),
+ VMSTATE_UINT32(command, struct DMAChannel),
+ VMSTATE_END_OF_LIST()
}
-}
+};
-static int pxa2xx_lcdc_load(QEMUFile *f, void *opaque, int version_id)
+static int pxa2xx_lcdc_post_load(void *opaque, int version_id)
{
- PXA2xxLCDState *s = (PXA2xxLCDState *) opaque;
- int i;
-
- s->irqlevel = qemu_get_be32(f);
- s->transp = qemu_get_be32(f);
-
- for (i = 0; i < 6; i ++)
- qemu_get_be32s(f, &s->control[i]);
- for (i = 0; i < 2; i ++)
- qemu_get_be32s(f, &s->status[i]);
- for (i = 0; i < 2; i ++)
- qemu_get_be32s(f, &s->ovl1c[i]);
- for (i = 0; i < 2; i ++)
- qemu_get_be32s(f, &s->ovl2c[i]);
- qemu_get_be32s(f, &s->ccr);
- qemu_get_be32s(f, &s->cmdcr);
- qemu_get_be32s(f, &s->trgbr);
- qemu_get_be32s(f, &s->tcr);
- qemu_get_be32s(f, &s->liidr);
- qemu_get_8s(f, &s->bscntr);
-
- for (i = 0; i < 7; i ++) {
- s->dma_ch[i].branch = qemu_get_betl(f);
- s->dma_ch[i].up = qemu_get_byte(f);
- qemu_get_buffer(f, s->dma_ch[i].pbuffer, sizeof(s->dma_ch[i].pbuffer));
-
- s->dma_ch[i].descriptor = qemu_get_betl(f);
- s->dma_ch[i].source = qemu_get_betl(f);
- qemu_get_be32s(f, &s->dma_ch[i].id);
- qemu_get_be32s(f, &s->dma_ch[i].command);
- }
+ PXA2xxLCDState *s = opaque;
s->bpp = LCCR3_BPP(s->control[3]);
s->xres = s->yres = s->pal_for = -1;
@@ -906,6 +860,31 @@ static int pxa2xx_lcdc_load(QEMUFile *f, void *opaque, int version_id)
return 0;
}
+static const VMStateDescription vmstate_pxa2xx_lcdc = {
+ .name = "pxa2xx_lcdc",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .post_load = pxa2xx_lcdc_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32(irqlevel, PXA2xxLCDState),
+ VMSTATE_INT32(transp, PXA2xxLCDState),
+ VMSTATE_UINT32_ARRAY(control, PXA2xxLCDState, 6),
+ VMSTATE_UINT32_ARRAY(status, PXA2xxLCDState, 2),
+ VMSTATE_UINT32_ARRAY(ovl1c, PXA2xxLCDState, 2),
+ VMSTATE_UINT32_ARRAY(ovl2c, PXA2xxLCDState, 2),
+ VMSTATE_UINT32(ccr, PXA2xxLCDState),
+ VMSTATE_UINT32(cmdcr, PXA2xxLCDState),
+ VMSTATE_UINT32(trgbr, PXA2xxLCDState),
+ VMSTATE_UINT32(tcr, PXA2xxLCDState),
+ VMSTATE_UINT32(liidr, PXA2xxLCDState),
+ VMSTATE_UINT8(bscntr, PXA2xxLCDState),
+ VMSTATE_STRUCT_ARRAY(dma_ch, PXA2xxLCDState, 7, 0,
+ vmstate_dma_channel, struct DMAChannel),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
#define BITS 8
#include "pxa2xx_template.h"
#define BITS 15
@@ -970,8 +949,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq)
exit(1);
}
- register_savevm(NULL, "pxa2xx_lcdc", 0, 0,
- pxa2xx_lcdc_save, pxa2xx_lcdc_load, s);
+ vmstate_register(NULL, 0, &vmstate_pxa2xx_lcdc, s);
return s;
}
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 175e5cb3a..bb49e393e 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -43,6 +43,8 @@
do { } while (0)
#endif
+#define VIRTIO_EXT_CODE 0x2603
+
struct BusInfo s390_virtio_bus_info = {
.name = "s390-virtio",
.size = sizeof(VirtIOS390Bus),
@@ -305,9 +307,13 @@ static void virtio_s390_notify(void *opaque, uint16_t vector)
{
VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
uint64_t token = s390_virtio_device_vq_token(dev, vector);
+ CPUState *env = s390_cpu_addr2state(0);
- /* XXX kvm dependency! */
- kvm_s390_virtio_irq(s390_cpu_addr2state(0), 0, token);
+ if (kvm_enabled()) {
+ kvm_s390_virtio_irq(env, 0, token);
+ } else {
+ cpu_inject_ext(env, VIRTIO_EXT_CODE, 0, token);
+ }
}
static unsigned virtio_s390_get_features(void *opaque)
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 48fb0d05c..698ff6f34 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -82,13 +82,12 @@ CPUState *s390_cpu_addr2state(uint16_t cpu_addr)
return ipi_states[cpu_addr];
}
-int s390_virtio_hypercall(CPUState *env, uint64_t mem_, uint64_t hypercall)
+int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall)
{
int r = 0, i;
- target_ulong mem = env->regs[2];
- dprintf("KVM hypercall: %ld\n", env->regs[1]);
- switch (env->regs[1]) {
+ dprintf("KVM hypercall: %ld\n", hypercall);
+ switch (hypercall) {
case KVM_S390_VIRTIO_NOTIFY:
if (mem > ram_size) {
VirtIOS390Device *dev = s390_virtio_bus_find_vring(s390_bus,
@@ -128,8 +127,7 @@ int s390_virtio_hypercall(CPUState *env, uint64_t mem_, uint64_t hypercall)
break;
}
- env->regs[2] = r;
- return 0;
+ return r;
}
/* PC hardware initialisation */
@@ -145,14 +143,9 @@ static void s390_init(ram_addr_t ram_size,
ram_addr_t kernel_size = 0;
ram_addr_t initrd_offset;
ram_addr_t initrd_size = 0;
+ uint8_t *storage_keys;
int i;
- /* XXX we only work on KVM for now */
-
- if (!kvm_enabled()) {
- fprintf(stderr, "The S390 target only works with KVM enabled\n");
- exit(1);
- }
/* get a BUS */
s390_bus = s390_virtio_bus_init(&ram_size);
@@ -161,6 +154,9 @@ static void s390_init(ram_addr_t ram_size,
ram_addr = qemu_ram_alloc(NULL, "s390.ram", ram_size);
cpu_register_physical_memory(0, ram_size, ram_addr);
+ /* allocate storage keys */
+ storage_keys = qemu_mallocz(ram_size / TARGET_PAGE_SIZE);
+
/* init CPUs */
if (cpu_model == NULL) {
cpu_model = "host";
@@ -178,6 +174,7 @@ static void s390_init(ram_addr_t ram_size,
ipi_states[i] = tmp_env;
tmp_env->halted = 1;
tmp_env->exception_index = EXCP_HLT;
+ tmp_env->storage_keys = storage_keys;
}
env->halted = 0;
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 7932c2457..ac9fcc1f3 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -279,64 +279,28 @@ static CPUWriteMemoryFunc * const gptm_writefn[] = {
gptm_write
};
-static void gptm_save(QEMUFile *f, void *opaque)
-{
- gptm_state *s = (gptm_state *)opaque;
-
- qemu_put_be32(f, s->config);
- qemu_put_be32(f, s->mode[0]);
- qemu_put_be32(f, s->mode[1]);
- qemu_put_be32(f, s->control);
- qemu_put_be32(f, s->state);
- qemu_put_be32(f, s->mask);
- qemu_put_be32(f, s->mode[0]);
- qemu_put_be32(f, s->mode[0]);
- qemu_put_be32(f, s->load[0]);
- qemu_put_be32(f, s->load[1]);
- qemu_put_be32(f, s->match[0]);
- qemu_put_be32(f, s->match[1]);
- qemu_put_be32(f, s->prescale[0]);
- qemu_put_be32(f, s->prescale[1]);
- qemu_put_be32(f, s->match_prescale[0]);
- qemu_put_be32(f, s->match_prescale[1]);
- qemu_put_be32(f, s->rtc);
- qemu_put_be64(f, s->tick[0]);
- qemu_put_be64(f, s->tick[1]);
- qemu_put_timer(f, s->timer[0]);
- qemu_put_timer(f, s->timer[1]);
-}
-
-static int gptm_load(QEMUFile *f, void *opaque, int version_id)
-{
- gptm_state *s = (gptm_state *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->config = qemu_get_be32(f);
- s->mode[0] = qemu_get_be32(f);
- s->mode[1] = qemu_get_be32(f);
- s->control = qemu_get_be32(f);
- s->state = qemu_get_be32(f);
- s->mask = qemu_get_be32(f);
- s->mode[0] = qemu_get_be32(f);
- s->mode[0] = qemu_get_be32(f);
- s->load[0] = qemu_get_be32(f);
- s->load[1] = qemu_get_be32(f);
- s->match[0] = qemu_get_be32(f);
- s->match[1] = qemu_get_be32(f);
- s->prescale[0] = qemu_get_be32(f);
- s->prescale[1] = qemu_get_be32(f);
- s->match_prescale[0] = qemu_get_be32(f);
- s->match_prescale[1] = qemu_get_be32(f);
- s->rtc = qemu_get_be32(f);
- s->tick[0] = qemu_get_be64(f);
- s->tick[1] = qemu_get_be64(f);
- qemu_get_timer(f, s->timer[0]);
- qemu_get_timer(f, s->timer[1]);
-
- return 0;
-}
+static const VMStateDescription vmstate_stellaris_gptm = {
+ .name = "stellaris_gptm",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(config, gptm_state),
+ VMSTATE_UINT32_ARRAY(mode, gptm_state, 2),
+ VMSTATE_UINT32(control, gptm_state),
+ VMSTATE_UINT32(state, gptm_state),
+ VMSTATE_UINT32(mask, gptm_state),
+ VMSTATE_UNUSED(8),
+ VMSTATE_UINT32_ARRAY(load, gptm_state, 2),
+ VMSTATE_UINT32_ARRAY(match, gptm_state, 2),
+ VMSTATE_UINT32_ARRAY(prescale, gptm_state, 2),
+ VMSTATE_UINT32_ARRAY(match_prescale, gptm_state, 2),
+ VMSTATE_UINT32(rtc, gptm_state),
+ VMSTATE_INT64_ARRAY(tick, gptm_state, 2),
+ VMSTATE_TIMER_ARRAY(timer, gptm_state, 2),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int stellaris_gptm_init(SysBusDevice *dev)
{
@@ -354,8 +318,7 @@ static int stellaris_gptm_init(SysBusDevice *dev)
s->opaque[0] = s->opaque[1] = s;
s->timer[0] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[0]);
s->timer[1] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[1]);
- register_savevm(&dev->qdev, "stellaris_gptm", -1, 1,
- gptm_save, gptm_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_stellaris_gptm, s);
return 0;
}
@@ -604,58 +567,37 @@ static void ssys_reset(void *opaque)
s->dcgc[0] = 1;
}
-static void ssys_save(QEMUFile *f, void *opaque)
-{
- ssys_state *s = (ssys_state *)opaque;
-
- qemu_put_be32(f, s->pborctl);
- qemu_put_be32(f, s->ldopctl);
- qemu_put_be32(f, s->int_mask);
- qemu_put_be32(f, s->int_status);
- qemu_put_be32(f, s->resc);
- qemu_put_be32(f, s->rcc);
- qemu_put_be32(f, s->rcgc[0]);
- qemu_put_be32(f, s->rcgc[1]);
- qemu_put_be32(f, s->rcgc[2]);
- qemu_put_be32(f, s->scgc[0]);
- qemu_put_be32(f, s->scgc[1]);
- qemu_put_be32(f, s->scgc[2]);
- qemu_put_be32(f, s->dcgc[0]);
- qemu_put_be32(f, s->dcgc[1]);
- qemu_put_be32(f, s->dcgc[2]);
- qemu_put_be32(f, s->clkvclr);
- qemu_put_be32(f, s->ldoarst);
-}
-
-static int ssys_load(QEMUFile *f, void *opaque, int version_id)
+static int stellaris_sys_post_load(void *opaque, int version_id)
{
- ssys_state *s = (ssys_state *)opaque;
+ ssys_state *s = opaque;
- if (version_id != 1)
- return -EINVAL;
-
- s->pborctl = qemu_get_be32(f);
- s->ldopctl = qemu_get_be32(f);
- s->int_mask = qemu_get_be32(f);
- s->int_status = qemu_get_be32(f);
- s->resc = qemu_get_be32(f);
- s->rcc = qemu_get_be32(f);
- s->rcgc[0] = qemu_get_be32(f);
- s->rcgc[1] = qemu_get_be32(f);
- s->rcgc[2] = qemu_get_be32(f);
- s->scgc[0] = qemu_get_be32(f);
- s->scgc[1] = qemu_get_be32(f);
- s->scgc[2] = qemu_get_be32(f);
- s->dcgc[0] = qemu_get_be32(f);
- s->dcgc[1] = qemu_get_be32(f);
- s->dcgc[2] = qemu_get_be32(f);
- s->clkvclr = qemu_get_be32(f);
- s->ldoarst = qemu_get_be32(f);
ssys_calculate_system_clock(s);
return 0;
}
+static const VMStateDescription vmstate_stellaris_sys = {
+ .name = "stellaris_sys",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .post_load = stellaris_sys_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(pborctl, ssys_state),
+ VMSTATE_UINT32(ldopctl, ssys_state),
+ VMSTATE_UINT32(int_mask, ssys_state),
+ VMSTATE_UINT32(int_status, ssys_state),
+ VMSTATE_UINT32(resc, ssys_state),
+ VMSTATE_UINT32(rcc, ssys_state),
+ VMSTATE_UINT32_ARRAY(rcgc, ssys_state, 3),
+ VMSTATE_UINT32_ARRAY(scgc, ssys_state, 3),
+ VMSTATE_UINT32_ARRAY(dcgc, ssys_state, 3),
+ VMSTATE_UINT32(clkvclr, ssys_state),
+ VMSTATE_UINT32(ldoarst, ssys_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static int stellaris_sys_init(uint32_t base, qemu_irq irq,
stellaris_board_info * board,
uint8_t *macaddr)
@@ -675,7 +617,7 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq,
DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(base, 0x00001000, iomemtype);
ssys_reset(s);
- register_savevm(NULL, "stellaris_sys", -1, 1, ssys_save, ssys_load, s);
+ vmstate_register(NULL, -1, &vmstate_stellaris_sys, s);
return 0;
}
@@ -843,36 +785,22 @@ static CPUWriteMemoryFunc * const stellaris_i2c_writefn[] = {
stellaris_i2c_write
};
-static void stellaris_i2c_save(QEMUFile *f, void *opaque)
-{
- stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
-
- qemu_put_be32(f, s->msa);
- qemu_put_be32(f, s->mcs);
- qemu_put_be32(f, s->mdr);
- qemu_put_be32(f, s->mtpr);
- qemu_put_be32(f, s->mimr);
- qemu_put_be32(f, s->mris);
- qemu_put_be32(f, s->mcr);
-}
-
-static int stellaris_i2c_load(QEMUFile *f, void *opaque, int version_id)
-{
- stellaris_i2c_state *s = (stellaris_i2c_state *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->msa = qemu_get_be32(f);
- s->mcs = qemu_get_be32(f);
- s->mdr = qemu_get_be32(f);
- s->mtpr = qemu_get_be32(f);
- s->mimr = qemu_get_be32(f);
- s->mris = qemu_get_be32(f);
- s->mcr = qemu_get_be32(f);
-
- return 0;
-}
+static const VMStateDescription vmstate_stellaris_i2c = {
+ .name = "stellaris_i2c",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(msa, stellaris_i2c_state),
+ VMSTATE_UINT32(mcs, stellaris_i2c_state),
+ VMSTATE_UINT32(mdr, stellaris_i2c_state),
+ VMSTATE_UINT32(mtpr, stellaris_i2c_state),
+ VMSTATE_UINT32(mimr, stellaris_i2c_state),
+ VMSTATE_UINT32(mris, stellaris_i2c_state),
+ VMSTATE_UINT32(mcr, stellaris_i2c_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int stellaris_i2c_init(SysBusDevice * dev)
{
@@ -890,8 +818,7 @@ static int stellaris_i2c_init(SysBusDevice * dev)
sysbus_init_mmio(dev, 0x1000, iomemtype);
/* ??? For now we only implement the master interface. */
stellaris_i2c_reset(s);
- register_savevm(&dev->qdev, "stellaris_i2c", -1, 1,
- stellaris_i2c_save, stellaris_i2c_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_stellaris_i2c, s);
return 0;
}
@@ -1129,60 +1056,40 @@ static CPUWriteMemoryFunc * const stellaris_adc_writefn[] = {
stellaris_adc_write
};
-static void stellaris_adc_save(QEMUFile *f, void *opaque)
-{
- stellaris_adc_state *s = (stellaris_adc_state *)opaque;
- int i;
- int j;
-
- qemu_put_be32(f, s->actss);
- qemu_put_be32(f, s->ris);
- qemu_put_be32(f, s->im);
- qemu_put_be32(f, s->emux);
- qemu_put_be32(f, s->ostat);
- qemu_put_be32(f, s->ustat);
- qemu_put_be32(f, s->sspri);
- qemu_put_be32(f, s->sac);
- for (i = 0; i < 4; i++) {
- qemu_put_be32(f, s->fifo[i].state);
- for (j = 0; j < 16; j++) {
- qemu_put_be32(f, s->fifo[i].data[j]);
- }
- qemu_put_be32(f, s->ssmux[i]);
- qemu_put_be32(f, s->ssctl[i]);
- }
- qemu_put_be32(f, s->noise);
-}
-
-static int stellaris_adc_load(QEMUFile *f, void *opaque, int version_id)
-{
- stellaris_adc_state *s = (stellaris_adc_state *)opaque;
- int i;
- int j;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->actss = qemu_get_be32(f);
- s->ris = qemu_get_be32(f);
- s->im = qemu_get_be32(f);
- s->emux = qemu_get_be32(f);
- s->ostat = qemu_get_be32(f);
- s->ustat = qemu_get_be32(f);
- s->sspri = qemu_get_be32(f);
- s->sac = qemu_get_be32(f);
- for (i = 0; i < 4; i++) {
- s->fifo[i].state = qemu_get_be32(f);
- for (j = 0; j < 16; j++) {
- s->fifo[i].data[j] = qemu_get_be32(f);
- }
- s->ssmux[i] = qemu_get_be32(f);
- s->ssctl[i] = qemu_get_be32(f);
+static const VMStateDescription vmstate_stellaris_adc = {
+ .name = "stellaris_adc",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(actss, stellaris_adc_state),
+ VMSTATE_UINT32(ris, stellaris_adc_state),
+ VMSTATE_UINT32(im, stellaris_adc_state),
+ VMSTATE_UINT32(emux, stellaris_adc_state),
+ VMSTATE_UINT32(ostat, stellaris_adc_state),
+ VMSTATE_UINT32(ustat, stellaris_adc_state),
+ VMSTATE_UINT32(sspri, stellaris_adc_state),
+ VMSTATE_UINT32(sac, stellaris_adc_state),
+ VMSTATE_UINT32(fifo[0].state, stellaris_adc_state),
+ VMSTATE_UINT32_ARRAY(fifo[0].data, stellaris_adc_state, 16),
+ VMSTATE_UINT32(ssmux[0], stellaris_adc_state),
+ VMSTATE_UINT32(ssctl[0], stellaris_adc_state),
+ VMSTATE_UINT32(fifo[1].state, stellaris_adc_state),
+ VMSTATE_UINT32_ARRAY(fifo[1].data, stellaris_adc_state, 16),
+ VMSTATE_UINT32(ssmux[1], stellaris_adc_state),
+ VMSTATE_UINT32(ssctl[1], stellaris_adc_state),
+ VMSTATE_UINT32(fifo[2].state, stellaris_adc_state),
+ VMSTATE_UINT32_ARRAY(fifo[2].data, stellaris_adc_state, 16),
+ VMSTATE_UINT32(ssmux[2], stellaris_adc_state),
+ VMSTATE_UINT32(ssctl[2], stellaris_adc_state),
+ VMSTATE_UINT32(fifo[3].state, stellaris_adc_state),
+ VMSTATE_UINT32_ARRAY(fifo[3].data, stellaris_adc_state, 16),
+ VMSTATE_UINT32(ssmux[3], stellaris_adc_state),
+ VMSTATE_UINT32(ssctl[3], stellaris_adc_state),
+ VMSTATE_UINT32(noise, stellaris_adc_state),
+ VMSTATE_END_OF_LIST()
}
- s->noise = qemu_get_be32(f);
-
- return 0;
-}
+};
static int stellaris_adc_init(SysBusDevice *dev)
{
@@ -1200,8 +1107,7 @@ static int stellaris_adc_init(SysBusDevice *dev)
sysbus_init_mmio(dev, 0x1000, iomemtype);
stellaris_adc_reset(s);
qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1);
- register_savevm(&dev->qdev, "stellaris_adc", -1, 1,
- stellaris_adc_save, stellaris_adc_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_stellaris_adc, s);
return 0;
}
@@ -1233,24 +1139,16 @@ static uint32_t stellaris_ssi_bus_transfer(SSISlave *dev, uint32_t val)
return ssi_transfer(s->bus[s->current_dev], val);
}
-static void stellaris_ssi_bus_save(QEMUFile *f, void *opaque)
-{
- stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
-
- qemu_put_be32(f, s->current_dev);
-}
-
-static int stellaris_ssi_bus_load(QEMUFile *f, void *opaque, int version_id)
-{
- stellaris_ssi_bus_state *s = (stellaris_ssi_bus_state *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->current_dev = qemu_get_be32(f);
-
- return 0;
-}
+static const VMStateDescription vmstate_stellaris_ssi_bus = {
+ .name = "stellaris_ssi_bus",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32(current_dev, stellaris_ssi_bus_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int stellaris_ssi_bus_init(SSISlave *dev)
{
@@ -1260,8 +1158,7 @@ static int stellaris_ssi_bus_init(SSISlave *dev)
s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1");
qdev_init_gpio_in(&dev->qdev, stellaris_ssi_bus_select, 1);
- register_savevm(&dev->qdev, "stellaris_ssi_bus", -1, 1,
- stellaris_ssi_bus_save, stellaris_ssi_bus_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_stellaris_ssi_bus, s);
return 0;
}
diff --git a/hw/stellaris_input.c b/hw/stellaris_input.c
index 16aae96f2..06c5f9d95 100644
--- a/hw/stellaris_input.c
+++ b/hw/stellaris_input.c
@@ -13,7 +13,7 @@
typedef struct {
qemu_irq irq;
int keycode;
- int pressed;
+ uint8_t pressed;
} gamepad_button;
typedef struct {
@@ -47,30 +47,29 @@ static void stellaris_gamepad_put_key(void * opaque, int keycode)
s->extension = 0;
}
-static void stellaris_gamepad_save(QEMUFile *f, void *opaque)
-{
- gamepad_state *s = (gamepad_state *)opaque;
- int i;
-
- qemu_put_be32(f, s->extension);
- for (i = 0; i < s->num_buttons; i++)
- qemu_put_byte(f, s->buttons[i].pressed);
-}
-
-static int stellaris_gamepad_load(QEMUFile *f, void *opaque, int version_id)
-{
- gamepad_state *s = (gamepad_state *)opaque;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->extension = qemu_get_be32(f);
- for (i = 0; i < s->num_buttons; i++)
- s->buttons[i].pressed = qemu_get_byte(f);
+static const VMStateDescription vmstate_stellaris_button = {
+ .name = "stellaris_button",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(pressed, gamepad_button),
+ VMSTATE_END_OF_LIST()
+ }
+};
- return 0;
-}
+static const VMStateDescription vmstate_stellaris_gamepad = {
+ .name = "stellaris_gamepad",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32(extension, gamepad_state),
+ VMSTATE_STRUCT_VARRAY_INT32(buttons, gamepad_state, num_buttons, 0,
+ vmstate_stellaris_button, gamepad_button),
+ VMSTATE_END_OF_LIST()
+ }
+};
/* Returns an array 5 ouput slots. */
void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode)
@@ -86,6 +85,5 @@ void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode)
}
s->num_buttons = n;
qemu_add_kbd_event_handler(stellaris_gamepad_put_key, s);
- register_savevm(NULL, "stellaris_gamepad", -1, 1,
- stellaris_gamepad_save, stellaris_gamepad_load, s);
+ vmstate_register(NULL, -1, &vmstate_stellaris_gamepad, s);
}
diff --git a/hw/strongarm.c b/hw/strongarm.c
new file mode 100644
index 000000000..de08bdf67
--- /dev/null
+++ b/hw/strongarm.c
@@ -0,0 +1,1598 @@
+/*
+ * StrongARM SA-1100/SA-1110 emulation
+ *
+ * Copyright (C) 2011 Dmitry Eremin-Solenikov
+ *
+ * Largely based on StrongARM emulation:
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Written by Andrzej Zaborowski <balrog@zabor.org>
+ *
+ * UART code based on QEMU 16550A UART emulation
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2008 Citrix Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "sysbus.h"
+#include "strongarm.h"
+#include "qemu-error.h"
+#include "arm-misc.h"
+#include "sysemu.h"
+#include "ssi.h"
+
+//#define DEBUG
+
+/*
+ TODO
+ - Implement cp15, c14 ?
+ - Implement cp15, c15 !!! (idle used in L)
+ - Implement idle mode handling/DIM
+ - Implement sleep mode/Wake sources
+ - Implement reset control
+ - Implement memory control regs
+ - PCMCIA handling
+ - Maybe support MBGNT/MBREQ
+ - DMA channels
+ - GPCLK
+ - IrDA
+ - MCP
+ - Enhance UART with modem signals
+ */
+
+#ifdef DEBUG
+# define DPRINTF(format, ...) printf(format , ## __VA_ARGS__)
+#else
+# define DPRINTF(format, ...) do { } while (0)
+#endif
+
+static struct {
+ target_phys_addr_t io_base;
+ int irq;
+} sa_serial[] = {
+ { 0x80010000, SA_PIC_UART1 },
+ { 0x80030000, SA_PIC_UART2 },
+ { 0x80050000, SA_PIC_UART3 },
+ { 0, 0 }
+};
+
+/* Interrupt Controller */
+typedef struct {
+ SysBusDevice busdev;
+ qemu_irq irq;
+ qemu_irq fiq;
+
+ uint32_t pending;
+ uint32_t enabled;
+ uint32_t is_fiq;
+ uint32_t int_idle;
+} StrongARMPICState;
+
+#define ICIP 0x00
+#define ICMR 0x04
+#define ICLR 0x08
+#define ICFP 0x10
+#define ICPR 0x20
+#define ICCR 0x0c
+
+#define SA_PIC_SRCS 32
+
+
+static void strongarm_pic_update(void *opaque)
+{
+ StrongARMPICState *s = opaque;
+
+ /* FIXME: reflect DIM */
+ qemu_set_irq(s->fiq, s->pending & s->enabled & s->is_fiq);
+ qemu_set_irq(s->irq, s->pending & s->enabled & ~s->is_fiq);
+}
+
+static void strongarm_pic_set_irq(void *opaque, int irq, int level)
+{
+ StrongARMPICState *s = opaque;
+
+ if (level) {
+ s->pending |= 1 << irq;
+ } else {
+ s->pending &= ~(1 << irq);
+ }
+
+ strongarm_pic_update(s);
+}
+
+static uint32_t strongarm_pic_mem_read(void *opaque, target_phys_addr_t offset)
+{
+ StrongARMPICState *s = opaque;
+
+ switch (offset) {
+ case ICIP:
+ return s->pending & ~s->is_fiq & s->enabled;
+ case ICMR:
+ return s->enabled;
+ case ICLR:
+ return s->is_fiq;
+ case ICCR:
+ return s->int_idle == 0;
+ case ICFP:
+ return s->pending & s->is_fiq & s->enabled;
+ case ICPR:
+ return s->pending;
+ default:
+ printf("%s: Bad register offset 0x" TARGET_FMT_plx "\n",
+ __func__, offset);
+ return 0;
+ }
+}
+
+static void strongarm_pic_mem_write(void *opaque, target_phys_addr_t offset,
+ uint32_t value)
+{
+ StrongARMPICState *s = opaque;
+
+ switch (offset) {
+ case ICMR:
+ s->enabled = value;
+ break;
+ case ICLR:
+ s->is_fiq = value;
+ break;
+ case ICCR:
+ s->int_idle = (value & 1) ? 0 : ~0;
+ break;
+ default:
+ printf("%s: Bad register offset 0x" TARGET_FMT_plx "\n",
+ __func__, offset);
+ break;
+ }
+ strongarm_pic_update(s);
+}
+
+static CPUReadMemoryFunc * const strongarm_pic_readfn[] = {
+ strongarm_pic_mem_read,
+ strongarm_pic_mem_read,
+ strongarm_pic_mem_read,
+};
+
+static CPUWriteMemoryFunc * const strongarm_pic_writefn[] = {
+ strongarm_pic_mem_write,
+ strongarm_pic_mem_write,
+ strongarm_pic_mem_write,
+};
+
+static int strongarm_pic_initfn(SysBusDevice *dev)
+{
+ StrongARMPICState *s = FROM_SYSBUS(StrongARMPICState, dev);
+ int iomemtype;
+
+ qdev_init_gpio_in(&dev->qdev, strongarm_pic_set_irq, SA_PIC_SRCS);
+ iomemtype = cpu_register_io_memory(strongarm_pic_readfn,
+ strongarm_pic_writefn, s, DEVICE_NATIVE_ENDIAN);
+ sysbus_init_mmio(dev, 0x1000, iomemtype);
+ sysbus_init_irq(dev, &s->irq);
+ sysbus_init_irq(dev, &s->fiq);
+
+ return 0;
+}
+
+static int strongarm_pic_post_load(void *opaque, int version_id)
+{
+ strongarm_pic_update(opaque);
+ return 0;
+}
+
+static VMStateDescription vmstate_strongarm_pic_regs = {
+ .name = "strongarm_pic",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .post_load = strongarm_pic_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(pending, StrongARMPICState),
+ VMSTATE_UINT32(enabled, StrongARMPICState),
+ VMSTATE_UINT32(is_fiq, StrongARMPICState),
+ VMSTATE_UINT32(int_idle, StrongARMPICState),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static SysBusDeviceInfo strongarm_pic_info = {
+ .init = strongarm_pic_initfn,
+ .qdev.name = "strongarm_pic",
+ .qdev.desc = "StrongARM PIC",
+ .qdev.size = sizeof(StrongARMPICState),
+ .qdev.vmsd = &vmstate_strongarm_pic_regs,
+};
+
+/* Real-Time Clock */
+#define RTAR 0x00 /* RTC Alarm register */
+#define RCNR 0x04 /* RTC Counter register */
+#define RTTR 0x08 /* RTC Timer Trim register */
+#define RTSR 0x10 /* RTC Status register */
+
+#define RTSR_AL (1 << 0) /* RTC Alarm detected */
+#define RTSR_HZ (1 << 1) /* RTC 1Hz detected */
+#define RTSR_ALE (1 << 2) /* RTC Alarm enable */
+#define RTSR_HZE (1 << 3) /* RTC 1Hz enable */
+
+/* 16 LSB of RTTR are clockdiv for internal trim logic,
+ * trim delete isn't emulated, so
+ * f = 32 768 / (RTTR_trim + 1) */
+
+typedef struct {
+ SysBusDevice busdev;
+ uint32_t rttr;
+ uint32_t rtsr;
+ uint32_t rtar;
+ uint32_t last_rcnr;
+ int64_t last_hz;
+ QEMUTimer *rtc_alarm;
+ QEMUTimer *rtc_hz;
+ qemu_irq rtc_irq;
+ qemu_irq rtc_hz_irq;
+} StrongARMRTCState;
+
+static inline void strongarm_rtc_int_update(StrongARMRTCState *s)
+{
+ qemu_set_irq(s->rtc_irq, s->rtsr & RTSR_AL);
+ qemu_set_irq(s->rtc_hz_irq, s->rtsr & RTSR_HZ);
+}
+
+static void strongarm_rtc_hzupdate(StrongARMRTCState *s)
+{
+ int64_t rt = qemu_get_clock_ms(rt_clock);
+ s->last_rcnr += ((rt - s->last_hz) << 15) /
+ (1000 * ((s->rttr & 0xffff) + 1));
+ s->last_hz = rt;
+}
+
+static inline void strongarm_rtc_timer_update(StrongARMRTCState *s)
+{
+ if ((s->rtsr & RTSR_HZE) && !(s->rtsr & RTSR_HZ)) {
+ qemu_mod_timer(s->rtc_hz, s->last_hz + 1000);
+ } else {
+ qemu_del_timer(s->rtc_hz);
+ }
+
+ if ((s->rtsr & RTSR_ALE) && !(s->rtsr & RTSR_AL)) {
+ qemu_mod_timer(s->rtc_alarm, s->last_hz +
+ (((s->rtar - s->last_rcnr) * 1000 *
+ ((s->rttr & 0xffff) + 1)) >> 15));
+ } else {
+ qemu_del_timer(s->rtc_alarm);
+ }
+}
+
+static inline void strongarm_rtc_alarm_tick(void *opaque)
+{
+ StrongARMRTCState *s = opaque;
+ s->rtsr |= RTSR_AL;
+ strongarm_rtc_timer_update(s);
+ strongarm_rtc_int_update(s);
+}
+
+static inline void strongarm_rtc_hz_tick(void *opaque)
+{
+ StrongARMRTCState *s = opaque;
+ s->rtsr |= RTSR_HZ;
+ strongarm_rtc_timer_update(s);
+ strongarm_rtc_int_update(s);
+}
+
+static uint32_t strongarm_rtc_read(void *opaque, target_phys_addr_t addr)
+{
+ StrongARMRTCState *s = opaque;
+
+ switch (addr) {
+ case RTTR:
+ return s->rttr;
+ case RTSR:
+ return s->rtsr;
+ case RTAR:
+ return s->rtar;
+ case RCNR:
+ return s->last_rcnr +
+ ((qemu_get_clock_ms(rt_clock) - s->last_hz) << 15) /
+ (1000 * ((s->rttr & 0xffff) + 1));
+ default:
+ printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+ return 0;
+ }
+}
+
+static void strongarm_rtc_write(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ StrongARMRTCState *s = opaque;
+ uint32_t old_rtsr;
+
+ switch (addr) {
+ case RTTR:
+ strongarm_rtc_hzupdate(s);
+ s->rttr = value;
+ strongarm_rtc_timer_update(s);
+ break;
+
+ case RTSR:
+ old_rtsr = s->rtsr;
+ s->rtsr = (value & (RTSR_ALE | RTSR_HZE)) |
+ (s->rtsr & ~(value & (RTSR_AL | RTSR_HZ)));
+
+ if (s->rtsr != old_rtsr) {
+ strongarm_rtc_timer_update(s);
+ }
+
+ strongarm_rtc_int_update(s);
+ break;
+
+ case RTAR:
+ s->rtar = value;
+ strongarm_rtc_timer_update(s);
+ break;
+
+ case RCNR:
+ strongarm_rtc_hzupdate(s);
+ s->last_rcnr = value;
+ strongarm_rtc_timer_update(s);
+ break;
+
+ default:
+ printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+ }
+}
+
+static CPUReadMemoryFunc * const strongarm_rtc_readfn[] = {
+ strongarm_rtc_read,
+ strongarm_rtc_read,
+ strongarm_rtc_read,
+};
+
+static CPUWriteMemoryFunc * const strongarm_rtc_writefn[] = {
+ strongarm_rtc_write,
+ strongarm_rtc_write,
+ strongarm_rtc_write,
+};
+
+static int strongarm_rtc_init(SysBusDevice *dev)
+{
+ StrongARMRTCState *s = FROM_SYSBUS(StrongARMRTCState, dev);
+ struct tm tm;
+ int iomemtype;
+
+ s->rttr = 0x0;
+ s->rtsr = 0;
+
+ qemu_get_timedate(&tm, 0);
+
+ s->last_rcnr = (uint32_t) mktimegm(&tm);
+ s->last_hz = qemu_get_clock_ms(rt_clock);
+
+ s->rtc_alarm = qemu_new_timer_ms(rt_clock, strongarm_rtc_alarm_tick, s);
+ s->rtc_hz = qemu_new_timer_ms(rt_clock, strongarm_rtc_hz_tick, s);
+
+ sysbus_init_irq(dev, &s->rtc_irq);
+ sysbus_init_irq(dev, &s->rtc_hz_irq);
+
+ iomemtype = cpu_register_io_memory(strongarm_rtc_readfn,
+ strongarm_rtc_writefn, s, DEVICE_NATIVE_ENDIAN);
+ sysbus_init_mmio(dev, 0x10000, iomemtype);
+
+ return 0;
+}
+
+static void strongarm_rtc_pre_save(void *opaque)
+{
+ StrongARMRTCState *s = opaque;
+
+ strongarm_rtc_hzupdate(s);
+}
+
+static int strongarm_rtc_post_load(void *opaque, int version_id)
+{
+ StrongARMRTCState *s = opaque;
+
+ strongarm_rtc_timer_update(s);
+ strongarm_rtc_int_update(s);
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_strongarm_rtc_regs = {
+ .name = "strongarm-rtc",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .pre_save = strongarm_rtc_pre_save,
+ .post_load = strongarm_rtc_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(rttr, StrongARMRTCState),
+ VMSTATE_UINT32(rtsr, StrongARMRTCState),
+ VMSTATE_UINT32(rtar, StrongARMRTCState),
+ VMSTATE_UINT32(last_rcnr, StrongARMRTCState),
+ VMSTATE_INT64(last_hz, StrongARMRTCState),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static SysBusDeviceInfo strongarm_rtc_sysbus_info = {
+ .init = strongarm_rtc_init,
+ .qdev.name = "strongarm-rtc",
+ .qdev.desc = "StrongARM RTC Controller",
+ .qdev.size = sizeof(StrongARMRTCState),
+ .qdev.vmsd = &vmstate_strongarm_rtc_regs,
+};
+
+/* GPIO */
+#define GPLR 0x00
+#define GPDR 0x04
+#define GPSR 0x08
+#define GPCR 0x0c
+#define GRER 0x10
+#define GFER 0x14
+#define GEDR 0x18
+#define GAFR 0x1c
+
+typedef struct StrongARMGPIOInfo StrongARMGPIOInfo;
+struct StrongARMGPIOInfo {
+ SysBusDevice busdev;
+ qemu_irq handler[28];
+ qemu_irq irqs[11];
+ qemu_irq irqX;
+
+ uint32_t ilevel;
+ uint32_t olevel;
+ uint32_t dir;
+ uint32_t rising;
+ uint32_t falling;
+ uint32_t status;
+ uint32_t gpsr;
+ uint32_t gafr;
+
+ uint32_t prev_level;
+};
+
+
+static void strongarm_gpio_irq_update(StrongARMGPIOInfo *s)
+{
+ int i;
+ for (i = 0; i < 11; i++) {
+ qemu_set_irq(s->irqs[i], s->status & (1 << i));
+ }
+
+ qemu_set_irq(s->irqX, (s->status & ~0x7ff));
+}
+
+static void strongarm_gpio_set(void *opaque, int line, int level)
+{
+ StrongARMGPIOInfo *s = opaque;
+ uint32_t mask;
+
+ mask = 1 << line;
+
+ if (level) {
+ s->status |= s->rising & mask &
+ ~s->ilevel & ~s->dir;
+ s->ilevel |= mask;
+ } else {
+ s->status |= s->falling & mask &
+ s->ilevel & ~s->dir;
+ s->ilevel &= ~mask;
+ }
+
+ if (s->status & mask) {
+ strongarm_gpio_irq_update(s);
+ }
+}
+
+static void strongarm_gpio_handler_update(StrongARMGPIOInfo *s)
+{
+ uint32_t level, diff;
+ int bit;
+
+ level = s->olevel & s->dir;
+
+ for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
+ bit = ffs(diff) - 1;
+ qemu_set_irq(s->handler[bit], (level >> bit) & 1);
+ }
+
+ s->prev_level = level;
+}
+
+static uint32_t strongarm_gpio_read(void *opaque, target_phys_addr_t offset)
+{
+ StrongARMGPIOInfo *s = opaque;
+
+ switch (offset) {
+ case GPDR: /* GPIO Pin-Direction registers */
+ return s->dir;
+
+ case GPSR: /* GPIO Pin-Output Set registers */
+ DPRINTF("%s: Read from a write-only register 0x" TARGET_FMT_plx "\n",
+ __func__, offset);
+ return s->gpsr; /* Return last written value. */
+
+ case GPCR: /* GPIO Pin-Output Clear registers */
+ DPRINTF("%s: Read from a write-only register 0x" TARGET_FMT_plx "\n",
+ __func__, offset);
+ return 31337; /* Specified as unpredictable in the docs. */
+
+ case GRER: /* GPIO Rising-Edge Detect Enable registers */
+ return s->rising;
+
+ case GFER: /* GPIO Falling-Edge Detect Enable registers */
+ return s->falling;
+
+ case GAFR: /* GPIO Alternate Function registers */
+ return s->gafr;
+
+ case GPLR: /* GPIO Pin-Level registers */
+ return (s->olevel & s->dir) |
+ (s->ilevel & ~s->dir);
+
+ case GEDR: /* GPIO Edge Detect Status registers */
+ return s->status;
+
+ default:
+ printf("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset);
+ }
+
+ return 0;
+}
+
+static void strongarm_gpio_write(void *opaque,
+ target_phys_addr_t offset, uint32_t value)
+{
+ StrongARMGPIOInfo *s = opaque;
+
+ switch (offset) {
+ case GPDR: /* GPIO Pin-Direction registers */
+ s->dir = value;
+ strongarm_gpio_handler_update(s);
+ break;
+
+ case GPSR: /* GPIO Pin-Output Set registers */
+ s->olevel |= value;
+ strongarm_gpio_handler_update(s);
+ s->gpsr = value;
+ break;
+
+ case GPCR: /* GPIO Pin-Output Clear registers */
+ s->olevel &= ~value;
+ strongarm_gpio_handler_update(s);
+ break;
+
+ case GRER: /* GPIO Rising-Edge Detect Enable registers */
+ s->rising = value;
+ break;
+
+ case GFER: /* GPIO Falling-Edge Detect Enable registers */
+ s->falling = value;
+ break;
+
+ case GAFR: /* GPIO Alternate Function registers */
+ s->gafr = value;
+ break;
+
+ case GEDR: /* GPIO Edge Detect Status registers */
+ s->status &= ~value;
+ strongarm_gpio_irq_update(s);
+ break;
+
+ default:
+ printf("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset);
+ }
+}
+
+static CPUReadMemoryFunc * const strongarm_gpio_readfn[] = {
+ strongarm_gpio_read,
+ strongarm_gpio_read,
+ strongarm_gpio_read
+};
+
+static CPUWriteMemoryFunc * const strongarm_gpio_writefn[] = {
+ strongarm_gpio_write,
+ strongarm_gpio_write,
+ strongarm_gpio_write
+};
+
+static DeviceState *strongarm_gpio_init(target_phys_addr_t base,
+ DeviceState *pic)
+{
+ DeviceState *dev;
+ int i;
+
+ dev = qdev_create(NULL, "strongarm-gpio");
+ qdev_init_nofail(dev);
+
+ sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+ for (i = 0; i < 12; i++)
+ sysbus_connect_irq(sysbus_from_qdev(dev), i,
+ qdev_get_gpio_in(pic, SA_PIC_GPIO0_EDGE + i));
+
+ return dev;
+}
+
+static int strongarm_gpio_initfn(SysBusDevice *dev)
+{
+ int iomemtype;
+ StrongARMGPIOInfo *s;
+ int i;
+
+ s = FROM_SYSBUS(StrongARMGPIOInfo, dev);
+
+ qdev_init_gpio_in(&dev->qdev, strongarm_gpio_set, 28);
+ qdev_init_gpio_out(&dev->qdev, s->handler, 28);
+
+ iomemtype = cpu_register_io_memory(strongarm_gpio_readfn,
+ strongarm_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
+
+ sysbus_init_mmio(dev, 0x1000, iomemtype);
+ for (i = 0; i < 11; i++) {
+ sysbus_init_irq(dev, &s->irqs[i]);
+ }
+ sysbus_init_irq(dev, &s->irqX);
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_strongarm_gpio_regs = {
+ .name = "strongarm-gpio",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(ilevel, StrongARMGPIOInfo),
+ VMSTATE_UINT32(olevel, StrongARMGPIOInfo),
+ VMSTATE_UINT32(dir, StrongARMGPIOInfo),
+ VMSTATE_UINT32(rising, StrongARMGPIOInfo),
+ VMSTATE_UINT32(falling, StrongARMGPIOInfo),
+ VMSTATE_UINT32(status, StrongARMGPIOInfo),
+ VMSTATE_UINT32(gafr, StrongARMGPIOInfo),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static SysBusDeviceInfo strongarm_gpio_info = {
+ .init = strongarm_gpio_initfn,
+ .qdev.name = "strongarm-gpio",
+ .qdev.desc = "StrongARM GPIO controller",
+ .qdev.size = sizeof(StrongARMGPIOInfo),
+};
+
+/* Peripheral Pin Controller */
+#define PPDR 0x00
+#define PPSR 0x04
+#define PPAR 0x08
+#define PSDR 0x0c
+#define PPFR 0x10
+
+typedef struct StrongARMPPCInfo StrongARMPPCInfo;
+struct StrongARMPPCInfo {
+ SysBusDevice busdev;
+ qemu_irq handler[28];
+
+ uint32_t ilevel;
+ uint32_t olevel;
+ uint32_t dir;
+ uint32_t ppar;
+ uint32_t psdr;
+ uint32_t ppfr;
+
+ uint32_t prev_level;
+};
+
+static void strongarm_ppc_set(void *opaque, int line, int level)
+{
+ StrongARMPPCInfo *s = opaque;
+
+ if (level) {
+ s->ilevel |= 1 << line;
+ } else {
+ s->ilevel &= ~(1 << line);
+ }
+}
+
+static void strongarm_ppc_handler_update(StrongARMPPCInfo *s)
+{
+ uint32_t level, diff;
+ int bit;
+
+ level = s->olevel & s->dir;
+
+ for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
+ bit = ffs(diff) - 1;
+ qemu_set_irq(s->handler[bit], (level >> bit) & 1);
+ }
+
+ s->prev_level = level;
+}
+
+static uint32_t strongarm_ppc_read(void *opaque, target_phys_addr_t offset)
+{
+ StrongARMPPCInfo *s = opaque;
+
+ switch (offset) {
+ case PPDR: /* PPC Pin Direction registers */
+ return s->dir | ~0x3fffff;
+
+ case PPSR: /* PPC Pin State registers */
+ return (s->olevel & s->dir) |
+ (s->ilevel & ~s->dir) |
+ ~0x3fffff;
+
+ case PPAR:
+ return s->ppar | ~0x41000;
+
+ case PSDR:
+ return s->psdr;
+
+ case PPFR:
+ return s->ppfr | ~0x7f001;
+
+ default:
+ printf("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset);
+ }
+
+ return 0;
+}
+
+static void strongarm_ppc_write(void *opaque,
+ target_phys_addr_t offset, uint32_t value)
+{
+ StrongARMPPCInfo *s = opaque;
+
+ switch (offset) {
+ case PPDR: /* PPC Pin Direction registers */
+ s->dir = value & 0x3fffff;
+ strongarm_ppc_handler_update(s);
+ break;
+
+ case PPSR: /* PPC Pin State registers */
+ s->olevel = value & s->dir & 0x3fffff;
+ strongarm_ppc_handler_update(s);
+ break;
+
+ case PPAR:
+ s->ppar = value & 0x41000;
+ break;
+
+ case PSDR:
+ s->psdr = value & 0x3fffff;
+ break;
+
+ case PPFR:
+ s->ppfr = value & 0x7f001;
+ break;
+
+ default:
+ printf("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset);
+ }
+}
+
+static CPUReadMemoryFunc * const strongarm_ppc_readfn[] = {
+ strongarm_ppc_read,
+ strongarm_ppc_read,
+ strongarm_ppc_read
+};
+
+static CPUWriteMemoryFunc * const strongarm_ppc_writefn[] = {
+ strongarm_ppc_write,
+ strongarm_ppc_write,
+ strongarm_ppc_write
+};
+
+static int strongarm_ppc_init(SysBusDevice *dev)
+{
+ int iomemtype;
+ StrongARMPPCInfo *s;
+
+ s = FROM_SYSBUS(StrongARMPPCInfo, dev);
+
+ qdev_init_gpio_in(&dev->qdev, strongarm_ppc_set, 22);
+ qdev_init_gpio_out(&dev->qdev, s->handler, 22);
+
+ iomemtype = cpu_register_io_memory(strongarm_ppc_readfn,
+ strongarm_ppc_writefn, s, DEVICE_NATIVE_ENDIAN);
+
+ sysbus_init_mmio(dev, 0x1000, iomemtype);
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_strongarm_ppc_regs = {
+ .name = "strongarm-ppc",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(ilevel, StrongARMPPCInfo),
+ VMSTATE_UINT32(olevel, StrongARMPPCInfo),
+ VMSTATE_UINT32(dir, StrongARMPPCInfo),
+ VMSTATE_UINT32(ppar, StrongARMPPCInfo),
+ VMSTATE_UINT32(psdr, StrongARMPPCInfo),
+ VMSTATE_UINT32(ppfr, StrongARMPPCInfo),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static SysBusDeviceInfo strongarm_ppc_info = {
+ .init = strongarm_ppc_init,
+ .qdev.name = "strongarm-ppc",
+ .qdev.desc = "StrongARM PPC controller",
+ .qdev.size = sizeof(StrongARMPPCInfo),
+};
+
+/* UART Ports */
+#define UTCR0 0x00
+#define UTCR1 0x04
+#define UTCR2 0x08
+#define UTCR3 0x0c
+#define UTDR 0x14
+#define UTSR0 0x1c
+#define UTSR1 0x20
+
+#define UTCR0_PE (1 << 0) /* Parity enable */
+#define UTCR0_OES (1 << 1) /* Even parity */
+#define UTCR0_SBS (1 << 2) /* 2 stop bits */
+#define UTCR0_DSS (1 << 3) /* 8-bit data */
+
+#define UTCR3_RXE (1 << 0) /* Rx enable */
+#define UTCR3_TXE (1 << 1) /* Tx enable */
+#define UTCR3_BRK (1 << 2) /* Force Break */
+#define UTCR3_RIE (1 << 3) /* Rx int enable */
+#define UTCR3_TIE (1 << 4) /* Tx int enable */
+#define UTCR3_LBM (1 << 5) /* Loopback */
+
+#define UTSR0_TFS (1 << 0) /* Tx FIFO nearly empty */
+#define UTSR0_RFS (1 << 1) /* Rx FIFO nearly full */
+#define UTSR0_RID (1 << 2) /* Receiver Idle */
+#define UTSR0_RBB (1 << 3) /* Receiver begin break */
+#define UTSR0_REB (1 << 4) /* Receiver end break */
+#define UTSR0_EIF (1 << 5) /* Error in FIFO */
+
+#define UTSR1_RNE (1 << 1) /* Receive FIFO not empty */
+#define UTSR1_TNF (1 << 2) /* Transmit FIFO not full */
+#define UTSR1_PRE (1 << 3) /* Parity error */
+#define UTSR1_FRE (1 << 4) /* Frame error */
+#define UTSR1_ROR (1 << 5) /* Receive Over Run */
+
+#define RX_FIFO_PRE (1 << 8)
+#define RX_FIFO_FRE (1 << 9)
+#define RX_FIFO_ROR (1 << 10)
+
+typedef struct {
+ SysBusDevice busdev;
+ CharDriverState *chr;
+ qemu_irq irq;
+
+ uint8_t utcr0;
+ uint16_t brd;
+ uint8_t utcr3;
+ uint8_t utsr0;
+ uint8_t utsr1;
+
+ uint8_t tx_fifo[8];
+ uint8_t tx_start;
+ uint8_t tx_len;
+ uint16_t rx_fifo[12]; /* value + error flags in high bits */
+ uint8_t rx_start;
+ uint8_t rx_len;
+
+ uint64_t char_transmit_time; /* time to transmit a char in ticks*/
+ bool wait_break_end;
+ QEMUTimer *rx_timeout_timer;
+ QEMUTimer *tx_timer;
+} StrongARMUARTState;
+
+static void strongarm_uart_update_status(StrongARMUARTState *s)
+{
+ uint16_t utsr1 = 0;
+
+ if (s->tx_len != 8) {
+ utsr1 |= UTSR1_TNF;
+ }
+
+ if (s->rx_len != 0) {
+ uint16_t ent = s->rx_fifo[s->rx_start];
+
+ utsr1 |= UTSR1_RNE;
+ if (ent & RX_FIFO_PRE) {
+ s->utsr1 |= UTSR1_PRE;
+ }
+ if (ent & RX_FIFO_FRE) {
+ s->utsr1 |= UTSR1_FRE;
+ }
+ if (ent & RX_FIFO_ROR) {
+ s->utsr1 |= UTSR1_ROR;
+ }
+ }
+
+ s->utsr1 = utsr1;
+}
+
+static void strongarm_uart_update_int_status(StrongARMUARTState *s)
+{
+ uint16_t utsr0 = s->utsr0 &
+ (UTSR0_REB | UTSR0_RBB | UTSR0_RID);
+ int i;
+
+ if ((s->utcr3 & UTCR3_TXE) &&
+ (s->utcr3 & UTCR3_TIE) &&
+ s->tx_len <= 4) {
+ utsr0 |= UTSR0_TFS;
+ }
+
+ if ((s->utcr3 & UTCR3_RXE) &&
+ (s->utcr3 & UTCR3_RIE) &&
+ s->rx_len > 4) {
+ utsr0 |= UTSR0_RFS;
+ }
+
+ for (i = 0; i < s->rx_len && i < 4; i++)
+ if (s->rx_fifo[(s->rx_start + i) % 12] & ~0xff) {
+ utsr0 |= UTSR0_EIF;
+ break;
+ }
+
+ s->utsr0 = utsr0;
+ qemu_set_irq(s->irq, utsr0);
+}
+
+static void strongarm_uart_update_parameters(StrongARMUARTState *s)
+{
+ int speed, parity, data_bits, stop_bits, frame_size;
+ QEMUSerialSetParams ssp;
+
+ /* Start bit. */
+ frame_size = 1;
+ if (s->utcr0 & UTCR0_PE) {
+ /* Parity bit. */
+ frame_size++;
+ if (s->utcr0 & UTCR0_OES) {
+ parity = 'E';
+ } else {
+ parity = 'O';
+ }
+ } else {
+ parity = 'N';
+ }
+ if (s->utcr0 & UTCR0_SBS) {
+ stop_bits = 2;
+ } else {
+ stop_bits = 1;
+ }
+
+ data_bits = (s->utcr0 & UTCR0_DSS) ? 8 : 7;
+ frame_size += data_bits + stop_bits;
+ speed = 3686400 / 16 / (s->brd + 1);
+ ssp.speed = speed;
+ ssp.parity = parity;
+ ssp.data_bits = data_bits;
+ ssp.stop_bits = stop_bits;
+ s->char_transmit_time = (get_ticks_per_sec() / speed) * frame_size;
+ if (s->chr) {
+ qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
+ }
+
+ DPRINTF(stderr, "%s speed=%d parity=%c data=%d stop=%d\n", s->chr->label,
+ speed, parity, data_bits, stop_bits);
+}
+
+static void strongarm_uart_rx_to(void *opaque)
+{
+ StrongARMUARTState *s = opaque;
+
+ if (s->rx_len) {
+ s->utsr0 |= UTSR0_RID;
+ strongarm_uart_update_int_status(s);
+ }
+}
+
+static void strongarm_uart_rx_push(StrongARMUARTState *s, uint16_t c)
+{
+ if ((s->utcr3 & UTCR3_RXE) == 0) {
+ /* rx disabled */
+ return;
+ }
+
+ if (s->wait_break_end) {
+ s->utsr0 |= UTSR0_REB;
+ s->wait_break_end = false;
+ }
+
+ if (s->rx_len < 12) {
+ s->rx_fifo[(s->rx_start + s->rx_len) % 12] = c;
+ s->rx_len++;
+ } else
+ s->rx_fifo[(s->rx_start + 11) % 12] |= RX_FIFO_ROR;
+}
+
+static int strongarm_uart_can_receive(void *opaque)
+{
+ StrongARMUARTState *s = opaque;
+
+ if (s->rx_len == 12) {
+ return 0;
+ }
+ /* It's best not to get more than 2/3 of RX FIFO, so advertise that much */
+ if (s->rx_len < 8) {
+ return 8 - s->rx_len;
+ }
+ return 1;
+}
+
+static void strongarm_uart_receive(void *opaque, const uint8_t *buf, int size)
+{
+ StrongARMUARTState *s = opaque;
+ int i;
+
+ for (i = 0; i < size; i++) {
+ strongarm_uart_rx_push(s, buf[i]);
+ }
+
+ /* call the timeout receive callback in 3 char transmit time */
+ qemu_mod_timer(s->rx_timeout_timer,
+ qemu_get_clock_ns(vm_clock) + s->char_transmit_time * 3);
+
+ strongarm_uart_update_status(s);
+ strongarm_uart_update_int_status(s);
+}
+
+static void strongarm_uart_event(void *opaque, int event)
+{
+ StrongARMUARTState *s = opaque;
+ if (event == CHR_EVENT_BREAK) {
+ s->utsr0 |= UTSR0_RBB;
+ strongarm_uart_rx_push(s, RX_FIFO_FRE);
+ s->wait_break_end = true;
+ strongarm_uart_update_status(s);
+ strongarm_uart_update_int_status(s);
+ }
+}
+
+static void strongarm_uart_tx(void *opaque)
+{
+ StrongARMUARTState *s = opaque;
+ uint64_t new_xmit_ts = qemu_get_clock_ns(vm_clock);
+
+ if (s->utcr3 & UTCR3_LBM) /* loopback */ {
+ strongarm_uart_receive(s, &s->tx_fifo[s->tx_start], 1);
+ } else if (s->chr) {
+ qemu_chr_write(s->chr, &s->tx_fifo[s->tx_start], 1);
+ }
+
+ s->tx_start = (s->tx_start + 1) % 8;
+ s->tx_len--;
+ if (s->tx_len) {
+ qemu_mod_timer(s->tx_timer, new_xmit_ts + s->char_transmit_time);
+ }
+ strongarm_uart_update_status(s);
+ strongarm_uart_update_int_status(s);
+}
+
+static uint32_t strongarm_uart_read(void *opaque, target_phys_addr_t addr)
+{
+ StrongARMUARTState *s = opaque;
+ uint16_t ret;
+
+ switch (addr) {
+ case UTCR0:
+ return s->utcr0;
+
+ case UTCR1:
+ return s->brd >> 8;
+
+ case UTCR2:
+ return s->brd & 0xff;
+
+ case UTCR3:
+ return s->utcr3;
+
+ case UTDR:
+ if (s->rx_len != 0) {
+ ret = s->rx_fifo[s->rx_start];
+ s->rx_start = (s->rx_start + 1) % 12;
+ s->rx_len--;
+ strongarm_uart_update_status(s);
+ strongarm_uart_update_int_status(s);
+ return ret;
+ }
+ return 0;
+
+ case UTSR0:
+ return s->utsr0;
+
+ case UTSR1:
+ return s->utsr1;
+
+ default:
+ printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+ return 0;
+ }
+}
+
+static void strongarm_uart_write(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ StrongARMUARTState *s = opaque;
+
+ switch (addr) {
+ case UTCR0:
+ s->utcr0 = value & 0x7f;
+ strongarm_uart_update_parameters(s);
+ break;
+
+ case UTCR1:
+ s->brd = (s->brd & 0xff) | ((value & 0xf) << 8);
+ strongarm_uart_update_parameters(s);
+ break;
+
+ case UTCR2:
+ s->brd = (s->brd & 0xf00) | (value & 0xff);
+ strongarm_uart_update_parameters(s);
+ break;
+
+ case UTCR3:
+ s->utcr3 = value & 0x3f;
+ if ((s->utcr3 & UTCR3_RXE) == 0) {
+ s->rx_len = 0;
+ }
+ if ((s->utcr3 & UTCR3_TXE) == 0) {
+ s->tx_len = 0;
+ }
+ strongarm_uart_update_status(s);
+ strongarm_uart_update_int_status(s);
+ break;
+
+ case UTDR:
+ if ((s->utcr3 & UTCR3_TXE) && s->tx_len != 8) {
+ s->tx_fifo[(s->tx_start + s->tx_len) % 8] = value;
+ s->tx_len++;
+ strongarm_uart_update_status(s);
+ strongarm_uart_update_int_status(s);
+ if (s->tx_len == 1) {
+ strongarm_uart_tx(s);
+ }
+ }
+ break;
+
+ case UTSR0:
+ s->utsr0 = s->utsr0 & ~(value &
+ (UTSR0_REB | UTSR0_RBB | UTSR0_RID));
+ strongarm_uart_update_int_status(s);
+ break;
+
+ default:
+ printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+ }
+}
+
+static CPUReadMemoryFunc * const strongarm_uart_readfn[] = {
+ strongarm_uart_read,
+ strongarm_uart_read,
+ strongarm_uart_read,
+};
+
+static CPUWriteMemoryFunc * const strongarm_uart_writefn[] = {
+ strongarm_uart_write,
+ strongarm_uart_write,
+ strongarm_uart_write,
+};
+
+static int strongarm_uart_init(SysBusDevice *dev)
+{
+ StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev);
+ int iomemtype;
+
+ iomemtype = cpu_register_io_memory(strongarm_uart_readfn,
+ strongarm_uart_writefn, s, DEVICE_NATIVE_ENDIAN);
+ sysbus_init_mmio(dev, 0x10000, iomemtype);
+ sysbus_init_irq(dev, &s->irq);
+
+ s->rx_timeout_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_rx_to, s);
+ s->tx_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_tx, s);
+
+ if (s->chr) {
+ qemu_chr_add_handlers(s->chr,
+ strongarm_uart_can_receive,
+ strongarm_uart_receive,
+ strongarm_uart_event,
+ s);
+ }
+
+ return 0;
+}
+
+static void strongarm_uart_reset(DeviceState *dev)
+{
+ StrongARMUARTState *s = DO_UPCAST(StrongARMUARTState, busdev.qdev, dev);
+
+ s->utcr0 = UTCR0_DSS; /* 8 data, no parity */
+ s->brd = 23; /* 9600 */
+ /* enable send & recv - this actually violates spec */
+ s->utcr3 = UTCR3_TXE | UTCR3_RXE;
+
+ s->rx_len = s->tx_len = 0;
+
+ strongarm_uart_update_parameters(s);
+ strongarm_uart_update_status(s);
+ strongarm_uart_update_int_status(s);
+}
+
+static int strongarm_uart_post_load(void *opaque, int version_id)
+{
+ StrongARMUARTState *s = opaque;
+
+ strongarm_uart_update_parameters(s);
+ strongarm_uart_update_status(s);
+ strongarm_uart_update_int_status(s);
+
+ /* tx and restart timer */
+ if (s->tx_len) {
+ strongarm_uart_tx(s);
+ }
+
+ /* restart rx timeout timer */
+ if (s->rx_len) {
+ qemu_mod_timer(s->rx_timeout_timer,
+ qemu_get_clock_ns(vm_clock) + s->char_transmit_time * 3);
+ }
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_strongarm_uart_regs = {
+ .name = "strongarm-uart",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .post_load = strongarm_uart_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(utcr0, StrongARMUARTState),
+ VMSTATE_UINT16(brd, StrongARMUARTState),
+ VMSTATE_UINT8(utcr3, StrongARMUARTState),
+ VMSTATE_UINT8(utsr0, StrongARMUARTState),
+ VMSTATE_UINT8_ARRAY(tx_fifo, StrongARMUARTState, 8),
+ VMSTATE_UINT8(tx_start, StrongARMUARTState),
+ VMSTATE_UINT8(tx_len, StrongARMUARTState),
+ VMSTATE_UINT16_ARRAY(rx_fifo, StrongARMUARTState, 12),
+ VMSTATE_UINT8(rx_start, StrongARMUARTState),
+ VMSTATE_UINT8(rx_len, StrongARMUARTState),
+ VMSTATE_BOOL(wait_break_end, StrongARMUARTState),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static SysBusDeviceInfo strongarm_uart_info = {
+ .init = strongarm_uart_init,
+ .qdev.name = "strongarm-uart",
+ .qdev.desc = "StrongARM UART controller",
+ .qdev.size = sizeof(StrongARMUARTState),
+ .qdev.reset = strongarm_uart_reset,
+ .qdev.vmsd = &vmstate_strongarm_uart_regs,
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_CHR("chardev", StrongARMUARTState, chr),
+ DEFINE_PROP_END_OF_LIST(),
+ }
+};
+
+/* Synchronous Serial Ports */
+typedef struct {
+ SysBusDevice busdev;
+ qemu_irq irq;
+ SSIBus *bus;
+
+ uint16_t sscr[2];
+ uint16_t sssr;
+
+ uint16_t rx_fifo[8];
+ uint8_t rx_level;
+ uint8_t rx_start;
+} StrongARMSSPState;
+
+#define SSCR0 0x60 /* SSP Control register 0 */
+#define SSCR1 0x64 /* SSP Control register 1 */
+#define SSDR 0x6c /* SSP Data register */
+#define SSSR 0x74 /* SSP Status register */
+
+/* Bitfields for above registers */
+#define SSCR0_SPI(x) (((x) & 0x30) == 0x00)
+#define SSCR0_SSP(x) (((x) & 0x30) == 0x10)
+#define SSCR0_UWIRE(x) (((x) & 0x30) == 0x20)
+#define SSCR0_PSP(x) (((x) & 0x30) == 0x30)
+#define SSCR0_SSE (1 << 7)
+#define SSCR0_DSS(x) (((x) & 0xf) + 1)
+#define SSCR1_RIE (1 << 0)
+#define SSCR1_TIE (1 << 1)
+#define SSCR1_LBM (1 << 2)
+#define SSSR_TNF (1 << 2)
+#define SSSR_RNE (1 << 3)
+#define SSSR_TFS (1 << 5)
+#define SSSR_RFS (1 << 6)
+#define SSSR_ROR (1 << 7)
+#define SSSR_RW 0x0080
+
+static void strongarm_ssp_int_update(StrongARMSSPState *s)
+{
+ int level = 0;
+
+ level |= (s->sssr & SSSR_ROR);
+ level |= (s->sssr & SSSR_RFS) && (s->sscr[1] & SSCR1_RIE);
+ level |= (s->sssr & SSSR_TFS) && (s->sscr[1] & SSCR1_TIE);
+ qemu_set_irq(s->irq, level);
+}
+
+static void strongarm_ssp_fifo_update(StrongARMSSPState *s)
+{
+ s->sssr &= ~SSSR_TFS;
+ s->sssr &= ~SSSR_TNF;
+ if (s->sscr[0] & SSCR0_SSE) {
+ if (s->rx_level >= 4) {
+ s->sssr |= SSSR_RFS;
+ } else {
+ s->sssr &= ~SSSR_RFS;
+ }
+ if (s->rx_level) {
+ s->sssr |= SSSR_RNE;
+ } else {
+ s->sssr &= ~SSSR_RNE;
+ }
+ /* TX FIFO is never filled, so it is always in underrun
+ condition if SSP is enabled */
+ s->sssr |= SSSR_TFS;
+ s->sssr |= SSSR_TNF;
+ }
+
+ strongarm_ssp_int_update(s);
+}
+
+static uint32_t strongarm_ssp_read(void *opaque, target_phys_addr_t addr)
+{
+ StrongARMSSPState *s = opaque;
+ uint32_t retval;
+
+ switch (addr) {
+ case SSCR0:
+ return s->sscr[0];
+ case SSCR1:
+ return s->sscr[1];
+ case SSSR:
+ return s->sssr;
+ case SSDR:
+ if (~s->sscr[0] & SSCR0_SSE) {
+ return 0xffffffff;
+ }
+ if (s->rx_level < 1) {
+ printf("%s: SSP Rx Underrun\n", __func__);
+ return 0xffffffff;
+ }
+ s->rx_level--;
+ retval = s->rx_fifo[s->rx_start++];
+ s->rx_start &= 0x7;
+ strongarm_ssp_fifo_update(s);
+ return retval;
+ default:
+ printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+ break;
+ }
+ return 0;
+}
+
+static void strongarm_ssp_write(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ StrongARMSSPState *s = opaque;
+
+ switch (addr) {
+ case SSCR0:
+ s->sscr[0] = value & 0xffbf;
+ if ((s->sscr[0] & SSCR0_SSE) && SSCR0_DSS(value) < 4) {
+ printf("%s: Wrong data size: %i bits\n", __func__,
+ SSCR0_DSS(value));
+ }
+ if (!(value & SSCR0_SSE)) {
+ s->sssr = 0;
+ s->rx_level = 0;
+ }
+ strongarm_ssp_fifo_update(s);
+ break;
+
+ case SSCR1:
+ s->sscr[1] = value & 0x2f;
+ if (value & SSCR1_LBM) {
+ printf("%s: Attempt to use SSP LBM mode\n", __func__);
+ }
+ strongarm_ssp_fifo_update(s);
+ break;
+
+ case SSSR:
+ s->sssr &= ~(value & SSSR_RW);
+ strongarm_ssp_int_update(s);
+ break;
+
+ case SSDR:
+ if (SSCR0_UWIRE(s->sscr[0])) {
+ value &= 0xff;
+ } else
+ /* Note how 32bits overflow does no harm here */
+ value &= (1 << SSCR0_DSS(s->sscr[0])) - 1;
+
+ /* Data goes from here to the Tx FIFO and is shifted out from
+ * there directly to the slave, no need to buffer it.
+ */
+ if (s->sscr[0] & SSCR0_SSE) {
+ uint32_t readval;
+ if (s->sscr[1] & SSCR1_LBM) {
+ readval = value;
+ } else {
+ readval = ssi_transfer(s->bus, value);
+ }
+
+ if (s->rx_level < 0x08) {
+ s->rx_fifo[(s->rx_start + s->rx_level++) & 0x7] = readval;
+ } else {
+ s->sssr |= SSSR_ROR;
+ }
+ }
+ strongarm_ssp_fifo_update(s);
+ break;
+
+ default:
+ printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
+ break;
+ }
+}
+
+static CPUReadMemoryFunc * const strongarm_ssp_readfn[] = {
+ strongarm_ssp_read,
+ strongarm_ssp_read,
+ strongarm_ssp_read,
+};
+
+static CPUWriteMemoryFunc * const strongarm_ssp_writefn[] = {
+ strongarm_ssp_write,
+ strongarm_ssp_write,
+ strongarm_ssp_write,
+};
+
+static int strongarm_ssp_post_load(void *opaque, int version_id)
+{
+ StrongARMSSPState *s = opaque;
+
+ strongarm_ssp_fifo_update(s);
+
+ return 0;
+}
+
+static int strongarm_ssp_init(SysBusDevice *dev)
+{
+ int iomemtype;
+ StrongARMSSPState *s = FROM_SYSBUS(StrongARMSSPState, dev);
+
+ sysbus_init_irq(dev, &s->irq);
+
+ iomemtype = cpu_register_io_memory(strongarm_ssp_readfn,
+ strongarm_ssp_writefn, s,
+ DEVICE_NATIVE_ENDIAN);
+ sysbus_init_mmio(dev, 0x1000, iomemtype);
+
+ s->bus = ssi_create_bus(&dev->qdev, "ssi");
+ return 0;
+}
+
+static void strongarm_ssp_reset(DeviceState *dev)
+{
+ StrongARMSSPState *s = DO_UPCAST(StrongARMSSPState, busdev.qdev, dev);
+ s->sssr = 0x03; /* 3 bit data, SPI, disabled */
+ s->rx_start = 0;
+ s->rx_level = 0;
+}
+
+static const VMStateDescription vmstate_strongarm_ssp_regs = {
+ .name = "strongarm-ssp",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .post_load = strongarm_ssp_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT16_ARRAY(sscr, StrongARMSSPState, 2),
+ VMSTATE_UINT16(sssr, StrongARMSSPState),
+ VMSTATE_UINT16_ARRAY(rx_fifo, StrongARMSSPState, 8),
+ VMSTATE_UINT8(rx_start, StrongARMSSPState),
+ VMSTATE_UINT8(rx_level, StrongARMSSPState),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static SysBusDeviceInfo strongarm_ssp_info = {
+ .init = strongarm_ssp_init,
+ .qdev.name = "strongarm-ssp",
+ .qdev.desc = "StrongARM SSP controller",
+ .qdev.size = sizeof(StrongARMSSPState),
+ .qdev.reset = strongarm_ssp_reset,
+ .qdev.vmsd = &vmstate_strongarm_ssp_regs,
+};
+
+/* Main CPU functions */
+StrongARMState *sa1110_init(unsigned int sdram_size, const char *rev)
+{
+ StrongARMState *s;
+ qemu_irq *pic;
+ int i;
+
+ s = qemu_mallocz(sizeof(StrongARMState));
+
+ if (!rev) {
+ rev = "sa1110-b5";
+ }
+
+ if (strncmp(rev, "sa1110", 6)) {
+ error_report("Machine requires a SA1110 processor.\n");
+ exit(1);
+ }
+
+ s->env = cpu_init(rev);
+
+ if (!s->env) {
+ error_report("Unable to find CPU definition\n");
+ exit(1);
+ }
+
+ cpu_register_physical_memory(SA_SDCS0,
+ sdram_size, qemu_ram_alloc(NULL, "strongarm.sdram",
+ sdram_size) | IO_MEM_RAM);
+
+ pic = arm_pic_init_cpu(s->env);
+ s->pic = sysbus_create_varargs("strongarm_pic", 0x90050000,
+ pic[ARM_PIC_CPU_IRQ], pic[ARM_PIC_CPU_FIQ], NULL);
+
+ sysbus_create_varargs("pxa25x-timer", 0x90000000,
+ qdev_get_gpio_in(s->pic, SA_PIC_OSTC0),
+ qdev_get_gpio_in(s->pic, SA_PIC_OSTC1),
+ qdev_get_gpio_in(s->pic, SA_PIC_OSTC2),
+ qdev_get_gpio_in(s->pic, SA_PIC_OSTC3),
+ NULL);
+
+ sysbus_create_simple("strongarm-rtc", 0x90010000,
+ qdev_get_gpio_in(s->pic, SA_PIC_RTC_ALARM));
+
+ s->gpio = strongarm_gpio_init(0x90040000, s->pic);
+
+ s->ppc = sysbus_create_varargs("strongarm-ppc", 0x90060000, NULL);
+
+ for (i = 0; sa_serial[i].io_base; i++) {
+ DeviceState *dev = qdev_create(NULL, "strongarm-uart");
+ qdev_prop_set_chr(dev, "chardev", serial_hds[i]);
+ qdev_init_nofail(dev);
+ sysbus_mmio_map(sysbus_from_qdev(dev), 0,
+ sa_serial[i].io_base);
+ sysbus_connect_irq(sysbus_from_qdev(dev), 0,
+ qdev_get_gpio_in(s->pic, sa_serial[i].irq));
+ }
+
+ s->ssp = sysbus_create_varargs("strongarm-ssp", 0x80070000,
+ qdev_get_gpio_in(s->pic, SA_PIC_SSP), NULL);
+ s->ssp_bus = (SSIBus *)qdev_get_child_bus(s->ssp, "ssi");
+
+ return s;
+}
+
+static void strongarm_register_devices(void)
+{
+ sysbus_register_withprop(&strongarm_pic_info);
+ sysbus_register_withprop(&strongarm_rtc_sysbus_info);
+ sysbus_register_withprop(&strongarm_gpio_info);
+ sysbus_register_withprop(&strongarm_ppc_info);
+ sysbus_register_withprop(&strongarm_uart_info);
+ sysbus_register_withprop(&strongarm_ssp_info);
+}
+device_init(strongarm_register_devices)
diff --git a/hw/strongarm.h b/hw/strongarm.h
new file mode 100644
index 000000000..a81b110e2
--- /dev/null
+++ b/hw/strongarm.h
@@ -0,0 +1,64 @@
+#ifndef _STRONGARM_H
+#define _STRONGARM_H
+
+#define SA_CS0 0x00000000
+#define SA_CS1 0x08000000
+#define SA_CS2 0x10000000
+#define SA_CS3 0x18000000
+#define SA_PCMCIA_CS0 0x20000000
+#define SA_PCMCIA_CS1 0x30000000
+#define SA_CS4 0x40000000
+#define SA_CS5 0x48000000
+/* system registers here */
+#define SA_SDCS0 0xc0000000
+#define SA_SDCS1 0xc8000000
+#define SA_SDCS2 0xd0000000
+#define SA_SDCS3 0xd8000000
+
+enum {
+ SA_PIC_GPIO0_EDGE = 0,
+ SA_PIC_GPIO1_EDGE,
+ SA_PIC_GPIO2_EDGE,
+ SA_PIC_GPIO3_EDGE,
+ SA_PIC_GPIO4_EDGE,
+ SA_PIC_GPIO5_EDGE,
+ SA_PIC_GPIO6_EDGE,
+ SA_PIC_GPIO7_EDGE,
+ SA_PIC_GPIO8_EDGE,
+ SA_PIC_GPIO9_EDGE,
+ SA_PIC_GPIO10_EDGE,
+ SA_PIC_GPIOX_EDGE,
+ SA_PIC_LCD,
+ SA_PIC_UDC,
+ SA_PIC_RSVD1,
+ SA_PIC_UART1,
+ SA_PIC_UART2,
+ SA_PIC_UART3,
+ SA_PIC_MCP,
+ SA_PIC_SSP,
+ SA_PIC_DMA_CH0,
+ SA_PIC_DMA_CH1,
+ SA_PIC_DMA_CH2,
+ SA_PIC_DMA_CH3,
+ SA_PIC_DMA_CH4,
+ SA_PIC_DMA_CH5,
+ SA_PIC_OSTC0,
+ SA_PIC_OSTC1,
+ SA_PIC_OSTC2,
+ SA_PIC_OSTC3,
+ SA_PIC_RTC_HZ,
+ SA_PIC_RTC_ALARM,
+};
+
+typedef struct {
+ CPUState *env;
+ DeviceState *pic;
+ DeviceState *gpio;
+ DeviceState *ppc;
+ DeviceState *ssp;
+ SSIBus *ssp_bus;
+} StrongARMState;
+
+StrongARMState *sa1110_init(unsigned int sdram_size, const char *rev);
+
+#endif
diff --git a/hw/syborg_keyboard.c b/hw/syborg_keyboard.c
index d295e99eb..706a03966 100644
--- a/hw/syborg_keyboard.c
+++ b/hw/syborg_keyboard.c
@@ -51,11 +51,11 @@ enum {
typedef struct {
SysBusDevice busdev;
- int int_enabled;
+ uint32_t int_enabled;
int extension_bit;
uint32_t fifo_size;
uint32_t *key_fifo;
- int read_pos, read_count;
+ uint32_t read_pos, read_count;
qemu_irq irq;
} SyborgKeyboardState;
@@ -165,43 +165,21 @@ static void syborg_keyboard_event(void *opaque, int keycode)
syborg_keyboard_update(s);
}
-static void syborg_keyboard_save(QEMUFile *f, void *opaque)
-{
- SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
- int i;
-
- qemu_put_be32(f, s->fifo_size);
- qemu_put_be32(f, s->int_enabled);
- qemu_put_be32(f, s->extension_bit);
- qemu_put_be32(f, s->read_pos);
- qemu_put_be32(f, s->read_count);
- for (i = 0; i < s->fifo_size; i++) {
- qemu_put_be32(f, s->key_fifo[i]);
- }
-}
-
-static int syborg_keyboard_load(QEMUFile *f, void *opaque, int version_id)
-{
- SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
- uint32_t val;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- val = qemu_get_be32(f);
- if (val != s->fifo_size)
- return -EINVAL;
-
- s->int_enabled = qemu_get_be32(f);
- s->extension_bit = qemu_get_be32(f);
- s->read_pos = qemu_get_be32(f);
- s->read_count = qemu_get_be32(f);
- for (i = 0; i < s->fifo_size; i++) {
- s->key_fifo[i] = qemu_get_be32(f);
+static const VMStateDescription vmstate_syborg_keyboard = {
+ .name = "syborg_keyboard",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_EQUAL(fifo_size, SyborgKeyboardState),
+ VMSTATE_UINT32(int_enabled, SyborgKeyboardState),
+ VMSTATE_UINT32(read_pos, SyborgKeyboardState),
+ VMSTATE_UINT32(read_count, SyborgKeyboardState),
+ VMSTATE_VARRAY_UINT32(key_fifo, SyborgKeyboardState, fifo_size, 1,
+ vmstate_info_uint32, uint32),
+ VMSTATE_END_OF_LIST()
}
- return 0;
-}
+};
static int syborg_keyboard_init(SysBusDevice *dev)
{
@@ -221,8 +199,7 @@ static int syborg_keyboard_init(SysBusDevice *dev)
qemu_add_kbd_event_handler(syborg_keyboard_event, s);
- register_savevm(&dev->qdev, "syborg_keyboard", -1, 1,
- syborg_keyboard_save, syborg_keyboard_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_syborg_keyboard, s);
return 0;
}
diff --git a/hw/syborg_pointer.c b/hw/syborg_pointer.c
index a88688846..2f9970704 100644
--- a/hw/syborg_pointer.c
+++ b/hw/syborg_pointer.c
@@ -152,52 +152,36 @@ static void syborg_pointer_event(void *opaque, int dx, int dy, int dz,
syborg_pointer_update(s);
}
-static void syborg_pointer_save(QEMUFile *f, void *opaque)
-{
- SyborgPointerState *s = (SyborgPointerState *)opaque;
- int i;
-
- qemu_put_be32(f, s->fifo_size);
- qemu_put_be32(f, s->absolute);
- qemu_put_be32(f, s->int_enabled);
- qemu_put_be32(f, s->read_pos);
- qemu_put_be32(f, s->read_count);
- for (i = 0; i < s->fifo_size; i++) {
- qemu_put_be32(f, s->event_fifo[i].x);
- qemu_put_be32(f, s->event_fifo[i].y);
- qemu_put_be32(f, s->event_fifo[i].z);
- qemu_put_be32(f, s->event_fifo[i].pointer_buttons);
+static const VMStateDescription vmstate_event_data = {
+ .name = "dbma_channel",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32(x, event_data),
+ VMSTATE_INT32(y, event_data),
+ VMSTATE_INT32(z, event_data),
+ VMSTATE_INT32(pointer_buttons, event_data),
+ VMSTATE_END_OF_LIST()
}
-}
+};
-static int syborg_pointer_load(QEMUFile *f, void *opaque, int version_id)
-{
- SyborgPointerState *s = (SyborgPointerState *)opaque;
- uint32_t val;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- val = qemu_get_be32(f);
- if (val != s->fifo_size)
- return -EINVAL;
-
- val = qemu_get_be32(f);
- if (val != s->absolute)
- return -EINVAL;
-
- s->int_enabled = qemu_get_be32(f);
- s->read_pos = qemu_get_be32(f);
- s->read_count = qemu_get_be32(f);
- for (i = 0; i < s->fifo_size; i++) {
- s->event_fifo[i].x = qemu_get_be32(f);
- s->event_fifo[i].y = qemu_get_be32(f);
- s->event_fifo[i].z = qemu_get_be32(f);
- s->event_fifo[i].pointer_buttons = qemu_get_be32(f);
+static const VMStateDescription vmstate_syborg_pointer = {
+ .name = "syborg_pointer",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_EQUAL(fifo_size, SyborgPointerState),
+ VMSTATE_UINT32_EQUAL(absolute, SyborgPointerState),
+ VMSTATE_INT32(int_enabled, SyborgPointerState),
+ VMSTATE_INT32(read_pos, SyborgPointerState),
+ VMSTATE_INT32(read_count, SyborgPointerState),
+ VMSTATE_STRUCT_VARRAY_UINT32(event_fifo, SyborgPointerState, fifo_size,
+ 1, vmstate_event_data, event_data),
+ VMSTATE_END_OF_LIST()
}
- return 0;
-}
+};
static int syborg_pointer_init(SysBusDevice *dev)
{
@@ -219,8 +203,7 @@ static int syborg_pointer_init(SysBusDevice *dev)
qemu_add_mouse_event_handler(syborg_pointer_event, s, s->absolute,
"Syborg Pointer");
- register_savevm(&dev->qdev, "syborg_pointer", -1, 1,
- syborg_pointer_save, syborg_pointer_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_syborg_pointer, s);
return 0;
}
diff --git a/hw/syborg_rtc.c b/hw/syborg_rtc.c
index 16d8f9edb..69f6ccf29 100644
--- a/hw/syborg_rtc.c
+++ b/hw/syborg_rtc.c
@@ -102,26 +102,17 @@ static CPUWriteMemoryFunc * const syborg_rtc_writefn[] = {
syborg_rtc_write
};
-static void syborg_rtc_save(QEMUFile *f, void *opaque)
-{
- SyborgRTCState *s = opaque;
-
- qemu_put_be64(f, s->offset);
- qemu_put_be64(f, s->data);
-}
-
-static int syborg_rtc_load(QEMUFile *f, void *opaque, int version_id)
-{
- SyborgRTCState *s = opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->offset = qemu_get_be64(f);
- s->data = qemu_get_be64(f);
-
- return 0;
-}
+static const VMStateDescription vmstate_syborg_rtc = {
+ .name = "syborg_keyboard",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT64(offset, SyborgRTCState),
+ VMSTATE_INT64(data, SyborgRTCState),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int syborg_rtc_init(SysBusDevice *dev)
{
@@ -137,8 +128,7 @@ static int syborg_rtc_init(SysBusDevice *dev)
qemu_get_timedate(&tm, 0);
s->offset = (uint64_t)mktime(&tm) * 1000000000;
- register_savevm(&dev->qdev, "syborg_rtc", -1, 1,
- syborg_rtc_save, syborg_rtc_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_syborg_rtc, s);
return 0;
}
diff --git a/hw/syborg_serial.c b/hw/syborg_serial.c
index 34ce076d4..df2950fe8 100644
--- a/hw/syborg_serial.c
+++ b/hw/syborg_serial.c
@@ -273,47 +273,24 @@ static CPUWriteMemoryFunc * const syborg_serial_writefn[] = {
syborg_serial_write
};
-static void syborg_serial_save(QEMUFile *f, void *opaque)
-{
- SyborgSerialState *s = opaque;
- int i;
-
- qemu_put_be32(f, s->fifo_size);
- qemu_put_be32(f, s->int_enable);
- qemu_put_be32(f, s->read_pos);
- qemu_put_be32(f, s->read_count);
- qemu_put_be32(f, s->dma_tx_ptr);
- qemu_put_be32(f, s->dma_rx_ptr);
- qemu_put_be32(f, s->dma_rx_size);
- for (i = 0; i < s->fifo_size; i++) {
- qemu_put_be32(f, s->read_fifo[i]);
- }
-}
-
-static int syborg_serial_load(QEMUFile *f, void *opaque, int version_id)
-{
- SyborgSerialState *s = opaque;
- int i;
-
- if (version_id != 1)
- return -EINVAL;
-
- i = qemu_get_be32(f);
- if (s->fifo_size != i)
- return -EINVAL;
-
- s->int_enable = qemu_get_be32(f);
- s->read_pos = qemu_get_be32(f);
- s->read_count = qemu_get_be32(f);
- s->dma_tx_ptr = qemu_get_be32(f);
- s->dma_rx_ptr = qemu_get_be32(f);
- s->dma_rx_size = qemu_get_be32(f);
- for (i = 0; i < s->fifo_size; i++) {
- s->read_fifo[i] = qemu_get_be32(f);
+static const VMStateDescription vmstate_syborg_serial = {
+ .name = "syborg_serial",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_EQUAL(fifo_size, SyborgSerialState),
+ VMSTATE_UINT32(int_enable, SyborgSerialState),
+ VMSTATE_INT32(read_pos, SyborgSerialState),
+ VMSTATE_INT32(read_count, SyborgSerialState),
+ VMSTATE_UINT32(dma_tx_ptr, SyborgSerialState),
+ VMSTATE_UINT32(dma_rx_ptr, SyborgSerialState),
+ VMSTATE_UINT32(dma_rx_size, SyborgSerialState),
+ VMSTATE_VARRAY_UINT32(read_fifo, SyborgSerialState, fifo_size, 1,
+ vmstate_info_uint32, uint32),
+ VMSTATE_END_OF_LIST()
}
-
- return 0;
-}
+};
static int syborg_serial_init(SysBusDevice *dev)
{
@@ -336,8 +313,6 @@ static int syborg_serial_init(SysBusDevice *dev)
}
s->read_fifo = qemu_mallocz(s->fifo_size * sizeof(s->read_fifo[0]));
- register_savevm(&dev->qdev, "syborg_serial", -1, 1,
- syborg_serial_save, syborg_serial_load, s);
return 0;
}
@@ -345,6 +320,7 @@ static SysBusDeviceInfo syborg_serial_info = {
.init = syborg_serial_init,
.qdev.name = "syborg,serial",
.qdev.size = sizeof(SyborgSerialState),
+ .qdev.vmsd = &vmstate_syborg_serial,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("fifo-size", SyborgSerialState, fifo_size, 16),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/syborg_timer.c b/hw/syborg_timer.c
index cedcd8ed4..50c813e96 100644
--- a/hw/syborg_timer.c
+++ b/hw/syborg_timer.c
@@ -174,34 +174,21 @@ static CPUWriteMemoryFunc * const syborg_timer_writefn[] = {
syborg_timer_write
};
-static void syborg_timer_save(QEMUFile *f, void *opaque)
-{
- SyborgTimerState *s = opaque;
-
- qemu_put_be32(f, s->running);
- qemu_put_be32(f, s->oneshot);
- qemu_put_be32(f, s->limit);
- qemu_put_be32(f, s->int_level);
- qemu_put_be32(f, s->int_enabled);
- qemu_put_ptimer(f, s->timer);
-}
-
-static int syborg_timer_load(QEMUFile *f, void *opaque, int version_id)
-{
- SyborgTimerState *s = opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->running = qemu_get_be32(f);
- s->oneshot = qemu_get_be32(f);
- s->limit = qemu_get_be32(f);
- s->int_level = qemu_get_be32(f);
- s->int_enabled = qemu_get_be32(f);
- qemu_get_ptimer(f, s->timer);
-
- return 0;
-}
+static const VMStateDescription vmstate_syborg_timer = {
+ .name = "syborg_timer",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32(running, SyborgTimerState),
+ VMSTATE_INT32(oneshot, SyborgTimerState),
+ VMSTATE_UINT32(limit, SyborgTimerState),
+ VMSTATE_UINT32(int_level, SyborgTimerState),
+ VMSTATE_UINT32(int_enabled, SyborgTimerState),
+ VMSTATE_PTIMER(timer, SyborgTimerState),
+ VMSTATE_END_OF_LIST()
+ }
+};
static int syborg_timer_init(SysBusDevice *dev)
{
@@ -222,8 +209,7 @@ static int syborg_timer_init(SysBusDevice *dev)
bh = qemu_bh_new(syborg_timer_tick, s);
s->timer = ptimer_init(bh);
ptimer_set_freq(s->timer, s->freq);
- register_savevm(&dev->qdev, "syborg_timer", -1, 1,
- syborg_timer_save, syborg_timer_load, s);
+ vmstate_register(&dev->qdev, -1, &vmstate_syborg_timer, s);
return 0;
}
diff --git a/qemu-timer.h b/qemu-timer.h
index bbc3452bc..2cacf6553 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -144,8 +144,6 @@ uint64_t ptimer_get_count(ptimer_state *s);
void ptimer_set_count(ptimer_state *s, uint64_t count);
void ptimer_run(ptimer_state *s, int oneshot);
void ptimer_stop(ptimer_state *s);
-void qemu_put_ptimer(QEMUFile *f, ptimer_state *s);
-void qemu_get_ptimer(QEMUFile *f, ptimer_state *s);
/* icount */
int64_t qemu_icount_round(int64_t count);
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 9f71db4c3..4ccb10b0f 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1374,7 +1374,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (likely(tb)) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
/* Exception index and error code are already set */
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 96e922b56..456ba51ac 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3367,8 +3367,7 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
return env;
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->pc = gen_opc_pc[pc_pos];
}
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index e247a7ade..d5af64465 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -363,6 +363,7 @@ enum arm_features {
ARM_FEATURE_V7MP, /* v7 Multiprocessing Extensions */
ARM_FEATURE_V4T,
ARM_FEATURE_V5,
+ ARM_FEATURE_STRONGARM,
};
static inline int arm_feature(CPUARMState *env, int feature)
@@ -393,6 +394,8 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
#define ARM_CPUID_ARM946 0x41059461
#define ARM_CPUID_TI915T 0x54029152
#define ARM_CPUID_TI925T 0x54029252
+#define ARM_CPUID_SA1100 0x4401A11B
+#define ARM_CPUID_SA1110 0x6901B119
#define ARM_CPUID_PXA250 0x69052100
#define ARM_CPUID_PXA255 0x69052d00
#define ARM_CPUID_PXA260 0x69052903
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 12127dee7..62ae72ec2 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -214,6 +214,11 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
env->cp15.c0_cachetype = 0xd172172;
env->cp15.c1_sys = 0x00000078;
break;
+ case ARM_CPUID_SA1100:
+ case ARM_CPUID_SA1110:
+ set_feature(env, ARM_FEATURE_STRONGARM);
+ env->cp15.c1_sys = 0x00000070;
+ break;
default:
cpu_abort(env, "Bad CPU ID: %x\n", id);
break;
@@ -378,6 +383,8 @@ static const struct arm_cpu_t arm_cpu_names[] = {
{ ARM_CPUID_CORTEXA9, "cortex-a9"},
{ ARM_CPUID_TI925T, "ti925t" },
{ ARM_CPUID_PXA250, "pxa250" },
+ { ARM_CPUID_SA1100, "sa1100" },
+ { ARM_CPUID_SA1110, "sa1110" },
{ ARM_CPUID_PXA255, "pxa255" },
{ ARM_CPUID_PXA260, "pxa260" },
{ ARM_CPUID_PXA261, "pxa261" },
@@ -1553,6 +1560,8 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
case 9:
if (arm_feature(env, ARM_FEATURE_OMAPCP))
break;
+ if (arm_feature(env, ARM_FEATURE_STRONGARM))
+ break; /* Ignore ReadBuffer access */
switch (crm) {
case 0: /* Cache lockdown. */
switch (op1) {
@@ -2542,6 +2551,7 @@ float64 VFP_HELPER(sito, d)(uint32_t x, CPUState *env)
uint32_t VFP_HELPER(toui, s)(float32 x, CPUState *env)
{
if (float32_is_any_nan(x)) {
+ float_raise(float_flag_invalid, &env->vfp.fp_status);
return 0;
}
return float32_to_uint32(x, &env->vfp.fp_status);
@@ -2550,6 +2560,7 @@ uint32_t VFP_HELPER(toui, s)(float32 x, CPUState *env)
uint32_t VFP_HELPER(toui, d)(float64 x, CPUState *env)
{
if (float64_is_any_nan(x)) {
+ float_raise(float_flag_invalid, &env->vfp.fp_status);
return 0;
}
return float64_to_uint32(x, &env->vfp.fp_status);
@@ -2558,6 +2569,7 @@ uint32_t VFP_HELPER(toui, d)(float64 x, CPUState *env)
uint32_t VFP_HELPER(tosi, s)(float32 x, CPUState *env)
{
if (float32_is_any_nan(x)) {
+ float_raise(float_flag_invalid, &env->vfp.fp_status);
return 0;
}
return float32_to_int32(x, &env->vfp.fp_status);
@@ -2566,6 +2578,7 @@ uint32_t VFP_HELPER(tosi, s)(float32 x, CPUState *env)
uint32_t VFP_HELPER(tosi, d)(float64 x, CPUState *env)
{
if (float64_is_any_nan(x)) {
+ float_raise(float_flag_invalid, &env->vfp.fp_status);
return 0;
}
return float64_to_int32(x, &env->vfp.fp_status);
@@ -2574,6 +2587,7 @@ uint32_t VFP_HELPER(tosi, d)(float64 x, CPUState *env)
uint32_t VFP_HELPER(touiz, s)(float32 x, CPUState *env)
{
if (float32_is_any_nan(x)) {
+ float_raise(float_flag_invalid, &env->vfp.fp_status);
return 0;
}
return float32_to_uint32_round_to_zero(x, &env->vfp.fp_status);
@@ -2582,6 +2596,7 @@ uint32_t VFP_HELPER(touiz, s)(float32 x, CPUState *env)
uint32_t VFP_HELPER(touiz, d)(float64 x, CPUState *env)
{
if (float64_is_any_nan(x)) {
+ float_raise(float_flag_invalid, &env->vfp.fp_status);
return 0;
}
return float64_to_uint32_round_to_zero(x, &env->vfp.fp_status);
@@ -2590,6 +2605,7 @@ uint32_t VFP_HELPER(touiz, d)(float64 x, CPUState *env)
uint32_t VFP_HELPER(tosiz, s)(float32 x, CPUState *env)
{
if (float32_is_any_nan(x)) {
+ float_raise(float_flag_invalid, &env->vfp.fp_status);
return 0;
}
return float32_to_int32_round_to_zero(x, &env->vfp.fp_status);
@@ -2598,6 +2614,7 @@ uint32_t VFP_HELPER(tosiz, s)(float32 x, CPUState *env)
uint32_t VFP_HELPER(tosiz, d)(float64 x, CPUState *env)
{
if (float64_is_any_nan(x)) {
+ float_raise(float_flag_invalid, &env->vfp.fp_status);
return 0;
}
return float64_to_int32_round_to_zero(x, &env->vfp.fp_status);
@@ -2636,6 +2653,7 @@ uint##fsz##_t VFP_HELPER(to##name, p)(float##fsz x, uint32_t shift, \
{ \
float##fsz tmp; \
if (float##fsz##_is_any_nan(x)) { \
+ float_raise(float_flag_invalid, &env->vfp.fp_status); \
return 0; \
} \
tmp = float##fsz##_scalbn(x, shift, &env->vfp.fp_status); \
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index ee7286b77..8334fbcf6 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -90,7 +90,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
raise_exception(env->exception_index);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index fc9ff8d9e..e1bda57e8 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9551,8 +9551,8 @@ static inline void gen_intermediate_code_internal(CPUState *env,
* This is handled in the same way as restoration of the
* PC in these situations: we will be called again with search_pc=1
* and generate a mapping of the condexec bits for each PC in
- * gen_opc_condexec_bits[]. gen_pc_load[] then uses this to restore
- * the condexec bits.
+ * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
+ * this to restore the condexec bits.
*
* Note that there are no instructions which can read the condexec
* bits, and none which can write non-static values to them, so
@@ -9817,8 +9817,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
#endif
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->regs[15] = gen_opc_pc[pc_pos];
env->condexec_bits = gen_opc_condexec_bits[pc_pos];
diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c
index be9eb06fd..34329e2a6 100644
--- a/target-cris/op_helper.c
+++ b/target-cris/op_helper.c
@@ -77,7 +77,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
/* Evaluate flags after retranslation. */
helper_top_evaluate_flags();
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 1c03fa5fb..e2607d64c 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3604,8 +3604,7 @@ void cpu_reset (CPUCRISState *env)
#endif
}
-void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->pc = gen_opc_pc[pc_pos];
}
diff --git a/target-i386/exec.h b/target-i386/exec.h
index ae6b94740..ee36a7181 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -111,13 +111,23 @@ static inline void svm_check_intercept(uint32_t type)
#define floatx_to_float32 floatx80_to_float32
#define floatx_to_float64 floatx80_to_float64
#define floatx_add floatx80_add
+#define floatx_div floatx80_div
#define floatx_mul floatx80_mul
#define floatx_sub floatx80_sub
+#define floatx_sqrt floatx80_sqrt
#define floatx_abs floatx80_abs
#define floatx_chs floatx80_chs
+#define floatx_scalbn floatx80_scalbn
#define floatx_round_to_int floatx80_round_to_int
#define floatx_compare floatx80_compare
#define floatx_compare_quiet floatx80_compare_quiet
+#define floatx_is_any_nan floatx80_is_any_nan
+#define floatx_is_neg floatx80_is_neg
+#define floatx_is_zero floatx80_is_zero
+#define floatx_zero floatx80_zero
+#define floatx_one floatx80_one
+#define floatx_ln2 floatx80_ln2
+#define floatx_pi floatx80_pi
#else
#define floatx_to_int32 float64_to_int32
#define floatx_to_int64 float64_to_int64
@@ -130,13 +140,23 @@ static inline void svm_check_intercept(uint32_t type)
#define floatx_to_float32 float64_to_float32
#define floatx_to_float64(x, e) (x)
#define floatx_add float64_add
+#define floatx_div float64_div
#define floatx_mul float64_mul
#define floatx_sub float64_sub
+#define floatx_sqrt float64_sqrt
#define floatx_abs float64_abs
#define floatx_chs float64_chs
+#define floatx_scalbn float64_scalbn
#define floatx_round_to_int float64_round_to_int
#define floatx_compare float64_compare
#define floatx_compare_quiet float64_compare_quiet
+#define floatx_is_any_nan float64_is_any_nan
+#define floatx_is_neg float64_is_neg
+#define floatx_is_zero float64_is_zero
+#define floatx_zero float64_zero
+#define floatx_one float64_one
+#define floatx_ln2 float64_ln2
+#define floatx_pi float64_pi
#endif
#define RC_MASK 0xc00
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index a73427fe4..3c539f37c 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -17,6 +17,7 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
+#include <math.h>
#include "exec.h"
#include "exec-all.h"
#include "host-utils.h"
@@ -94,15 +95,25 @@ static const uint8_t rclb_table[32] = {
6, 7, 8, 0, 1, 2, 3, 4,
};
+#if defined(CONFIG_SOFTFLOAT)
+# define floatx_lg2 make_floatx80( 0x3ffd, 0x9a209a84fbcff799LL )
+# define floatx_l2e make_floatx80( 0x3fff, 0xb8aa3b295c17f0bcLL )
+# define floatx_l2t make_floatx80( 0x4000, 0xd49a784bcd1b8afeLL )
+#else
+# define floatx_lg2 (0.30102999566398119523L)
+# define floatx_l2e (1.44269504088896340739L)
+# define floatx_l2t (3.32192809488736234781L)
+#endif
+
static const CPU86_LDouble f15rk[7] =
{
- 0.00000000000000000000L,
- 1.00000000000000000000L,
- 3.14159265358979323851L, /*pi*/
- 0.30102999566398119523L, /*lg2*/
- 0.69314718055994530943L, /*ln2*/
- 1.44269504088896340739L, /*l2e*/
- 3.32192809488736234781L, /*l2t*/
+ floatx_zero,
+ floatx_one,
+ floatx_pi,
+ floatx_lg2,
+ floatx_ln2,
+ floatx_l2e,
+ floatx_l2t,
};
/* broken thread support */
@@ -3431,6 +3442,28 @@ void helper_verw(target_ulong selector1)
/* x87 FPU helpers */
+static inline double CPU86_LDouble_to_double(CPU86_LDouble a)
+{
+ union {
+ float64 f64;
+ double d;
+ } u;
+
+ u.f64 = floatx_to_float64(a, &env->fp_status);
+ return u.d;
+}
+
+static inline CPU86_LDouble double_to_CPU86_LDouble(double a)
+{
+ union {
+ float64 f64;
+ double d;
+ } u;
+
+ u.d = a;
+ return float64_to_floatx(u.f64, &env->fp_status);
+}
+
static void fpu_set_exception(int mask)
{
env->fpus |= mask;
@@ -3440,9 +3473,10 @@ static void fpu_set_exception(int mask)
static inline CPU86_LDouble helper_fdiv(CPU86_LDouble a, CPU86_LDouble b)
{
- if (b == 0.0)
+ if (floatx_is_zero(b)) {
fpu_set_exception(FPUS_ZE);
- return a / b;
+ }
+ return floatx_div(a, b, &env->fp_status);
}
static void fpu_raise_exception(void)
@@ -3920,9 +3954,10 @@ void helper_fbld_ST0(target_ulong ptr)
v = ldub(ptr + i);
val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
}
- tmp = val;
- if (ldub(ptr + 9) & 0x80)
- tmp = -tmp;
+ tmp = int64_to_floatx(val, &env->fp_status);
+ if (ldub(ptr + 9) & 0x80) {
+ floatx_chs(tmp);
+ }
fpush();
ST0 = tmp;
}
@@ -3957,17 +3992,19 @@ void helper_fbst_ST0(target_ulong ptr)
void helper_f2xm1(void)
{
- ST0 = pow(2.0,ST0) - 1.0;
+ double val = CPU86_LDouble_to_double(ST0);
+ val = pow(2.0, val) - 1.0;
+ ST0 = double_to_CPU86_LDouble(val);
}
void helper_fyl2x(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = CPU86_LDouble_to_double(ST0);
- fptemp = ST0;
if (fptemp>0.0){
- fptemp = log(fptemp)/log(2.0); /* log2(ST) */
- ST1 *= fptemp;
+ fptemp = log(fptemp)/log(2.0); /* log2(ST) */
+ fptemp *= CPU86_LDouble_to_double(ST1);
+ ST1 = double_to_CPU86_LDouble(fptemp);
fpop();
} else {
env->fpus &= (~0x4700);
@@ -3977,15 +4014,15 @@ void helper_fyl2x(void)
void helper_fptan(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = CPU86_LDouble_to_double(ST0);
- fptemp = ST0;
if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
env->fpus |= 0x400;
} else {
- ST0 = tan(fptemp);
+ fptemp = tan(fptemp);
+ ST0 = double_to_CPU86_LDouble(fptemp);
fpush();
- ST0 = 1.0;
+ ST0 = floatx_one;
env->fpus &= (~0x400); /* C2 <-- 0 */
/* the above code is for |arg| < 2**52 only */
}
@@ -3993,45 +4030,57 @@ void helper_fptan(void)
void helper_fpatan(void)
{
- CPU86_LDouble fptemp, fpsrcop;
+ double fptemp, fpsrcop;
- fpsrcop = ST1;
- fptemp = ST0;
- ST1 = atan2(fpsrcop,fptemp);
+ fpsrcop = CPU86_LDouble_to_double(ST1);
+ fptemp = CPU86_LDouble_to_double(ST0);
+ ST1 = double_to_CPU86_LDouble(atan2(fpsrcop, fptemp));
fpop();
}
void helper_fxtract(void)
{
CPU86_LDoubleU temp;
- unsigned int expdif;
temp.d = ST0;
- expdif = EXPD(temp) - EXPBIAS;
- /*DP exponent bias*/
- ST0 = expdif;
- fpush();
- BIASEXPONENT(temp);
- ST0 = temp.d;
+
+ if (floatx_is_zero(ST0)) {
+ /* Easy way to generate -inf and raising division by 0 exception */
+ ST0 = floatx_div(floatx_chs(floatx_one), floatx_zero, &env->fp_status);
+ fpush();
+ ST0 = temp.d;
+ } else {
+ int expdif;
+
+ expdif = EXPD(temp) - EXPBIAS;
+ /*DP exponent bias*/
+ ST0 = int32_to_floatx(expdif, &env->fp_status);
+ fpush();
+ BIASEXPONENT(temp);
+ ST0 = temp.d;
+ }
}
void helper_fprem1(void)
{
- CPU86_LDouble dblq, fpsrcop, fptemp;
+ double st0, st1, dblq, fpsrcop, fptemp;
CPU86_LDoubleU fpsrcop1, fptemp1;
int expdif;
signed long long int q;
- if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
- ST0 = 0.0 / 0.0; /* NaN */
+ st0 = CPU86_LDouble_to_double(ST0);
+ st1 = CPU86_LDouble_to_double(ST1);
+
+ if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
+ ST0 = double_to_CPU86_LDouble(0.0 / 0.0); /* NaN */
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
return;
}
- fpsrcop = ST0;
- fptemp = ST1;
- fpsrcop1.d = fpsrcop;
- fptemp1.d = fptemp;
+ fpsrcop = st0;
+ fptemp = st1;
+ fpsrcop1.d = ST0;
+ fptemp1.d = ST1;
expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
if (expdif < 0) {
@@ -4045,7 +4094,7 @@ void helper_fprem1(void)
dblq = fpsrcop / fptemp;
/* round dblq towards nearest integer */
dblq = rint(dblq);
- ST0 = fpsrcop - fptemp * dblq;
+ st0 = fpsrcop - fptemp * dblq;
/* convert dblq to q by truncating towards zero */
if (dblq < 0.0)
@@ -4061,31 +4110,35 @@ void helper_fprem1(void)
} else {
env->fpus |= 0x400; /* C2 <-- 1 */
fptemp = pow(2.0, expdif - 50);
- fpsrcop = (ST0 / ST1) / fptemp;
+ fpsrcop = (st0 / st1) / fptemp;
/* fpsrcop = integer obtained by chopping */
fpsrcop = (fpsrcop < 0.0) ?
-(floor(fabs(fpsrcop))) : floor(fpsrcop);
- ST0 -= (ST1 * fpsrcop * fptemp);
+ st0 -= (st1 * fpsrcop * fptemp);
}
+ ST0 = double_to_CPU86_LDouble(st0);
}
void helper_fprem(void)
{
- CPU86_LDouble dblq, fpsrcop, fptemp;
+ double st0, st1, dblq, fpsrcop, fptemp;
CPU86_LDoubleU fpsrcop1, fptemp1;
int expdif;
signed long long int q;
- if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
- ST0 = 0.0 / 0.0; /* NaN */
+ st0 = CPU86_LDouble_to_double(ST0);
+ st1 = CPU86_LDouble_to_double(ST1);
+
+ if (isinf(st0) || isnan(st0) || isnan(st1) || (st1 == 0.0)) {
+ ST0 = double_to_CPU86_LDouble(0.0 / 0.0); /* NaN */
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
return;
}
- fpsrcop = (CPU86_LDouble)ST0;
- fptemp = (CPU86_LDouble)ST1;
- fpsrcop1.d = fpsrcop;
- fptemp1.d = fptemp;
+ fpsrcop = st0;
+ fptemp = st1;
+ fpsrcop1.d = ST0;
+ fptemp1.d = ST1;
expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
if (expdif < 0) {
@@ -4099,7 +4152,7 @@ void helper_fprem(void)
dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
/* round dblq towards zero */
dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
- ST0 = fpsrcop/*ST0*/ - fptemp * dblq;
+ st0 = fpsrcop/*ST0*/ - fptemp * dblq;
/* convert dblq to q by truncating towards zero */
if (dblq < 0.0)
@@ -4116,22 +4169,23 @@ void helper_fprem(void)
int N = 32 + (expdif % 32); /* as per AMD docs */
env->fpus |= 0x400; /* C2 <-- 1 */
fptemp = pow(2.0, (double)(expdif - N));
- fpsrcop = (ST0 / ST1) / fptemp;
+ fpsrcop = (st0 / st1) / fptemp;
/* fpsrcop = integer obtained by chopping */
fpsrcop = (fpsrcop < 0.0) ?
-(floor(fabs(fpsrcop))) : floor(fpsrcop);
- ST0 -= (ST1 * fpsrcop * fptemp);
+ st0 -= (st1 * fpsrcop * fptemp);
}
+ ST0 = double_to_CPU86_LDouble(st0);
}
void helper_fyl2xp1(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = CPU86_LDouble_to_double(ST0);
- fptemp = ST0;
if ((fptemp+1.0)>0.0) {
fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
- ST1 *= fptemp;
+ fptemp *= CPU86_LDouble_to_double(ST1);
+ ST1 = double_to_CPU86_LDouble(fptemp);
fpop();
} else {
env->fpus &= (~0x4700);
@@ -4141,27 +4195,23 @@ void helper_fyl2xp1(void)
void helper_fsqrt(void)
{
- CPU86_LDouble fptemp;
-
- fptemp = ST0;
- if (fptemp<0.0) {
+ if (floatx_is_neg(ST0)) {
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
env->fpus |= 0x400;
}
- ST0 = sqrt(fptemp);
+ ST0 = floatx_sqrt(ST0, &env->fp_status);
}
void helper_fsincos(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = CPU86_LDouble_to_double(ST0);
- fptemp = ST0;
if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
env->fpus |= 0x400;
} else {
- ST0 = sin(fptemp);
+ ST0 = double_to_CPU86_LDouble(sin(fptemp));
fpush();
- ST0 = cos(fptemp);
+ ST0 = double_to_CPU86_LDouble(cos(fptemp));
env->fpus &= (~0x400); /* C2 <-- 0 */
/* the above code is for |arg| < 2**63 only */
}
@@ -4174,18 +4224,22 @@ void helper_frndint(void)
void helper_fscale(void)
{
- ST0 = ldexp (ST0, (int)(ST1));
+ if (floatx_is_any_nan(ST1)) {
+ ST0 = ST1;
+ } else {
+ int n = floatx_to_int32_round_to_zero(ST1, &env->fp_status);
+ ST0 = floatx_scalbn(ST0, n, &env->fp_status);
+ }
}
void helper_fsin(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = CPU86_LDouble_to_double(ST0);
- fptemp = ST0;
if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
env->fpus |= 0x400;
} else {
- ST0 = sin(fptemp);
+ ST0 = double_to_CPU86_LDouble(sin(fptemp));
env->fpus &= (~0x400); /* C2 <-- 0 */
/* the above code is for |arg| < 2**53 only */
}
@@ -4193,13 +4247,12 @@ void helper_fsin(void)
void helper_fcos(void)
{
- CPU86_LDouble fptemp;
+ double fptemp = CPU86_LDouble_to_double(ST0);
- fptemp = ST0;
if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
env->fpus |= 0x400;
} else {
- ST0 = cos(fptemp);
+ ST0 = double_to_CPU86_LDouble(cos(fptemp));
env->fpus &= (~0x400); /* C2 <-- 0 */
/* the above code is for |arg5 < 2**63 only */
}
@@ -4781,16 +4834,6 @@ void helper_boundl(target_ulong a0, int v)
}
}
-static float approx_rsqrt(float a)
-{
- return 1.0 / sqrt(a);
-}
-
-static float approx_rcp(float a)
-{
- return 1.0 / a;
-}
-
#if !defined(CONFIG_USER_ONLY)
#define MMUSUFFIX _mmu
@@ -4835,7 +4878,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
raise_exception_err(env->exception_index, env->error_code);
diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index ac0f15007..703be99cd 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -778,28 +778,38 @@ int64_t helper_cvttsd2sq(XMMReg *s)
void helper_rsqrtps(XMMReg *d, XMMReg *s)
{
- d->XMM_S(0) = approx_rsqrt(s->XMM_S(0));
- d->XMM_S(1) = approx_rsqrt(s->XMM_S(1));
- d->XMM_S(2) = approx_rsqrt(s->XMM_S(2));
- d->XMM_S(3) = approx_rsqrt(s->XMM_S(3));
+ d->XMM_S(0) = float32_div(float32_one,
+ float32_sqrt(s->XMM_S(0), &env->sse_status),
+ &env->sse_status);
+ d->XMM_S(1) = float32_div(float32_one,
+ float32_sqrt(s->XMM_S(1), &env->sse_status),
+ &env->sse_status);
+ d->XMM_S(2) = float32_div(float32_one,
+ float32_sqrt(s->XMM_S(2), &env->sse_status),
+ &env->sse_status);
+ d->XMM_S(3) = float32_div(float32_one,
+ float32_sqrt(s->XMM_S(3), &env->sse_status),
+ &env->sse_status);
}
void helper_rsqrtss(XMMReg *d, XMMReg *s)
{
- d->XMM_S(0) = approx_rsqrt(s->XMM_S(0));
+ d->XMM_S(0) = float32_div(float32_one,
+ float32_sqrt(s->XMM_S(0), &env->sse_status),
+ &env->sse_status);
}
void helper_rcpps(XMMReg *d, XMMReg *s)
{
- d->XMM_S(0) = approx_rcp(s->XMM_S(0));
- d->XMM_S(1) = approx_rcp(s->XMM_S(1));
- d->XMM_S(2) = approx_rcp(s->XMM_S(2));
- d->XMM_S(3) = approx_rcp(s->XMM_S(3));
+ d->XMM_S(0) = float32_div(float32_one, s->XMM_S(0), &env->sse_status);
+ d->XMM_S(1) = float32_div(float32_one, s->XMM_S(1), &env->sse_status);
+ d->XMM_S(2) = float32_div(float32_one, s->XMM_S(2), &env->sse_status);
+ d->XMM_S(3) = float32_div(float32_one, s->XMM_S(3), &env->sse_status);
}
void helper_rcpss(XMMReg *d, XMMReg *s)
{
- d->XMM_S(0) = approx_rcp(s->XMM_S(0));
+ d->XMM_S(0) = float32_div(float32_one, s->XMM_S(0), &env->sse_status);
}
static inline uint64_t helper_extrq(uint64_t src, int shift, int len)
@@ -1272,14 +1282,16 @@ void helper_pfpnacc(MMXReg *d, MMXReg *s)
void helper_pfrcp(MMXReg *d, MMXReg *s)
{
- d->MMX_S(0) = approx_rcp(s->MMX_S(0));
+ d->MMX_S(0) = float32_div(float32_one, s->MMX_S(0), &env->mmx_status);
d->MMX_S(1) = d->MMX_S(0);
}
void helper_pfrsqrt(MMXReg *d, MMXReg *s)
{
d->MMX_L(1) = s->MMX_L(0) & 0x7fffffff;
- d->MMX_S(1) = approx_rsqrt(d->MMX_S(1));
+ d->MMX_S(1) = float32_div(float32_one,
+ float32_sqrt(d->MMX_S(1), &env->mmx_status),
+ &env->mmx_status);
d->MMX_L(1) |= s->MMX_L(0) & 0x80000000;
d->MMX_L(0) = d->MMX_L(1);
}
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 7d1340ed0..199302e51 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7890,8 +7890,7 @@ void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
gen_intermediate_code_internal(env, tb, 1);
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
int cc_op;
#ifdef DEBUG_DISAS
@@ -7903,8 +7902,8 @@ void gen_pc_load(CPUState *env, TranslationBlock *tb,
qemu_log("0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]);
}
}
- qemu_log("spc=0x%08lx pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
- searched_pc, pc_pos, gen_opc_pc[pc_pos] - tb->cs_base,
+ qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
+ pc_pos, gen_opc_pc[pc_pos] - tb->cs_base,
(uint32_t)tb->cs_base);
}
#endif
diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c
index e84ba488b..c72b1df47 100644
--- a/target-lm32/op_helper.c
+++ b/target-lm32/op_helper.c
@@ -95,7 +95,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
cpu_loop_exit();
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index efc9b5a85..51b4f5a81 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -1212,8 +1212,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, "\n\n");
}
-void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->pc = gen_opc_pc[pc_pos];
}
diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c
index 07111073f..9b13bdbcc 100644
--- a/target-m68k/op_helper.c
+++ b/target-m68k/op_helper.c
@@ -68,7 +68,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
cpu_loop_exit();
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 038c0af3e..9e5578d45 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3113,8 +3113,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf (f, "FPRESULT = %12g\n", *(double *)&env->fp_result);
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->pc = gen_opc_pc[pc_pos];
}
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index b7cd6b288..c7b2f97d9 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -60,7 +60,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
cpu_loop_exit();
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index bff3a11bc..b47b92e90 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1940,8 +1940,7 @@ void cpu_reset (CPUState *env)
#endif
}
-void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->sregs[SR_PC] = gen_opc_pc[pc_pos];
}
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 8cba535a3..b8e4991f3 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -54,7 +54,7 @@ static void do_restore_state (void *pc_ptr)
tb = tb_find_pc (pc);
if (tb) {
- cpu_restore_state (tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
#endif
@@ -1972,7 +1972,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
helper_raise_exception_err(env->exception_index, env->error_code);
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 953c52806..4eaa8261c 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -12737,8 +12737,7 @@ void cpu_reset (CPUMIPSState *env)
env->exception_index = EXCP_NONE;
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->active_tc.PC = gen_opc_pc[pc_pos];
env->hflags &= ~MIPS_HFLAG_BMASK;
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 28d40ac9a..d5db484b4 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -3741,7 +3741,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (likely(tb)) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
helper_raise_exception_err(env->exception_index, env->error_code);
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 3c3ee24c9..a943dbcf8 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9367,8 +9367,7 @@ void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
gen_intermediate_code_internal(env, tb, 1);
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->nip = gen_opc_pc[pc_pos];
}
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index 402df2d85..be455b9de 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -61,7 +61,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
if (likely(tb)) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
/* XXX */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 2cb893f21..4d45e3261 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -54,8 +54,7 @@ void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
{
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->psw.addr = gen_opc_pc[pc_pos];
}
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index c127860cd..b909d18bc 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -32,7 +32,7 @@ static void cpu_restore_state_from_retaddr(void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, NULL);
+ cpu_restore_state(tb, env, pc);
}
}
}
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 88098d7c2..93c863650 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -2069,8 +2069,7 @@ void gen_intermediate_code_pc(CPUState * env, struct TranslationBlock *tb)
gen_intermediate_code_internal(env, tb, 1);
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->pc = gen_opc_pc[pc_pos];
env->flags = gen_opc_hflags[pc_pos];
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 854f168c6..ffffb8c0b 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -4375,7 +4375,7 @@ static void cpu_restore_state2(void *retaddr)
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
- cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
+ cpu_restore_state(tb, env, pc);
}
}
}
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 883ecd2d2..3c958b26d 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5080,8 +5080,7 @@ void gen_intermediate_code_init(CPUSPARCState *env)
}
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
target_ulong npc;
env->pc = gen_opc_pc[pc_pos];
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index a6ba991e9..98eaeb3d4 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -2098,8 +2098,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
#endif
}
-void gen_pc_load(CPUState *env, TranslationBlock *tb,
- unsigned long searched_pc, int pc_pos, void *puc)
+void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
{
env->regs[31] = gen_opc_pc[pc_pos];
}
diff --git a/translate-all.c b/translate-all.c
index efcfb9adc..2ca190ca8 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -112,8 +112,7 @@ int cpu_gen_code(CPUState *env, TranslationBlock *tb, int *gen_code_size_ptr)
/* The cpu state corresponding to 'searched_pc' is restored.
*/
int cpu_restore_state(TranslationBlock *tb,
- CPUState *env, unsigned long searched_pc,
- void *puc)
+ CPUState *env, unsigned long searched_pc)
{
TCGContext *s = &tcg_ctx;
int j;
@@ -157,7 +156,7 @@ int cpu_restore_state(TranslationBlock *tb,
j--;
env->icount_decr.u16.low -= gen_opc_icount[j];
- gen_pc_load(env, tb, searched_pc, j, puc);
+ restore_state_to_opc(env, tb, j);
#ifdef CONFIG_PROFILER
s->restore_time += profile_getclock() - ti;