Commit b4a8c9ae authored by Peter Maydell's avatar Peter Maydell

Merge remote-tracking branch 'pmaydell/tags/pull-target-arm-20140131' into staging

target-arm queue:
 * implementation of first part of the A64 Neon instruction set
 * v8 AArch32 rounding and 16<->64 fp conversion instructions
 * fix MIDR value on Zynq boards
 * some minor bugfixes/code cleanups

# gpg: Signature made Fri 31 Jan 2014 15:06:34 GMT using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"

* pmaydell/tags/pull-target-arm-20140131: (34 commits)
  arm_gic: Fix GICD_ICPENDR and GICD_ISPENDR writes
  arm_gic: Introduce define for GIC_NR_SGIS
  target-arm: A64: Add SIMD shift by immediate
  target-arm: A64: Add simple SIMD 3-same floating point ops
  target-arm: A64: Add integer ops from SIMD 3-same group
  target-arm: A64: Add logic ops from SIMD 3 same group
  target-arm: A64: Add top level decode for SIMD 3-same group
  target-arm: A64: Add SIMD scalar 3 same add, sub and compare ops
  target-arm: A64: Add SIMD three-different ABDL instructions
  target-arm: A64: Add SIMD three-different multiply accumulate insns
  target-arm: Add AArch32 SIMD VCVTA, VCVTN, VCVTP and VCVTM
  target-arm: Add AArch32 FP VCVTA, VCVTN, VCVTP and VCVTM
  target-arm: Add AArch32 SIMD VRINTA, VRINTN, VRINTP, VRINTM, VRINTZ
  target-arm: Add set_neon_rmode helper
  target-arm: Add support for AArch32 SIMD VRINTX
  target-arm: Add support for AArch32 FP VRINTX
  target-arm: Add support for AArch32 FP VRINTZ
  target-arm: Add support for AArch32 FP VRINTR
  target-arm: Add AArch32 FP VRINTA, VRINTN, VRINTP and VRINTM
  target-arm: Move arm_rmode_to_sf to a shared location.
  ...
Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 850bbe1b 5b0adce1
......@@ -173,6 +173,11 @@ static void default_reset_secondary(ARMCPU *cpu,
env->regs[15] = info->smp_loader_start;
}
static inline bool have_dtb(const struct arm_boot_info *info)
{
return info->dtb_filename || info->get_dtb;
}
#define WRITE_WORD(p, value) do { \
stl_phys_notdirty(p, value); \
p += 4; \
......@@ -421,7 +426,7 @@ static void do_cpu_reset(void *opaque)
env->regs[15] = info->loader_start;
}
if (!info->dtb_filename) {
if (!have_dtb(info)) {
if (old_param) {
set_kernel_args_old(info);
} else {
......@@ -542,7 +547,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
/* for device tree boot, we pass the DTB directly in r2. Otherwise
* we point to the kernel args.
*/
if (info->dtb_filename || info->get_dtb) {
if (have_dtb(info)) {
/* Place the DTB after the initrd in memory. Note that some
* kernels will trash anything in the 4K page the initrd
* ends in, so make sure the DTB isn't caught up in that.
......
......@@ -37,6 +37,7 @@
#define IRQ_OFFSET 32 /* pic interrupts start from index 32 */
#define MPCORE_PERIPHBASE 0xF8F00000
#define ZYNQ_BOARD_MIDR 0x413FC090
static const int dma_irqs[8] = {
46, 47, 48, 49, 72, 73, 74, 75
......@@ -125,6 +126,12 @@ static void zynq_init(QEMUMachineInitArgs *args)
cpu = ARM_CPU(object_new(object_class_get_name(cpu_oc)));
object_property_set_int(OBJECT(cpu), ZYNQ_BOARD_MIDR, "midr", &err);
if (err) {
error_report("%s", error_get_pretty(err));
exit(1);
}
object_property_set_int(OBJECT(cpu), MPCORE_PERIPHBASE, "reset-cbar", &err);
if (err) {
error_report("%s", error_get_pretty(err));
......
......@@ -18,25 +18,35 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#define SKIP_PIXEL(to) to += deststep
#define SKIP_PIXEL(to) (to += deststep)
#if DEPTH == 8
# define PIXEL_TYPE uint8_t
# define COPY_PIXEL(to, from) *to = from; SKIP_PIXEL(to)
# define COPY_PIXEL1(to, from) *to ++ = from
# define PIXEL_TYPE uint8_t
# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0)
# define COPY_PIXEL1(to, from) (*to++ = from)
#elif DEPTH == 15 || DEPTH == 16
# define PIXEL_TYPE uint16_t
# define COPY_PIXEL(to, from) *to = from; SKIP_PIXEL(to)
# define COPY_PIXEL1(to, from) *to ++ = from
# define PIXEL_TYPE uint16_t
# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0)
# define COPY_PIXEL1(to, from) (*to++ = from)
#elif DEPTH == 24
# define PIXEL_TYPE uint8_t
# define COPY_PIXEL(to, from) \
to[0] = from; to[1] = (from) >> 8; to[2] = (from) >> 16; SKIP_PIXEL(to)
# define COPY_PIXEL1(to, from) \
*to ++ = from; *to ++ = (from) >> 8; *to ++ = (from) >> 16
# define PIXEL_TYPE uint8_t
# define COPY_PIXEL(to, from) \
do { \
to[0] = from; \
to[1] = (from) >> 8; \
to[2] = (from) >> 16; \
SKIP_PIXEL(to); \
} while (0)
# define COPY_PIXEL1(to, from) \
do { \
*to++ = from; \
*to++ = (from) >> 8; \
*to++ = (from) >> 16; \
} while (0)
#elif DEPTH == 32
# define PIXEL_TYPE uint32_t
# define COPY_PIXEL(to, from) *to = from; SKIP_PIXEL(to)
# define COPY_PIXEL1(to, from) *to ++ = from
# define PIXEL_TYPE uint32_t
# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0)
# define COPY_PIXEL1(to, from) (*to++ = from)
#else
# error unknown bit depth
#endif
......
......@@ -14,12 +14,16 @@
#if BITS == 8
#define COPY_PIXEL(to, from) *(to++) = from
#elif BITS == 15 || BITS == 16
#define COPY_PIXEL(to, from) *(uint16_t *)to = from; to += 2;
#define COPY_PIXEL(to, from) do { *(uint16_t *)to = from; to += 2; } while (0)
#elif BITS == 24
#define COPY_PIXEL(to, from) \
*(to++) = from; *(to++) = (from) >> 8; *(to++) = (from) >> 16
#define COPY_PIXEL(to, from) \
do { \
*(to++) = from; \
*(to++) = (from) >> 8; \
*(to++) = (from) >> 16; \
} while (0)
#elif BITS == 32
#define COPY_PIXEL(to, from) *(uint32_t *)to = from; to += 4;
#define COPY_PIXEL(to, from) do { *(uint32_t *)to = from; to += 4; } while (0)
#else
#error unknown bit depth
#endif
......
......@@ -11,14 +11,26 @@
# define SKIP_PIXEL(to) to += deststep
#if BITS == 8
# define COPY_PIXEL(to, from) *to = from; SKIP_PIXEL(to)
# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0)
#elif BITS == 15 || BITS == 16
# define COPY_PIXEL(to, from) *(uint16_t *) to = from; SKIP_PIXEL(to)
# define COPY_PIXEL(to, from) \
do { \
*(uint16_t *) to = from; \
SKIP_PIXEL(to); \
} while (0)
#elif BITS == 24
# define COPY_PIXEL(to, from) \
*(uint16_t *) to = from; *(to + 2) = (from) >> 16; SKIP_PIXEL(to)
# define COPY_PIXEL(to, from) \
do { \
*(uint16_t *) to = from; \
*(to + 2) = (from) >> 16; \
SKIP_PIXEL(to); \
} while (0)
#elif BITS == 32
# define COPY_PIXEL(to, from) *(uint32_t *) to = from; SKIP_PIXEL(to)
# define COPY_PIXEL(to, from) \
do { \
*(uint32_t *) to = from; \
SKIP_PIXEL(to); \
} while (0)
#else
# error unknown bit depth
#endif
......
......@@ -22,14 +22,18 @@
*/
#if BITS == 8
# define SET_PIXEL(addr, color) *(uint8_t*)addr = color;
# define SET_PIXEL(addr, color) (*(uint8_t *)addr = color)
#elif BITS == 15 || BITS == 16
# define SET_PIXEL(addr, color) *(uint16_t*)addr = color;
# define SET_PIXEL(addr, color) (*(uint16_t *)addr = color)
#elif BITS == 24
# define SET_PIXEL(addr, color) \
addr[0] = color; addr[1] = (color) >> 8; addr[2] = (color) >> 16;
# define SET_PIXEL(addr, color) \
do { \
addr[0] = color; \
addr[1] = (color) >> 8; \
addr[2] = (color) >> 16; \
} while (0)
#elif BITS == 32
# define SET_PIXEL(addr, color) *(uint32_t*)addr = color;
# define SET_PIXEL(addr, color) (*(uint32_t *)addr = color)
#else
# error unknown bit depth
#endif
......
......@@ -380,8 +380,10 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
if (irq >= s->num_irq)
goto bad_reg;
if (irq < 16)
value = 0xff;
if (irq < GIC_NR_SGIS) {
value = 0xff;
}
for (i = 0; i < 8; i++) {
if (value & (1 << i)) {
int mask =
......@@ -406,8 +408,10 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
if (irq >= s->num_irq)
goto bad_reg;
if (irq < 16)
value = 0;
if (irq < GIC_NR_SGIS) {
value = 0;
}
for (i = 0; i < 8; i++) {
if (value & (1 << i)) {
int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
......@@ -423,8 +427,9 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
if (irq >= s->num_irq)
goto bad_reg;
if (irq < 16)
irq = 0;
if (irq < GIC_NR_SGIS) {
value = 0;
}
for (i = 0; i < 8; i++) {
if (value & (1 << i)) {
......@@ -436,6 +441,10 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
if (irq >= s->num_irq)
goto bad_reg;
if (irq < GIC_NR_SGIS) {
value = 0;
}
for (i = 0; i < 8; i++) {
/* ??? This currently clears the pending bit for all CPUs, even
for per-CPU interrupts. It's unclear whether this is the
......
......@@ -27,6 +27,7 @@
#define GIC_MAXIRQ 1020
/* First 32 are private to each CPU (SGIs and PPIs). */
#define GIC_INTERNAL 32
#define GIC_NR_SGIS 16
/* Maximum number of possible CPU interfaces, determined by GIC architecture */
#define GIC_NCPU 8
......
......@@ -982,6 +982,7 @@ static const ARMCPUInfo arm_cpus[] = {
static Property arm_cpu_properties[] = {
DEFINE_PROP_BOOL("start-powered-off", ARMCPU, start_powered_off, false),
DEFINE_PROP_UINT32("midr", ARMCPU, midr, 0),
DEFINE_PROP_END_OF_LIST()
};
......
......@@ -496,6 +496,8 @@ enum arm_fprounding {
FPROUNDING_ODD
};
int arm_rmode_to_sf(int rmode);
enum arm_cpu_mode {
ARM_CPU_MODE_USR = 0x10,
ARM_CPU_MODE_FIQ = 0x11,
......
......@@ -122,3 +122,34 @@ uint64_t HELPER(vfp_cmped_a64)(float64 x, float64 y, void *fp_status)
{
return float_rel_to_flags(float64_compare(x, y, fp_status));
}
uint64_t HELPER(simd_tbl)(CPUARMState *env, uint64_t result, uint64_t indices,
uint32_t rn, uint32_t numregs)
{
/* Helper function for SIMD TBL and TBX. We have to do the table
* lookup part for the 64 bits worth of indices we're passed in.
* result is the initial results vector (either zeroes for TBL
* or some guest values for TBX), rn the register number where
* the table starts, and numregs the number of registers in the table.
* We return the results of the lookups.
*/
int shift;
for (shift = 0; shift < 64; shift += 8) {
int index = extract64(indices, shift, 8);
if (index < 16 * numregs) {
/* Convert index (a byte offset into the virtual table
* which is a series of 128-bit vectors concatenated)
* into the correct vfp.regs[] element plus a bit offset
* into that element, bearing in mind that the table
* can wrap around from V31 to V0.
*/
int elt = (rn * 2 + (index >> 3)) % 64;
int bitidx = (index & 7) * 8;
uint64_t val = extract64(env->vfp.regs[elt], bitidx, 8);
result = deposit64(result, shift, 8, val);
}
}
return result;
}
......@@ -26,3 +26,4 @@ DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr)
DEF_HELPER_3(vfp_cmpes_a64, i64, f32, f32, ptr)
DEF_HELPER_3(vfp_cmpd_a64, i64, f64, f64, ptr)
DEF_HELPER_3(vfp_cmped_a64, i64, f64, f64, ptr)
DEF_HELPER_FLAGS_5(simd_tbl, TCG_CALL_NO_RWG_SE, i64, env, i64, i64, i32, i32)
......@@ -4048,6 +4048,23 @@ uint32_t HELPER(set_rmode)(uint32_t rmode, CPUARMState *env)
return prev_rmode;
}
/* Set the current fp rounding mode in the standard fp status and return
* the old one. This is for NEON instructions that need to change the
* rounding mode but wish to use the standard FPSCR values for everything
* else. Always set the rounding mode back to the correct value after
* modifying it.
* The argument is a softfloat float_round_ value.
*/
uint32_t HELPER(set_neon_rmode)(uint32_t rmode, CPUARMState *env)
{
float_status *fp_status = &env->vfp.standard_fp_status;
uint32_t prev_rmode = get_float_rounding_mode(fp_status);
set_float_rounding_mode(rmode, fp_status);
return prev_rmode;
}
/* Half precision conversions. */
static float32 do_fcvt_f16_to_f32(uint32_t a, CPUARMState *env, float_status *s)
{
......@@ -4418,3 +4435,31 @@ float64 HELPER(rintd)(float64 x, void *fp_status)
return ret;
}
/* Convert ARM rounding mode to softfloat */
int arm_rmode_to_sf(int rmode)
{
switch (rmode) {
case FPROUNDING_TIEAWAY:
rmode = float_round_ties_away;
break;
case FPROUNDING_ODD:
/* FIXME: add support for TIEAWAY and ODD */
qemu_log_mask(LOG_UNIMP, "arm: unimplemented rounding mode: %d\n",
rmode);
case FPROUNDING_TIEEVEN:
default:
rmode = float_round_nearest_even;
break;
case FPROUNDING_POSINF:
rmode = float_round_up;
break;
case FPROUNDING_NEGINF:
rmode = float_round_down;
break;
case FPROUNDING_ZERO:
rmode = float_round_to_zero;
break;
}
return rmode;
}
......@@ -149,6 +149,7 @@ DEF_HELPER_3(vfp_ultod, f64, i64, i32, ptr)
DEF_HELPER_3(vfp_uqtod, f64, i64, i32, ptr)
DEF_HELPER_FLAGS_2(set_rmode, TCG_CALL_NO_RWG, i32, i32, env)
DEF_HELPER_FLAGS_2(set_neon_rmode, TCG_CALL_NO_RWG, i32, i32, env)
DEF_HELPER_2(vfp_fcvt_f16_to_f32, f32, i32, env)
DEF_HELPER_2(vfp_fcvt_f32_to_f16, i32, f32, env)
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment